mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-02-15 18:48:28 -05:00
Closes #146 - Attempts to deal with emoji in gutter
Adds ability to automagically set the width of the gutter annotations
This commit is contained in:
@@ -6,17 +6,18 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
## [5.1.1-beta]
|
## [5.2.0-beta]
|
||||||
### Added
|
### Added
|
||||||
- Adds new `Changed Files` node to the `Repository Status` node of the `GitLens` custom view's `Repository View` (enabled via `"gitlens.insiders": true`) -- closes [#139](https://github.com/eamodio/vscode-gitlens/issues/139)
|
- Adds new `Changed Files` node to the `Repository Status` node of the `GitLens` custom view's `Repository View` -- closes [#139](https://github.com/eamodio/vscode-gitlens/issues/139)
|
||||||
- Provides a file-based view of all the changed files in the working tree and/or files in commits that haven't yet been pushed upstream
|
- Provides a file-based view of all the changed files in the working tree (enabled via `"gitlens.insiders": true`) and/or files in commits that haven't yet been pushed upstream
|
||||||
- Adds `gitlens.gitExplorer.enabled` setting to specify whether or not to show the `GitLens` custom view - closes [#144](https://github.com/eamodio/vscode-gitlens/issues/144)
|
- Adds `gitlens.gitExplorer.enabled` setting to specify whether or not to show the `GitLens` custom view - closes [#144](https://github.com/eamodio/vscode-gitlens/issues/144)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
- Chnages the default of the `gitlens.gitExplorer.commitFormat` setting to add parentheses around the commit id
|
- Changes the default of the `gitlens.gitExplorer.commitFormat` setting to add parentheses around the commit id
|
||||||
- Removes many menu items from `editor/title` & `editor/title/context` by default -- can be re-enabled via the `gitlens.advanced.menus` setting
|
- Removes many menu items from `editor/title` & `editor/title/context` by default -- can be re-enabled via the `gitlens.advanced.menus` setting
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- Fixes [#146](https://github.com/eamodio/vscode-gitlens/issues/146) - Blame gutter annotation issue when commit contains emoji
|
||||||
- Fixes an issue when running `Open File in Remote` with a multi-line selection wasn't properly opening the selection in GitLab -- thanks to [PR #145](https://github.com/eamodio/vscode-gitlens/pull/145) by Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron))!
|
- Fixes an issue when running `Open File in Remote` with a multi-line selection wasn't properly opening the selection in GitLab -- thanks to [PR #145](https://github.com/eamodio/vscode-gitlens/pull/145) by Amanda Cameron ([@AmandaCameron](https://github.com/AmandaCameron))!
|
||||||
- Fixes an issue where the `gitlens.advanced.menus` setting wasn't controlling all the menu items properly
|
- Fixes an issue where the `gitlens.advanced.menus` setting wasn't controlling all the menu items properly
|
||||||
|
|
||||||
|
|||||||
27
package-lock.json
generated
27
package-lock.json
generated
@@ -47,11 +47,6 @@
|
|||||||
"json-stable-stringify": "1.0.1"
|
"json-stable-stringify": "1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ansi-regex": {
|
|
||||||
"version": "3.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
|
||||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
|
|
||||||
},
|
|
||||||
"ansi-styles": {
|
"ansi-styles": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||||
@@ -1336,11 +1331,6 @@
|
|||||||
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
"integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-fullwidth-code-point": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
|
||||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
|
||||||
},
|
|
||||||
"is-glob": {
|
"is-glob": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
|
||||||
@@ -2334,15 +2324,6 @@
|
|||||||
"integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=",
|
"integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"string-width": {
|
|
||||||
"version": "2.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
|
||||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
|
||||||
"requires": {
|
|
||||||
"is-fullwidth-code-point": "2.0.0",
|
|
||||||
"strip-ansi": "4.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
|
||||||
@@ -2358,14 +2339,6 @@
|
|||||||
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
|
"integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"strip-ansi": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
|
||||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
|
||||||
"requires": {
|
|
||||||
"ansi-regex": "3.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"strip-bom": {
|
"strip-bom": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
|
||||||
|
|||||||
@@ -1921,7 +1921,6 @@
|
|||||||
"lodash.once": "4.1.1",
|
"lodash.once": "4.1.1",
|
||||||
"moment": "2.18.1",
|
"moment": "2.18.1",
|
||||||
"spawn-rx": "2.0.11",
|
"spawn-rx": "2.0.11",
|
||||||
"string-width": "2.1.1",
|
|
||||||
"tmp": "0.0.33"
|
"tmp": "0.0.33"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Dates, Strings } from '../system';
|
import { Dates, Objects, Strings } from '../system';
|
||||||
import { DecorationInstanceRenderOptions, DecorationOptions, MarkdownString, ThemableDecorationRenderOptions } from 'vscode';
|
import { DecorationInstanceRenderOptions, DecorationOptions, MarkdownString, ThemableDecorationRenderOptions } from 'vscode';
|
||||||
import { DiffWithCommand, OpenCommitInRemoteCommand, ShowQuickCommitDetailsCommand } from '../commands';
|
import { DiffWithCommand, OpenCommitInRemoteCommand, ShowQuickCommitDetailsCommand } from '../commands';
|
||||||
import { IThemeConfig, themeDefaults } from '../configuration';
|
import { IThemeConfig, themeDefaults } from '../configuration';
|
||||||
@@ -133,9 +133,23 @@ export class Annotations {
|
|||||||
} as DecorationOptions;
|
} as DecorationOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gutterRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig): IRenderOptions {
|
static gutterRenderOptions(cfgTheme: IThemeConfig, heatmap: IHeatmapConfig, options: ICommitFormatOptions): IRenderOptions {
|
||||||
const cfgFileTheme = cfgTheme.annotations.file.gutter;
|
const cfgFileTheme = cfgTheme.annotations.file.gutter;
|
||||||
|
|
||||||
|
// Try to get the width of the string, if there is a cap
|
||||||
|
let width = 4; // Start with a padding
|
||||||
|
for (const token of Objects.values<Strings.ITokenOptions | undefined>(options.tokenOptions)) {
|
||||||
|
if (token === undefined) continue;
|
||||||
|
|
||||||
|
// If any token is uncapped, kick out and set no max
|
||||||
|
if (token.truncateTo == null) {
|
||||||
|
width = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
width += token.truncateTo;
|
||||||
|
}
|
||||||
|
|
||||||
let borderStyle = undefined;
|
let borderStyle = undefined;
|
||||||
let borderWidth = undefined;
|
let borderWidth = undefined;
|
||||||
if (heatmap.enabled) {
|
if (heatmap.enabled) {
|
||||||
@@ -152,7 +166,8 @@ export class Annotations {
|
|||||||
borderStyle: borderStyle,
|
borderStyle: borderStyle,
|
||||||
borderWidth: borderWidth,
|
borderWidth: borderWidth,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
margin: '0 26px -1px 0'
|
margin: '0 26px -1px 0',
|
||||||
|
width: (width > 4) ? `${width}ch` : undefined
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
backgroundColor: cfgFileTheme.dark.backgroundColor || undefined,
|
backgroundColor: cfgFileTheme.dark.backgroundColor || undefined,
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
|
|||||||
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const offset = this.uri.offset;
|
const offset = this.uri.offset;
|
||||||
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap);
|
const renderOptions = Annotations.gutterRenderOptions(this._config.theme, cfg.heatmap, options);
|
||||||
const separateLines = this._config.theme.annotations.file.gutter.separateLines;
|
const separateLines = this._config.theme.annotations.file.gutter.separateLines;
|
||||||
|
|
||||||
const decorations: DecorationOptions[] = [];
|
const decorations: DecorationOptions[] = [];
|
||||||
@@ -58,7 +58,7 @@ export class GutterBlameAnnotationProvider extends BlameAnnotationProviderBase {
|
|||||||
...gutter.renderOptions,
|
...gutter.renderOptions,
|
||||||
before: {
|
before: {
|
||||||
...gutter.renderOptions!.before,
|
...gutter.renderOptions!.before,
|
||||||
contentText: GlyphChars.Space.repeat(Strings.getWidth(gutter.renderOptions!.before!.contentText!))
|
contentText: GlyphChars.Space.repeat(Strings.width(gutter.renderOptions!.before!.contentText!))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export abstract class Formatter<TItem = any, TOptions extends IFormatOptions = I
|
|||||||
|
|
||||||
let max = options.truncateTo;
|
let max = options.truncateTo;
|
||||||
|
|
||||||
const width = Strings.getWidth(s);
|
const width = Strings.width(s);
|
||||||
if (max === undefined) {
|
if (max === undefined) {
|
||||||
if (this.collapsableWhitespace === 0) return s;
|
if (this.collapsableWhitespace === 0) return s;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
const _escapeRegExp = require('lodash.escaperegexp');
|
const _escapeRegExp = require('lodash.escaperegexp');
|
||||||
const stringWidth = require('string-width');
|
|
||||||
|
|
||||||
export namespace Strings {
|
export namespace Strings {
|
||||||
export function escapeRegExp(s: string): string {
|
export function escapeRegExp(s: string): string {
|
||||||
return _escapeRegExp(s);
|
return _escapeRegExp(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getWidth(s: string): number {
|
|
||||||
return stringWidth(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
const TokenRegex = /\$\{([^|]*?)(?:\|(\d+)(\-|\?)?)?\}/g;
|
const TokenRegex = /\$\{([^|]*?)(?:\|(\d+)(\-|\?)?)?\}/g;
|
||||||
const TokenSanitizeRegex = /\$\{(\w*?)(?:\W|\d)*?\}/g;
|
const TokenSanitizeRegex = /\$\{(\w*?)(?:\W|\d)*?\}/g;
|
||||||
|
|
||||||
@@ -68,19 +63,19 @@ export namespace Strings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function padLeft(s: string, padTo: number, padding: string = '\u00a0') {
|
export function padLeft(s: string, padTo: number, padding: string = '\u00a0') {
|
||||||
const diff = padTo - getWidth(s);
|
const diff = padTo - width(s);
|
||||||
return (diff <= 0) ? s : '\u00a0'.repeat(diff) + s;
|
return (diff <= 0) ? s : '\u00a0'.repeat(diff) + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function padLeftOrTruncate(s: string, max: number, padding?: string) {
|
export function padLeftOrTruncate(s: string, max: number, padding?: string) {
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len < max) return padLeft(s, max, padding);
|
if (len < max) return padLeft(s, max, padding);
|
||||||
if (len > max) return truncate(s, max);
|
if (len > max) return truncate(s, max);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function padRight(s: string, padTo: number, padding: string = '\u00a0') {
|
export function padRight(s: string, padTo: number, padding: string = '\u00a0') {
|
||||||
const diff = padTo - getWidth(s);
|
const diff = padTo - width(s);
|
||||||
return (diff <= 0) ? s : s + '\u00a0'.repeat(diff);
|
return (diff <= 0) ? s : s + '\u00a0'.repeat(diff);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,14 +83,14 @@ export namespace Strings {
|
|||||||
const left = max < 0;
|
const left = max < 0;
|
||||||
max = Math.abs(max);
|
max = Math.abs(max);
|
||||||
|
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len < max) return left ? padLeft(s, max, padding) : padRight(s, max, padding);
|
if (len < max) return left ? padLeft(s, max, padding) : padRight(s, max, padding);
|
||||||
if (len > max) return truncate(s, max);
|
if (len > max) return truncate(s, max);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function padRightOrTruncate(s: string, max: number, padding?: string) {
|
export function padRightOrTruncate(s: string, max: number, padding?: string) {
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len < max) return padRight(s, max, padding);
|
if (len < max) return padRight(s, max, padding);
|
||||||
if (len > max) return truncate(s, max);
|
if (len > max) return truncate(s, max);
|
||||||
return s;
|
return s;
|
||||||
@@ -112,15 +107,15 @@ export namespace Strings {
|
|||||||
export function truncate(s: string, truncateTo: number, ellipsis: string = '\u2026') {
|
export function truncate(s: string, truncateTo: number, ellipsis: string = '\u2026') {
|
||||||
if (!s) return s;
|
if (!s) return s;
|
||||||
|
|
||||||
const len = getWidth(s);
|
const len = width(s);
|
||||||
if (len <= truncateTo) return s;
|
if (len <= truncateTo) return s;
|
||||||
if (len === s.length) return `${s.substring(0, truncateTo - 1)}${ellipsis}`;
|
if (len === s.length) return `${s.substring(0, truncateTo - 1)}${ellipsis}`;
|
||||||
|
|
||||||
// Skip ahead to start as far as we can by assuming all the double-width characters won't be truncated
|
// Skip ahead to start as far as we can by assuming all the double-width characters won't be truncated
|
||||||
let chars = Math.floor(truncateTo / (len / s.length));
|
let chars = Math.floor(truncateTo / (len / s.length));
|
||||||
let count = getWidth(s.substring(0, chars));
|
let count = width(s.substring(0, chars));
|
||||||
while (count < truncateTo) {
|
while (count < truncateTo) {
|
||||||
count += getWidth(s[chars++]);
|
count += width(s[chars++]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count >= truncateTo) {
|
if (count >= truncateTo) {
|
||||||
@@ -129,4 +124,107 @@ export namespace Strings {
|
|||||||
|
|
||||||
return `${s.substring(0, chars)}${ellipsis}`;
|
return `${s.substring(0, chars)}${ellipsis}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ansiRegex = /[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:[a-zA-Z\\d]*(?:;[a-zA-Z\\d]*)*)?\\u0007)|(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PRZcf-ntqry=><~]))/g;
|
||||||
|
|
||||||
|
export function width(s: string): number {
|
||||||
|
if (!s || s.length === 0) return 0;
|
||||||
|
|
||||||
|
s = s.replace(ansiRegex, '');
|
||||||
|
|
||||||
|
let count = 0;
|
||||||
|
let emoji = 0;
|
||||||
|
let joiners = 0;
|
||||||
|
|
||||||
|
const graphemes = [...s];
|
||||||
|
for (let i = 0; i < graphemes.length; i++) {
|
||||||
|
const code = graphemes[i].codePointAt(0)!;
|
||||||
|
|
||||||
|
// Ignore control characters
|
||||||
|
if (code <= 0x1F || (code >= 0x7F && code <= 0x9F)) continue;
|
||||||
|
|
||||||
|
// Ignore combining characters
|
||||||
|
if (code >= 0x300 && code <= 0x36F) continue;
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/30757193/find-out-if-character-in-string-is-emoji
|
||||||
|
if (
|
||||||
|
(code >= 0x1F600 && code <= 0x1F64F) || // Emoticons
|
||||||
|
(code >= 0x1F300 && code <= 0x1F5FF) || // Misc Symbols and Pictographs
|
||||||
|
(code >= 0x1F680 && code <= 0x1F6FF) || // Transport and Map
|
||||||
|
(code >= 0x2600 && code <= 0x26FF) || // Misc symbols
|
||||||
|
(code >= 0x2700 && code <= 0x27BF) || // Dingbats
|
||||||
|
(code >= 0xFE00 && code <= 0xFE0F) || // Variation Selectors
|
||||||
|
(code >= 0x1F900 && code <= 0x1F9FF) || // Supplemental Symbols and Pictographs
|
||||||
|
(code >= 65024 && code <= 65039) || // Variation selector
|
||||||
|
(code >= 8400 && code <= 8447) // Combining Diacritical Marks for Symbols
|
||||||
|
) {
|
||||||
|
if (code >= 0x1F3FB && code <= 0x1F3FF) continue; // emoji modifier fitzpatrick type
|
||||||
|
|
||||||
|
emoji++;
|
||||||
|
count += 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ignore zero-width joiners '\u200d'
|
||||||
|
if (code === 8205) {
|
||||||
|
joiners++;
|
||||||
|
count -= 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Surrogates
|
||||||
|
if (code > 0xFFFF) {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
count += isFullwidthCodePoint(code) ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const offset = emoji - joiners;
|
||||||
|
if (offset > 1) {
|
||||||
|
count += offset - 1;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFullwidthCodePoint(cp: number) {
|
||||||
|
// code points are derived from:
|
||||||
|
// http://www.unix.org/Public/UNIDATA/EastAsianWidth.txt
|
||||||
|
if (
|
||||||
|
cp >= 0x1100 && (
|
||||||
|
cp <= 0x115f || // Hangul Jamo
|
||||||
|
cp === 0x2329 || // LEFT-POINTING ANGLE BRACKET
|
||||||
|
cp === 0x232a || // RIGHT-POINTING ANGLE BRACKET
|
||||||
|
// CJK Radicals Supplement .. Enclosed CJK Letters and Months
|
||||||
|
(0x2e80 <= cp && cp <= 0x3247 && cp !== 0x303f) ||
|
||||||
|
// Enclosed CJK Letters and Months .. CJK Unified Ideographs Extension A
|
||||||
|
(0x3250 <= cp && cp <= 0x4dbf) ||
|
||||||
|
// CJK Unified Ideographs .. Yi Radicals
|
||||||
|
(0x4e00 <= cp && cp <= 0xa4c6) ||
|
||||||
|
// Hangul Jamo Extended-A
|
||||||
|
(0xa960 <= cp && cp <= 0xa97c) ||
|
||||||
|
// Hangul Syllables
|
||||||
|
(0xac00 <= cp && cp <= 0xd7a3) ||
|
||||||
|
// CJK Compatibility Ideographs
|
||||||
|
(0xf900 <= cp && cp <= 0xfaff) ||
|
||||||
|
// Vertical Forms
|
||||||
|
(0xfe10 <= cp && cp <= 0xfe19) ||
|
||||||
|
// CJK Compatibility Forms .. Small Form Variants
|
||||||
|
(0xfe30 <= cp && cp <= 0xfe6b) ||
|
||||||
|
// Halfwidth and Fullwidth Forms
|
||||||
|
(0xff01 <= cp && cp <= 0xff60) ||
|
||||||
|
(0xffe0 <= cp && cp <= 0xffe6) ||
|
||||||
|
// Kana Supplement
|
||||||
|
(0x1b000 <= cp && cp <= 0x1b001) ||
|
||||||
|
// Enclosed Ideographic Supplement
|
||||||
|
(0x1f200 <= cp && cp <= 0x1f251) ||
|
||||||
|
// CJK Unified Ideographs Extension B .. Tertiary Ideographic Plane
|
||||||
|
(0x20000 <= cp && cp <= 0x3fffd)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user