Skip to content
Snippets Groups Projects
Commit d238c1da authored by marihachi's avatar marihachi
Browse files

Merge branch 'develop' into master

parents 63997204 ade4f04f
No related branches found
Tags v0.15.0
No related merge requests found
{
"name": "mfm-js",
"version": "0.14.1",
"version": "0.15.0",
"description": "An MFM parser implementation with PEG.js",
"main": "./built/index.js",
"types": "./built/index.d.ts",
......@@ -12,6 +12,7 @@
"tsc": "tsc",
"tsd": "tsd",
"parse": "node ./built/cli/parse",
"parse-plain": "node ./built/cli/parsePlain",
"test": "mocha -r ts-node/register 'test/**/*.ts' && npm run tsd"
},
"repository": {
......
import { performance } from 'perf_hooks';
import inputLine, { InputCanceledError } from './misc/inputLine';
import { parsePlain } from '..';
async function entryPoint() {
console.log('intaractive plain parser');
while (true) {
let input: string;
try {
input = await inputLine('> ');
}
catch (err) {
if (err instanceof InputCanceledError) {
console.log('bye.');
return;
}
throw err;
}
// replace special chars
input = input
.replace(/\\n/g, '\n')
.replace(/\\t/g, '\t')
.replace(/\\u00a0/g, '\u00a0');
try {
const parseTimeStart = performance.now();
const result = parsePlain(input);
const parseTimeEnd = performance.now();
console.log(JSON.stringify(result));
const parseTime = (parseTimeEnd - parseTimeStart).toFixed(3);
console.log(`parsing time: ${parseTime}ms`);
}
catch (err) {
console.log('parsing error:');
console.log(err);
}
console.log();
}
}
entryPoint()
.catch(err => {
console.log(err);
process.exit(1);
});
......@@ -66,7 +66,7 @@ fullParser
= nodes:(&. n:(block / inline) { return n; })* { return mergeText(nodes); }
plainParser
= nodes:(&. n:(emojiCode / unicodeEmoji / text) { return n; })* { return mergeText(nodes); }
= nodes:(&. n:(emojiCode / unicodeEmoji / plainText) { return n; })* { return mergeText(nodes); }
inlineParser
= nodes:(&. n:inline { return n; })* { return mergeText(nodes); }
......@@ -165,7 +165,7 @@ inline
/ url
/ link
/ fn
/ text
/ inlineText
// inline: emoji code
......@@ -219,16 +219,22 @@ small
// inline: italic
italic
= italicTag
/ italicAlt
italicTag
= "<i>" content:(!"</i>" i:inline { return i; })+ "</i>"
{
return ITALIC(mergeText(content));
}
/ "*" content:$(!"*" ([a-z0-9]i / _))+ "*"
italicAlt
= "*" content:$(!"*" ([a-z0-9]i / _))+ "*" &(EOF / LF / _)
{
const parsedContent = applyParser(content, 'inlineParser');
return ITALIC(parsedContent);
}
/ "_" content:$(!"_" ([a-z0-9]i / _))+ "_"
/ "_" content:$(!"_" ([a-z0-9]i / _))+ "_" &(EOF / LF / _)
{
const parsedContent = applyParser(content, 'inlineParser');
return ITALIC(parsedContent);
......@@ -289,7 +295,7 @@ mentionHostPart
// inline: hashtag
hashtag
= "#" content:hashtagContent
= "#" !("\uFE0F"? "\u20E3") content:hashtagContent
{
return HASHTAG(content);
}
......@@ -382,7 +388,13 @@ fnArg
// inline: text
text
inlineText
= !(LF / _) . &(hashtag / mention / italicAlt) . { return text(); } // hashtag, mention, italic ignore
/ . /* text node */
// inline: text (for plainParser)
plainText
= . /* text node */
//
......
......@@ -4,7 +4,29 @@ import {
TEXT, CENTER, FN, UNI_EMOJI, MENTION, EMOJI_CODE, HASHTAG, N_URL, BOLD, SMALL, ITALIC, STRIKE, QUOTE, MATH_BLOCK, SEARCH, CODE_BLOCK, LINK
} from '../built/index';
describe('parser', () => {
describe('PlainParser', () => {
describe('text', () => {
it('basic', () => {
const input = 'abc';
const output = [TEXT('abc')];
assert.deepStrictEqual(mfm.parsePlain(input), output);
});
it('ignore hashtag', () => {
const input = 'abc#abc';
const output = [TEXT('abc#abc')];
assert.deepStrictEqual(mfm.parsePlain(input), output);
});
it('keycap number sign', () => {
const input = 'abc#️⃣abc';
const output = [TEXT('abc'), UNI_EMOJI('#️⃣'), TEXT('abc')];
assert.deepStrictEqual(mfm.parsePlain(input), output);
});
});
});
describe('FullParser', () => {
describe('text', () => {
it('普通のテキストを入力すると1つのテキストノードが返される', () => {
const input = 'abc';
......@@ -222,6 +244,12 @@ describe('parser', () => {
const output = [TEXT('今起きた'), UNI_EMOJI('😇')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('keycap number sign', () => {
const input = 'abc#️⃣123';
const output = [TEXT('abc'), UNI_EMOJI('#️⃣'), TEXT('123')];
assert.deepStrictEqual(mfm.parse(input), output);
});
});
describe('big', () => {
......@@ -338,7 +366,7 @@ describe('parser', () => {
});
});
describe('italic 1', () => {
describe('italic tag', () => {
it('basic', () => {
const input = '<i>abc</i>';
const output = [
......@@ -376,7 +404,7 @@ describe('parser', () => {
});
});
describe('italic 2', () => {
describe('italic alt 1', () => {
it('basic', () => {
const input = '*abc*';
const output = [
......@@ -386,6 +414,54 @@ describe('parser', () => {
];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('basic 2', () => {
const input = 'before *abc* after';
const output = [
TEXT('before '),
ITALIC([
TEXT('abc')
]),
TEXT(' after')
];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('ignore a italic syntax if the before char is neither a space nor an LF', () => {
const input = 'before*abc*after';
const output = [TEXT('before*abc*after')];
assert.deepStrictEqual(mfm.parse(input), output);
});
});
describe('italic alt 2', () => {
it('basic', () => {
const input = '_abc_';
const output = [
ITALIC([
TEXT('abc')
])
];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('basic 2', () => {
const input = 'before _abc_ after';
const output = [
TEXT('before '),
ITALIC([
TEXT('abc')
]),
TEXT(' after')
];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('ignore a italic syntax if the before char is neither a space nor an LF', () => {
const input = 'before_abc_after';
const output = [TEXT('before_abc_after')];
assert.deepStrictEqual(mfm.parse(input), output);
});
});
// strike
......@@ -394,12 +470,73 @@ describe('parser', () => {
// mathInline
// mention
describe('mention', () => {
it('basic', () => {
const input = '@abc';
const output = [MENTION('abc', null, '@abc')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('basic 2', () => {
const input = 'before @abc after';
const output = [TEXT('before '), MENTION('abc', null, '@abc'), TEXT(' after')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('basic remote', () => {
const input = '@abc@misskey.io';
const output = [MENTION('abc', 'misskey.io', '@abc@misskey.io')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('basic remote 2', () => {
const input = 'before @abc@misskey.io after';
const output = [TEXT('before '), MENTION('abc', 'misskey.io', '@abc@misskey.io'), TEXT(' after')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('basic remote 3', () => {
const input = 'before\n@abc@misskey.io\nafter';
const output = [TEXT('before\n'), MENTION('abc', 'misskey.io', '@abc@misskey.io'), TEXT('\nafter')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('ignore format of mail address', () => {
const input = 'abc@example.com';
const output = [TEXT('abc@example.com')];
assert.deepStrictEqual(mfm.parse(input), output);
});
});
describe('hashtag', () => {
it('and unicode emoji', () => {
const input = '#️⃣abc123#abc';
const output = [UNI_EMOJI('#️⃣'), TEXT('abc123'), HASHTAG('abc')];
it('basic', () => {
const input = '#abc';
const output = [HASHTAG('abc')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('basic 2', () => {
const input = 'before #abc after';
const output = [TEXT('before '), HASHTAG('abc'), TEXT(' after')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('with keycap number sign', () => {
const input = '#️⃣abc123 #abc';
const output = [UNI_EMOJI('#️⃣'), TEXT('abc123 '), HASHTAG('abc')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('with keycap number sign 2', () => {
const input = `abc
#️⃣abc`;
const output = [TEXT('abc\n'), UNI_EMOJI('#️⃣'), TEXT('abc')];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('ignore a hashtag if the before char is neither a space nor an LF', () => {
const input = 'abc#abc';
const output = [TEXT('abc#abc')];
assert.deepStrictEqual(mfm.parse(input), output);
});
});
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment