securemark 0.294.2 → 0.294.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.294.4
4
+
5
+ - Refactoring.
6
+
7
+ ## 0.294.3
8
+
9
+ - Refactoring.
10
+
3
11
  ## 0.294.2
4
12
 
5
13
  - Refactoring.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /*! securemark v0.294.2 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
1
+ /*! securemark v0.294.4 https://github.com/falsandtru/securemark | (c) 2017, falsandtru | UNLICENSED License */
2
2
  (function webpackUniversalModuleDefinition(root, factory) {
3
3
  if(typeof exports === 'object' && typeof module === 'object')
4
4
  module.exports = factory(require("Prism"), require("DOMPurify"));
@@ -5705,7 +5705,7 @@ const source_1 = __webpack_require__(8745);
5705
5705
  const util_1 = __webpack_require__(4992);
5706
5706
  const dom_1 = __webpack_require__(394);
5707
5707
  exports.syntax = />*(?=>>[^>\s]\S*[^\S\n]*(?:$|\n))/y;
5708
- exports.cite = (0, combinator_1.line)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(exports.syntax), (0, combinator_1.union)([anchor_1.anchor,
5708
+ exports.cite = (0, combinator_1.line)((0, combinator_1.fmap)((0, combinator_1.open)((0, source_1.str)(exports.syntax), (0, combinator_1.union)([(0, combinator_1.line)(anchor_1.anchor),
5709
5709
  // Subject page representation.
5710
5710
  // リンクの実装は後で検討
5711
5711
  (0, combinator_1.focus)(/>>#\S*(?=\s*$)/y, ({
@@ -6160,14 +6160,16 @@ const account_1 = __webpack_require__(4107);
6160
6160
  const hashtag_1 = __webpack_require__(5764);
6161
6161
  const hashnum_1 = __webpack_require__(8684);
6162
6162
  const anchor_1 = __webpack_require__(8535);
6163
- const source_1 = __webpack_require__(8745);
6164
- exports.autolink = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(new RegExp([/(?<![0-9a-z])@/yi.source, /(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source, /(?<![0-9a-z])>>/yi.source, /(?<![0-9a-z][.+-]?)!?[0-9a-z]/yi.source].join('|').replace(/emoji/g, hashtag_1.emoji), 'yiu'), (0, combinator_1.state)(~1 /* State.autolink */, (0, combinator_1.union)([url_1.lineurl, url_1.url, email_1.email,
6163
+ exports.autolink = (0, combinator_1.lazy)(() => (0, combinator_1.validate)(new RegExp([/(?<![0-9a-z])@/yi.source, /(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source, /(?<![0-9a-z])>>/yi.source, /(?<![0-9a-z][.+-]?|[@#])!?[0-9a-z]/yi.source].join('|').replace(/emoji/g, hashtag_1.emoji), 'yiu'), (0, combinator_1.state)(~1 /* State.autolink */, (0, combinator_1.union)([url_1.lineurl, url_1.url, email_1.email,
6165
6164
  // Escape unmatched email-like strings.
6166
- (0, source_1.str)(/[0-9a-z]+(?:[_.+-][0-9a-z]+[:@]?|:|@(?=@))*/yi), channel_1.channel, account_1.account,
6165
+ //str(/[0-9a-z]+(?:[_.+-][0-9a-z]+[:@]?|:|@(?=@))*/yi),
6166
+ channel_1.channel, account_1.account,
6167
6167
  // Escape unmatched account-like strings.
6168
- (0, source_1.str)(/@+(?:[0-9a-z]+(?:[_.+-][0-9a-z]+)*)?/yi), hashtag_1.hashtag, hashnum_1.hashnum,
6168
+ //str(/@+(?:[0-9a-z]+(?:[_.+-][0-9a-z]+)*)?/yi),
6169
+ hashtag_1.hashtag, hashnum_1.hashnum,
6169
6170
  // Escape unmatched hashtag-like strings.
6170
- (0, source_1.str)(new RegExp(/#+(?:(?:[^\p{C}\p{S}\p{P}\s]|emoji)+(?:['_.+-](?:[^\p{C}\p{S}\p{P}\s]|emoji)+)*)?/yu.source.replace(/emoji/g, hashtag_1.emoji), 'yu')), anchor_1.anchor]))));
6171
+ //str(new RegExp(/#+(?:(?:[^\p{C}\p{S}\p{P}\s]|emoji)+(?:['_.+-](?:[^\p{C}\p{S}\p{P}\s]|emoji)+)*)?/yu.source.replace(/emoji/g, emoji), 'yu')),
6172
+ anchor_1.anchor]))));
6171
6173
 
6172
6174
  /***/ },
6173
6175
 
@@ -6187,15 +6189,11 @@ const link_1 = __webpack_require__(3628);
6187
6189
  const source_1 = __webpack_require__(8745);
6188
6190
  const dom_1 = __webpack_require__(394);
6189
6191
  // https://example/@user must be a user page or a redirect page going there.
6190
- exports.account = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9a-z])@/yi, (0, combinator_1.tails)([(0, source_1.str)(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi), (0, source_1.str)(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![0-9a-z@#]|>>|:\S)/yi)]), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/@')}` : `/${source}`} }`, link_1.unsafelink, false), ([{
6192
+ exports.account = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9a-z])@/yi, (0, combinator_1.tails)([(0, source_1.str)(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi), (0, source_1.str)(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![-.]?[0-9a-z@#]|>>|:\S)/yi)]), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1).replace('/', '/@')}` : `/${source}`} }`, (0, combinator_1.union)([link_1.unsafelink]), false), ([{
6191
6193
  value
6192
6194
  }]) => new parser_1.List([new parser_1.Data((0, dom_1.define)(value, {
6193
6195
  class: 'account'
6194
- }))])))), ({
6195
- context: {
6196
- source
6197
- }
6198
- }) => new parser_1.List([new parser_1.Data(source)])])));
6196
+ }))]))))));
6199
6197
 
6200
6198
  /***/ },
6201
6199
 
@@ -6221,15 +6219,11 @@ const dom_1 = __webpack_require__(394);
6221
6219
  // cid: YYYY-MMDD-HHMM-SSmmm
6222
6220
  // 内部表現はUnixTimeに統一する(時系列順)
6223
6221
  // 外部表現は投稿ごとに投稿者の投稿時のタイムゾーンに統一する(非時系列順)
6224
- exports.anchor = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9a-z])>>/yi, (0, source_1.str)(/(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(?![0-9a-z@#]|>>|:\S)/yi), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `/@${source.slice(2).replace('/', '/timeline?at=')}` : `?at=${source.slice(2)}`} }`, link_1.unsafelink, false), ([{
6222
+ exports.anchor = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9a-z])>>/yi, (0, source_1.str)(/(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(?!-?[0-9a-z@#]|>>|:\S)/yi), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `/@${source.slice(2).replace('/', '/timeline?at=')}` : `?at=${source.slice(2)}`} }`, (0, combinator_1.union)([link_1.unsafelink]), false), ([{
6225
6223
  value
6226
6224
  }]) => new parser_1.List([new parser_1.Data((0, dom_1.define)(value, {
6227
6225
  class: 'anchor'
6228
- }))])))), ({
6229
- context: {
6230
- source
6231
- }
6232
- }) => new parser_1.List([new parser_1.Data(source)])])));
6226
+ }))]))))));
6233
6227
 
6234
6228
  /***/ },
6235
6229
 
@@ -6250,9 +6244,9 @@ const hashtag_1 = __webpack_require__(5764);
6250
6244
  const source_1 = __webpack_require__(8745);
6251
6245
  const dom_1 = __webpack_require__(394);
6252
6246
  // https://example/@user?ch=a+b must be a user channel page or a redirect page going there.
6253
- exports.channel = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.sequence)([(0, combinator_1.open)(/(?<![0-9a-z])@/yi, (0, combinator_1.tails)([(0, source_1.str)(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi), (0, source_1.str)(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![0-9a-z@]|>>|:\S)/yi)]), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.some)((0, combinator_1.open)('#', (0, combinator_1.verify)((0, source_1.str)(new RegExp([/(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+(?![0-9a-z@]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source].join('').replace(/emoji/g, hashtag_1.emoji), 'yu')), ([{
6247
+ exports.channel = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.sequence)([(0, combinator_1.open)(/(?<![0-9a-z])@/yi, (0, combinator_1.tails)([(0, source_1.str)(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi), (0, source_1.str)(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![-.]?[0-9a-z@]|>>|:\S)/yi)]), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.some)((0, combinator_1.open)('#', (0, combinator_1.verify)((0, source_1.str)(new RegExp([/(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+(?![0-9a-z@]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source].join('').replace(/emoji/g, hashtag_1.emoji), 'yu')), ([{
6254
6248
  value
6255
- }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)), false, [3 | 0 /* Backtrack.autolink */]))]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1, source.indexOf('#')).replace('/', '/@')}` : `/${source.slice(0, source.indexOf('#'))}`} }`, link_1.unsafelink, false), ([{
6249
+ }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)), false, [3 | 0 /* Backtrack.autolink */]))]), (0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.includes('/') ? `https://${source.slice(1, source.indexOf('#')).replace('/', '/@')}` : `/${source.slice(0, source.indexOf('#'))}`} }`, (0, combinator_1.union)([link_1.unsafelink]), false), ([{
6256
6250
  value: el
6257
6251
  }], {
6258
6252
  source,
@@ -6265,11 +6259,7 @@ exports.channel = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, com
6265
6259
  class: 'channel',
6266
6260
  href: url
6267
6261
  }, src))]);
6268
- }))), ({
6269
- context: {
6270
- source
6271
- }
6272
- }) => new parser_1.List([new parser_1.Data(source)])])));
6262
+ })))));
6273
6263
 
6274
6264
  /***/ },
6275
6265
 
@@ -6288,20 +6278,16 @@ const combinator_1 = __webpack_require__(3484);
6288
6278
  const source_1 = __webpack_require__(8745);
6289
6279
  const dom_1 = __webpack_require__(394);
6290
6280
  // https://html.spec.whatwg.org/multipage/input.html
6291
- exports.email = (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9a-z][_.+-]?)(?=[0-9a-z])/yi, (0, combinator_1.verify)((0, source_1.str)(/[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z]){0,255}@[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*(?![0-9a-z@#]|>>|:\S)/yi), ([{
6281
+ exports.email = (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9a-z][_.+-]?|[@#])(?=[0-9a-z])/yi, (0, combinator_1.verify)((0, source_1.str)(/[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z]){0,255}@[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*(?![.-]?[0-9a-z@#]|>>|:\S)/yi), ([{
6292
6282
  value
6293
- }]) => value.length <= 255), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, ({
6283
+ }]) => value.length <= 255), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.union)([({
6294
6284
  context: {
6295
6285
  source
6296
6286
  }
6297
6287
  }) => new parser_1.List([new parser_1.Data((0, dom_1.html)('a', {
6298
6288
  class: 'email',
6299
6289
  href: `mailto:${source}`
6300
- }, source))]))), ({
6301
- context: {
6302
- source
6303
- }
6304
- }) => new parser_1.List([new parser_1.Data(source)])]));
6290
+ }, source))])]))));
6305
6291
 
6306
6292
  /***/ },
6307
6293
 
@@ -6321,16 +6307,12 @@ const link_1 = __webpack_require__(3628);
6321
6307
  const hashtag_1 = __webpack_require__(5764);
6322
6308
  const source_1 = __webpack_require__(8745);
6323
6309
  const dom_1 = __webpack_require__(394);
6324
- exports.hashnum = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(new RegExp([/(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source].join('').replace(/emoji/g, hashtag_1.emoji), 'yu'), (0, source_1.str)(new RegExp([/[0-9]{1,9}(?![0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source].join('').replace(/emoji/g, hashtag_1.emoji), 'yu')), false, [1 | 0 /* Backtrack.autolink */]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.slice(1)} }`, link_1.unsafelink, false), ([{
6310
+ exports.hashnum = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(new RegExp([/(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source].join('').replace(/emoji/g, hashtag_1.emoji), 'yu'), (0, source_1.str)(new RegExp([/[0-9]{1,9}(?![0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source].join('').replace(/emoji/g, hashtag_1.emoji), 'yu')), false, [1 | 0 /* Backtrack.autolink */]), (0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${source.slice(1)} }`, (0, combinator_1.union)([link_1.unsafelink]), false), ([{
6325
6311
  value
6326
6312
  }]) => new parser_1.List([new parser_1.Data((0, dom_1.define)(value, {
6327
6313
  class: 'hashnum',
6328
6314
  href: null
6329
- }))])))), ({
6330
- context: {
6331
- source
6332
- }
6333
- }) => new parser_1.List([new parser_1.Data(source)])])));
6315
+ }))]))))));
6334
6316
 
6335
6317
  /***/ },
6336
6318
 
@@ -6354,15 +6336,11 @@ const dom_1 = __webpack_require__(394);
6354
6336
  exports.emoji = String.raw`\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F`;
6355
6337
  exports.hashtag = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(new RegExp([/(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source].join('').replace(/emoji/g, exports.emoji), 'yu'), (0, combinator_1.verify)((0, source_1.str)(new RegExp([/(?!['_])(?:[^\p{C}\p{S}\p{P}\s]|emoji|'(?=[0-9A-Za-z])|_(?=[^'\p{C}\p{S}\p{P}\s]|emoji))+(?![0-9a-z@#]|>>|:\S|[^\p{C}\p{S}\p{P}\s]|emoji)/yu.source].join('').replace(/emoji/g, exports.emoji), 'yu')), ([{
6356
6338
  value
6357
- }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`, link_1.unsafelink, false), ([{
6339
+ }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.fmap)((0, combinator_1.convert)(source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`, (0, combinator_1.union)([link_1.unsafelink]), false), ([{
6358
6340
  value
6359
6341
  }]) => new parser_1.List([new parser_1.Data((0, dom_1.define)(value, {
6360
6342
  class: 'hashtag'
6361
- }))])))), ({
6362
- context: {
6363
- source
6364
- }
6365
- }) => new parser_1.List([new parser_1.Data(source)])])));
6343
+ }))]))))));
6366
6344
 
6367
6345
  /***/ },
6368
6346
 
@@ -6378,18 +6356,11 @@ Object.defineProperty(exports, "__esModule", ({
6378
6356
  exports.lineurl = exports.url = void 0;
6379
6357
  const parser_1 = __webpack_require__(605);
6380
6358
  const combinator_1 = __webpack_require__(3484);
6359
+ const inline_1 = __webpack_require__(7973);
6381
6360
  const link_1 = __webpack_require__(3628);
6382
6361
  const source_1 = __webpack_require__(8745);
6383
- exports.url = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9A-Za-z][.+-]?)https?:\/\/(?=[\x21-\x7E])/y, (0, combinator_1.precedence)(0, (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(source_1.unescsource, /(?<![-+*=~^_,.;:!?])[-+*=~^_,.;:!?]*(?=[\\$"`\[\](){}<>()[]{}|]|[^\x21-\x7E]|$)/y), (0, combinator_1.precedence)(1, (0, combinator_1.verify)(bracket, ns => ns.length > 0))]), undefined, [[/[^\x21-\x7E]|\$/y, 9]])), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink, false))), ({
6384
- context: {
6385
- source
6386
- }
6387
- }) => new parser_1.List([new parser_1.Data(source)])])));
6388
- exports.lineurl = (0, combinator_1.lazy)(() => (0, combinator_1.focus)(/(?<=^|[\r\n])!?https?:\/\/\S+(?=[^\S\n]*(?=$|\n))/y, (0, combinator_1.tails)([(0, source_1.str)('!'), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink, false))), ({
6389
- context: {
6390
- source
6391
- }
6392
- }) => new parser_1.List([new parser_1.Data(source)])])])));
6362
+ exports.url = (0, combinator_1.lazy)(() => (0, combinator_1.rewrite)((0, combinator_1.open)(/(?<![0-9A-Za-z][.+-]?|[@#])https?:\/\/(?=[\x21-\x7E])/y, (0, combinator_1.precedence)(0, (0, combinator_1.some)((0, combinator_1.union)([(0, combinator_1.some)(source_1.unescsource, /(?<![-+*=~^_,.;:!?]|\/{3})(?:[-+*=~^_,.;:!?]|\/{3,}(?!\/))*(?=[\\$"`\[\](){}<>()[]{}|]|[^\x21-\x7E]|$)/y), (0, combinator_1.precedence)(1, (0, combinator_1.verify)(bracket, ns => ns.length > 0))]), undefined, [[/[^\x21-\x7E]|\$/y, 9]])), false, [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink, false))), (0, combinator_1.open)((0, source_1.str)(/[^:]+/y), (0, combinator_1.some)(inline_1.inline))])));
6363
+ exports.lineurl = (0, combinator_1.lazy)(() => (0, combinator_1.focus)(/(?<=^|[\r\n])!?https?:\/\/\S+(?=[^\S\n]*(?=$|\n))/y, (0, combinator_1.tails)([(0, source_1.str)('!'), (0, combinator_1.union)([(0, combinator_1.constraint)(1 /* State.autolink */, (0, combinator_1.state)(1 /* State.autolink */, (0, combinator_1.convert)(url => `{ ${url} }`, link_1.unsafelink, false))), (0, combinator_1.open)((0, source_1.str)(/[^:]+/y), (0, combinator_1.some)(inline_1.inline))])])));
6393
6364
  const bracket = (0, combinator_1.lazy)(() => (0, combinator_1.union)([(0, combinator_1.surround)((0, source_1.str)('('), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ')')), (0, source_1.str)(')'), true, undefined, () => new parser_1.List(), [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.surround)((0, source_1.str)('['), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), ']')), (0, source_1.str)(']'), true, undefined, () => new parser_1.List(), [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.surround)((0, source_1.str)('{'), (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)((0, combinator_1.union)([bracket, source_1.unescsource]), '}')), (0, source_1.str)('}'), true, undefined, () => new parser_1.List(), [3 | 0 /* Backtrack.autolink */]), (0, combinator_1.surround)((0, source_1.str)('"'), (0, combinator_1.precedence)(2, (0, combinator_1.recursion)(6 /* Recursion.terminal */, (0, combinator_1.some)(source_1.unescsource, '"'))), (0, source_1.str)('"'), true, undefined, () => new parser_1.List(), [3 | 0 /* Backtrack.autolink */])]));
6394
6365
 
6395
6366
  /***/ },
@@ -8971,8 +8942,8 @@ var blank;
8971
8942
  (function (blank) {
8972
8943
  blank.line = new RegExp(
8973
8944
  // TODO: 行全体をエスケープ
8974
- /^(?:[^\S\r\n])*(?!\s)(\\?[^\S\r\n]|&IHN;|<wbr[^\S\n]*>|\\$)+$/mg.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`), 'gm');
8975
- blank.start = new RegExp(/(?:\\?[^\S\r\n]|&IHN;|<wbr[^\S\n]*>)+/y.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`), 'y');
8945
+ /^(?:[^\S\r\n])*(?!\s)(\\?[^\S\r\n]|&IHN;|<wbr ?>|\\$)+$/mg.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`), 'gm');
8946
+ blank.start = new RegExp(/(?:\\?[^\S\r\n]|&IHN;|<wbr ?>)+/y.source.replace('IHN', `(?:${normalize_1.invisibleHTMLEntityNames.join('|')})`), 'y');
8976
8947
  })(blank || (exports.blank = blank = {}));
8977
8948
  function visualize(parser) {
8978
8949
  return (0, combinator_1.convert)(source => source.replace(blank.line, `${"\u001B" /* Command.Escape */}$1`), parser, false);
@@ -8980,7 +8951,7 @@ function visualize(parser) {
8980
8951
  exports.visualize = visualize;
8981
8952
  function blankWith(starts, delimiter) {
8982
8953
  if (delimiter === undefined) return blankWith('', starts);
8983
- return new RegExp(String.raw`(?:(?=${starts})(?:\\?\s|&(?:${normalize_1.invisibleHTMLEntityNames.join('|')});|<wbr[^\S\n]*>)${
8954
+ return new RegExp(String.raw`(?:(?=${starts})(?:\\?\s|&(?:${normalize_1.invisibleHTMLEntityNames.join('|')});|<wbr ?>)${
8984
8955
  // 空行除去
8985
8956
  // 完全な空行はエスケープ済みなので再帰的バックトラックにはならない。
8986
8957
  starts && '+'})?${typeof delimiter === 'string' ? delimiter.replace(/[*+()\[\]]/g, '\\$&') : delimiter.source}`, 'y');
@@ -8990,7 +8961,6 @@ function tightStart(parser, except) {
8990
8961
  return input => isTightStart(input, except) ? parser(input) : undefined;
8991
8962
  }
8992
8963
  exports.tightStart = tightStart;
8993
- const wbr = /<wbr[^\S\n]*>/y;
8994
8964
  function isTightStart(input, except) {
8995
8965
  const {
8996
8966
  context
@@ -9018,9 +8988,8 @@ function isTightStart(input, except) {
9018
8988
  context.position = position;
9019
8989
  return true;
9020
8990
  case '<':
9021
- wbr.lastIndex = position;
9022
8991
  switch (true) {
9023
- case source.length - position >= 5 && source.startsWith('<wbr', position) && (source[position + 5] === '>' || wbr.test(source)):
8992
+ case source.length - position >= 5 && source.startsWith('<wbr', position) && (source[position + 4] === '>' || source.startsWith(' >', position + 4)):
9024
8993
  return false;
9025
8994
  }
9026
8995
  return true;
package/markdown.d.ts CHANGED
@@ -1096,13 +1096,10 @@ export namespace MarkdownParser {
1096
1096
  AutolinkParser.UrlParser.LineUrlParser,
1097
1097
  AutolinkParser.UrlParser,
1098
1098
  AutolinkParser.EmailParser,
1099
- SourceParser.StrParser,
1100
1099
  AutolinkParser.ChannelParser,
1101
1100
  AutolinkParser.AccountParser,
1102
- SourceParser.StrParser,
1103
1101
  AutolinkParser.HashtagParser,
1104
1102
  AutolinkParser.HashnumParser,
1105
- SourceParser.StrParser,
1106
1103
  AutolinkParser.AnchorParser,
1107
1104
  ]> {
1108
1105
  }
@@ -1110,9 +1107,9 @@ export namespace MarkdownParser {
1110
1107
  export interface UrlParser extends
1111
1108
  // https://host
1112
1109
  Inline<'url'>,
1113
- Parser<string | HTMLAnchorElement, Context, [
1110
+ Parser<string | HTMLElement, Context, [
1114
1111
  LinkParser.UnsafeLinkParser,
1115
- Parser<string, Context, []>,
1112
+ InlineParser,
1116
1113
  ]> {
1117
1114
  }
1118
1115
  export namespace UrlParser {
@@ -1122,7 +1119,7 @@ export namespace MarkdownParser {
1122
1119
  SourceParser.StrParser,
1123
1120
  Parser<string | HTMLElement, Context, [
1124
1121
  InlineParser.LinkParser.UnsafeLinkParser,
1125
- Parser<string, Context, []>,
1122
+ InlineParser,
1126
1123
  ]>,
1127
1124
  ]> {
1128
1125
  }
@@ -1150,7 +1147,6 @@ export namespace MarkdownParser {
1150
1147
  Inline<'email'>,
1151
1148
  Parser<string | HTMLAnchorElement, Context, [
1152
1149
  Parser<HTMLAnchorElement, Context, []>,
1153
- Parser<string, Context, []>,
1154
1150
  ]> {
1155
1151
  }
1156
1152
  export interface ChannelParser extends
@@ -1158,7 +1154,6 @@ export namespace MarkdownParser {
1158
1154
  Inline<'channel'>,
1159
1155
  Parser<string | HTMLAnchorElement, Context, [
1160
1156
  LinkParser.UnsafeLinkParser,
1161
- Parser<string, Context, []>,
1162
1157
  ]> {
1163
1158
  }
1164
1159
  export interface AccountParser extends
@@ -1166,7 +1161,6 @@ export namespace MarkdownParser {
1166
1161
  Inline<'account'>,
1167
1162
  Parser<string | HTMLAnchorElement, Context, [
1168
1163
  LinkParser.UnsafeLinkParser,
1169
- Parser<string, Context, []>,
1170
1164
  ]> {
1171
1165
  }
1172
1166
  export interface HashtagParser extends
@@ -1174,7 +1168,6 @@ export namespace MarkdownParser {
1174
1168
  Inline<'hashtag'>,
1175
1169
  Parser<string | HTMLAnchorElement, Context, [
1176
1170
  LinkParser.UnsafeLinkParser,
1177
- Parser<string, Context, []>,
1178
1171
  ]> {
1179
1172
  }
1180
1173
  export interface HashnumParser extends
@@ -1182,7 +1175,6 @@ export namespace MarkdownParser {
1182
1175
  Inline<'hashnum'>,
1183
1176
  Parser<string | HTMLAnchorElement, Context, [
1184
1177
  LinkParser.UnsafeLinkParser,
1185
- Parser<string, Context, []>,
1186
1178
  ]> {
1187
1179
  }
1188
1180
  export interface AnchorParser extends
@@ -1190,7 +1182,6 @@ export namespace MarkdownParser {
1190
1182
  Inline<'anchor'>,
1191
1183
  Parser<string | HTMLAnchorElement, Context, [
1192
1184
  LinkParser.UnsafeLinkParser,
1193
- Parser<string, Context, []>,
1194
1185
  ]> {
1195
1186
  }
1196
1187
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "securemark",
3
- "version": "0.294.2",
3
+ "version": "0.294.4",
4
4
  "description": "Secure markdown renderer working on browsers for user input data.",
5
5
  "private": false,
6
6
  "homepage": "https://github.com/falsandtru/securemark",
@@ -12,7 +12,7 @@ export const cite: ReplyParser.CiteParser = line(fmap(
12
12
  open(
13
13
  str(syntax),
14
14
  union([
15
- anchor,
15
+ line(anchor),
16
16
  // Subject page representation.
17
17
  // リンクの実装は後で検討
18
18
  focus(/>>#\S*(?=\s*$)/y, ({ context: { source } }) => new List([new Data(html('a', { class: 'anchor' }, source))])),
@@ -10,21 +10,24 @@ describe('Unit: parser/inline/autolink/account', () => {
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
13
- assert.deepStrictEqual(inspect(parser('@'), ctx), [['@'], '']);
14
- assert.deepStrictEqual(inspect(parser('@+'), ctx), [['@'], '+']);
15
- assert.deepStrictEqual(inspect(parser('@_'), ctx), [['@'], '_']);
16
- assert.deepStrictEqual(inspect(parser('@-'), ctx), [['@'], '-']);
17
- assert.deepStrictEqual(inspect(parser('@.'), ctx), [['@'], '.']);
18
- assert.deepStrictEqual(inspect(parser('@0'), ctx), [['@0'], '']);
19
- assert.deepStrictEqual(inspect(parser('@a@'), ctx), [['@a'], '@']);
20
- assert.deepStrictEqual(inspect(parser('@a@b'), ctx), [['@a'], '@b']);
21
- assert.deepStrictEqual(inspect(parser('@a@b@c'), ctx), [['@a'], '@b@c']);
22
- assert.deepStrictEqual(inspect(parser('@ab@'), ctx), [['@ab'], '@']);
23
- assert.deepStrictEqual(inspect(parser('@@'), ctx), [['@@'], '']);
24
- assert.deepStrictEqual(inspect(parser('@@a'), ctx), [['@@a'], '']);
25
- assert.deepStrictEqual(inspect(parser('@@@a'), ctx), [['@@@a'], '']);
26
- assert.deepStrictEqual(inspect(parser('@#'), ctx), [['@', '#'], '']);
27
- assert.deepStrictEqual(inspect(parser('@#a'), ctx), [['@', '<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
13
+ assert.deepStrictEqual(inspect(parser('@'), ctx), undefined);
14
+ assert.deepStrictEqual(inspect(parser('@+'), ctx), undefined);
15
+ assert.deepStrictEqual(inspect(parser('@_'), ctx), undefined);
16
+ assert.deepStrictEqual(inspect(parser('@-'), ctx), undefined);
17
+ assert.deepStrictEqual(inspect(parser('@.'), ctx), undefined);
18
+ assert.deepStrictEqual(inspect(parser('@0'), ctx), undefined);
19
+ assert.deepStrictEqual(inspect(parser('@a@'), ctx), undefined);
20
+ assert.deepStrictEqual(inspect(parser('@a@b'), ctx), undefined);
21
+ assert.deepStrictEqual(inspect(parser('@a@b@c'), ctx), undefined);
22
+ assert.deepStrictEqual(inspect(parser('@ab@'), ctx), undefined);
23
+ assert.deepStrictEqual(inspect(parser('@@'), ctx), undefined);
24
+ assert.deepStrictEqual(inspect(parser('@@a'), ctx), undefined);
25
+ assert.deepStrictEqual(inspect(parser('@@@a'), ctx), undefined);
26
+ assert.deepStrictEqual(inspect(parser('@#'), ctx), undefined);
27
+ assert.deepStrictEqual(inspect(parser('@#a'), ctx), undefined);
28
+ assert.deepStrictEqual(inspect(parser('@a.b:c'), ctx), undefined);
29
+ assert.deepStrictEqual(inspect(parser('@a.domain.com:b'), ctx), undefined);
30
+ assert.deepStrictEqual(inspect(parser('@http://host'), ctx), undefined);
28
31
  assert.deepStrictEqual(inspect(parser(' @a'), ctx), undefined);
29
32
  });
30
33
 
@@ -38,8 +41,6 @@ describe('Unit: parser/inline/autolink/account', () => {
38
41
  assert.deepStrictEqual(inspect(parser('@a--b'), ctx), [['<a class="account" href="/@a">@a</a>'], '--b']);
39
42
  assert.deepStrictEqual(inspect(parser('@a.'), ctx), [['<a class="account" href="/@a">@a</a>'], '.']);
40
43
  assert.deepStrictEqual(inspect(parser('@a.domain.com'), ctx), [['<a class="account" href="/@a.domain.com">@a.domain.com</a>'], '']);
41
- assert.deepStrictEqual(inspect(parser('@http://host'), ctx), [['@http'], '://host']);
42
- assert.deepStrictEqual(inspect(parser('@ttp://host'), ctx), [ [ '@ttp' ], '://host' ]);
43
44
  assert.deepStrictEqual(inspect(parser('@domain/a'), ctx), [['<a class="account" href="https://domain/@a" target="_blank">@domain/a</a>'], '']);
44
45
  assert.deepStrictEqual(inspect(parser('@domain.com/a'), ctx), [['<a class="account" href="https://domain.com/@a" target="_blank">@domain.com/a</a>'], '']);
45
46
  });
@@ -13,20 +13,16 @@ export const account: AutolinkParser.AccountParser = lazy(() => rewrite(
13
13
  /(?<![0-9a-z])@/yi,
14
14
  tails([
15
15
  str(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi),
16
- str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![0-9a-z@#]|>>|:\S)/yi),
16
+ str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![-.]?[0-9a-z@#]|>>|:\S)/yi),
17
17
  ]),
18
18
  false,
19
19
  [3 | Backtrack.autolink]),
20
- union([
21
- constraint(State.autolink, state(State.autolink, fmap(convert(
22
- source =>
23
- `[${source}]{ ${
24
- source.includes('/')
25
- ? `https://${source.slice(1).replace('/', '/@')}`
26
- : `/${source}`
27
- } }`,
28
- unsafelink,
29
- false),
30
- ([{ value }]) => new List([new Data(define(value, { class: 'account' }))])))),
31
- ({ context: { source } }) => new List([new Data(source)]),
32
- ])));
20
+ constraint(State.autolink, state(State.autolink, fmap(convert(
21
+ source =>
22
+ `[${source}]{ ${source.includes('/')
23
+ ? `https://${source.slice(1).replace('/', '/@')}`
24
+ : `/${source}`
25
+ } }`,
26
+ union([unsafelink]),
27
+ false),
28
+ ([{ value }]) => new List([new Data(define(value, { class: 'account' }))]))))));
@@ -15,10 +15,11 @@ describe('Unit: parser/inline/autolink/anchor', () => {
15
15
  assert.deepStrictEqual(inspect(parser('>>-0'), ctx), undefined);
16
16
  assert.deepStrictEqual(inspect(parser('>>01#'), ctx), undefined);
17
17
  assert.deepStrictEqual(inspect(parser('>>01@'), ctx), undefined);
18
+ assert.deepStrictEqual(inspect(parser('>>0-1:2'), ctx), undefined);
18
19
  assert.deepStrictEqual(inspect(parser('>>https://host'), ctx), undefined);
19
20
  assert.deepStrictEqual(inspect(parser('>>tel:1234567890'), ctx), undefined);
20
21
  assert.deepStrictEqual(inspect(parser('>>>'), ctx), undefined);
21
- assert.deepStrictEqual(inspect(parser('a>>0'), ctx), [['a'], '>>0']);
22
+ assert.deepStrictEqual(inspect(parser('a>>0'), ctx), undefined);
22
23
  assert.deepStrictEqual(inspect(parser(' >>0'), ctx), undefined);
23
24
  });
24
25
 
@@ -19,18 +19,15 @@ import { define } from 'typed-dom/dom';
19
19
  export const anchor: AutolinkParser.AnchorParser = lazy(() => rewrite(
20
20
  open(
21
21
  /(?<![0-9a-z])>>/yi,
22
- str(/(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(?![0-9a-z@#]|>>|:\S)/yi),
22
+ str(/(?:[a-z][0-9a-z]*(?:-[0-9a-z]+)*\/)?[0-9a-z]+(?:-[0-9a-z]+)*(?!-?[0-9a-z@#]|>>|:\S)/yi),
23
23
  false,
24
24
  [3 | Backtrack.autolink]),
25
- union([
26
- constraint(State.autolink, state(State.autolink, fmap(convert(
27
- source =>
28
- `[${source}]{ ${source.includes('/')
29
- ? `/@${source.slice(2).replace('/', '/timeline?at=')}`
30
- : `?at=${source.slice(2)}`
31
- } }`,
32
- unsafelink,
33
- false),
34
- ([{ value }]) => new List([new Data(define(value, { class: 'anchor' }))])))),
35
- ({ context: { source } }) => new List([new Data(source)]),
36
- ])));
25
+ constraint(State.autolink, state(State.autolink, fmap(convert(
26
+ source =>
27
+ `[${source}]{ ${source.includes('/')
28
+ ? `/@${source.slice(2).replace('/', '/timeline?at=')}`
29
+ : `?at=${source.slice(2)}`
30
+ } }`,
31
+ union([unsafelink]),
32
+ false),
33
+ ([{ value }]) => new List([new Data(define(value, { class: 'anchor' }))]))))));
@@ -10,12 +10,12 @@ describe('Unit: parser/inline/autolink/channel', () => {
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
13
- assert.deepStrictEqual(inspect(parser('@a@'), ctx), [['@a'], '@']);
14
- assert.deepStrictEqual(inspect(parser('@a@b'), ctx), [['@a'], '@b']);
15
- assert.deepStrictEqual(inspect(parser('@a#'), ctx), [['@a'], '#']);
16
- assert.deepStrictEqual(inspect(parser('@a#1'), ctx), [['@a'], '#1']);
17
- assert.deepStrictEqual(inspect(parser('@a#b@'), ctx), [['@a'], '#b@']);
18
- assert.deepStrictEqual(inspect(parser('@a#1@b'), ctx), [['@a'], '#1@b']);
13
+ assert.deepStrictEqual(inspect(parser('@a@'), ctx), undefined);
14
+ assert.deepStrictEqual(inspect(parser('@a@b'), ctx), undefined);
15
+ assert.deepStrictEqual(inspect(parser('@a#'), ctx), undefined);
16
+ assert.deepStrictEqual(inspect(parser('@a#1'), ctx), undefined);
17
+ assert.deepStrictEqual(inspect(parser('@a#b@'), ctx), undefined);
18
+ assert.deepStrictEqual(inspect(parser('@a#1@b'), ctx), undefined);
19
19
  assert.deepStrictEqual(inspect(parser(' @a#b'), ctx), undefined);
20
20
  });
21
21
 
@@ -15,7 +15,7 @@ export const channel: AutolinkParser.ChannelParser = lazy(() => rewrite(
15
15
  /(?<![0-9a-z])@/yi,
16
16
  tails([
17
17
  str(/[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*\//yi),
18
- str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![0-9a-z@]|>>|:\S)/yi),
18
+ str(/[a-z][0-9a-z]*(?:[-.][0-9a-z]+)*(?![-.]?[0-9a-z@]|>>|:\S)/yi),
19
19
  ]),
20
20
  false,
21
21
  [3 | Backtrack.autolink]),
@@ -29,20 +29,16 @@ export const channel: AutolinkParser.ChannelParser = lazy(() => rewrite(
29
29
  false,
30
30
  [3 | Backtrack.autolink])),
31
31
  ]),
32
- union([
33
- constraint(State.autolink, state(State.autolink, fmap(convert(
34
- source =>
35
- `[${source}]{ ${
36
- source.includes('/')
37
- ? `https://${source.slice(1, source.indexOf('#')).replace('/', '/@')}`
38
- : `/${source.slice(0, source.indexOf('#'))}`
39
- } }`,
40
- unsafelink,
41
- false),
42
- ([{ value: el }], { source, position, range = 0 }) => {
43
- const src = source.slice(position - range, position);
44
- const url = `${el.getAttribute('href')}?ch=${src.slice(src.indexOf('#') + 1).replace(/#/g, '+')}`;
45
- return new List([new Data(define(el, { class: 'channel', href: url }, src))]);
46
- }))),
47
- ({ context: { source } }) => new List([new Data(source)]),
48
- ])));
32
+ constraint(State.autolink, state(State.autolink, fmap(convert(
33
+ source =>
34
+ `[${source}]{ ${source.includes('/')
35
+ ? `https://${source.slice(1, source.indexOf('#')).replace('/', '/@')}`
36
+ : `/${source.slice(0, source.indexOf('#'))}`
37
+ } }`,
38
+ union([unsafelink]),
39
+ false),
40
+ ([{ value: el }], { source, position, range = 0 }) => {
41
+ const src = source.slice(position - range, position);
42
+ const url = `${el.getAttribute('href')}?ch=${src.slice(src.indexOf('#') + 1).replace(/#/g, '+')}`;
43
+ return new List([new Data(define(el, { class: 'channel', href: url }, src))]);
44
+ })))));
@@ -10,25 +10,25 @@ describe('Unit: parser/inline/autolink/email', () => {
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
13
- assert.deepStrictEqual(inspect(parser('a@'), ctx), [['a'], '@']);
14
- assert.deepStrictEqual(inspect(parser('a@+'), ctx), [['a'], '@+']);
15
- assert.deepStrictEqual(inspect(parser('a@_'), ctx), [['a'], '@_']);
16
- assert.deepStrictEqual(inspect(parser('a@-'), ctx), [['a'], '@-']);
17
- assert.deepStrictEqual(inspect(parser('a@.'), ctx), [['a'], '@.']);
18
- assert.deepStrictEqual(inspect(parser('a@b@'), ctx), [['a'], '@b@']);
19
- assert.deepStrictEqual(inspect(parser('a@bc@'), ctx), [['a'], '@bc@']);
20
- assert.deepStrictEqual(inspect(parser('a@b@c'), ctx), [['a'], '@b@c']);
21
- assert.deepStrictEqual(inspect(parser('a@b#'), ctx), [['a'], '@b#']);
22
- assert.deepStrictEqual(inspect(parser('a@b#1'), ctx), [['a'], '@b#1']);
23
- assert.deepStrictEqual(inspect(parser('a@@'), ctx), [['a@', '@'], '']);
24
- assert.deepStrictEqual(inspect(parser('a@@b'), ctx), [['a@', '<a class="account" href="/@b">@b</a>'], '']);
25
- assert.deepStrictEqual(inspect(parser('a+@b'), ctx), [['a'], '+@b']);
26
- assert.deepStrictEqual(inspect(parser('a__b@c'), ctx), [['a'], '__b@c']);
27
- assert.deepStrictEqual(inspect(parser('a..b@c'), ctx), [['a'], '..b@c']);
28
- assert.deepStrictEqual(inspect(parser('a++b@c'), ctx), [['a'], '++b@c']);
29
- assert.deepStrictEqual(inspect(parser('a@http://host'), ctx), [['a'], '@http://host']);
30
- assert.deepStrictEqual(inspect(parser('a@ttp://host'), ctx), [['a'], '@ttp://host']);
31
- assert.deepStrictEqual(inspect(parser(`a@${'b'.repeat(64)}`), ctx), [['a'], `@${'b'.repeat(64)}`]);
13
+ assert.deepStrictEqual(inspect(parser('a@'), ctx), undefined);
14
+ assert.deepStrictEqual(inspect(parser('a@+'), ctx), undefined);
15
+ assert.deepStrictEqual(inspect(parser('a@_'), ctx), undefined);
16
+ assert.deepStrictEqual(inspect(parser('a@-'), ctx), undefined);
17
+ assert.deepStrictEqual(inspect(parser('a@.'), ctx), undefined);
18
+ assert.deepStrictEqual(inspect(parser('a@b@'), ctx), undefined);
19
+ assert.deepStrictEqual(inspect(parser('a@bc@'), ctx), undefined);
20
+ assert.deepStrictEqual(inspect(parser('a@b@c'), ctx), undefined);
21
+ assert.deepStrictEqual(inspect(parser('a@b#'), ctx), undefined);
22
+ assert.deepStrictEqual(inspect(parser('a@b#1'), ctx), undefined);
23
+ assert.deepStrictEqual(inspect(parser('a@@'), ctx), undefined);
24
+ assert.deepStrictEqual(inspect(parser('a@@b'), ctx), undefined);
25
+ assert.deepStrictEqual(inspect(parser('a+@b'), ctx), undefined);
26
+ assert.deepStrictEqual(inspect(parser('a__b@c'), ctx), undefined);
27
+ assert.deepStrictEqual(inspect(parser('a..b@c'), ctx), undefined);
28
+ assert.deepStrictEqual(inspect(parser('a++b@c'), ctx), undefined);
29
+ assert.deepStrictEqual(inspect(parser('a@b.c:d'), ctx), undefined);
30
+ assert.deepStrictEqual(inspect(parser('a@http://host'), ctx), undefined);
31
+ assert.deepStrictEqual(inspect(parser(`a@${'b'.repeat(64)}`), ctx), undefined);
32
32
  assert.deepStrictEqual(inspect(parser(' a@b'), ctx), undefined);
33
33
  });
34
34
 
@@ -8,14 +8,14 @@ import { html } from 'typed-dom/dom';
8
8
  // https://html.spec.whatwg.org/multipage/input.html
9
9
 
10
10
  export const email: AutolinkParser.EmailParser = rewrite(
11
- open(/(?<![0-9a-z][_.+-]?)(?=[0-9a-z])/yi,
11
+ open(/(?<![0-9a-z][_.+-]?|[@#])(?=[0-9a-z])/yi,
12
12
  verify(
13
- str(/[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z]){0,255}@[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*(?![0-9a-z@#]|>>|:\S)/yi),
13
+ str(/[0-9a-z](?:[_.+-](?=[0-9a-z])|[0-9a-z]){0,255}@[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?(?:\.[0-9a-z](?:(?:[0-9a-z]|-(?=[0-9a-z])){0,61}[0-9a-z])?)*(?![.-]?[0-9a-z@#]|>>|:\S)/yi),
14
14
  ([{ value }]) => value.length <= 255),
15
15
  false,
16
16
  [3 | Backtrack.autolink]),
17
- union([
18
- constraint(State.autolink, state(State.autolink,
19
- ({ context: { source } }) => new List([new Data(html('a', { class: 'email', href: `mailto:${source}` }, source))]))),
20
- ({ context: { source } }) => new List([new Data(source)]),
21
- ]));
17
+ constraint(State.autolink, state(State.autolink,
18
+ union([
19
+ ({ context: { source } }) =>
20
+ new List([new Data(html('a', { class: 'email', href: `mailto:${source}` }, source))])
21
+ ]))));
@@ -10,27 +10,27 @@ describe('Unit: parser/inline/autolink/hashnum', () => {
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
13
- assert.deepStrictEqual(inspect(parser('#'), ctx), [['#'], '']);
14
- assert.deepStrictEqual(inspect(parser('# '), ctx), [['#'], ' ']);
15
- assert.deepStrictEqual(inspect(parser('#1#'), ctx), [['#1'], '#']);
16
- assert.deepStrictEqual(inspect(parser('#1#2'), ctx), [['#1'], '#2']);
17
- assert.deepStrictEqual(inspect(parser('#1#2#3'), ctx), [['#1'], '#2#3']);
18
- assert.deepStrictEqual(inspect(parser('#1@2'), ctx), [['#1'], '@2']);
19
- assert.deepStrictEqual(inspect(parser('#\\'), ctx), [['#'], '\\']);
20
- assert.deepStrictEqual(inspect(parser('#\\ '), ctx), [['#'], '\\ ']);
21
- assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), [['#'], '\\\n']);
22
- assert.deepStrictEqual(inspect(parser('##'), ctx), [['##'], '']);
23
- assert.deepStrictEqual(inspect(parser('##1'), ctx), [['##1'], '']);
24
- assert.deepStrictEqual(inspect(parser('###1'), ctx), [['###1'], '']);
25
- assert.deepStrictEqual(inspect(parser('#{}'), ctx), [['#'], '{}']);
26
- assert.deepStrictEqual(inspect(parser('#{{}'), ctx), [['#'], '{{}']);
27
- assert.deepStrictEqual(inspect(parser('#{}}'), ctx), [['#'], '{}}']);
28
- assert.deepStrictEqual(inspect(parser('#{#}'), ctx), [['#'], '{#}']);
29
- assert.deepStrictEqual(inspect(parser('#{1}'), ctx), [['#'], '{1}']);
30
- assert.deepStrictEqual(inspect(parser('# '), ctx), [['#'], ' ']);
13
+ assert.deepStrictEqual(inspect(parser('#'), ctx), undefined);
14
+ assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
15
+ assert.deepStrictEqual(inspect(parser('#1#'), ctx), undefined);
16
+ assert.deepStrictEqual(inspect(parser('#1#2'), ctx), undefined);
17
+ assert.deepStrictEqual(inspect(parser('#1#2#3'), ctx), undefined);
18
+ assert.deepStrictEqual(inspect(parser('#1@2'), ctx), undefined);
19
+ assert.deepStrictEqual(inspect(parser('#\\'), ctx), undefined);
20
+ assert.deepStrictEqual(inspect(parser('#\\ '), ctx), undefined);
21
+ assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), undefined);
22
+ assert.deepStrictEqual(inspect(parser('##'), ctx), undefined);
23
+ assert.deepStrictEqual(inspect(parser('##1'), ctx), undefined);
24
+ assert.deepStrictEqual(inspect(parser('###1'), ctx), undefined);
25
+ assert.deepStrictEqual(inspect(parser('#{}'), ctx), undefined);
26
+ assert.deepStrictEqual(inspect(parser('#{{}'), ctx), undefined);
27
+ assert.deepStrictEqual(inspect(parser('#{}}'), ctx), undefined);
28
+ assert.deepStrictEqual(inspect(parser('#{#}'), ctx), undefined);
29
+ assert.deepStrictEqual(inspect(parser('#{1}'), ctx), undefined);
30
+ assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}`), ctx), undefined);
31
+ assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}a`), ctx), undefined);
32
+ assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
31
33
  assert.deepStrictEqual(inspect(parser(' #1'), ctx), undefined);
32
- assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}`), ctx), [[`#${'1'.repeat(10)}`], '']);
33
- assert.deepStrictEqual(inspect(parser(`#${'1'.repeat(10)}a`), ctx), [[`#${'1'.repeat(10)}a`], '']);
34
34
  });
35
35
 
36
36
  it('valid', () => {
@@ -17,11 +17,9 @@ export const hashnum: AutolinkParser.HashnumParser = lazy(() => rewrite(
17
17
  ].join('').replace(/emoji/g, emoji), 'yu')),
18
18
  false,
19
19
  [1 | Backtrack.autolink]),
20
- union([
21
- constraint(State.autolink, state(State.autolink, fmap(convert(
22
- source => `[${source}]{ ${source.slice(1)} }`,
23
- unsafelink,
24
- false),
25
- ([{ value }]) => new List([new Data(define(value, { class: 'hashnum', href: null }))])))),
26
- ({ context: { source } }) => new List([new Data(source)]),
27
- ])));
20
+ constraint(State.autolink, state(State.autolink, fmap(convert(
21
+ source => `[${source}]{ ${source.slice(1)} }`,
22
+ union([unsafelink]),
23
+ false),
24
+ ([{ value }]) => new List([new Data(define(value, { class: 'hashnum', href: null }))])))),
25
+ ));
@@ -10,33 +10,33 @@ describe('Unit: parser/inline/autolink/hashtag', () => {
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
13
- assert.deepStrictEqual(inspect(parser('#'), ctx), [['#'], '']);
14
- assert.deepStrictEqual(inspect(parser('# '), ctx), [['#'], ' ']);
15
- assert.deepStrictEqual(inspect(parser('#a#'), ctx), [['#a'], '#']);
16
- assert.deepStrictEqual(inspect(parser('#a#b'), ctx), [['#a'], '#b']);
17
- assert.deepStrictEqual(inspect(parser('#a#b#c'), ctx), [['#a'], '#b#c']);
18
- assert.deepStrictEqual(inspect(parser('#a@b'), ctx), [['#a'], '@b']);
19
- assert.deepStrictEqual(inspect(parser('#@'), ctx), [['#', '@'], '']);
20
- assert.deepStrictEqual(inspect(parser('#@a'), ctx), [['#', '<a class="account" href="/@a">@a</a>'], '']);
21
- assert.deepStrictEqual(inspect(parser('#\\'), ctx), [['#'], '\\']);
22
- assert.deepStrictEqual(inspect(parser('#\\ '), ctx), [['#'], '\\ ']);
23
- assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), [['#'], '\\\n']);
24
- assert.deepStrictEqual(inspect(parser('##'), ctx), [['##'], '']);
25
- assert.deepStrictEqual(inspect(parser('##a'), ctx), [['##a'], '']);
26
- assert.deepStrictEqual(inspect(parser('###a'), ctx), [['###a'], '']);
27
- assert.deepStrictEqual(inspect(parser(`#'`), ctx), [['#'], `'`]);
28
- assert.deepStrictEqual(inspect(parser(`#'0`), ctx), [[`#`], `'0`]);
29
- assert.deepStrictEqual(inspect(parser(`#'00`), ctx), [[`#`], `'00`]);
30
- assert.deepStrictEqual(inspect(parser('#_'), ctx), [['#'], '_']);
31
- assert.deepStrictEqual(inspect(parser('#_a'), ctx), [['#'], '_a']);
32
- assert.deepStrictEqual(inspect(parser('#(a)'), ctx), [['#'], '(a)']);
33
- assert.deepStrictEqual(inspect(parser('#{}'), ctx), [['#'], '{}']);
34
- assert.deepStrictEqual(inspect(parser('#{{}'), ctx), [['#'], '{{}']);
35
- assert.deepStrictEqual(inspect(parser('#{}}'), ctx), [['#'], '{}}']);
36
- assert.deepStrictEqual(inspect(parser('#{#}'), ctx), [['#'], '{#}']);
37
- assert.deepStrictEqual(inspect(parser('#{a}'), ctx), [['#'], '{a}']);
38
- assert.deepStrictEqual(inspect(parser('#12345a'), ctx), [['#12345a'], '']);
39
- assert.deepStrictEqual(inspect(parser('# '), ctx), [['#'], ' ']);
13
+ assert.deepStrictEqual(inspect(parser('#'), ctx), undefined);
14
+ assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
15
+ assert.deepStrictEqual(inspect(parser('#a#'), ctx), undefined);
16
+ assert.deepStrictEqual(inspect(parser('#a#b'), ctx), undefined);
17
+ assert.deepStrictEqual(inspect(parser('#a#b#c'), ctx), undefined);
18
+ assert.deepStrictEqual(inspect(parser('#a@b'), ctx), undefined);
19
+ assert.deepStrictEqual(inspect(parser('#@'), ctx), undefined);
20
+ assert.deepStrictEqual(inspect(parser('#@a'), ctx), undefined);
21
+ assert.deepStrictEqual(inspect(parser('#\\'), ctx), undefined);
22
+ assert.deepStrictEqual(inspect(parser('#\\ '), ctx), undefined);
23
+ assert.deepStrictEqual(inspect(parser('#\\\n'), ctx), undefined);
24
+ assert.deepStrictEqual(inspect(parser('##'), ctx), undefined);
25
+ assert.deepStrictEqual(inspect(parser('##a'), ctx), undefined);
26
+ assert.deepStrictEqual(inspect(parser('###a'), ctx), undefined);
27
+ assert.deepStrictEqual(inspect(parser(`#'`), ctx), undefined);
28
+ assert.deepStrictEqual(inspect(parser(`#'0`), ctx), undefined);
29
+ assert.deepStrictEqual(inspect(parser(`#'00`), ctx), undefined);
30
+ assert.deepStrictEqual(inspect(parser('#_'), ctx), undefined);
31
+ assert.deepStrictEqual(inspect(parser('#_a'), ctx), undefined);
32
+ assert.deepStrictEqual(inspect(parser('#(a)'), ctx), undefined);
33
+ assert.deepStrictEqual(inspect(parser('#{}'), ctx), undefined);
34
+ assert.deepStrictEqual(inspect(parser('#{{}'), ctx), undefined);
35
+ assert.deepStrictEqual(inspect(parser('#{}}'), ctx), undefined);
36
+ assert.deepStrictEqual(inspect(parser('#{#}'), ctx), undefined);
37
+ assert.deepStrictEqual(inspect(parser('#{a}'), ctx), undefined);
38
+ assert.deepStrictEqual(inspect(parser('#12345a'), ctx), undefined);
39
+ assert.deepStrictEqual(inspect(parser('# '), ctx), undefined);
40
40
  assert.deepStrictEqual(inspect(parser(' #a'), ctx), undefined);
41
41
  });
42
42
 
@@ -23,11 +23,8 @@ export const hashtag: AutolinkParser.HashtagParser = lazy(() => rewrite(
23
23
  ([{ value }]) => !/^[0-9]{1,4}$|^[0-9]{5}/.test(value)),
24
24
  false,
25
25
  [3 | Backtrack.autolink]),
26
- union([
27
- constraint(State.autolink, state(State.autolink, fmap(convert(
28
- source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`,
29
- unsafelink,
30
- false),
31
- ([{ value }]) => new List([new Data(define(value, { class: 'hashtag' }))])))),
32
- ({ context: { source } }) => new List([new Data(source)]),
33
- ])));
26
+ constraint(State.autolink, state(State.autolink, fmap(convert(
27
+ source => `[${source}]{ ${`/hashtags/${source.slice(1)}`} }`,
28
+ union([unsafelink]),
29
+ false),
30
+ ([{ value }]) => new List([new Data(define(value, { class: 'hashtag' }))]))))));
@@ -10,12 +10,12 @@ describe('Unit: parser/inline/autolink/url', () => {
10
10
 
11
11
  it('invalid', () => {
12
12
  assert.deepStrictEqual(inspect(parser(''), ctx), undefined);
13
- assert.deepStrictEqual(inspect(parser(' http'), ctx), [['http'], '']);
14
- assert.deepStrictEqual(inspect(parser(' ttp'), ctx), [['ttp'], '']);
15
- assert.deepStrictEqual(inspect(parser(' http://'), ctx), [['http:'], '//']);
16
- assert.deepStrictEqual(inspect(parser(' http://['), ctx), [['http:'], '//[']);
17
- assert.deepStrictEqual(inspect(parser(' http://]'), ctx), [['http:'], '//]']);
18
- assert.deepStrictEqual(inspect(parser(' Http://host'), ctx), [['Http:'], '//host']);
13
+ assert.deepStrictEqual(inspect(parser(' '), ctx), undefined);
14
+ assert.deepStrictEqual(inspect(parser(' http'), ctx), undefined);
15
+ assert.deepStrictEqual(inspect(parser(' http://'), ctx), undefined);
16
+ assert.deepStrictEqual(inspect(parser(' http://['), ctx), undefined);
17
+ assert.deepStrictEqual(inspect(parser(' http://]'), ctx), undefined);
18
+ assert.deepStrictEqual(inspect(parser(' Http://host'), ctx), undefined);
19
19
  assert.deepStrictEqual(inspect(parser(' http://[::ffff:0:0%1]'), ctx), [['<a class="invalid">http://[::ffff:0:0%1]</a>'], '']);
20
20
  assert.deepStrictEqual(inspect(parser(' http://[::ffff:0:0/96]'), ctx), [['<a class="invalid">http://[::ffff:0:0/96]</a>'], '']);
21
21
  });
@@ -60,7 +60,9 @@ describe('Unit: parser/inline/autolink/url', () => {
60
60
  assert.deepStrictEqual(inspect(parser(' http://host^'), ctx), [['<a class="url" href="http://host" target="_blank">http://host</a>'], '^']);
61
61
  assert.deepStrictEqual(inspect(parser(' http://host_'), ctx), [['<a class="url" href="http://host" target="_blank">http://host</a>'], '_']);
62
62
  assert.deepStrictEqual(inspect(parser(' http://host/'), ctx), [['<a class="url" href="http://host/" target="_blank">http://host/</a>'], '']);
63
- assert.deepStrictEqual(inspect(parser(` http://host'`), ctx), [['<a class="url" href="http://host\'" target="_blank">http://host\'</a>'], '']);
63
+ assert.deepStrictEqual(inspect(parser(' http://host//'), ctx), [['<a class="url" href="http://host//" target="_blank">http://host//</a>'], '']);
64
+ assert.deepStrictEqual(inspect(parser(' http://host///'), ctx), [['<a class="url" href="http://host" target="_blank">http://host</a>'], '///']);
65
+ assert.deepStrictEqual(inspect(parser(` http://host'`), ctx), [[`<a class="url" href="http://host'" target="_blank">http://host'</a>`], '']);
64
66
  assert.deepStrictEqual(inspect(parser(' http://host"'), ctx), [['<a class="url" href="http://host" target="_blank">http://host</a>'], '"']);
65
67
  assert.deepStrictEqual(inspect(parser(' http://host`'), ctx), [['<a class="url" href="http://host" target="_blank">http://host</a>'], '`']);
66
68
  assert.deepStrictEqual(inspect(parser(' http://host|'), ctx), [['<a class="url" href="http://host" target="_blank">http://host</a>'], '|']);
@@ -1,15 +1,16 @@
1
1
  import { AutolinkParser } from '../../inline';
2
2
  import { State, Recursion, Backtrack } from '../../context';
3
- import { List, Data } from '../../../combinator/data/parser';
3
+ import { List } from '../../../combinator/data/parser';
4
4
  import { union, tails, some, recursion, precedence, state, constraint, verify, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
5
+ import { inline } from '../../inline';
5
6
  import { unsafelink } from '../link';
6
7
  import { unescsource, str } from '../../source';
7
8
 
8
9
  export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
9
10
  open(
10
- /(?<![0-9A-Za-z][.+-]?)https?:\/\/(?=[\x21-\x7E])/y,
11
+ /(?<![0-9A-Za-z][.+-]?|[@#])https?:\/\/(?=[\x21-\x7E])/y,
11
12
  precedence(0, some(union([
12
- some(unescsource, /(?<![-+*=~^_,.;:!?])[-+*=~^_,.;:!?]*(?=[\\$"`\[\](){}<>()[]{}|]|[^\x21-\x7E]|$)/y),
13
+ some(unescsource, /(?<![-+*=~^_,.;:!?]|\/{3})(?:[-+*=~^_,.;:!?]|\/{3,}(?!\/))*(?=[\\$"`\[\](){}<>()[]{}|]|[^\x21-\x7E]|$)/y),
13
14
  precedence(1, verify(bracket, ns => ns.length > 0)),
14
15
  ]), undefined, [[/[^\x21-\x7E]|\$/y, 9]])),
15
16
  false,
@@ -19,7 +20,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => rewrite(
19
20
  url => `{ ${url} }`,
20
21
  unsafelink,
21
22
  false))),
22
- ({ context: { source } }) => new List([new Data(source)]),
23
+ open(str(/[^:]+/y), some(inline)),
23
24
  ])));
24
25
 
25
26
  export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
@@ -31,7 +32,7 @@ export const lineurl: AutolinkParser.UrlParser.LineUrlParser = lazy(() => focus(
31
32
  url => `{ ${url} }`,
32
33
  unsafelink,
33
34
  false))),
34
- ({ context: { source } }) => new List([new Data(source)]),
35
+ open(str(/[^:]+/y), some(inline)),
35
36
  ]),
36
37
  ])));
37
38
 
@@ -8,14 +8,13 @@ import { account } from './autolink/account';
8
8
  import { hashtag, emoji } from './autolink/hashtag';
9
9
  import { hashnum } from './autolink/hashnum';
10
10
  import { anchor } from './autolink/anchor';
11
- import { str } from '../source';
12
11
 
13
12
  export const autolink: AutolinkParser = lazy(() =>
14
13
  validate(new RegExp([
15
14
  /(?<![0-9a-z])@/yi.source,
16
15
  /(?<![^\p{C}\p{S}\p{P}\s]|emoji)#/yiu.source,
17
16
  /(?<![0-9a-z])>>/yi.source,
18
- /(?<![0-9a-z][.+-]?)!?[0-9a-z]/yi.source,
17
+ /(?<![0-9a-z][.+-]?|[@#])!?[0-9a-z]/yi.source,
19
18
  ].join('|').replace(/emoji/g, emoji), 'yiu'),
20
19
  state(~State.autolink,
21
20
  union([
@@ -23,14 +22,14 @@ export const autolink: AutolinkParser = lazy(() =>
23
22
  url,
24
23
  email,
25
24
  // Escape unmatched email-like strings.
26
- str(/[0-9a-z]+(?:[_.+-][0-9a-z]+[:@]?|:|@(?=@))*/yi),
25
+ //str(/[0-9a-z]+(?:[_.+-][0-9a-z]+[:@]?|:|@(?=@))*/yi),
27
26
  channel,
28
27
  account,
29
28
  // Escape unmatched account-like strings.
30
- str(/@+(?:[0-9a-z]+(?:[_.+-][0-9a-z]+)*)?/yi),
29
+ //str(/@+(?:[0-9a-z]+(?:[_.+-][0-9a-z]+)*)?/yi),
31
30
  hashtag,
32
31
  hashnum,
33
32
  // Escape unmatched hashtag-like strings.
34
- str(new RegExp(/#+(?:(?:[^\p{C}\p{S}\p{P}\s]|emoji)+(?:['_.+-](?:[^\p{C}\p{S}\p{P}\s]|emoji)+)*)?/yu.source.replace(/emoji/g, emoji), 'yu')),
33
+ //str(new RegExp(/#+(?:(?:[^\p{C}\p{S}\p{P}\s]|emoji)+(?:['_.+-](?:[^\p{C}\p{S}\p{P}\s]|emoji)+)*)?/yu.source.replace(/emoji/g, emoji), 'yu')),
35
34
  anchor,
36
35
  ]))));
@@ -13,7 +13,7 @@ describe('Unit: parser/inline/deletion', () => {
13
13
  assert.deepStrictEqual(inspect(parser('~'), ctx), undefined);
14
14
  assert.deepStrictEqual(inspect(parser('~~'), ctx), undefined);
15
15
  assert.deepStrictEqual(inspect(parser('~~a'), ctx), [['~~', 'a'], '']);
16
- assert.deepStrictEqual(inspect(parser('~~a~'), ctx), [['~~', 'a', '~'], '']);
16
+ assert.deepStrictEqual(inspect(parser('~~a~'), ctx), [['~~', 'a~'], '']);
17
17
  assert.deepStrictEqual(inspect(parser(' ~~a~~'), ctx), undefined);
18
18
  });
19
19
 
@@ -65,6 +65,7 @@ describe('Unit: parser/inline/html', () => {
65
65
  it('basic', () => {
66
66
  assert.deepStrictEqual(inspect(parser('<wbr>'), ctx), [['<wbr>'], '']);
67
67
  assert.deepStrictEqual(inspect(parser('<wbr >'), ctx), [['<wbr>'], '']);
68
+ assert.deepStrictEqual(inspect(parser('<wbr >'), ctx), [['<span class="invalid">&lt;wbr </span>'], ' >']);
68
69
  assert.deepStrictEqual(inspect(parser('<wbr>a'), ctx), [['<wbr>'], 'a']);
69
70
  assert.deepStrictEqual(inspect(parser('<bdi >a</bdi>'), ctx), [['<bdi>a</bdi>'], '']);
70
71
  assert.deepStrictEqual(inspect(parser('<bdi >a</bdi>'), ctx), [['<span class="invalid">&lt;bdi &gt;a&lt;/bdi&gt;</span>'], '']);
@@ -13,7 +13,7 @@ describe('Unit: parser/inline/insertion', () => {
13
13
  assert.deepStrictEqual(inspect(parser('+'), ctx), undefined);
14
14
  assert.deepStrictEqual(inspect(parser('++'), ctx), undefined);
15
15
  assert.deepStrictEqual(inspect(parser('++a'), ctx), [['++', 'a'], '']);
16
- assert.deepStrictEqual(inspect(parser('++a+'), ctx), [['++', 'a', '+'], '']);
16
+ assert.deepStrictEqual(inspect(parser('++a+'), ctx), [['++', 'a+'], '']);
17
17
  assert.deepStrictEqual(inspect(parser(' ++a++'), ctx), undefined);
18
18
  });
19
19
 
@@ -16,8 +16,8 @@ describe('Unit: parser/inline/italic', () => {
16
16
  assert.deepStrictEqual(inspect(parser('///a\n///'), ctx), [['///', 'a', '<br>', '///'], '']);
17
17
  assert.deepStrictEqual(inspect(parser('///a\\ ///'), ctx), [['///', 'a', ' ', '///'], '']);
18
18
  assert.deepStrictEqual(inspect(parser('///a\\\n///'), ctx), [['///', 'a', '<br>', '///'], '']);
19
- assert.deepStrictEqual(inspect(parser('///a/b'), ctx), [['///', 'a', '/b'], '']);
20
- assert.deepStrictEqual(inspect(parser('///a//b'), ctx), [['///', 'a', '//b'], '']);
19
+ assert.deepStrictEqual(inspect(parser('///a/b'), ctx), [['///', 'a/b'], '']);
20
+ assert.deepStrictEqual(inspect(parser('///a//b'), ctx), [['///', 'a//b'], '']);
21
21
  assert.deepStrictEqual(inspect(parser('///a*b///'), ctx), [['///', 'a', '*', 'b', '///'], '']);
22
22
  assert.deepStrictEqual(inspect(parser('/// ///'), ctx), undefined);
23
23
  assert.deepStrictEqual(inspect(parser('/// a///'), ctx), undefined);
@@ -180,7 +180,6 @@ describe('Unit: parser/inline/link', () => {
180
180
  assert.deepStrictEqual(inspect(parser('[[![]{a}]{b}]{b}'), ctx), [['<a class="link" href="b">[![]{a}]{b}</a>'], '']);
181
181
  assert.deepStrictEqual(inspect(parser('[((a))]{b}'), ctx), [['<a class="link" href="b"><span class="paren">((a))</span></a>'], '']);
182
182
  assert.deepStrictEqual(inspect(parser('[[[a]]]{b}'), ctx), [['<a class="link" href="b">[[a]]</a>'], '']);
183
- assert.deepStrictEqual(inspect(parser('[!http://host]{/}'), ctx), [['<a class="link" href="/" target="_blank"><img class="media" data-src="http://host" alt="http://host"></a>'], '']);
184
183
  assert.deepStrictEqual(inspect(parser('[#a]{b}'), ctx), [['<a class="link" href="b">#a</a>'], '']);
185
184
  assert.deepStrictEqual(inspect(parser('[@a]{b}'), ctx), [['<a class="link" href="b">@a</a>'], '']);
186
185
  assert.deepStrictEqual(inspect(parser('[@a@b]{c}'), ctx), [['<a class="link" href="c">@a@b</a>'], '']);
@@ -13,7 +13,7 @@ describe('Unit: parser/inline/mark', () => {
13
13
  assert.deepStrictEqual(inspect(parser('='), ctx), undefined);
14
14
  assert.deepStrictEqual(inspect(parser('=='), ctx), undefined);
15
15
  assert.deepStrictEqual(inspect(parser('==a'), ctx), [['==', 'a'], '']);
16
- assert.deepStrictEqual(inspect(parser('==a='), ctx), [['==', 'a', '='], '']);
16
+ assert.deepStrictEqual(inspect(parser('==a='), ctx), [['==', 'a='], '']);
17
17
  assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=='], '']);
18
18
  assert.deepStrictEqual(inspect(parser('==a =='), ctx), [['==', 'a', ' ', '=='], '']);
19
19
  assert.deepStrictEqual(inspect(parser('==a\n=='), ctx), [['==', 'a', '<br>', '=='], '']);
@@ -165,19 +165,19 @@ describe('Unit: parser/inline', () => {
165
165
  assert.deepStrictEqual(inspect(parser('"[% *"*"*'), ctx), [['"', '[%', ' ', '*', '"', '*', '"', '*'], '']);
166
166
  assert.deepStrictEqual(inspect(parser('"[% "*"* %]'), ctx), [['"', '<span class="remark"><input type="checkbox"><span>[% "*"* %]</span></span>'], '']);
167
167
  assert.deepStrictEqual(inspect(parser('"{{""}}'), ctx), [['"', '{', '{', '"', '"', '}', '}'], '']);
168
- assert.deepStrictEqual(inspect(parser('[#http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::http://host/(&lt;bdi&gt;)">http://host/(&lt;bdi&gt;)</a>', '</bdi', '>'], '']);
169
- assert.deepStrictEqual(inspect(parser('[#@a/http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::@a/http://host/(&lt;bdi&gt;)">@a/http://host/(&lt;bdi&gt;)</a>', '</bdi', '>'], '']);
168
+ assert.deepStrictEqual(inspect(parser('[#http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::http://host/(&lt;bdi&gt;)">http://host/<span class="paren">(<span class="invalid">&lt;bdi&gt;</span>)</span></a>', '</bdi', '>'], '']);
169
+ assert.deepStrictEqual(inspect(parser('[#@a/http://host/(<bdi>)]</bdi>'), ctx), [['<a class="index" href="#index::@a/http://host/(&lt;bdi&gt;)">@a/http://host/<span class="paren">(<span class="invalid">&lt;bdi&gt;</span>)</span></a>', '</bdi', '>'], '']);
170
170
  assert.deepStrictEqual(inspect(parser('[#a|<bdi>]</bdi>'), ctx), [['<a class="index" href="#index::a|&lt;bdi&gt;">a|<span class="invalid">&lt;bdi&gt;</span></a>', '</bdi', '>'], '']);
171
171
  assert.deepStrictEqual(inspect(parser('[[#a|<bdi>]</bdi>'), ctx), [['[', '<a class="index" href="#index::a|&lt;bdi&gt;">a|<span class="invalid">&lt;bdi&gt;</span></a>', '</bdi', '>'], '']);
172
172
  });
173
173
 
174
174
  it('uri', () => {
175
175
  assert.deepStrictEqual(inspect(parser('\nhttp://host'), ctx), [['<br>', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
176
- assert.deepStrictEqual(inspect(parser('0http://host'), ctx), [['0http:', '//host'], '']);
177
- assert.deepStrictEqual(inspect(parser('0aAhttp://host'), ctx), [['0aAhttp:', '//host'], '']);
176
+ assert.deepStrictEqual(inspect(parser('0http://host'), ctx), [['0http', '://host'], '']);
177
+ assert.deepStrictEqual(inspect(parser('0aAhttp://host'), ctx), [['0aAhttp', '://host'], '']);
178
178
  assert.deepStrictEqual(inspect(parser('?http://host'), ctx), [['?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
179
179
  assert.deepStrictEqual(inspect(parser('0!http://host'), ctx), [['0', '!', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
180
- assert.deepStrictEqual(inspect(parser('0?http://host'), ctx), [['0', '?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
180
+ assert.deepStrictEqual(inspect(parser('0?http://host'), ctx), [['0?', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
181
181
  assert.deepStrictEqual(inspect(parser('_http://host'), ctx), [['_', '<a class="url" href="http://host" target="_blank">http://host</a>'], '']);
182
182
  assert.deepStrictEqual(inspect(parser('_http://host_'), ctx), [['_', '<a class="url" href="http://host" target="_blank">http://host</a>', '_'], '']);
183
183
  assert.deepStrictEqual(inspect(parser('*http://host*'), ctx), [['<em><a class="url" href="http://host" target="_blank">http://host</a></em>'], '']);
@@ -210,7 +210,7 @@ describe('Unit: parser/inline', () => {
210
210
 
211
211
  it('account', () => {
212
212
  assert.deepStrictEqual(inspect(parser('@a'), ctx), [['<a class="account" href="/@a">@a</a>'], '']);
213
- assert.deepStrictEqual(inspect(parser('@http://host'), ctx), [['@http', '://host'], '']);
213
+ assert.deepStrictEqual(inspect(parser('@http://host'), ctx), [['@', 'http', '://host'], '']);
214
214
  assert.deepStrictEqual(inspect(parser('_@a'), ctx), [['_', '<a class="account" href="/@a">@a</a>'], '']);
215
215
  assert.deepStrictEqual(inspect(parser('_@a_'), ctx), [['_', '<a class="account" href="/@a">@a</a>', '_'], '']);
216
216
  assert.deepStrictEqual(inspect(parser('*@a*'), ctx), [['<em><a class="account" href="/@a">@a</a></em>'], '']);
@@ -222,9 +222,9 @@ describe('Unit: parser/inline', () => {
222
222
  assert.deepStrictEqual(inspect(parser('#a#'), ctx), [['#a', '#'], '']);
223
223
  assert.deepStrictEqual(inspect(parser('#a#b'), ctx), [['#a', '#b'], '']);
224
224
  assert.deepStrictEqual(inspect(parser('#a'), ctx), [['<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
225
- assert.deepStrictEqual(inspect(parser('#http://host'), ctx), [['#http', '://host'], '']);
225
+ assert.deepStrictEqual(inspect(parser('#http://host'), ctx), [['#', 'http', '://host'], '']);
226
226
  assert.deepStrictEqual(inspect(parser('#a\nb\n#c\n[#d]'), ctx), [['<a class="hashtag" href="/hashtags/a">#a</a>', '<br>', 'b', '<br>', '<a class="hashtag" href="/hashtags/c">#c</a>', '<br>', '<a class="index" href="#index::d">d</a>'], '']);
227
- assert.deepStrictEqual(inspect(parser('##a'), ctx), [['##a'], '']);
227
+ assert.deepStrictEqual(inspect(parser('##a'), ctx), [['#', '<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
228
228
  assert.deepStrictEqual(inspect(parser('_#a'), ctx), [['_', '<a class="hashtag" href="/hashtags/a">#a</a>'], '']);
229
229
  assert.deepStrictEqual(inspect(parser('_#a_'), ctx), [['_', '<a class="hashtag" href="/hashtags/a">#a</a>', '_'], '']);
230
230
  assert.deepStrictEqual(inspect(parser('_#a_b'), ctx), [['_', '<a class="hashtag" href="/hashtags/a_b">#a_b</a>'], '']);
@@ -233,8 +233,8 @@ describe('Unit: parser/inline', () => {
233
233
  assert.deepStrictEqual(inspect(parser('0a#b'), ctx), [['0a', '#b'], '']);
234
234
  assert.deepStrictEqual(inspect(parser('あ#b'), ctx), [['あ', '#b'], '']);
235
235
  assert.deepStrictEqual(inspect(parser('あい#b'), ctx), [['あい', '#b'], '']);
236
- assert.deepStrictEqual(inspect(parser('0aあ#b'), ctx), [['0a', 'あ', '#b'], '']);
237
- assert.deepStrictEqual(inspect(parser('0aあい#b'), ctx), [['0a', 'あい', '#b'], '']);
236
+ assert.deepStrictEqual(inspect(parser('0aあ#b'), ctx), [['0aあ', '#b'], '']);
237
+ assert.deepStrictEqual(inspect(parser('0aあい#b'), ctx), [['0aあい', '#b'], '']);
238
238
  assert.deepStrictEqual(inspect(parser('「#あ」'), ctx), [['「', '<a class="hashtag" href="/hashtags/あ">#あ</a>', '」'], '']);
239
239
  assert.deepStrictEqual(inspect(parser('a\n#b'), ctx), [['a', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
240
240
  assert.deepStrictEqual(inspect(parser('a\\\n#b'), ctx), [['a', '<br>', '<a class="hashtag" href="/hashtags/b">#b</a>'], '']);
@@ -248,7 +248,7 @@ describe('Unit: parser/inline', () => {
248
248
  it('hashnum', () => {
249
249
  assert.deepStrictEqual(inspect(parser('#1'), ctx), [['<a class="hashnum">#1</a>'], '']);
250
250
  assert.deepStrictEqual(inspect(parser(`#1'`), ctx), [[`<a class="hashnum">#1</a>`, `'`], '']);
251
- assert.deepStrictEqual(inspect(parser('#1234567890@a'), ctx), [['#1234567890', '@a'], '']);
251
+ assert.deepStrictEqual(inspect(parser('#1234567890@a'), ctx), [['#', '1234567890', '@a'], '']);
252
252
  assert.deepStrictEqual(inspect(parser('_#1'), ctx), [['_', '<a class="hashnum">#1</a>'], '']);
253
253
  assert.deepStrictEqual(inspect(parser('_#1_'), ctx), [['_', '<a class="hashnum">#1</a>', '_'], '']);
254
254
  assert.deepStrictEqual(inspect(parser('_#1_0'), ctx), [['_', '<a class="hashtag" href="/hashtags/1_0">#1_0</a>'], '']);
@@ -8,11 +8,11 @@ import { invisibleHTMLEntityNames } from './api/normalize';
8
8
  export namespace blank {
9
9
  export const line = new RegExp(
10
10
  // TODO: 行全体をエスケープ
11
- /^(?:[^\S\r\n])*(?!\s)(\\?[^\S\r\n]|&IHN;|<wbr[^\S\n]*>|\\$)+$/mg.source
11
+ /^(?:[^\S\r\n])*(?!\s)(\\?[^\S\r\n]|&IHN;|<wbr ?>|\\$)+$/mg.source
12
12
  .replace('IHN', `(?:${invisibleHTMLEntityNames.join('|')})`),
13
13
  'gm');
14
14
  export const start = new RegExp(
15
- /(?:\\?[^\S\r\n]|&IHN;|<wbr[^\S\n]*>)+/y.source
15
+ /(?:\\?[^\S\r\n]|&IHN;|<wbr ?>)+/y.source
16
16
  .replace('IHN', `(?:${invisibleHTMLEntityNames.join('|')})`), 'y');
17
17
  }
18
18
 
@@ -46,7 +46,7 @@ export function blankWith(starts: '' | '\n', delimiter: string | RegExp): RegExp
46
46
  export function blankWith(starts: '' | '\n', delimiter?: string | RegExp): RegExp {
47
47
  if (delimiter === undefined) return blankWith('', starts);
48
48
  return new RegExp(String.raw
49
- `(?:(?=${starts})(?:\\?\s|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr[^\S\n]*>)${
49
+ `(?:(?=${starts})(?:\\?\s|&(?:${invisibleHTMLEntityNames.join('|')});|<wbr ?>)${
50
50
  // 空行除去
51
51
  // 完全な空行はエスケープ済みなので再帰的バックトラックにはならない。
52
52
  starts && '+'
@@ -75,7 +75,6 @@ export function tightStart<N>(parser: Parser<N>, except?: string): Parser<N> {
75
75
  ? parser(input)
76
76
  : undefined;
77
77
  }
78
- const wbr = /<wbr[^\S\n]*>/y;
79
78
  function isTightStart(input: Input<MarkdownParser.Context>, except?: string): boolean {
80
79
  const { context } = input;
81
80
  const { source, position } = context;
@@ -100,11 +99,10 @@ function isTightStart(input: Input<MarkdownParser.Context>, except?: string): bo
100
99
  context.position = position;
101
100
  return true;
102
101
  case '<':
103
- wbr.lastIndex = position;
104
102
  switch (true) {
105
103
  case source.length - position >= 5
106
104
  && source.startsWith('<wbr', position)
107
- && (source[position + 5] === '>' || wbr.test(source)):
105
+ && (source[position + 4] === '>' || source.startsWith(' >', position + 4)):
108
106
  return false;
109
107
  }
110
108
  return true;