[MFM] Improve hashtag detection

This commit is contained in:
syuilo 2018-11-27 02:08:51 +09:00
parent cf40470708
commit bdd12c0bfc
2 changed files with 39 additions and 10 deletions

View File

@ -30,17 +30,23 @@ function makeNodeWithChildren(name: string, children: Node[], props?: any): Node
}
function getTrailingPosition(x: string): number {
let pendingBracket = 0;
const brackets = [
['(', ')'],
['「', '」'],
];
const pendingBrackets = [] as any;
const end = x.split('').findIndex(char => {
if (char == ')') {
if (pendingBracket > 0) {
pendingBracket--;
const closeMatch = brackets.map(x => x[1]).indexOf(char);
const openMatch = brackets.map(x => x[0]).indexOf(char);
if (closeMatch != -1) {
if (pendingBrackets[closeMatch] > 0) {
pendingBrackets[closeMatch]--;
return false;
} else {
return true;
}
} else if (char == '(') {
pendingBracket++;
} else if (openMatch != -1) {
pendingBrackets[openMatch] = (pendingBrackets[openMatch] || 0) + 1;
return false;
} else {
return false;
@ -156,7 +162,7 @@ const mfm = P.createLanguage({
let hashtag = match[1];
hashtag = hashtag.substr(0, getTrailingPosition(hashtag));
if (hashtag.match(/^[0-9]+$/)) return P.makeFailure(i, 'not a hashtag');
if (!['\n', ' ', '(', null, undefined].includes(input[i - 1])) return P.makeFailure(i, 'require space before "#"');
if (!['\n', ' ', '(', '「', null, undefined].includes(input[i - 1])) return P.makeFailure(i, 'require space before "#"');
return P.makeSuccess(i + ('#' + hashtag).length, makeNode('hashtag', { hashtag: hashtag }));
}),
//#endregion

View File

@ -213,21 +213,44 @@ describe('Text', () => {
});
it('with brackets', () => {
const tokens = analyze('(#foo)');
const tokens1 = analyze('(#foo)');
assert.deepEqual([
text('('),
node('hashtag', { hashtag: 'foo' }),
text(')'),
], tokens1);
const tokens2 = analyze('「#foo」');
assert.deepEqual([
text('「'),
node('hashtag', { hashtag: 'foo' }),
text('」'),
], tokens2);
});
it('with mixed brackets', () => {
const tokens = analyze('「#foo(bar)」');
assert.deepEqual([
text('「'),
node('hashtag', { hashtag: 'foo(bar)' }),
text('」'),
], tokens);
});
it('with brackets (space before)', () => {
const tokens = analyze('(bar #foo)');
const tokens1 = analyze('(bar #foo)');
assert.deepEqual([
text('(bar '),
node('hashtag', { hashtag: 'foo' }),
text(')'),
], tokens);
], tokens1);
const tokens2 = analyze('「bar #foo」');
assert.deepEqual([
text('「bar '),
node('hashtag', { hashtag: 'foo' }),
text('」'),
], tokens2);
});
it('disallow number only', () => {