From ee0c14e0964d32bd5e01715b8d3eef615fdfda02 Mon Sep 17 00:00:00 2001 From: marihachi Date: Sun, 5 Jun 2022 16:26:51 +0900 Subject: [PATCH 1/8] implement plain syntax --- src/internal/parser.pegjs | 18 ++++++++++++++++++ src/node.ts | 10 +++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/internal/parser.pegjs b/src/internal/parser.pegjs index 947c794b..36909149 100644 --- a/src/internal/parser.pegjs +++ b/src/internal/parser.pegjs @@ -21,6 +21,7 @@ N_URL, LINK, FN, + NOMFM, TEXT } = require('../node'); @@ -126,6 +127,7 @@ full / hashtag / url / fn + / nomfm / link / search // block / inlineText @@ -144,6 +146,7 @@ inline / hashtag / url / fn + / nomfm / link / inlineText @@ -158,6 +161,7 @@ L_inline / inlineCode / mathInline / L_fn + / nomfm / L_inlineText plain @@ -553,6 +557,20 @@ fnArg return { k: k, v: true }; } +// inline: nomfm + +nomfm + = "" LF? content:nomfmContent LF? "" +{ + return NOMFM(TEXT(content)); +} + +nomfmContent + = (!(LF? "") .)+ +{ + return text(); +} + // inline: text inlineText diff --git a/src/node.ts b/src/node.ts index 1ac5fbed..8df195c3 100644 --- a/src/node.ts +++ b/src/node.ts @@ -53,7 +53,7 @@ export type MfmCenter = { export const CENTER = (children: MfmInline[]): NodeType<'center'> => { return { type: 'center', children }; }; export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | - MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmText; + MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmNomfm | MfmText; export type MfmUnicodeEmoji = { type: 'unicodeEmoji'; @@ -173,6 +173,13 @@ export type MfmFn = { }; export const FN = (name: string, args: MfmFn['props']['args'], children: MfmFn['children']): NodeType<'fn'> => { return { type: 'fn', props: { name, args }, children }; }; +export type MfmNomfm = { + type: 'plain'; + props?: Record; + children: MfmText[]; +}; +export const NOMFM = (text: MfmText): NodeType<'plain'> => { return { type: 'plain', children: [text] }; }; + export type MfmText = { type: 'text'; props: { @@ -201,5 +208,6 @@ export type NodeType = T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : + T extends 'plain' ? MfmNomfm : T extends 'text' ? MfmText : never; From 51e46a855bad11f48f59756d232ec41b33cff056 Mon Sep 17 00:00:00 2001 From: marihachi Date: Sun, 5 Jun 2022 16:37:04 +0900 Subject: [PATCH 2/8] public api --- etc/mfm-js.api.md | 14 ++++++++++++-- src/index.ts | 2 ++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/etc/mfm-js.api.md b/etc/mfm-js.api.md index ea4f238d..0fed8f93 100644 --- a/etc/mfm-js.api.md +++ b/etc/mfm-js.api.md @@ -105,7 +105,7 @@ export type MfmHashtag = { }; // @public (undocumented) -export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmText; +export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmNomfm | MfmText; // @public (undocumented) export type MfmInlineCode = { @@ -165,6 +165,13 @@ export type MfmMention = { // @public (undocumented) export type MfmNode = MfmBlock | MfmInline; +// @public (undocumented) +export type MfmNomfm = { + type: 'plain'; + props?: Record; + children: MfmText[]; +}; + // @public (undocumented) export type MfmQuote = { type: 'quote'; @@ -228,7 +235,10 @@ export type MfmUrl = { export const N_URL: (value: string, brackets?: boolean | undefined) => NodeType<'url'>; // @public (undocumented) -export type NodeType = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'text' ? MfmText : never; +export type NodeType = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'plain' ? MfmNomfm : T extends 'text' ? MfmText : never; + +// @public (undocumented) +export const NOMFM: (text: MfmText) => NodeType<'plain'>; // @public (undocumented) export function parse(input: string, opts?: Partial<{ diff --git a/src/index.ts b/src/index.ts index 6382ad05..2f16a558 100644 --- a/src/index.ts +++ b/src/index.ts @@ -35,6 +35,7 @@ export { MfmUrl, MfmLink, MfmFn, + MfmNomfm, MfmText, } from './node'; @@ -60,5 +61,6 @@ export { N_URL, LINK, FN, + NOMFM, TEXT, } from './node'; From 2bca0a43c27f80bccd0c732bb9f05dd0afeb7e7e Mon Sep 17 00:00:00 2001 From: marihachi Date: Sun, 5 Jun 2022 16:52:48 +0900 Subject: [PATCH 3/8] plain syntax --- src/internal/parser.pegjs | 2 +- src/node.ts | 2 +- test/api.ts | 10 ++++++++++ test/parser.ts | 24 +++++++++++++++++++++++- 4 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/internal/parser.pegjs b/src/internal/parser.pegjs index 36909149..9a33e7d3 100644 --- a/src/internal/parser.pegjs +++ b/src/internal/parser.pegjs @@ -562,7 +562,7 @@ fnArg nomfm = "" LF? content:nomfmContent LF? "" { - return NOMFM(TEXT(content)); + return NOMFM(content); } nomfmContent diff --git a/src/node.ts b/src/node.ts index 8df195c3..b676fdf5 100644 --- a/src/node.ts +++ b/src/node.ts @@ -178,7 +178,7 @@ export type MfmNomfm = { props?: Record; children: MfmText[]; }; -export const NOMFM = (text: MfmText): NodeType<'plain'> => { return { type: 'plain', children: [text] }; }; +export const NOMFM = (text: string): NodeType<'plain'> => { return { type: 'plain', children: [TEXT(text)] }; }; export type MfmText = { type: 'text'; diff --git a/test/api.ts b/test/api.ts index 89744441..463178c8 100644 --- a/test/api.ts +++ b/test/api.ts @@ -147,6 +147,16 @@ after`; assert.strictEqual(mfm.toString(mfm.parse(input)), '$[spin.speed=1s,alternate Hello]'); }); + it('nomfm', () => { + const input = 'a\n\nHello\nworld\n\nb'; + assert.strictEqual(mfm.toString(mfm.parse(input)), 'a\n\nHello\nworld\n\nb'); + }); + + it('1 line nomfm', () => { + const input = 'a\nHello\nb'; + assert.strictEqual(mfm.toString(mfm.parse(input)), 'a\n\nHello\n\nb'); + }); + it('preserve url brackets', () => { const input1 = 'https://github.com/syuilo/ai'; assert.strictEqual(mfm.toString(mfm.parse(input1)), input1); diff --git a/test/parser.ts b/test/parser.ts index 0760e833..1d0d41f0 100644 --- a/test/parser.ts +++ b/test/parser.ts @@ -1,7 +1,7 @@ import assert from 'assert'; import * as mfm from '../src/index'; import { - TEXT, CENTER, FN, UNI_EMOJI, MENTION, EMOJI_CODE, HASHTAG, N_URL, BOLD, SMALL, ITALIC, STRIKE, QUOTE, MATH_BLOCK, SEARCH, CODE_BLOCK, LINK, INLINE_CODE, MATH_INLINE + TEXT, CENTER, FN, UNI_EMOJI, MENTION, EMOJI_CODE, HASHTAG, N_URL, BOLD, SMALL, ITALIC, STRIKE, QUOTE, MATH_BLOCK, SEARCH, CODE_BLOCK, LINK, INLINE_CODE, MATH_INLINE, NOMFM } from '../src/index'; describe('PlainParser', () => { @@ -1138,6 +1138,28 @@ hoge`; }); }); + describe('nomfm', () => { + it('multiple line', () => { + const input = 'a\n\nHello\nworld\n\nb'; + const output = [ + TEXT('a\n'), + NOMFM('Hello\nworld'), + TEXT('\nb') + ]; + assert.deepStrictEqual(mfm.parse(input), output); + }); + + it('single line', () => { + const input = 'a\nHello world\nb'; + const output = [ + TEXT('a\n'), + NOMFM('Hello world'), + TEXT('\nb') + ]; + assert.deepStrictEqual(mfm.parse(input), output); + }); + }); + describe('nesting limit', () => { describe('quote', () => { it('basic', () => { From a3cfeb0f65b9c0239379ab4c30a3e19aef3214d7 Mon Sep 17 00:00:00 2001 From: marihachi Date: Sun, 5 Jun 2022 16:55:24 +0900 Subject: [PATCH 4/8] public api --- etc/mfm-js.api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/etc/mfm-js.api.md b/etc/mfm-js.api.md index 0fed8f93..012e879c 100644 --- a/etc/mfm-js.api.md +++ b/etc/mfm-js.api.md @@ -238,7 +238,7 @@ export const N_URL: (value: string, brackets?: boolean | undefined) => NodeType< export type NodeType = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'plain' ? MfmNomfm : T extends 'text' ? MfmText : never; // @public (undocumented) -export const NOMFM: (text: MfmText) => NodeType<'plain'>; +export const NOMFM: (text: string) => NodeType<'plain'>; // @public (undocumented) export function parse(input: string, opts?: Partial<{ From b2a7189701aa43813edcb8ff37c18d84d02546cb Mon Sep 17 00:00:00 2001 From: marihachi Date: Sun, 5 Jun 2022 17:02:46 +0900 Subject: [PATCH 5/8] plain syntax --- src/internal/util.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/internal/util.ts b/src/internal/util.ts index a9ece072..04df9e22 100644 --- a/src/internal/util.ts +++ b/src/internal/util.ts @@ -103,6 +103,9 @@ export function stringifyNode(node: MfmNode): string { const args = (argFields.length > 0) ? '.' + argFields.join(',') : ''; return `$[${ node.props.name }${ args } ${ stringifyTree(node.children) }]`; } + case 'plain': { + return `\n${ stringifyTree(node.children) }\n`; + } case 'text': { return node.props.text; } From 741b54d116bf3eb062ac28877161aae8bd1fdc3e Mon Sep 17 00:00:00 2001 From: marihachi Date: Mon, 6 Jun 2022 10:31:41 +0900 Subject: [PATCH 6/8] Update test/parser.ts Co-authored-by: syuilo --- test/parser.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/parser.ts b/test/parser.ts index 1d0d41f0..74d555bd 100644 --- a/test/parser.ts +++ b/test/parser.ts @@ -1140,20 +1140,20 @@ hoge`; describe('nomfm', () => { it('multiple line', () => { - const input = 'a\n\nHello\nworld\n\nb'; + const input = 'a\n\n**Hello**\nworld\n\nb'; const output = [ TEXT('a\n'), - NOMFM('Hello\nworld'), + NOMFM('**Hello**\nworld'), TEXT('\nb') ]; assert.deepStrictEqual(mfm.parse(input), output); }); it('single line', () => { - const input = 'a\nHello world\nb'; + const input = 'a\n**Hello** world\nb'; const output = [ TEXT('a\n'), - NOMFM('Hello world'), + NOMFM('**Hello** world'), TEXT('\nb') ]; assert.deepStrictEqual(mfm.parse(input), output); From 990d13e07a5c6f7df2ad74b9f403417961333dc7 Mon Sep 17 00:00:00 2001 From: marihachi Date: Tue, 7 Jun 2022 00:32:04 +0900 Subject: [PATCH 7/8] plain parser -> simple parser --- README.md | 10 +++++----- docs/api.md | 4 ++-- package.json | 6 +++--- src/api.ts | 8 ++++---- src/cli/{parsePlain.ts => parseSimple.ts} | 6 +++--- src/index.ts | 2 +- src/internal/parser.pegjs | 12 ++++++------ src/node.ts | 2 +- test/parser.ts | 14 +++++++------- 9 files changed, 32 insertions(+), 32 deletions(-) rename src/cli/{parsePlain.ts => parseSimple.ts} (88%) diff --git a/README.md b/README.md index 99e53818..0c504624 100644 --- a/README.md +++ b/README.md @@ -28,11 +28,11 @@ I'm @ai, A bot of misskey! https://github.com/syuilo/ai `; -// Generate a MFM tree from the MFM text. +// Generate a MFM tree from the full MFM text. const mfmTree = mfm.parse(inputText); -// Generate a MFM tree from the MFM plain text. -const plainMfmTree = mfm.parsePlain('I like the hot soup :soup:​'); +// Generate a MFM tree from the simple MFM text. +const simpleMfmTree = mfm.parseSimple('I like the hot soup :soup:​'); // Reverse to a MFM text from the MFM tree. const text = mfm.toString(mfmTree); @@ -62,9 +62,9 @@ full parser: npm run parse ``` -plain parser: +simple parser: ``` -npm run parse-plain +npm run parse-simple ``` ## License diff --git a/docs/api.md b/docs/api.md index 0e2d5539..9fb5603b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -36,13 +36,13 @@ console.log(JSON.stringify(nodes)); // => [{"type":"bold","children":[{"type":"text","props":{"text":"cannot nest"}}]}] ``` -## parsePlain API +## parseSimple API 入力文字列からノードツリーを生成します。 絵文字コードとUnicode絵文字を利用可能です。 例: ```ts -const nodes = mfm.parsePlain('Hello :surprised_ai:'); +const nodes = mfm.parseSimple('Hello :surprised_ai:'); console.log(JSON.stringify(nodes)); // => [{"type":"text","props":{"text":"Hello "}},{"type":"emojiCode","props":{"name":"surprised_ai"}}] ``` diff --git a/package.json b/package.json index cea67a42..562eedf6 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,13 @@ "scripts": { "build": "npm run tsc && npm run peg", "build-debug": "npm run tsc && npm run peg-debug", - "peg": "peggy --cache -o src/internal/parser.js --allowed-start-rules fullParser,plainParser src/internal/parser.pegjs && npm run peg-copy", - "peg-debug": "peggy --cache -o src/internal/parser.js --allowed-start-rules fullParser,inlineParser,plainParser --trace src/internal/parser.pegjs && npm run peg-copy", + "peg": "peggy --cache -o src/internal/parser.js --allowed-start-rules fullParser,simpleParser src/internal/parser.pegjs && npm run peg-copy", + "peg-debug": "peggy --cache -o src/internal/parser.js --allowed-start-rules fullParser,inlineParser,simpleParser --trace src/internal/parser.pegjs && npm run peg-copy", "peg-copy": "copyfiles -f src/internal/parser.js built/internal/", "tsc": "tsc", "tsd": "tsd", "parse": "node ./built/cli/parse", - "parse-plain": "node ./built/cli/parsePlain", + "parse-simple": "node ./built/cli/parseSimple", "api": "npx api-extractor run --local --verbose", "api-prod": "npx api-extractor run --verbose", "lint": "eslint . --ext .js,.jsx,.ts,.tsx", diff --git a/src/api.ts b/src/api.ts index a7f7af73..96e03021 100644 --- a/src/api.ts +++ b/src/api.ts @@ -1,5 +1,5 @@ import peg from 'peggy'; -import { MfmNode, MfmPlainNode } from './node'; +import { MfmNode, MfmSimpleNode } from './node'; import { stringifyNode, stringifyTree, inspectOne } from './internal/util'; // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -18,10 +18,10 @@ export function parse(input: string, opts: Partial<{ fnNameList: string[]; nestL } /** - * Generates a MfmNode tree of plain from the MFM string. + * Generates a MfmSimpleNode tree from the MFM string. */ -export function parsePlain(input: string): MfmPlainNode[] { - const nodes = parser.parse(input, { startRule: 'plainParser' }); +export function parseSimple(input: string): MfmSimpleNode[] { + const nodes = parser.parse(input, { startRule: 'simpleParser' }); return nodes; } diff --git a/src/cli/parsePlain.ts b/src/cli/parseSimple.ts similarity index 88% rename from src/cli/parsePlain.ts rename to src/cli/parseSimple.ts index 258f26c1..41674b4f 100644 --- a/src/cli/parsePlain.ts +++ b/src/cli/parseSimple.ts @@ -1,9 +1,9 @@ import { performance } from 'perf_hooks'; import inputLine, { InputCanceledError } from './misc/inputLine'; -import { parsePlain } from '..'; +import { parseSimple } from '..'; async function entryPoint() { - console.log('intaractive plain parser'); + console.log('intaractive simple parser'); while (true) { let input: string; @@ -26,7 +26,7 @@ async function entryPoint() { try { const parseTimeStart = performance.now(); - const result = parsePlain(input); + const result = parseSimple(input); const parseTimeEnd = performance.now(); console.log(JSON.stringify(result)); const parseTime = (parseTimeEnd - parseTimeStart).toFixed(3); diff --git a/src/index.ts b/src/index.ts index 2f16a558..0e169da2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ export { parse, - parsePlain, + parseSimple, toString, inspect, extract, diff --git a/src/internal/parser.pegjs b/src/internal/parser.pegjs index 9a33e7d3..d927abdb 100644 --- a/src/internal/parser.pegjs +++ b/src/internal/parser.pegjs @@ -102,8 +102,8 @@ fullParser = nodes:(&. @full)* { return mergeText(nodes); } -plainParser - = nodes:(&. @plain)* { return mergeText(nodes); } +simpleParser + = nodes:(&. @simple)* { return mergeText(nodes); } // // syntax list @@ -164,10 +164,10 @@ L_inline / nomfm / L_inlineText -plain +simple = emojiCode / unicodeEmoji - / plainText + / simpleText // // block rules @@ -581,9 +581,9 @@ L_inlineText = !(LF / _) [a-z0-9]i &italicAlt . { return text(); } // italic ignore / . /* text node */ -// inline: text (for plainParser) +// inline: text (for simpleParser) -plainText +simpleText = . /* text node */ // diff --git a/src/node.ts b/src/node.ts index b676fdf5..197b7c77 100644 --- a/src/node.ts +++ b/src/node.ts @@ -1,6 +1,6 @@ export type MfmNode = MfmBlock | MfmInline; -export type MfmPlainNode = MfmUnicodeEmoji | MfmEmojiCode | MfmText; +export type MfmSimpleNode = MfmUnicodeEmoji | MfmEmojiCode | MfmText; export type MfmBlock = MfmQuote | MfmSearch | MfmCodeBlock | MfmMathBlock | MfmCenter; diff --git a/test/parser.ts b/test/parser.ts index 74d555bd..ead475d8 100644 --- a/test/parser.ts +++ b/test/parser.ts @@ -4,24 +4,24 @@ import { TEXT, CENTER, FN, UNI_EMOJI, MENTION, EMOJI_CODE, HASHTAG, N_URL, BOLD, SMALL, ITALIC, STRIKE, QUOTE, MATH_BLOCK, SEARCH, CODE_BLOCK, LINK, INLINE_CODE, MATH_INLINE, NOMFM } from '../src/index'; -describe('PlainParser', () => { +describe('SimpleParser', () => { describe('text', () => { it('basic', () => { const input = 'abc'; const output = [TEXT('abc')]; - assert.deepStrictEqual(mfm.parsePlain(input), output); + assert.deepStrictEqual(mfm.parseSimple(input), output); }); it('ignore hashtag', () => { const input = 'abc#abc'; const output = [TEXT('abc#abc')]; - assert.deepStrictEqual(mfm.parsePlain(input), output); + assert.deepStrictEqual(mfm.parseSimple(input), output); }); it('keycap number sign', () => { const input = 'abc#️⃣abc'; const output = [TEXT('abc'), UNI_EMOJI('#️⃣'), TEXT('abc')]; - assert.deepStrictEqual(mfm.parsePlain(input), output); + assert.deepStrictEqual(mfm.parseSimple(input), output); }); }); @@ -29,20 +29,20 @@ describe('PlainParser', () => { it('basic', () => { const input = ':foo:'; const output = [EMOJI_CODE('foo')]; - assert.deepStrictEqual(mfm.parsePlain(input), output); + assert.deepStrictEqual(mfm.parseSimple(input), output); }); it('between texts', () => { const input = 'foo:bar:baz'; const output = [TEXT('foo'), EMOJI_CODE('bar'), TEXT('baz')]; - assert.deepStrictEqual(mfm.parsePlain(input), output); + assert.deepStrictEqual(mfm.parseSimple(input), output); }); }); it('disallow other syntaxes', () => { const input = 'foo **bar** baz'; const output = [TEXT('foo **bar** baz')]; - assert.deepStrictEqual(mfm.parsePlain(input), output); + assert.deepStrictEqual(mfm.parseSimple(input), output); }); }); From 437b7d4850ab1c0050e66f11ebd7f8731d0358b4 Mon Sep 17 00:00:00 2001 From: marihachi Date: Tue, 7 Jun 2022 00:40:55 +0900 Subject: [PATCH 8/8] nomfm -> plain --- etc/mfm-js.api.md | 19 ++++++++++--------- src/index.ts | 5 +++-- src/internal/parser.pegjs | 18 +++++++++--------- src/node.ts | 8 ++++---- test/api.ts | 4 ++-- test/parser.ts | 8 ++++---- 6 files changed, 32 insertions(+), 30 deletions(-) diff --git a/etc/mfm-js.api.md b/etc/mfm-js.api.md index 012e879c..7a0d0657 100644 --- a/etc/mfm-js.api.md +++ b/etc/mfm-js.api.md @@ -105,7 +105,7 @@ export type MfmHashtag = { }; // @public (undocumented) -export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmNomfm | MfmText; +export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmPlain | MfmText; // @public (undocumented) export type MfmInlineCode = { @@ -166,7 +166,7 @@ export type MfmMention = { export type MfmNode = MfmBlock | MfmInline; // @public (undocumented) -export type MfmNomfm = { +export type MfmPlain = { type: 'plain'; props?: Record; children: MfmText[]; @@ -189,6 +189,9 @@ export type MfmSearch = { children?: []; }; +// @public (undocumented) +export type MfmSimpleNode = MfmUnicodeEmoji | MfmEmojiCode | MfmText; + // @public (undocumented) export type MfmSmall = { type: 'small'; @@ -235,10 +238,7 @@ export type MfmUrl = { export const N_URL: (value: string, brackets?: boolean | undefined) => NodeType<'url'>; // @public (undocumented) -export type NodeType = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'plain' ? MfmNomfm : T extends 'text' ? MfmText : never; - -// @public (undocumented) -export const NOMFM: (text: string) => NodeType<'plain'>; +export type NodeType = T extends 'quote' ? MfmQuote : T extends 'search' ? MfmSearch : T extends 'blockCode' ? MfmCodeBlock : T extends 'mathBlock' ? MfmMathBlock : T extends 'center' ? MfmCenter : T extends 'unicodeEmoji' ? MfmUnicodeEmoji : T extends 'emojiCode' ? MfmEmojiCode : T extends 'bold' ? MfmBold : T extends 'small' ? MfmSmall : T extends 'italic' ? MfmItalic : T extends 'strike' ? MfmStrike : T extends 'inlineCode' ? MfmInlineCode : T extends 'mathInline' ? MfmMathInline : T extends 'mention' ? MfmMention : T extends 'hashtag' ? MfmHashtag : T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : T extends 'plain' ? MfmPlain : T extends 'text' ? MfmText : never; // @public (undocumented) export function parse(input: string, opts?: Partial<{ @@ -246,10 +246,11 @@ export function parse(input: string, opts?: Partial<{ nestLimit: number; }>): MfmNode[]; -// Warning: (ae-forgotten-export) The symbol "MfmPlainNode" needs to be exported by the entry point index.d.ts -// // @public (undocumented) -export function parsePlain(input: string): MfmPlainNode[]; +export function parseSimple(input: string): MfmSimpleNode[]; + +// @public (undocumented) +export const PLAIN: (text: string) => NodeType<'plain'>; // @public (undocumented) export const QUOTE: (children: MfmNode[]) => NodeType<'quote'>; diff --git a/src/index.ts b/src/index.ts index 0e169da2..da1baabe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ export { export { NodeType, MfmNode, + MfmSimpleNode, MfmBlock, MfmInline, } from './node'; @@ -35,7 +36,7 @@ export { MfmUrl, MfmLink, MfmFn, - MfmNomfm, + MfmPlain, MfmText, } from './node'; @@ -61,6 +62,6 @@ export { N_URL, LINK, FN, - NOMFM, + PLAIN, TEXT, } from './node'; diff --git a/src/internal/parser.pegjs b/src/internal/parser.pegjs index d927abdb..6a955f5b 100644 --- a/src/internal/parser.pegjs +++ b/src/internal/parser.pegjs @@ -21,7 +21,7 @@ N_URL, LINK, FN, - NOMFM, + PLAIN, TEXT } = require('../node'); @@ -127,7 +127,7 @@ full / hashtag / url / fn - / nomfm + / plain / link / search // block / inlineText @@ -146,7 +146,7 @@ inline / hashtag / url / fn - / nomfm + / plain / link / inlineText @@ -161,7 +161,7 @@ L_inline / inlineCode / mathInline / L_fn - / nomfm + / plain / L_inlineText simple @@ -557,15 +557,15 @@ fnArg return { k: k, v: true }; } -// inline: nomfm +// inline: plain -nomfm - = "" LF? content:nomfmContent LF? "" +plain + = "" LF? content:plainContent LF? "" { - return NOMFM(content); + return PLAIN(content); } -nomfmContent +plainContent = (!(LF? "") .)+ { return text(); diff --git a/src/node.ts b/src/node.ts index 197b7c77..2f004385 100644 --- a/src/node.ts +++ b/src/node.ts @@ -53,7 +53,7 @@ export type MfmCenter = { export const CENTER = (children: MfmInline[]): NodeType<'center'> => { return { type: 'center', children }; }; export type MfmInline = MfmUnicodeEmoji | MfmEmojiCode | MfmBold | MfmSmall | MfmItalic | MfmStrike | - MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmNomfm | MfmText; + MfmInlineCode | MfmMathInline | MfmMention | MfmHashtag | MfmUrl | MfmLink | MfmFn | MfmPlain | MfmText; export type MfmUnicodeEmoji = { type: 'unicodeEmoji'; @@ -173,12 +173,12 @@ export type MfmFn = { }; export const FN = (name: string, args: MfmFn['props']['args'], children: MfmFn['children']): NodeType<'fn'> => { return { type: 'fn', props: { name, args }, children }; }; -export type MfmNomfm = { +export type MfmPlain = { type: 'plain'; props?: Record; children: MfmText[]; }; -export const NOMFM = (text: string): NodeType<'plain'> => { return { type: 'plain', children: [TEXT(text)] }; }; +export const PLAIN = (text: string): NodeType<'plain'> => { return { type: 'plain', children: [TEXT(text)] }; }; export type MfmText = { type: 'text'; @@ -208,6 +208,6 @@ export type NodeType = T extends 'url' ? MfmUrl : T extends 'link' ? MfmLink : T extends 'fn' ? MfmFn : - T extends 'plain' ? MfmNomfm : + T extends 'plain' ? MfmPlain : T extends 'text' ? MfmText : never; diff --git a/test/api.ts b/test/api.ts index 463178c8..1c7d20fc 100644 --- a/test/api.ts +++ b/test/api.ts @@ -147,12 +147,12 @@ after`; assert.strictEqual(mfm.toString(mfm.parse(input)), '$[spin.speed=1s,alternate Hello]'); }); - it('nomfm', () => { + it('plain', () => { const input = 'a\n\nHello\nworld\n\nb'; assert.strictEqual(mfm.toString(mfm.parse(input)), 'a\n\nHello\nworld\n\nb'); }); - it('1 line nomfm', () => { + it('1 line plain', () => { const input = 'a\nHello\nb'; assert.strictEqual(mfm.toString(mfm.parse(input)), 'a\n\nHello\n\nb'); }); diff --git a/test/parser.ts b/test/parser.ts index ead475d8..93a9b7cb 100644 --- a/test/parser.ts +++ b/test/parser.ts @@ -1,7 +1,7 @@ import assert from 'assert'; import * as mfm from '../src/index'; import { - TEXT, CENTER, FN, UNI_EMOJI, MENTION, EMOJI_CODE, HASHTAG, N_URL, BOLD, SMALL, ITALIC, STRIKE, QUOTE, MATH_BLOCK, SEARCH, CODE_BLOCK, LINK, INLINE_CODE, MATH_INLINE, NOMFM + TEXT, CENTER, FN, UNI_EMOJI, MENTION, EMOJI_CODE, HASHTAG, N_URL, BOLD, SMALL, ITALIC, STRIKE, QUOTE, MATH_BLOCK, SEARCH, CODE_BLOCK, LINK, INLINE_CODE, MATH_INLINE, PLAIN } from '../src/index'; describe('SimpleParser', () => { @@ -1138,12 +1138,12 @@ hoge`; }); }); - describe('nomfm', () => { + describe('plain', () => { it('multiple line', () => { const input = 'a\n\n**Hello**\nworld\n\nb'; const output = [ TEXT('a\n'), - NOMFM('**Hello**\nworld'), + PLAIN('**Hello**\nworld'), TEXT('\nb') ]; assert.deepStrictEqual(mfm.parse(input), output); @@ -1153,7 +1153,7 @@ hoge`; const input = 'a\n**Hello** world\nb'; const output = [ TEXT('a\n'), - NOMFM('**Hello** world'), + PLAIN('**Hello** world'), TEXT('\nb') ]; assert.deepStrictEqual(mfm.parse(input), output);