securemark 0.258.8 → 0.259.1
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 +12 -0
- package/design.md +4 -4
- package/dist/index.js +138 -131
- package/markdown.d.ts +37 -19
- package/package.json +1 -1
- package/src/combinator/data/parser/context.ts +16 -17
- package/src/parser/api/bind.ts +2 -2
- package/src/parser/api/parse.ts +2 -2
- package/src/parser/block/reply/cite.test.ts +3 -1
- package/src/parser/block/reply/cite.ts +1 -0
- package/src/parser/context.ts +15 -6
- package/src/parser/inline/annotation.ts +3 -4
- package/src/parser/inline/autolink/account.ts +2 -2
- package/src/parser/inline/autolink/anchor.ts +2 -2
- package/src/parser/inline/autolink/hashnum.ts +2 -2
- package/src/parser/inline/autolink/hashtag.ts +2 -2
- package/src/parser/inline/autolink/url.ts +2 -2
- package/src/parser/inline/autolink.ts +1 -1
- package/src/parser/inline/bracket.ts +8 -8
- package/src/parser/inline/comment.ts +2 -2
- package/src/parser/inline/deletion.ts +2 -2
- package/src/parser/inline/emphasis.ts +2 -2
- package/src/parser/inline/emstrong.ts +2 -2
- package/src/parser/inline/extension/index.ts +3 -4
- package/src/parser/inline/extension/placeholder.ts +2 -2
- package/src/parser/inline/html.ts +2 -2
- package/src/parser/inline/insertion.ts +2 -2
- package/src/parser/inline/link.ts +70 -66
- package/src/parser/inline/mark.ts +2 -2
- package/src/parser/inline/media.ts +11 -10
- package/src/parser/inline/reference.ts +3 -4
- package/src/parser/inline/ruby.ts +2 -2
- package/src/parser/inline/strong.ts +2 -2
- package/src/parser/inline/template.ts +2 -2
- package/src/parser/inline.ts +0 -1
- package/src/parser/source/text.ts +2 -2
package/markdown.d.ts
CHANGED
|
@@ -577,6 +577,7 @@ export namespace MarkdownParser {
|
|
|
577
577
|
InlineParser.AutolinkParser.AnchorParser,
|
|
578
578
|
Parser<HTMLAnchorElement, Context, []>,
|
|
579
579
|
Parser<HTMLAnchorElement, Context, []>,
|
|
580
|
+
Parser<HTMLAnchorElement, Context, []>,
|
|
580
581
|
]>,
|
|
581
582
|
]> {
|
|
582
583
|
}
|
|
@@ -660,7 +661,7 @@ export namespace MarkdownParser {
|
|
|
660
661
|
export interface AnnotationParser extends
|
|
661
662
|
// ((abc))
|
|
662
663
|
Inline<'annotation'>,
|
|
663
|
-
Parser<HTMLElement
|
|
664
|
+
Parser<HTMLElement, Context, [
|
|
664
665
|
InlineParser,
|
|
665
666
|
]> {
|
|
666
667
|
}
|
|
@@ -669,7 +670,7 @@ export namespace MarkdownParser {
|
|
|
669
670
|
// [[^abbr]]
|
|
670
671
|
// [[^abbr| abc]]
|
|
671
672
|
Inline<'reference'>,
|
|
672
|
-
Parser<HTMLElement
|
|
673
|
+
Parser<HTMLElement, Context, [
|
|
673
674
|
ReferenceParser.AbbrParser,
|
|
674
675
|
InlineParser,
|
|
675
676
|
InlineParser,
|
|
@@ -689,7 +690,7 @@ export namespace MarkdownParser {
|
|
|
689
690
|
export interface TemplateParser extends
|
|
690
691
|
// {{abc}}
|
|
691
692
|
Inline<'template'>,
|
|
692
|
-
Parser<HTMLSpanElement
|
|
693
|
+
Parser<HTMLSpanElement, Context, [
|
|
693
694
|
TemplateParser.BracketParser,
|
|
694
695
|
SourceParser.EscapableSourceParser,
|
|
695
696
|
]> {
|
|
@@ -842,21 +843,38 @@ export namespace MarkdownParser {
|
|
|
842
843
|
// { uri }
|
|
843
844
|
// [abc]{uri nofollow}
|
|
844
845
|
Inline<'link'>,
|
|
845
|
-
Parser<HTMLElement | string, Context, [
|
|
846
|
-
LinkParser.ContentParser,
|
|
847
|
-
LinkParser.ParameterParser,
|
|
848
|
-
]> {
|
|
849
|
-
}
|
|
850
|
-
export interface TextLinkParser extends
|
|
851
|
-
// { uri }
|
|
852
|
-
// [abc]{uri nofollow}
|
|
853
|
-
Inline<'textlink'>,
|
|
854
846
|
Parser<HTMLAnchorElement, Context, [
|
|
855
|
-
LinkParser.
|
|
856
|
-
LinkParser.
|
|
847
|
+
LinkParser.MediaLinkParser,
|
|
848
|
+
LinkParser.TextLinkParser,
|
|
857
849
|
]> {
|
|
858
850
|
}
|
|
859
851
|
export namespace LinkParser {
|
|
852
|
+
export interface TextLinkParser extends
|
|
853
|
+
Inline<'link/textlink'>,
|
|
854
|
+
Parser<HTMLAnchorElement, Context, [
|
|
855
|
+
Parser<(HTMLElement | string)[], Context, [
|
|
856
|
+
InlineParser,
|
|
857
|
+
]>,
|
|
858
|
+
LinkParser.ParameterParser,
|
|
859
|
+
]> {
|
|
860
|
+
}
|
|
861
|
+
export interface MediaLinkParser extends
|
|
862
|
+
Inline<'link/medialink'>,
|
|
863
|
+
Parser<HTMLAnchorElement, Context, [
|
|
864
|
+
Parser<HTMLElement[], Context, [
|
|
865
|
+
MediaParser,
|
|
866
|
+
ShortmediaParser,
|
|
867
|
+
]>,
|
|
868
|
+
LinkParser.ParameterParser,
|
|
869
|
+
]> {
|
|
870
|
+
}
|
|
871
|
+
export interface UnsafeLinkParser extends
|
|
872
|
+
Inline<'link/unsafelink'>,
|
|
873
|
+
Parser<HTMLAnchorElement, Context, [
|
|
874
|
+
LinkParser.TextParser,
|
|
875
|
+
LinkParser.ParameterParser,
|
|
876
|
+
]> {
|
|
877
|
+
}
|
|
860
878
|
export interface ContentParser extends
|
|
861
879
|
Inline<'link/content'>,
|
|
862
880
|
Parser<(HTMLElement | string)[], Context, [
|
|
@@ -1093,7 +1111,7 @@ export namespace MarkdownParser {
|
|
|
1093
1111
|
// https://host
|
|
1094
1112
|
Inline<'url'>,
|
|
1095
1113
|
Parser<HTMLAnchorElement, Context, [
|
|
1096
|
-
|
|
1114
|
+
LinkParser.UnsafeLinkParser,
|
|
1097
1115
|
]> {
|
|
1098
1116
|
}
|
|
1099
1117
|
export namespace UrlParser {
|
|
@@ -1135,28 +1153,28 @@ export namespace MarkdownParser {
|
|
|
1135
1153
|
// @user
|
|
1136
1154
|
Inline<'account'>,
|
|
1137
1155
|
Parser<HTMLAnchorElement, Context, [
|
|
1138
|
-
|
|
1156
|
+
LinkParser.UnsafeLinkParser,
|
|
1139
1157
|
]> {
|
|
1140
1158
|
}
|
|
1141
1159
|
export interface HashtagParser extends
|
|
1142
1160
|
// #tag
|
|
1143
1161
|
Inline<'hashtag'>,
|
|
1144
1162
|
Parser<HTMLAnchorElement, Context, [
|
|
1145
|
-
|
|
1163
|
+
LinkParser.UnsafeLinkParser,
|
|
1146
1164
|
]> {
|
|
1147
1165
|
}
|
|
1148
1166
|
export interface HashnumParser extends
|
|
1149
1167
|
// #1
|
|
1150
1168
|
Inline<'hashnum'>,
|
|
1151
1169
|
Parser<HTMLAnchorElement, Context, [
|
|
1152
|
-
|
|
1170
|
+
LinkParser.UnsafeLinkParser,
|
|
1153
1171
|
]> {
|
|
1154
1172
|
}
|
|
1155
1173
|
export interface AnchorParser extends
|
|
1156
1174
|
// >>1
|
|
1157
1175
|
Inline<'anchor'>,
|
|
1158
1176
|
Parser<HTMLAnchorElement, Context, [
|
|
1159
|
-
|
|
1177
|
+
LinkParser.UnsafeLinkParser,
|
|
1160
1178
|
]> {
|
|
1161
1179
|
}
|
|
1162
1180
|
}
|
package/package.json
CHANGED
|
@@ -56,41 +56,39 @@ function apply<T>(parser: Parser<T>, source: string, context: Ctx, changes: [str
|
|
|
56
56
|
return result;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
export function syntax<P extends Parser<unknown>>(syntax: number, precedence: number, cost: number, parser: P): P;
|
|
60
|
-
export function syntax<T>(syntax: number,
|
|
61
|
-
return creation(cost, (source, context) => {
|
|
59
|
+
export function syntax<P extends Parser<unknown>>(syntax: number, precedence: number, cost: number, state: number, parser: P): P;
|
|
60
|
+
export function syntax<T>(syntax: number, prec: number, cost: number, state: number, parser?: Parser<T>): Parser<T> {
|
|
61
|
+
return creation(cost, precedence(prec, (source, context) => {
|
|
62
62
|
if (source === '') return;
|
|
63
63
|
const memo = context.memo ??= new Memo();
|
|
64
64
|
context.memorable ??= ~0;
|
|
65
|
-
const p = context.precedence;
|
|
66
|
-
context.precedence = precedence;
|
|
67
65
|
const position = source.length;
|
|
68
|
-
const
|
|
69
|
-
const
|
|
66
|
+
const st0 = context.state ?? 0;
|
|
67
|
+
const st1 = context.state = st0 | state;
|
|
68
|
+
const cache = syntax && memo.get(position, syntax, st1);
|
|
70
69
|
const result: Result<T> = cache
|
|
71
70
|
? cache.length === 0
|
|
72
71
|
? undefined
|
|
73
72
|
: [cache[0], source.slice(cache[1])]
|
|
74
73
|
: parser!(source, context);
|
|
75
|
-
if (syntax &&
|
|
76
|
-
cache ?? memo.set(position, syntax,
|
|
77
|
-
assert.deepStrictEqual(cache && cache, cache && memo.get(position, syntax,
|
|
74
|
+
if (syntax && st0 & context.memorable!) {
|
|
75
|
+
cache ?? memo.set(position, syntax, st1, eval(result), source.length - exec(result, '').length);
|
|
76
|
+
assert.deepStrictEqual(cache && cache, cache && memo.get(position, syntax, st1));
|
|
78
77
|
}
|
|
79
|
-
if (result && !
|
|
80
|
-
assert(!(
|
|
81
|
-
memo.clear(position);
|
|
78
|
+
if (result && !st0 && memo.length! >= position + 2) {
|
|
79
|
+
assert(!(st0 & context.memorable!));
|
|
80
|
+
memo.clear(position + 2);
|
|
82
81
|
}
|
|
83
|
-
context.
|
|
82
|
+
context.state = st0;
|
|
84
83
|
return result;
|
|
85
|
-
});
|
|
84
|
+
}));
|
|
86
85
|
}
|
|
87
86
|
|
|
88
87
|
export function creation<P extends Parser<unknown>>(parser: P): P;
|
|
89
88
|
export function creation<P extends Parser<unknown>>(cost: number, parser: P): P;
|
|
90
89
|
export function creation(cost: number | Parser<unknown>, parser?: Parser<unknown>): Parser<unknown> {
|
|
91
90
|
if (typeof cost === 'function') return creation(1, cost);
|
|
92
|
-
|
|
93
|
-
assert(cost >= 0);
|
|
91
|
+
assert(cost > 0);
|
|
94
92
|
return (source, context) => {
|
|
95
93
|
const { resources = { clock: 1, recursion: 1 } } = context;
|
|
96
94
|
if (resources.clock <= 0) throw new Error('Too many creations');
|
|
@@ -107,6 +105,7 @@ export function creation(cost: number | Parser<unknown>, parser?: Parser<unknown
|
|
|
107
105
|
|
|
108
106
|
export function precedence<P extends Parser<unknown>>(precedence: number, parser: P): P;
|
|
109
107
|
export function precedence<T>(precedence: number, parser: Parser<T>): Parser<T> {
|
|
108
|
+
assert(precedence > 0);
|
|
110
109
|
return (source, context) => {
|
|
111
110
|
const p = context.precedence;
|
|
112
111
|
context.precedence = precedence;
|
package/src/parser/api/bind.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { eval } from '../../combinator/data/parser';
|
|
|
5
5
|
import { segment, validate, MAX_INPUT_SIZE } from '../segment';
|
|
6
6
|
import { header } from '../header';
|
|
7
7
|
import { block } from '../block';
|
|
8
|
-
import {
|
|
8
|
+
import { State } from '../context';
|
|
9
9
|
import { normalize } from './normalize';
|
|
10
10
|
import { headers } from './header';
|
|
11
11
|
import { figure } from '../processor/figure';
|
|
@@ -24,7 +24,7 @@ export function bind(target: DocumentFragment | HTMLElement | ShadowRoot, settin
|
|
|
24
24
|
let context: MarkdownParser.Context = {
|
|
25
25
|
...settings,
|
|
26
26
|
host: settings.host ?? new ReadonlyURL(location.pathname, location.origin),
|
|
27
|
-
memorable: backtrackable,
|
|
27
|
+
memorable: State.backtrackable,
|
|
28
28
|
};
|
|
29
29
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
30
30
|
assert(!settings.id);
|
package/src/parser/api/parse.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { eval } from '../../combinator/data/parser';
|
|
|
5
5
|
import { segment, validate, MAX_SEGMENT_SIZE } from '../segment';
|
|
6
6
|
import { header } from '../header';
|
|
7
7
|
import { block } from '../block';
|
|
8
|
-
import {
|
|
8
|
+
import { State } from '../context';
|
|
9
9
|
import { normalize } from './normalize';
|
|
10
10
|
import { headers } from './header';
|
|
11
11
|
import { figure } from '../processor/figure';
|
|
@@ -30,7 +30,7 @@ export function parse(source: string, opts: Options = {}, context?: MarkdownPars
|
|
|
30
30
|
...context?.resources && {
|
|
31
31
|
resources: context.resources,
|
|
32
32
|
},
|
|
33
|
-
memorable: backtrackable,
|
|
33
|
+
memorable: State.backtrackable,
|
|
34
34
|
};
|
|
35
35
|
if (context.host?.origin === 'null') throw new Error(`Invalid host: ${context.host.href}`);
|
|
36
36
|
const node = frag();
|
|
@@ -18,7 +18,7 @@ describe('Unit: parser/block/reply/cite', () => {
|
|
|
18
18
|
assert.deepStrictEqual(inspect(parser('>>\\')), undefined);
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('>>01#')), undefined);
|
|
20
20
|
assert.deepStrictEqual(inspect(parser('>>01@')), undefined);
|
|
21
|
-
assert.deepStrictEqual(inspect(parser('>>
|
|
21
|
+
assert.deepStrictEqual(inspect(parser('>>http://')), undefined);
|
|
22
22
|
assert.deepStrictEqual(inspect(parser('>>tel:1234567890')), undefined);
|
|
23
23
|
assert.deepStrictEqual(inspect(parser('>>..')), undefined);
|
|
24
24
|
assert.deepStrictEqual(inspect(parser('>> 0')), undefined);
|
|
@@ -43,6 +43,8 @@ describe('Unit: parser/block/reply/cite', () => {
|
|
|
43
43
|
assert.deepStrictEqual(inspect(parser('>>#a')), [['<span class="cite">><a class="anchor" data-depth="1">>#a</a></span>', '<br>'], '']);
|
|
44
44
|
assert.deepStrictEqual(inspect(parser('>>#index:a')), [['<span class="cite">><a class="anchor" data-depth="1">>#index:a</a></span>', '<br>'], '']);
|
|
45
45
|
assert.deepStrictEqual(inspect(parser('>>#:~:text=a')), [['<span class="cite">><a class="anchor" data-depth="1">>#:~:text=a</a></span>', '<br>'], '']);
|
|
46
|
+
assert.deepStrictEqual(inspect(parser('>>http://host')), [['<span class="cite">><a class="anchor" href="http://host" target="_blank" data-depth="1">>http://host</a></span>', '<br>'], '']);
|
|
47
|
+
assert.deepStrictEqual(inspect(parser('>>https://host')), [['<span class="cite">><a class="anchor" href="https://host" target="_blank" data-depth="1">>https://host</a></span>', '<br>'], '']);
|
|
46
48
|
});
|
|
47
49
|
|
|
48
50
|
});
|
|
@@ -14,6 +14,7 @@ export const cite: ReplyParser.CiteParser = creation(line(fmap(validate(
|
|
|
14
14
|
// リンクの実装は後で検討
|
|
15
15
|
focus(/^>>\.[^\S\n]*(?:$|\n)/, () => [[html('a', { class: 'anchor' }, '>>.')], '']),
|
|
16
16
|
focus(/^>>#\S*[^\S\n]*(?:$|\n)/, source => [[html('a', { class: 'anchor' }, source)], '']),
|
|
17
|
+
focus(/^>>https?:\/\/\w\S*[^\S\n]*(?:$|\n)/, source => [[html('a', { class: 'anchor', href: source.slice(2).trimEnd(), target: '_blank' }, source)], '']),
|
|
17
18
|
]),
|
|
18
19
|
]))),
|
|
19
20
|
([el, quotes = '']: [HTMLElement, string?]) => [
|
package/src/parser/context.ts
CHANGED
|
@@ -23,10 +23,19 @@ export const enum State {
|
|
|
23
23
|
link = 1 << 2,
|
|
24
24
|
media = 1 << 1,
|
|
25
25
|
autolink = 1 << 0,
|
|
26
|
+
none = 0,
|
|
27
|
+
linkable = 0
|
|
28
|
+
| State.annotation
|
|
29
|
+
| State.reference
|
|
30
|
+
| State.index
|
|
31
|
+
| State.label
|
|
32
|
+
| State.link
|
|
33
|
+
| State.media
|
|
34
|
+
| State.autolink,
|
|
35
|
+
backtrackable = 0
|
|
36
|
+
| State.annotation
|
|
37
|
+
| State.reference
|
|
38
|
+
| State.index
|
|
39
|
+
| State.link
|
|
40
|
+
| State.media,
|
|
26
41
|
}
|
|
27
|
-
export const backtrackable = 0
|
|
28
|
-
| State.annotation
|
|
29
|
-
| State.reference
|
|
30
|
-
| State.index
|
|
31
|
-
| State.link
|
|
32
|
-
| State.media;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { AnnotationParser } from '../inline';
|
|
3
|
-
import { union, some, context, syntax, constraint,
|
|
3
|
+
import { union, some, context, syntax, constraint, surround, lazy } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
5
|
import { Syntax, State } from '../context';
|
|
6
6
|
import { startLoose, trimNode } from '../visibility';
|
|
@@ -9,11 +9,10 @@ import { html, defrag } from 'typed-dom/dom';
|
|
|
9
9
|
export const annotation: AnnotationParser = lazy(() => surround(
|
|
10
10
|
'((',
|
|
11
11
|
constraint(State.annotation, false,
|
|
12
|
-
|
|
13
|
-
syntax(Syntax.annotation, 6, 1,
|
|
12
|
+
syntax(Syntax.annotation, 6, 1, State.annotation | State.media,
|
|
14
13
|
startLoose(
|
|
15
14
|
context({ delimiters: undefined },
|
|
16
|
-
some(union([inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])), ')')))
|
|
15
|
+
some(union([inline]), ')', [[/^\\?\n/, 9], [')', 2], ['))', 6]])), ')'))),
|
|
17
16
|
'))',
|
|
18
17
|
false,
|
|
19
18
|
([, ns], rest) => [[html('sup', { class: 'annotation' }, [html('span', trimNode(defrag(ns)))])], rest]));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { union, tails, verify, rewrite, open, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
-
import {
|
|
3
|
+
import { unsafelink } from '../link';
|
|
4
4
|
import { str } from '../../source';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
6
|
|
|
@@ -24,5 +24,5 @@ export const account: AutolinkParser.AccountParser = lazy(() => fmap(rewrite(
|
|
|
24
24
|
? `https://${source.slice(1).replace('/', '/@')}`
|
|
25
25
|
: `/${source}`
|
|
26
26
|
} }`,
|
|
27
|
-
union([
|
|
27
|
+
union([unsafelink]))),
|
|
28
28
|
([el]) => [define(el, { class: 'account' })]));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { union, validate, focus, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
-
import {
|
|
3
|
+
import { unsafelink } from '../link';
|
|
4
4
|
import { define } from 'typed-dom/dom';
|
|
5
5
|
|
|
6
6
|
// Timeline(pseudonym): user/tid
|
|
@@ -21,5 +21,5 @@ export const anchor: AutolinkParser.AnchorParser = lazy(() => validate('>>', fma
|
|
|
21
21
|
? `/@${source.slice(2).replace('/', '/timeline/')}`
|
|
22
22
|
: `?at=${source.slice(2)}`
|
|
23
23
|
} }`,
|
|
24
|
-
union([
|
|
24
|
+
union([unsafelink]))),
|
|
25
25
|
([el]) => [define(el, { class: 'anchor' })])));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { union, rewrite, open, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
-
import {
|
|
3
|
+
import { unsafelink } from '../link';
|
|
4
4
|
import { emoji } from './hashtag';
|
|
5
5
|
import { str } from '../../source';
|
|
6
6
|
import { define } from 'typed-dom/dom';
|
|
@@ -9,5 +9,5 @@ export const hashnum: AutolinkParser.HashnumParser = lazy(() => fmap(rewrite(
|
|
|
9
9
|
open('#', str(new RegExp(/^[0-9]{1,16}(?![^\p{C}\p{S}\p{P}\s]|emoji|['_])/u.source.replace(/emoji/, emoji), 'u'))),
|
|
10
10
|
convert(
|
|
11
11
|
source => `[${source}]{ ${source.slice(1)} }`,
|
|
12
|
-
union([
|
|
12
|
+
union([unsafelink]))),
|
|
13
13
|
([el]) => [define(el, { class: 'hashnum', href: null })]));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { union, tails, verify, rewrite, open, convert, fmap, lazy } from '../../../combinator';
|
|
3
|
-
import {
|
|
3
|
+
import { unsafelink } from '../link';
|
|
4
4
|
import { str } from '../../source';
|
|
5
5
|
import { define } from 'typed-dom/dom';
|
|
6
6
|
|
|
@@ -31,5 +31,5 @@ export const hashtag: AutolinkParser.HashtagParser = lazy(() => fmap(rewrite(
|
|
|
31
31
|
? `https://${source.slice(1).replace('/', '/hashtags/')}`
|
|
32
32
|
: `/hashtags/${source.slice(1)}`
|
|
33
33
|
} }`,
|
|
34
|
-
union([
|
|
34
|
+
union([unsafelink]))),
|
|
35
35
|
([el]) => [define(el, { class: 'hashtag' }, el.innerText)]));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AutolinkParser } from '../../inline';
|
|
2
2
|
import { union, some, creation, precedence, validate, focus, rewrite, convert, surround, open, lazy } from '../../../combinator';
|
|
3
|
-
import {
|
|
3
|
+
import { unsafelink } from '../link';
|
|
4
4
|
import { unescsource } from '../../source';
|
|
5
5
|
|
|
6
6
|
const closer = /^[-+*=~^,.;:!?]*(?=[\\"`|\[\](){}<>]|$)/;
|
|
@@ -11,7 +11,7 @@ export const url: AutolinkParser.UrlParser = lazy(() => validate(['http://', 'ht
|
|
|
11
11
|
focus(/^[\x21-\x7E]+/, some(union([bracket, some(unescsource, closer)])))),
|
|
12
12
|
convert(
|
|
13
13
|
url => `{ ${url} }`,
|
|
14
|
-
union([
|
|
14
|
+
union([unsafelink])))));
|
|
15
15
|
|
|
16
16
|
const bracket: AutolinkParser.UrlParser.BracketParser = lazy(() => creation(precedence(2, union([
|
|
17
17
|
surround('(', some(union([bracket, unescsource]), ')'), ')', true),
|
|
@@ -14,7 +14,7 @@ import { stringify } from '../util';
|
|
|
14
14
|
export const autolink: AutolinkParser = fmap(
|
|
15
15
|
validate(/^(?:[@#>0-9A-Za-z]|\S[#>])/,
|
|
16
16
|
constraint(State.autolink, false,
|
|
17
|
-
syntax(Syntax.autolink, 1, 1,
|
|
17
|
+
syntax(Syntax.autolink, 1, 1, State.none,
|
|
18
18
|
some(union([
|
|
19
19
|
url,
|
|
20
20
|
email,
|
|
@@ -3,29 +3,29 @@ import { BracketParser } from '../inline';
|
|
|
3
3
|
import { union, some, syntax, surround, lazy } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
5
|
import { str } from '../source';
|
|
6
|
-
import { Syntax } from '../context';
|
|
6
|
+
import { Syntax, State } from '../context';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
import { unshift, push } from 'spica/array';
|
|
9
9
|
|
|
10
10
|
const index = /^[0-9A-Za-z]+(?:(?:[.-]|, )[0-9A-Za-z]+)*/;
|
|
11
11
|
|
|
12
12
|
export const bracket: BracketParser = lazy(() => union([
|
|
13
|
-
surround(str('('), syntax(Syntax.none, 2, 1, str(index)), str(')')),
|
|
14
|
-
surround(str('('), syntax(Syntax.bracket, 2, 1, some(inline, ')', [[')', 2]])), str(')'), true,
|
|
13
|
+
surround(str('('), syntax(Syntax.none, 2, 1, State.none, str(index)), str(')')),
|
|
14
|
+
surround(str('('), syntax(Syntax.bracket, 2, 1, State.none, some(inline, ')', [[')', 2]])), str(')'), true,
|
|
15
15
|
([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
|
|
16
16
|
([as, bs = []], rest) => [unshift([''], unshift(as, bs)), rest]),
|
|
17
|
-
surround(str('('), syntax(Syntax.none, 2, 1, str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0))))), str(')')),
|
|
18
|
-
surround(str('('), syntax(Syntax.bracket, 2, 1, some(inline, ')', [[')', 2]])), str(')'), true,
|
|
17
|
+
surround(str('('), syntax(Syntax.none, 2, 1, State.none, str(new RegExp(index.source.replace(', ', '[,、]').replace(/[09AZaz.]|\-(?!\w)/g, c => c.trimStart() && String.fromCharCode(c.charCodeAt(0) + 0xFEE0))))), str(')')),
|
|
18
|
+
surround(str('('), syntax(Syntax.bracket, 2, 1, State.none, some(inline, ')', [[')', 2]])), str(')'), true,
|
|
19
19
|
([as, bs = [], cs], rest) => [[html('span', { class: 'paren' }, defrag(push(unshift(as, bs), cs)))], rest],
|
|
20
20
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
21
|
-
surround(str('['), syntax(Syntax.bracket, 2, 1, some(inline, ']', [[']', 2]])), str(']'), true,
|
|
21
|
+
surround(str('['), syntax(Syntax.bracket, 2, 1, State.none, some(inline, ']', [[']', 2]])), str(']'), true,
|
|
22
22
|
undefined,
|
|
23
23
|
([as, bs = []], rest) => [unshift([''], unshift(as, bs)), rest]),
|
|
24
|
-
surround(str('{'), syntax(Syntax.bracket, 2, 1, some(inline, '}', [['}', 2]])), str('}'), true,
|
|
24
|
+
surround(str('{'), syntax(Syntax.bracket, 2, 1, State.none, some(inline, '}', [['}', 2]])), str('}'), true,
|
|
25
25
|
undefined,
|
|
26
26
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
27
27
|
// Control media blinking in editing rather than control confusion of pairs of quote marks.
|
|
28
|
-
surround(str('"'), syntax(Syntax.quote, 8, 1, some(inline, '"', [['"', 8]])), str('"'), true,
|
|
28
|
+
surround(str('"'), syntax(Syntax.quote, 8, 1, State.none, some(inline, '"', [['"', 8]])), str('"'), true,
|
|
29
29
|
undefined,
|
|
30
30
|
([as, bs = []], rest) => [unshift(as, bs), rest]),
|
|
31
31
|
]));
|
|
@@ -2,12 +2,12 @@ import { CommentParser } from '../inline';
|
|
|
2
2
|
import { union, some, syntax, validate, surround, open, close, match, lazy } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { text, str } from '../source';
|
|
5
|
-
import { Syntax } from '../context';
|
|
5
|
+
import { Syntax, State } from '../context';
|
|
6
6
|
import { html, defrag } from 'typed-dom/dom';
|
|
7
7
|
import { memoize } from 'spica/memoize';
|
|
8
8
|
import { unshift, push } from 'spica/array';
|
|
9
9
|
|
|
10
|
-
export const comment: CommentParser = lazy(() => validate('[%', syntax(Syntax.none, 4, 1, match(
|
|
10
|
+
export const comment: CommentParser = lazy(() => validate('[%', syntax(Syntax.none, 4, 1, State.none, match(
|
|
11
11
|
/^\[(%+)\s/,
|
|
12
12
|
memoize(
|
|
13
13
|
([, fence]) =>
|
|
@@ -2,14 +2,14 @@ import { DeletionParser } from '../inline';
|
|
|
2
2
|
import { union, some, syntax, surround, open, lazy } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { str } from '../source';
|
|
5
|
-
import { Syntax } from '../context';
|
|
5
|
+
import { Syntax, State } from '../context';
|
|
6
6
|
import { blankWith } from '../visibility';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
import { unshift } from 'spica/array';
|
|
9
9
|
|
|
10
10
|
export const deletion: DeletionParser = lazy(() => surround(
|
|
11
11
|
str('~~'),
|
|
12
|
-
syntax(Syntax.none, 1, 1,
|
|
12
|
+
syntax(Syntax.none, 1, 1, State.none,
|
|
13
13
|
some(union([
|
|
14
14
|
some(inline, blankWith('\n', '~~')),
|
|
15
15
|
open('\n', some(inline, '~'), true),
|
|
@@ -4,14 +4,14 @@ import { inline } from '../inline';
|
|
|
4
4
|
import { emstrong } from './emstrong';
|
|
5
5
|
import { strong } from './strong';
|
|
6
6
|
import { str } from '../source';
|
|
7
|
-
import { Syntax } from '../context';
|
|
7
|
+
import { Syntax, State } from '../context';
|
|
8
8
|
import { startTight, blankWith } from '../visibility';
|
|
9
9
|
import { html, defrag } from 'typed-dom/dom';
|
|
10
10
|
import { unshift } from 'spica/array';
|
|
11
11
|
|
|
12
12
|
export const emphasis: EmphasisParser = lazy(() => surround(
|
|
13
13
|
str('*'),
|
|
14
|
-
syntax(Syntax.none, 1, 1,
|
|
14
|
+
syntax(Syntax.none, 1, 1, State.none,
|
|
15
15
|
startTight(some(union([
|
|
16
16
|
strong,
|
|
17
17
|
some(inline, blankWith('*')),
|
|
@@ -5,7 +5,7 @@ import { inline } from '../inline';
|
|
|
5
5
|
import { strong } from './strong';
|
|
6
6
|
import { emphasis } from './emphasis';
|
|
7
7
|
import { str } from '../source';
|
|
8
|
-
import { Syntax } from '../context';
|
|
8
|
+
import { Syntax, State } from '../context';
|
|
9
9
|
import { startTight, blankWith } from '../visibility';
|
|
10
10
|
import { html, defrag } from 'typed-dom/dom';
|
|
11
11
|
import { unshift } from 'spica/array';
|
|
@@ -29,7 +29,7 @@ const subemphasis: IntermediateParser<EmphasisParser> = lazy(() => some(union([
|
|
|
29
29
|
|
|
30
30
|
export const emstrong: EmStrongParser = lazy(() => surround(
|
|
31
31
|
str('***'),
|
|
32
|
-
syntax(Syntax.none, 1, 1,
|
|
32
|
+
syntax(Syntax.none, 1, 1, State.none,
|
|
33
33
|
startTight(some(union([
|
|
34
34
|
some(inline, blankWith('*')),
|
|
35
35
|
open(some(inline, '*'), inline),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { ExtensionParser } from '../../inline';
|
|
3
|
-
import { union, some, syntax, creation, precedence, constraint,
|
|
3
|
+
import { union, some, syntax, creation, precedence, constraint, validate, surround, open, lazy, fmap } from '../../../combinator';
|
|
4
4
|
import { inline } from '../../inline';
|
|
5
5
|
import { indexee, identity } from './indexee';
|
|
6
6
|
import { txt, str, stropt } from '../../source';
|
|
@@ -13,13 +13,12 @@ import IndexParser = ExtensionParser.IndexParser;
|
|
|
13
13
|
export const index: IndexParser = lazy(() => validate('[#', fmap(indexee(surround(
|
|
14
14
|
'[#',
|
|
15
15
|
constraint(State.index, false,
|
|
16
|
-
|
|
17
|
-
syntax(Syntax.index, 2, 1,
|
|
16
|
+
syntax(Syntax.index, 2, 1, State.linkable,
|
|
18
17
|
startTight(
|
|
19
18
|
open(stropt(/^\|?/), trimBlankEnd(some(union([
|
|
20
19
|
signature,
|
|
21
20
|
inline,
|
|
22
|
-
]), ']', [[/^\\?\n/, 9], [']', 2]])), true))))
|
|
21
|
+
]), ']', [[/^\\?\n/, 9], [']', 2]])), true)))),
|
|
23
22
|
']',
|
|
24
23
|
false,
|
|
25
24
|
([, ns], rest) => [[html('a', defrag(ns))], rest])),
|
|
@@ -2,7 +2,7 @@ import { ExtensionParser } from '../../inline';
|
|
|
2
2
|
import { union, some, syntax, validate, surround, lazy } from '../../../combinator';
|
|
3
3
|
import { inline } from '../../inline';
|
|
4
4
|
import { str } from '../../source';
|
|
5
|
-
import { Syntax } from '../../context';
|
|
5
|
+
import { Syntax, State } from '../../context';
|
|
6
6
|
import { startTight } from '../../visibility';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
import { unshift } from 'spica/array';
|
|
@@ -13,7 +13,7 @@ import { unshift } from 'spica/array';
|
|
|
13
13
|
|
|
14
14
|
export const placeholder: ExtensionParser.PlaceholderParser = lazy(() => validate(['[:', '[^'], surround(
|
|
15
15
|
str(/^\[[:^]/),
|
|
16
|
-
syntax(Syntax.none, 2, 1,
|
|
16
|
+
syntax(Syntax.none, 2, 1, State.none,
|
|
17
17
|
startTight(some(union([inline]), ']', [[/^\\?\n/, 9], [']', 2]]))),
|
|
18
18
|
str(']'), false,
|
|
19
19
|
([as, bs], rest) => [[
|
|
@@ -3,7 +3,7 @@ import { HTMLParser } from '../inline';
|
|
|
3
3
|
import { union, subsequence, some, syntax, validate, focus, surround, open, match, lazy } from '../../combinator';
|
|
4
4
|
import { inline } from '../inline';
|
|
5
5
|
import { str } from '../source';
|
|
6
|
-
import { Syntax } from '../context';
|
|
6
|
+
import { Syntax, State } from '../context';
|
|
7
7
|
import { isStartLooseNodes, blankWith } from '../visibility';
|
|
8
8
|
import { html as h, defrag } from 'typed-dom/dom';
|
|
9
9
|
import { memoize } from 'spica/memoize';
|
|
@@ -19,7 +19,7 @@ const attrspecs = {
|
|
|
19
19
|
Object.setPrototypeOf(attrspecs, null);
|
|
20
20
|
Object.values(attrspecs).forEach(o => Object.setPrototypeOf(o, null));
|
|
21
21
|
|
|
22
|
-
export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)/i, syntax(Syntax.none, 5, 1, union([
|
|
22
|
+
export const html: HTMLParser = lazy(() => validate('<', validate(/^<[a-z]+(?=[^\S\n]|>)/i, syntax(Syntax.none, 5, 1, State.none, union([
|
|
23
23
|
focus(
|
|
24
24
|
/^<wbr[^\S\n]*>/i,
|
|
25
25
|
() => [[h('wbr')], '']),
|
|
@@ -2,14 +2,14 @@ import { InsertionParser } from '../inline';
|
|
|
2
2
|
import { union, some, syntax, surround, open, lazy } from '../../combinator';
|
|
3
3
|
import { inline } from '../inline';
|
|
4
4
|
import { str } from '../source';
|
|
5
|
-
import { Syntax } from '../context';
|
|
5
|
+
import { Syntax, State } from '../context';
|
|
6
6
|
import { blankWith } from '../visibility';
|
|
7
7
|
import { html, defrag } from 'typed-dom/dom';
|
|
8
8
|
import { unshift } from 'spica/array';
|
|
9
9
|
|
|
10
10
|
export const insertion: InsertionParser = lazy(() => surround(
|
|
11
11
|
str('++'),
|
|
12
|
-
syntax(Syntax.none, 1, 1,
|
|
12
|
+
syntax(Syntax.none, 1, 1, State.none,
|
|
13
13
|
some(union([
|
|
14
14
|
some(inline, blankWith('\n', '++')),
|
|
15
15
|
open('\n', some(inline, '+'), true),
|