リンクラベル関係の変更 (#107)

* fix link label matching

* 🚀
* add syntax rules of link label
* fix #104
* remove unnecessary applyParser() call
This commit is contained in:
marihachi 2022-05-12 20:31:29 +09:00 committed by GitHub
parent fcbda2ecac
commit 49941cd9ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 28 deletions

View file

@ -7,7 +7,7 @@
"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,inlineParser,plainParser src/internal/parser.pegjs && npm run peg-copy",
"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-copy": "copyfiles -f src/internal/parser.js built/internal/",
"tsc": "tsc",

View file

@ -41,10 +41,6 @@
return parseFunc(input, parseOpts);
}
// link
const linkLabel = options.linkLabel || false;
// emoji
const emojiRegex = require('twemoji-parser/dist/lib/regex').default;
@ -108,9 +104,6 @@ fullParser
plainParser
= nodes:(&. @plain)* { return mergeText(nodes); }
inlineParser
= nodes:(&. @inline)* { return mergeText(nodes); }
//
// syntax list
//
@ -154,6 +147,19 @@ inline
/ link
/ inlineText
L_inline
= emojiCode
/ unicodeEmoji
/ L_big
/ L_bold
/ L_small
/ L_italic
/ L_strike
/ inlineCode
/ mathInline
/ L_fn
/ L_inlineText
plain
= emojiCode
/ unicodeEmoji
@ -277,6 +283,15 @@ big
bigContent
= &{ return enterNest(); } @(@(!"***" @inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_big
= "***" content:L_bigContent "***"
{
return FN('tada', { }, mergeText(content));
}
L_bigContent
= &{ return enterNest(); } @(@(!"***" @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
// inline: bold
bold
@ -290,8 +305,7 @@ bold
}
/ "__" content:$(!"__" @([a-z0-9]i / _))+ "__"
{
const parsedContent = applyParser(content, 'inlineParser');
return BOLD(parsedContent);
return BOLD([TEXT(content)]);
}
boldContent
@ -300,6 +314,26 @@ boldContent
boldTagContent
= &{ return enterNest(); } @(@(!"</b>" @inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_bold
= "**" content:L_boldContent "**"
{
return BOLD(mergeText(content));
}
/ "<b>" content:L_boldTagContent "</b>"
{
return BOLD(mergeText(content));
}
/ "__" content:$(!"__" @([a-z0-9]i / _))+ "__"
{
return BOLD([TEXT(content)]);
}
L_boldContent
= &{ return enterNest(); } @(@(!"**" @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_boldTagContent
= &{ return enterNest(); } @(@(!"</b>" @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
// inline: small
small
@ -311,6 +345,15 @@ small
smallContent
= &{ return enterNest(); } @(@(!"</small>" @inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_small
= "<small>" content:L_smallContent "</small>"
{
return SMALL(mergeText(content));
}
L_smallContent
= &{ return enterNest(); } @(@(!"</small>" @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
// inline: italic
italic
@ -320,21 +363,29 @@ italic
}
/ italicAlt
italicAlt
= "*" content:$(!"*" ([a-z0-9]i / _))+ "*" &(EOF / LF / _ / ![a-z0-9]i)
L_italic
= "<i>" content:L_italicContent "</i>"
{
const parsedContent = applyParser(content, 'inlineParser');
return ITALIC(parsedContent);
return ITALIC(mergeText(content));
}
/ "_" content:$(!"_" ([a-z0-9]i / _))+ "_" &(EOF / LF / _ / ![a-z0-9]i)
/ italicAlt
italicAlt
= "*" content:$([a-z0-9]i / _)+ "*" &(EOF / LF / _ / ![a-z0-9]i)
{
const parsedContent = applyParser(content, 'inlineParser');
return ITALIC(parsedContent);
return ITALIC([TEXT(content)]);
}
/ "_" content:$([a-z0-9]i / _)+ "_" &(EOF / LF / _ / ![a-z0-9]i)
{
return ITALIC([TEXT(content)]);
}
italicContent
= &{ return enterNest(); } @(@(!"</i>" @inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_italicContent
= &{ return enterNest(); } @(@(!"</i>" @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
// inline: strike
strike
@ -353,6 +404,22 @@ strikeContent
strikeTagContent
= &{ return enterNest(); } @(@(!("</s>" / LF) @inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_strike
= "~~" content:L_strikeContent "~~"
{
return STRIKE(mergeText(content));
}
/ "<s>" content:L_strikeTagContent "</s>"
{
return STRIKE(mergeText(content));
}
L_strikeContent
= &{ return enterNest(); } @(@(!("~" / LF) @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_strikeTagContent
= &{ return enterNest(); } @(@(!("</s>" / LF) @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
// inline: inlineCode
inlineCode
@ -372,7 +439,7 @@ mathInline
// inline: mention
mention
= &{ return !linkLabel; } "@" name:mentionName host:("@" @mentionHost)?
= "@" name:mentionName host:("@" @mentionHost)?
{
return MENTION(name, host, text());
}
@ -414,11 +481,11 @@ hashPairInner
// inline: URL
url
= &{ return !linkLabel; } "<" url:$("http" "s"? "://" (!(">" / _) CHAR)+) ">"
= "<" url:$("http" "s"? "://" (!(">" / _) CHAR)+) ">"
{
return N_URL(url, true);
}
/ &{ return !linkLabel; } "http" "s"? "://" (&([.,]+ urlContentPart) . / urlContentPart)+
/ "http" "s"? "://" (&([.,]+ urlContentPart) . / urlContentPart)+
{
// NOTE: last char is neither "." nor ",".
return N_URL(text());
@ -435,19 +502,13 @@ urlPairInner
// inline: link
link
= &{ return !linkLabel; } silent:"?"? "[" label:linkLabel "](" url:url ")"
= silent:"?"? "[" label:linkLabel "](" url:url ")"
{
return LINK((silent != null), url.props.url, mergeText(label));
}
linkLabel
= (!"](" CHAR)+
{
const label = applyParser(text(), 'inlineParser', {
linkLabel: true
});
return label;
}
= (!"]" @L_inline)+
// inline: fn
@ -458,9 +519,19 @@ fn
return FN(name, args, mergeText(content));
}
L_fn
= "$[" name:$([a-z0-9_]i)+ &{ return ensureFnName(name); } args:fnArgs? _ content:L_fnContent "]"
{
args = args || {};
return FN(name, args, mergeText(content));
}
fnContent
= &{ return enterNest(); } @(@(!"]" @inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
L_fnContent
= &{ return enterNest(); } @(@(!"]" @L_inline)+ &{ return leaveNest(); } / &{ return fallbackNest(); })
fnArgs
= "." head:fnArg tails:("," @fnArg)*
{
@ -487,6 +558,10 @@ inlineText
= !(LF / _) [a-z0-9]i &(hashtag / mention / italicAlt) . { return text(); } // hashtag, mention, italic ignore
/ . /* text node */
L_inlineText
= !(LF / _) [a-z0-9]i &italicAlt . { return text(); } // italic ignore
/ . /* text node */
// inline: text (for plainParser)
plainText

View file

@ -1073,6 +1073,17 @@ hoge`;
];
assert.deepStrictEqual(mfm.parse(input), output);
});
it('with brackets before', () => {
const input = '[test] foo [bar](https://example.com)';
const output = [
TEXT('[test] foo '),
LINK(false, 'https://example.com', [
TEXT('bar')
]),
];
assert.deepStrictEqual(mfm.parse(input), output);
});
});
describe('fn', () => {