pull/12118/head
Henry Heino 2025-04-16 10:07:10 -07:00
parent f380af08bd
commit eb86086e9d
3 changed files with 111 additions and 116 deletions

View File

@ -62,6 +62,7 @@ packages/app-mobile/locales
packages/app-mobile/node_modules
packages/app-mobile/pluginAssets/
packages/fork-*
!packages/fork-uslug
packages/default-plugins/plugin-base-repo/
packages/default-plugins/plugin-sources/
packages/htmlpack/dist/

View File

@ -1,53 +1,51 @@
/**
* Based on @joplin/fork-uslug
*
* The original is Copyright (c) 2012 Jeremy Selier
*
* MIT Licensed
*
* You may find a copy of this license in the LICENSE file that should have been provided
* to you with a copy of this software.
*/
import uslug from "./uslug";
// Based on @joplin/fork-uslug
//
// The original is Copyright (c) 2012 Jeremy Selier
//
// MIT Licensed
//
// You may find a copy of this license in the LICENSE file that should have been provided
// to you with a copy of this software.
import uslug from './uslug';
const word0 = 'Ελληνικά';
const word1 = [word0, word0].join('-');
const word2 = [word0, word0].join(' - ');
const tests: Array<[string, string]> = [
['', ''],
['The \u212B symbol invented by A. J. \u00C5ngstr\u00F6m (1814, L\u00F6gd\u00F6, \u2013 1874) denotes the length 10\u207B\u00B9\u2070 m.', 'the-å-symbol-invented-by-a-j-ångström-1814-lögdö-1874-denotes-the-length-1010-m'],
['Быстрее и лучше!', 'быстрее-и-лучше'],
['xx x - "#$@ x', 'xx-x-x'],
['Bän...g (bang)', 'bäng-bang'],
[word0, word0.toLowerCase()],
[word1, word1.toLowerCase()],
[word2, word1.toLowerCase()],
[' a ', 'a'],
['tags/', 'tags'],
['y_u_no', 'y_u_no'],
['el-ni\xf1o', 'el-ni\xf1o'],
['x荿', 'x荿'],
['ϧ΃蒬蓣', '\u03e7蒬蓣'],
['¿x', 'x'],
['汉语/漢語', '汉语漢語'],
['فار,سي', 'فارسي'],
['เแโ|ใไ', 'เแโใไ'],
['日本語ドキュメンテ(ーション)', '日本語ドキュメンテーション'],
['一二三四五六七八九十!。。。', '一二三四五六七八九十'],
['संसद में काम नहीं तो वेतन क्यों?', 'संसद-में-काम-नहीं-तो-वेतन-क्यों'],
['เร่งรัด \'ปรับเงินเดือนท้องถิ่น 1 ขั้น\' ตามมติ ครม.', 'เร่งรัด-ปรับเงินเดือนท้องถิ่น-1-ขั้น-ตามมติ-ครม'],
['オバマ大統領が病院爆撃の調査へ同意するように、協力してください!', 'オバマ大統領が病院爆撃の調査へ同意するように-協力してください'],
['일본정부 법무대신(法務大臣): 우리는 일본 입관법의 재검토를 요구한다!', '일본정부-법무대신法務大臣-우리는-일본-입관법의-재검토를-요구한다'],
['😁', 'grin'],
['😁a', 'grina'],
['🐶🐶🐶🐱', 'dogdogdogcat'],
const tests: [string, string][] = [
['', ''],
['The \u212B symbol invented by A. J. \u00C5ngstr\u00F6m (1814, L\u00F6gd\u00F6, \u2013 1874) denotes the length 10\u207B\u00B9\u2070 m.', 'the-å-symbol-invented-by-a-j-ångström-1814-lögdö-1874-denotes-the-length-1010-m'],
['Быстрее и лучше!', 'быстрее-и-лучше'],
['xx x - "#$@ x', 'xx-x-x'],
['Bän...g (bang)', 'bäng-bang'],
[word0, word0.toLowerCase()],
[word1, word1.toLowerCase()],
[word2, word1.toLowerCase()],
[' a ', 'a'],
['tags/', 'tags'],
['y_u_no', 'y_u_no'],
['el-ni\xf1o', 'el-ni\xf1o'],
['x荿', 'x荿'],
['ϧ΃蒬蓣', '\u03e7蒬蓣'],
['¿x', 'x'],
['汉语/漢語', '汉语漢語'],
['فار,سي', 'فارسي'],
['เแโ|ใไ', 'เแโใไ'],
['日本語ドキュメンテ(ーション)', '日本語ドキュメンテーション'],
['一二三四五六七八九十!。。。', '一二三四五六七八九十'],
['संसद में काम नहीं तो वेतन क्यों?', 'संसद-में-काम-नहीं-तो-वेतन-क्यों'],
['เร่งรัด \'ปรับเงินเดือนท้องถิ่น 1 ขั้น\' ตามมติ ครม.', 'เร่งรัด-ปรับเงินเดือนท้องถิ่น-1-ขั้น-ตามมติ-ครม'],
['オバマ大統領が病院爆撃の調査へ同意するように、協力してください!', 'オバマ大統領が病院爆撃の調査へ同意するように-協力してください'],
['일본정부 법무대신(法務大臣): 우리는 일본 입관법의 재검토를 요구한다!', '일본정부-법무대신法務大臣-우리는-일본-입관법의-재검토를-요구한다'],
['😁', 'grin'],
['😁a', 'grina'],
['🐶🐶🐶🐱', 'dogdogdogcat'],
];
describe('uslug', () => {
it.each(tests)('should convert %s to %s', (input, expected) => {
expect(uslug(input)).toBe(expected);
});
it('should support "allowedChars"', () => {
expect(uslug('qbc,fe', { allowedChars: 'q' })).toBe('qbcfe');
});
});
it.each(tests)('should convert %s to %s', (input, expected) => {
expect(uslug(input)).toBe(expected);
});
it('should support "allowedChars"', () => {
expect(uslug('qbc,fe', { allowedChars: 'q' })).toBe('qbcfe');
});
});

View File

@ -1,13 +1,11 @@
/**
* Based on @joplin/fork-uslug
*
* The original is Copyright (c) 2012 Jeremy Selier
*
* MIT Licensed
*
* You may find a copy of this license in the LICENSE file that should have been provided
* to you with a copy of this software.
*/
// Based on @joplin/fork-uslug
//
// The original is Copyright (c) 2012 Jeremy Selier
//
// MIT Licensed
//
// You may find a copy of this license in the LICENSE file that should have been provided
// to you with a copy of this software.
const nodeEmoji = require('node-emoji');
@ -15,85 +13,83 @@ const nodeEmoji = require('node-emoji');
// \p{} regexes.
let regexes_;
try {
regexes_ = {
L: new RegExp('\\p{L}', 'u'),
N: new RegExp('\\p{N}', 'u'),
Z: new RegExp('\\p{Z}', 'u'),
M: new RegExp('\\p{M}', 'u'),
};
regexes_ = {
// eslint-disable-next-line prefer-regex-literals -- Needed to prevent syntax errors
L: new RegExp('\\p{L}', 'u'), N: new RegExp('\\p{N}', 'u'), Z: new RegExp('\\p{Z}', 'u'), M: new RegExp('\\p{M}', 'u'),
};
} catch (error) {
console.error(error);
regexes_ = undefined;
console.error(error);
regexes_ = undefined;
}
const _unicodeCategory = function (c: string) {
if (!regexes_) {
console.warn('Unicode RegExps not loaded. Skipping category check.');
return undefined;
}
const _unicodeCategory = function(c: string) {
if (!regexes_) {
console.warn('Unicode RegExps not loaded. Skipping category check.');
return undefined;
}
for (const [key, val] of Object.entries(regexes_)) {
if (c.match(val)) return key;
}
return undefined;
for (const [key, val] of Object.entries(regexes_)) {
if (c.match(val)) return key;
}
return undefined;
};
interface Options {
lower?: boolean;
spaces?: boolean;
allowedChars?: string;
lower?: boolean;
spaces?: boolean;
allowedChars?: string;
}
export default function (string: string, options: Options = {}) {
string = string || '';
export default function(string: string, options: Options = {}) {
string = string || '';
options = options || {};
options = options || {};
const allowedChars = options.allowedChars || '-_~';
const lower = typeof options.lower === 'boolean' ? options.lower : true;
const spaces = typeof options.spaces === 'boolean' ? options.spaces : false;
const allowedChars = options.allowedChars || '-_~';
const lower = typeof options.lower === 'boolean' ? options.lower : true;
const spaces = typeof options.spaces === 'boolean' ? options.spaces : false;
const rv = [];
const rv = [];
const noEmojiString: string = nodeEmoji.unemojify(string);
const chars = noEmojiString.normalize('NFKC').split('');
const noEmojiString: string = nodeEmoji.unemojify(string);
const chars = noEmojiString.normalize('NFKC').split('');
for (let i = 0; i < chars.length; i++) {
let c = chars[i];
let code = c.charCodeAt(0);
for (let i = 0; i < chars.length; i++) {
const c = chars[i];
const code = c.charCodeAt(0);
// Allow Common CJK Unified Ideographs
// See: http://www.unicode.org/versions/Unicode6.0.0/ch12.pdf - Table 12-2
// Allow Common CJK Unified Ideographs
// See: http://www.unicode.org/versions/Unicode6.0.0/ch12.pdf - Table 12-2
if (0x4E00 <= code && code <= 0x9FFF) {
rv.push(c);
continue;
}
if (0x4E00 <= code && code <= 0x9FFF) {
rv.push(c);
continue;
}
// Allow Hangul
if (0xAC00 <= code && code <= 0xD7A3) {
rv.push(c);
continue;
}
// Allow Hangul
if (0xAC00 <= code && code <= 0xD7A3) {
rv.push(c);
continue;
}
// Japanese ideographic punctuation
if ((0x3000 <= code && code <= 0x3002) || (0xFF01 <= code && code <= 0xFF02)) {
rv.push(' ');
}
// Japanese ideographic punctuation
if ((0x3000 <= code && code <= 0x3002) || (0xFF01 <= code && code <= 0xFF02)) {
rv.push(' ');
}
if (allowedChars.indexOf(c) != -1) {
rv.push(c);
continue;
}
if (allowedChars.indexOf(c) !== -1) {
rv.push(c);
continue;
}
const val = _unicodeCategory(c);
if (val && ~'LNM'.indexOf(val)) rv.push(c);
if (val && ~'Z'.indexOf(val)) rv.push(' ');
}
let slug = rv.join('').replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ');
const val = _unicodeCategory(c);
if (val && ~'LNM'.indexOf(val)) rv.push(c);
if (val && ~'Z'.indexOf(val)) rv.push(' ');
}
let slug = rv.join('').replace(/^\s+|\s+$/g, '').replace(/\s+/g, ' ');
if (!spaces) slug = slug.replace(/[\s\-]+/g, '-');
if (lower) slug = slug.toLowerCase();
if (!spaces) slug = slug.replace(/[\s-]+/g, '-');
if (lower) slug = slug.toLowerCase();
return slug;
};
return slug;
}