securemark 0.235.0 → 0.235.3
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/dist/securemark.js +197 -177
- package/markdown.d.ts +5 -2
- package/package-lock.json +36 -60
- package/package.json +3 -3
- package/src/combinator/control/manipulation/context.test.ts +4 -4
- package/src/combinator/control/manipulation/resource.ts +6 -3
- package/src/combinator/control/manipulation/surround.ts +3 -4
- package/src/combinator/data/parser/inits.ts +1 -1
- package/src/combinator/data/parser/sequence.ts +1 -1
- package/src/combinator/data/parser/some.ts +23 -25
- package/src/combinator/data/parser.ts +33 -10
- package/src/parser/api/bind.test.ts +3 -3
- package/src/parser/api/parse.test.ts +12 -5
- package/src/parser/block/blockquote.test.ts +1 -1
- package/src/parser/block/extension/aside.test.ts +1 -1
- package/src/parser/block/extension/example.test.ts +2 -2
- package/src/parser/block/extension/fig.test.ts +20 -20
- package/src/parser/block/extension/figure.test.ts +31 -28
- package/src/parser/block/extension/figure.ts +5 -3
- package/src/parser/block/extension/table.ts +6 -6
- package/src/parser/block/paragraph.test.ts +1 -1
- package/src/parser/block.ts +1 -2
- package/src/parser/inline/annotation.ts +3 -3
- package/src/parser/inline/bracket.test.ts +10 -10
- package/src/parser/inline/bracket.ts +5 -8
- package/src/parser/inline/deletion.test.ts +4 -1
- package/src/parser/inline/deletion.ts +7 -4
- package/src/parser/inline/emphasis.ts +3 -6
- package/src/parser/inline/emstrong.ts +7 -8
- package/src/parser/inline/html.test.ts +25 -17
- package/src/parser/inline/html.ts +39 -15
- package/src/parser/inline/htmlentity.test.ts +1 -1
- package/src/parser/inline/htmlentity.ts +17 -10
- package/src/parser/inline/insertion.test.ts +4 -1
- package/src/parser/inline/insertion.ts +7 -4
- package/src/parser/inline/link.test.ts +3 -0
- package/src/parser/inline/link.ts +6 -7
- package/src/parser/inline/mark.ts +3 -6
- package/src/parser/inline/media.test.ts +3 -0
- package/src/parser/inline/media.ts +1 -1
- package/src/parser/inline/reference.ts +6 -6
- package/src/parser/inline/ruby.ts +1 -1
- package/src/parser/inline/strong.test.ts +1 -1
- package/src/parser/inline/strong.ts +3 -6
- package/src/parser/inline.test.ts +2 -3
- package/src/parser/processor/figure.test.ts +28 -28
- package/src/parser/processor/figure.ts +1 -1
- package/src/parser/util.ts +43 -39
package/markdown.d.ts
CHANGED
|
@@ -852,7 +852,6 @@ export namespace MarkdownParser {
|
|
|
852
852
|
SourceParser.StrParser,
|
|
853
853
|
SourceParser.StrParser,
|
|
854
854
|
SourceParser.StrParser,
|
|
855
|
-
SourceParser.StrParser,
|
|
856
855
|
]> {
|
|
857
856
|
}
|
|
858
857
|
}
|
|
@@ -927,6 +926,7 @@ export namespace MarkdownParser {
|
|
|
927
926
|
HTMLParser.OpenTagParser,
|
|
928
927
|
HTMLParser.TagParser,
|
|
929
928
|
HTMLParser.TagParser,
|
|
929
|
+
HTMLParser.TagParser,
|
|
930
930
|
]> {
|
|
931
931
|
}
|
|
932
932
|
export namespace HTMLParser {
|
|
@@ -940,6 +940,7 @@ export namespace MarkdownParser {
|
|
|
940
940
|
Inline<'html/tag'>,
|
|
941
941
|
Parser<HTMLElement | string, Context, [
|
|
942
942
|
InlineParser,
|
|
943
|
+
InlineParser,
|
|
943
944
|
]> {
|
|
944
945
|
}
|
|
945
946
|
export namespace TagParser {
|
|
@@ -956,6 +957,7 @@ export namespace MarkdownParser {
|
|
|
956
957
|
Inline<'insertion'>,
|
|
957
958
|
Parser<HTMLElement | string, Context, [
|
|
958
959
|
InlineParser,
|
|
960
|
+
InlineParser,
|
|
959
961
|
]> {
|
|
960
962
|
}
|
|
961
963
|
export interface DeletionParser extends
|
|
@@ -963,6 +965,7 @@ export namespace MarkdownParser {
|
|
|
963
965
|
Inline<'deletion'>,
|
|
964
966
|
Parser<HTMLElement | string, Context, [
|
|
965
967
|
InlineParser,
|
|
968
|
+
InlineParser,
|
|
966
969
|
]> {
|
|
967
970
|
}
|
|
968
971
|
export interface MarkParser extends
|
|
@@ -1137,9 +1140,9 @@ export namespace MarkdownParser {
|
|
|
1137
1140
|
// ""
|
|
1138
1141
|
Inline<'bracket'>,
|
|
1139
1142
|
Parser<HTMLElement | string, Context, [
|
|
1140
|
-
SourceParser.StrParser,
|
|
1141
1143
|
SourceParser.StrParser,
|
|
1142
1144
|
InlineParser,
|
|
1145
|
+
SourceParser.StrParser,
|
|
1143
1146
|
InlineParser,
|
|
1144
1147
|
InlineParser,
|
|
1145
1148
|
InlineParser,
|
package/package-lock.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.235.
|
|
3
|
+
"version": "0.235.3",
|
|
4
4
|
"lockfileVersion": 1,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"dependencies": {
|
|
@@ -448,12 +448,6 @@
|
|
|
448
448
|
"which": "^2.0.2"
|
|
449
449
|
},
|
|
450
450
|
"dependencies": {
|
|
451
|
-
"lru-cache": {
|
|
452
|
-
"version": "7.7.2",
|
|
453
|
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.2.tgz",
|
|
454
|
-
"integrity": "sha512-WkdIOIF7HkfVHXxKLjhH6lyAxSFoSO5NZpZS9cH8Oe5rAI2ZDrVmIweDAZUHqIhl0zasQUprVVR8uv2yggYYvw==",
|
|
455
|
-
"dev": true
|
|
456
|
-
},
|
|
457
451
|
"mkdirp": {
|
|
458
452
|
"version": "1.0.4",
|
|
459
453
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
|
@@ -1800,12 +1794,6 @@
|
|
|
1800
1794
|
"unique-filename": "^1.1.1"
|
|
1801
1795
|
},
|
|
1802
1796
|
"dependencies": {
|
|
1803
|
-
"lru-cache": {
|
|
1804
|
-
"version": "7.7.2",
|
|
1805
|
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.2.tgz",
|
|
1806
|
-
"integrity": "sha512-WkdIOIF7HkfVHXxKLjhH6lyAxSFoSO5NZpZS9cH8Oe5rAI2ZDrVmIweDAZUHqIhl0zasQUprVVR8uv2yggYYvw==",
|
|
1807
|
-
"dev": true
|
|
1808
|
-
},
|
|
1809
1797
|
"mkdirp": {
|
|
1810
1798
|
"version": "1.0.4",
|
|
1811
1799
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
|
@@ -1927,9 +1915,9 @@
|
|
|
1927
1915
|
"dev": true
|
|
1928
1916
|
},
|
|
1929
1917
|
"caniuse-lite": {
|
|
1930
|
-
"version": "1.0.
|
|
1931
|
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.
|
|
1932
|
-
"integrity": "sha512-
|
|
1918
|
+
"version": "1.0.30001323",
|
|
1919
|
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001323.tgz",
|
|
1920
|
+
"integrity": "sha512-e4BF2RlCVELKx8+RmklSEIVub1TWrmdhvA5kEUueummz1XyySW0DVk+3x9HyhU9MuWTa2BhqLgEuEmUwASAdCA==",
|
|
1933
1921
|
"dev": true
|
|
1934
1922
|
},
|
|
1935
1923
|
"chalk": {
|
|
@@ -3033,9 +3021,9 @@
|
|
|
3033
3021
|
"dev": true
|
|
3034
3022
|
},
|
|
3035
3023
|
"electron-to-chromium": {
|
|
3036
|
-
"version": "1.4.
|
|
3037
|
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.
|
|
3038
|
-
"integrity": "sha512-
|
|
3024
|
+
"version": "1.4.103",
|
|
3025
|
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.103.tgz",
|
|
3026
|
+
"integrity": "sha512-c/uKWR1Z/W30Wy/sx3dkZoj4BijbXX85QKWu9jJfjho3LBAXNEGAEW3oWiGb+dotA6C6BzCTxL2/aLes7jlUeg==",
|
|
3039
3027
|
"dev": true
|
|
3040
3028
|
},
|
|
3041
3029
|
"elliptic": {
|
|
@@ -7069,13 +7057,10 @@
|
|
|
7069
7057
|
"dev": true
|
|
7070
7058
|
},
|
|
7071
7059
|
"lru-cache": {
|
|
7072
|
-
"version": "
|
|
7073
|
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-
|
|
7074
|
-
"integrity": "sha512-
|
|
7075
|
-
"dev": true
|
|
7076
|
-
"requires": {
|
|
7077
|
-
"yallist": "^4.0.0"
|
|
7078
|
-
}
|
|
7060
|
+
"version": "7.7.3",
|
|
7061
|
+
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.3.tgz",
|
|
7062
|
+
"integrity": "sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==",
|
|
7063
|
+
"dev": true
|
|
7079
7064
|
},
|
|
7080
7065
|
"make-dir": {
|
|
7081
7066
|
"version": "3.1.0",
|
|
@@ -7116,14 +7101,6 @@
|
|
|
7116
7101
|
"promise-retry": "^2.0.1",
|
|
7117
7102
|
"socks-proxy-agent": "^6.1.1",
|
|
7118
7103
|
"ssri": "^8.0.1"
|
|
7119
|
-
},
|
|
7120
|
-
"dependencies": {
|
|
7121
|
-
"lru-cache": {
|
|
7122
|
-
"version": "7.7.2",
|
|
7123
|
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.2.tgz",
|
|
7124
|
-
"integrity": "sha512-WkdIOIF7HkfVHXxKLjhH6lyAxSFoSO5NZpZS9cH8Oe5rAI2ZDrVmIweDAZUHqIhl0zasQUprVVR8uv2yggYYvw==",
|
|
7125
|
-
"dev": true
|
|
7126
|
-
}
|
|
7127
7104
|
}
|
|
7128
7105
|
},
|
|
7129
7106
|
"make-iterator": {
|
|
@@ -8007,9 +7984,9 @@
|
|
|
8007
7984
|
}
|
|
8008
7985
|
},
|
|
8009
7986
|
"npm-check-updates": {
|
|
8010
|
-
"version": "12.5.
|
|
8011
|
-
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.5.
|
|
8012
|
-
"integrity": "sha512-
|
|
7987
|
+
"version": "12.5.5",
|
|
7988
|
+
"resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.5.5.tgz",
|
|
7989
|
+
"integrity": "sha512-7LH6KN6F1fZMtY4zNYAQPpJU1ToxZ6sSCxk948vrLIz97aNqmPLSX72MrmbOWwpyBgLCPbFJWY/k3zE18pmxfw==",
|
|
8013
7990
|
"dev": true,
|
|
8014
7991
|
"requires": {
|
|
8015
7992
|
"chalk": "^4.1.2",
|
|
@@ -8021,7 +7998,7 @@
|
|
|
8021
7998
|
"fp-and-or": "^0.1.3",
|
|
8022
7999
|
"get-stdin": "^8.0.0",
|
|
8023
8000
|
"globby": "^11.0.4",
|
|
8024
|
-
"hosted-git-info": "^
|
|
8001
|
+
"hosted-git-info": "^5.0.0",
|
|
8025
8002
|
"json-parse-helpfulerror": "^1.0.3",
|
|
8026
8003
|
"jsonlines": "^0.1.1",
|
|
8027
8004
|
"libnpmconfig": "^1.2.1",
|
|
@@ -8063,12 +8040,12 @@
|
|
|
8063
8040
|
}
|
|
8064
8041
|
},
|
|
8065
8042
|
"hosted-git-info": {
|
|
8066
|
-
"version": "
|
|
8067
|
-
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-
|
|
8068
|
-
"integrity": "sha512-
|
|
8043
|
+
"version": "5.0.0",
|
|
8044
|
+
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-5.0.0.tgz",
|
|
8045
|
+
"integrity": "sha512-rRnjWu0Bxj+nIfUOkz0695C0H6tRrN5iYIzYejb0tDEefe2AekHu/U5Kn9pEie5vsJqpNQU02az7TGSH3qpz4Q==",
|
|
8069
8046
|
"dev": true,
|
|
8070
8047
|
"requires": {
|
|
8071
|
-
"lru-cache": "^
|
|
8048
|
+
"lru-cache": "^7.5.1"
|
|
8072
8049
|
}
|
|
8073
8050
|
},
|
|
8074
8051
|
"locate-path": {
|
|
@@ -8149,12 +8126,6 @@
|
|
|
8149
8126
|
"requires": {
|
|
8150
8127
|
"lru-cache": "^7.5.1"
|
|
8151
8128
|
}
|
|
8152
|
-
},
|
|
8153
|
-
"lru-cache": {
|
|
8154
|
-
"version": "7.7.2",
|
|
8155
|
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.2.tgz",
|
|
8156
|
-
"integrity": "sha512-WkdIOIF7HkfVHXxKLjhH6lyAxSFoSO5NZpZS9cH8Oe5rAI2ZDrVmIweDAZUHqIhl0zasQUprVVR8uv2yggYYvw==",
|
|
8157
|
-
"dev": true
|
|
8158
8129
|
}
|
|
8159
8130
|
}
|
|
8160
8131
|
},
|
|
@@ -9189,12 +9160,6 @@
|
|
|
9189
9160
|
"lru-cache": "^7.5.1"
|
|
9190
9161
|
}
|
|
9191
9162
|
},
|
|
9192
|
-
"lru-cache": {
|
|
9193
|
-
"version": "7.7.2",
|
|
9194
|
-
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.2.tgz",
|
|
9195
|
-
"integrity": "sha512-WkdIOIF7HkfVHXxKLjhH6lyAxSFoSO5NZpZS9cH8Oe5rAI2ZDrVmIweDAZUHqIhl0zasQUprVVR8uv2yggYYvw==",
|
|
9196
|
-
"dev": true
|
|
9197
|
-
},
|
|
9198
9163
|
"normalize-package-data": {
|
|
9199
9164
|
"version": "4.0.0",
|
|
9200
9165
|
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-4.0.0.tgz",
|
|
@@ -9787,6 +9752,17 @@
|
|
|
9787
9752
|
"dev": true,
|
|
9788
9753
|
"requires": {
|
|
9789
9754
|
"lru-cache": "^6.0.0"
|
|
9755
|
+
},
|
|
9756
|
+
"dependencies": {
|
|
9757
|
+
"lru-cache": {
|
|
9758
|
+
"version": "6.0.0",
|
|
9759
|
+
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
|
9760
|
+
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
|
9761
|
+
"dev": true,
|
|
9762
|
+
"requires": {
|
|
9763
|
+
"yallist": "^4.0.0"
|
|
9764
|
+
}
|
|
9765
|
+
}
|
|
9790
9766
|
}
|
|
9791
9767
|
},
|
|
9792
9768
|
"semver-diff": {
|
|
@@ -10940,9 +10916,9 @@
|
|
|
10940
10916
|
"dev": true
|
|
10941
10917
|
},
|
|
10942
10918
|
"typed-dom": {
|
|
10943
|
-
"version": "0.0.
|
|
10944
|
-
"resolved": "https://registry.npmjs.org/typed-dom/-/typed-dom-0.0.
|
|
10945
|
-
"integrity": "sha512-
|
|
10919
|
+
"version": "0.0.250",
|
|
10920
|
+
"resolved": "https://registry.npmjs.org/typed-dom/-/typed-dom-0.0.250.tgz",
|
|
10921
|
+
"integrity": "sha512-hjCpUI+E7St1bGVgyjYZww0ruhXLbPrcih6puElqXTIGHG9JHqd70p94RVilWup/mKoLnzeIdbFDYHLuloCfdQ==",
|
|
10946
10922
|
"dev": true
|
|
10947
10923
|
},
|
|
10948
10924
|
"typedarray": {
|
|
@@ -10961,9 +10937,9 @@
|
|
|
10961
10937
|
}
|
|
10962
10938
|
},
|
|
10963
10939
|
"typescript": {
|
|
10964
|
-
"version": "4.6.
|
|
10965
|
-
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.
|
|
10966
|
-
"integrity": "sha512-
|
|
10940
|
+
"version": "4.6.3",
|
|
10941
|
+
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz",
|
|
10942
|
+
"integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==",
|
|
10967
10943
|
"dev": true
|
|
10968
10944
|
},
|
|
10969
10945
|
"ua-parser-js": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "securemark",
|
|
3
|
-
"version": "0.235.
|
|
3
|
+
"version": "0.235.3",
|
|
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",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"semver": "^7.3.5",
|
|
64
64
|
"spica": "0.0.515",
|
|
65
65
|
"tsify": "^5.0.4",
|
|
66
|
-
"typed-dom": "0.0.
|
|
67
|
-
"typescript": "4.6.
|
|
66
|
+
"typed-dom": "0.0.250",
|
|
67
|
+
"typescript": "4.6.3",
|
|
68
68
|
"vinyl-buffer": "^1.0.1",
|
|
69
69
|
"vinyl-source-stream": "^2.0.0"
|
|
70
70
|
},
|
|
@@ -13,7 +13,7 @@ describe('Unit: combinator/context', () => {
|
|
|
13
13
|
(s, context) => [[context.resources?.budget ?? NaN], s.slice(1)]));
|
|
14
14
|
|
|
15
15
|
it('root', () => {
|
|
16
|
-
const base: Context = { resources: { budget: 3 } };
|
|
16
|
+
const base: Context = { resources: { budget: 3, recursion: 1 } };
|
|
17
17
|
const ctx: Context = {};
|
|
18
18
|
assert.deepStrictEqual(reset(base, parser)('123', ctx), [[3, 2, 1], '']);
|
|
19
19
|
assert(base.resources?.budget === 3);
|
|
@@ -24,8 +24,8 @@ describe('Unit: combinator/context', () => {
|
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
it('node', () => {
|
|
27
|
-
const base: Context = { resources: { budget: 3 } };
|
|
28
|
-
const ctx: Context = { resources: { budget: 1 } };
|
|
27
|
+
const base: Context = { resources: { budget: 3, recursion: 1 } };
|
|
28
|
+
const ctx: Context = { resources: { budget: 1, recursion: 1 } };
|
|
29
29
|
assert.deepStrictEqual(reset(base, parser)('1', ctx), [[1], '']);
|
|
30
30
|
assert(base.resources?.budget === 3);
|
|
31
31
|
assert(ctx.resources?.budget === 0);
|
|
@@ -41,7 +41,7 @@ describe('Unit: combinator/context', () => {
|
|
|
41
41
|
|
|
42
42
|
it('', () => {
|
|
43
43
|
const base: Context = { state: true };
|
|
44
|
-
const ctx: Context = { resources: { budget: 3 } };
|
|
44
|
+
const ctx: Context = { resources: { budget: 3, recursion: 1 } };
|
|
45
45
|
assert.deepStrictEqual(context(base, parser)('123', ctx), [[true, true, true], '']);
|
|
46
46
|
assert(ctx.resources?.budget === 0);
|
|
47
47
|
assert(ctx.state === undefined);
|
|
@@ -6,10 +6,13 @@ export function creator(cost: number | Parser<unknown>, parser?: Parser<unknown>
|
|
|
6
6
|
if (typeof cost === 'function') return creator(1, cost);
|
|
7
7
|
assert(cost > 0);
|
|
8
8
|
return (source, context) => {
|
|
9
|
-
const { resources } = context;
|
|
10
|
-
if (resources
|
|
9
|
+
const { resources = { budget: 1, recursion: 1 } } = context;
|
|
10
|
+
if (resources.budget <= 0) throw new Error('Too many creations.');
|
|
11
|
+
if (resources.recursion <= 0) throw new Error('Too much recursion.');
|
|
12
|
+
--resources.recursion;
|
|
11
13
|
const result = parser!(source, context);
|
|
12
|
-
|
|
14
|
+
++resources.recursion;
|
|
15
|
+
if (result) {
|
|
13
16
|
resources.budget -= cost;
|
|
14
17
|
}
|
|
15
18
|
return result;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
2
|
import { Parser, Result, Ctx, Tree, Context, SubParsers, SubTree, IntermediateParser, eval, exec, check } from '../../data/parser';
|
|
3
3
|
import { fmap } from '../monad/fmap';
|
|
4
|
-
import { creator } from './resource';
|
|
5
4
|
import { unshift, push } from 'spica/array';
|
|
6
5
|
|
|
7
6
|
export function surround<P extends Parser<unknown>, S = string>(
|
|
@@ -69,14 +68,14 @@ export function surround<T>(
|
|
|
69
68
|
function match(pattern: string | RegExp): (source: string, context: Ctx) => [never[], string] | undefined {
|
|
70
69
|
switch (typeof pattern) {
|
|
71
70
|
case 'string':
|
|
72
|
-
return
|
|
71
|
+
return source => source.slice(0, pattern.length) === pattern ? [[], source.slice(pattern.length)] : undefined;
|
|
73
72
|
case 'object':
|
|
74
|
-
return
|
|
73
|
+
return source => {
|
|
75
74
|
const m = source.match(pattern);
|
|
76
75
|
return m
|
|
77
76
|
? [[], source.slice(m[0].length)]
|
|
78
77
|
: undefined;
|
|
79
|
-
}
|
|
78
|
+
};
|
|
80
79
|
}
|
|
81
80
|
}
|
|
82
81
|
|
|
@@ -14,7 +14,7 @@ export function inits<T, D extends Parser<T>[]>(parsers: D): Parser<T, Ctx, D> {
|
|
|
14
14
|
const result = parsers[i](rest, context);
|
|
15
15
|
assert(check(rest, result));
|
|
16
16
|
if (!result) break;
|
|
17
|
-
assert(!context?.delimiters?.
|
|
17
|
+
assert(!context?.delimiters?.match(rest));
|
|
18
18
|
nodes = nodes
|
|
19
19
|
? push(nodes, eval(result))
|
|
20
20
|
: eval(result);
|
|
@@ -14,7 +14,7 @@ export function sequence<T, D extends Parser<T>[]>(parsers: D): Parser<T, Ctx, D
|
|
|
14
14
|
const result = parsers[i](rest, context);
|
|
15
15
|
assert(check(rest, result));
|
|
16
16
|
if (!result) return;
|
|
17
|
-
assert(!context?.delimiters?.
|
|
17
|
+
assert(!context?.delimiters?.match(rest));
|
|
18
18
|
nodes = nodes
|
|
19
19
|
? push(nodes, eval(result))
|
|
20
20
|
: eval(result);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { undefined } from 'spica/global';
|
|
2
|
-
import { Parser, eval, exec, check } from '../parser';
|
|
2
|
+
import { Parser, Delimiters, eval, exec, check } from '../parser';
|
|
3
3
|
import { memoize, reduce } from 'spica/memoize';
|
|
4
4
|
import { push } from 'spica/array';
|
|
5
5
|
|
|
@@ -13,19 +13,18 @@ const signature = (pattern: string | RegExp | undefined): string => {
|
|
|
13
13
|
return `r/${pattern.source}/${pattern.flags}`;
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
signature));
|
|
16
|
+
const matcher = memoize(
|
|
17
|
+
(pattern: string | RegExp | undefined): (source: string) => boolean => {
|
|
18
|
+
switch (typeof pattern) {
|
|
19
|
+
case 'undefined':
|
|
20
|
+
return () => false;
|
|
21
|
+
case 'string':
|
|
22
|
+
return source => source.slice(0, pattern.length) === pattern;
|
|
23
|
+
case 'object':
|
|
24
|
+
return reduce(source => pattern.test(source));
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
signature);
|
|
29
28
|
|
|
30
29
|
export function some<P extends Parser<unknown>>(parser: P, until?: string | RegExp | number, deep?: string | RegExp, limit?: number): P;
|
|
31
30
|
export function some<T>(parser: Parser<T>, until?: string | RegExp | number, deep?: string | RegExp, limit = -1): Parser<T> {
|
|
@@ -34,25 +33,24 @@ export function some<T>(parser: Parser<T>, until?: string | RegExp | number, dee
|
|
|
34
33
|
assert(deep instanceof RegExp ? !deep.flags.match(/[gmy]/) && deep.source.startsWith('^') : true);
|
|
35
34
|
if (typeof until === 'number') return some(parser, undefined, deep, until);
|
|
36
35
|
const match = matcher(until);
|
|
37
|
-
const
|
|
38
|
-
|
|
36
|
+
const delimiter = {
|
|
37
|
+
signature: signature(deep),
|
|
38
|
+
matcher: matcher(deep),
|
|
39
|
+
} as const;
|
|
39
40
|
return (source, context) => {
|
|
40
41
|
if (source === '') return;
|
|
41
42
|
let rest = source;
|
|
42
43
|
let nodes: T[] | undefined;
|
|
43
|
-
if (
|
|
44
|
+
if (deep && context) {
|
|
44
45
|
// bracket > annotation > bracket > reference > bracket > link > media | bracket
|
|
45
46
|
// bracket > annotation > bracket > reference > bracket > index > bracket
|
|
46
|
-
context.delimiters ??=
|
|
47
|
-
context.delimiters.
|
|
48
|
-
context.delimiters.matchers[sig] ??= delim;
|
|
49
|
-
assert(context.delimiters.matchers[sig] === delim);
|
|
47
|
+
context.delimiters ??= new Delimiters();
|
|
48
|
+
context.delimiters.push(delimiter);
|
|
50
49
|
}
|
|
51
|
-
const { stack, matchers } = context.delimiters ?? {};
|
|
52
50
|
while (true) {
|
|
53
51
|
if (rest === '') break;
|
|
54
52
|
if (match(rest)) break;
|
|
55
|
-
if (
|
|
53
|
+
if (context.delimiters?.match(rest)) break;
|
|
56
54
|
const result = parser(rest, context);
|
|
57
55
|
assert.doesNotThrow(() => limit < 0 && check(rest, result));
|
|
58
56
|
if (!result) break;
|
|
@@ -62,8 +60,8 @@ export function some<T>(parser: Parser<T>, until?: string | RegExp | number, dee
|
|
|
62
60
|
rest = exec(result);
|
|
63
61
|
if (limit >= 0 && source.length - rest.length > limit) break;
|
|
64
62
|
}
|
|
65
|
-
if (
|
|
66
|
-
|
|
63
|
+
if (deep && context.delimiters) {
|
|
64
|
+
context.delimiters.pop();
|
|
67
65
|
}
|
|
68
66
|
assert(rest.length <= source.length);
|
|
69
67
|
return nodes && rest.length < source.length
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
export interface Ctx {
|
|
2
|
-
readonly resources?: {
|
|
3
|
-
budget: number;
|
|
4
|
-
};
|
|
5
|
-
delimiters?: {
|
|
6
|
-
readonly stack: string[];
|
|
7
|
-
readonly matchers: Record<string, (source: string) => boolean>;
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
|
|
11
1
|
export type Parser<T, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
|
|
12
2
|
= (source: string, context: C) => Result<T, C, D>;
|
|
13
3
|
export type Result<T, C extends Ctx = Ctx, D extends Parser<unknown, C>[] = any>
|
|
14
4
|
= readonly [T[], string, C, D]
|
|
15
5
|
| readonly [T[], string]
|
|
16
6
|
| undefined;
|
|
7
|
+
export interface Ctx {
|
|
8
|
+
readonly resources?: {
|
|
9
|
+
budget: number;
|
|
10
|
+
recursion: number;
|
|
11
|
+
};
|
|
12
|
+
delimiters?: Delimiters;
|
|
13
|
+
}
|
|
17
14
|
export type Tree<P extends Parser<unknown>> = P extends Parser<infer T> ? T : never;
|
|
18
15
|
export type SubParsers<P extends Parser<unknown>> = P extends Parser<unknown, any, infer D> ? D : never;
|
|
19
16
|
export type Context<P extends Parser<unknown>> = P extends Parser<unknown, infer C> ? C : never;
|
|
@@ -22,6 +19,32 @@ export type IntermediateParser<P extends Parser<unknown>> = Parser<SubTree<P>, C
|
|
|
22
19
|
type ExtractSubTree<D extends Parser<unknown>[]> = ExtractSubParser<D> extends infer T ? T extends Parser<infer U> ? U : never : never;
|
|
23
20
|
type ExtractSubParser<D extends Parser<unknown>[]> = D extends (infer P)[] ? P extends Parser<unknown> ? P : never : never;
|
|
24
21
|
|
|
22
|
+
export class Delimiters {
|
|
23
|
+
private readonly stack: string[] = [];
|
|
24
|
+
private readonly matchers: Record<string, (source: string) => boolean> = {};
|
|
25
|
+
public push(delimiter: { readonly signature: string; readonly matcher: (source: string) => boolean; }): void {
|
|
26
|
+
const { signature, matcher } = delimiter;
|
|
27
|
+
this.stack.push(signature);
|
|
28
|
+
this.matchers[signature] ??= matcher;
|
|
29
|
+
assert(this.matchers[signature] === matcher);
|
|
30
|
+
}
|
|
31
|
+
public pop(): void {
|
|
32
|
+
assert(this.stack.length > 0);
|
|
33
|
+
this.stack.pop();
|
|
34
|
+
}
|
|
35
|
+
public match(source: string): boolean {
|
|
36
|
+
const { stack, matchers } = this;
|
|
37
|
+
const log = {};
|
|
38
|
+
for (let i = 0; i < stack.length; ++i) {
|
|
39
|
+
const sig = stack[i];
|
|
40
|
+
if (sig in log) continue;
|
|
41
|
+
if (matchers[sig](source)) return true;
|
|
42
|
+
log[sig] = false;
|
|
43
|
+
}
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
25
48
|
export { eval_ as eval };
|
|
26
49
|
function eval_<T>(result: NonNullable<Result<T>>, default_?: T[]): T[];
|
|
27
50
|
function eval_<T>(result: Result<T>, default_: T[]): T[];
|
|
@@ -34,7 +34,7 @@ describe('Unit: parser/api/bind', () => {
|
|
|
34
34
|
assert.deepStrictEqual(
|
|
35
35
|
inspect(iter),
|
|
36
36
|
[
|
|
37
|
-
'<h1 class="error"
|
|
37
|
+
'<h1 class="error">Error: Too large input over 1,000,000 bytes.</h1>',
|
|
38
38
|
`<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
|
|
39
39
|
]);
|
|
40
40
|
});
|
|
@@ -46,9 +46,9 @@ describe('Unit: parser/api/bind', () => {
|
|
|
46
46
|
assert.deepStrictEqual(
|
|
47
47
|
inspect(iter, 3),
|
|
48
48
|
[
|
|
49
|
-
'<h1 class="error"
|
|
49
|
+
'<h1 class="error">Error: Too large segment over 100,000 bytes.</h1>',
|
|
50
50
|
`<pre class="error" translate="no">${'\n'.repeat(997)}...</pre>`,
|
|
51
|
-
'<h1 class="error"
|
|
51
|
+
'<h1 class="error">Error: Too large segment over 100,000 bytes.</h1>',
|
|
52
52
|
]);
|
|
53
53
|
});
|
|
54
54
|
|
|
@@ -118,7 +118,7 @@ describe('Unit: parser/api/parse', () => {
|
|
|
118
118
|
'<p><a href="https://source/hashtags/a" target="_blank" class="hashtag">#a</a></p>',
|
|
119
119
|
'<p><a href="https://domain/hashtags/a" target="_blank" class="hashtag">#domain/a</a></p>',
|
|
120
120
|
'<p><a class="index" href="#index:a">a</a></p>',
|
|
121
|
-
'<figure data-label="$-a" data-group="$" data-number="1" id="label:$-a"><div
|
|
121
|
+
'<figure data-label="$-a" data-group="$" data-number="1" id="label:$-a"><div><div class="math" translate="no">$$\n$$</div></div><figcaption><span class="figindex">(1)</span></figcaption></figure>',
|
|
122
122
|
'<p><a class="label" data-label="$-a" href="#label:$-a">(1)</a></p>',
|
|
123
123
|
'<p><sup class="annotation" id="annotation:ref:1" title="a"><span hidden="">a</span><a href="#annotation:def:1">*1</a></sup></p>',
|
|
124
124
|
'<p><a href="https://source/x/a" target="_blank">a</a></p>',
|
|
@@ -201,7 +201,7 @@ describe('Unit: parser/api/parse', () => {
|
|
|
201
201
|
assert.deepStrictEqual(
|
|
202
202
|
[...parse('$-a\n$$\n$$\n\n(($-a[[b]][[c*d*]]))', { footnotes }).children].map(el => el.outerHTML),
|
|
203
203
|
[
|
|
204
|
-
'<figure data-label="$-a" data-group="$" data-number="1" id="label:$-a"><div
|
|
204
|
+
'<figure data-label="$-a" data-group="$" data-number="1" id="label:$-a"><div><div class="math" translate="no">$$\n$$</div></div><figcaption><span class="figindex">(1)</span></figcaption></figure>',
|
|
205
205
|
'<p><sup class="annotation" id="annotation:ref:1" title="(1)[1][2]"><span hidden=""><a class="label" data-label="$-a" href="#label:$-a">(1)</a><sup class="reference" id="reference:ref:1" title="b"><span hidden="">b</span><a href="#reference:def:1">[1]</a></sup><sup class="reference" id="reference:ref:2" title="cd"><span hidden="">c<em>d</em></span><a href="#reference:def:2">[2]</a></sup></span><a href="#annotation:def:1">*1</a></sup></p>',
|
|
206
206
|
]);
|
|
207
207
|
assert.deepStrictEqual(
|
|
@@ -218,10 +218,17 @@ describe('Unit: parser/api/parse', () => {
|
|
|
218
218
|
['<p>a<span class="linebreak"> </span>b</p>']);
|
|
219
219
|
});
|
|
220
220
|
|
|
221
|
-
it('
|
|
221
|
+
it('recursion', () => {
|
|
222
222
|
assert.deepStrictEqual(
|
|
223
|
-
[...parse(
|
|
224
|
-
['
|
|
223
|
+
[...parse('('.repeat(199)).children].map(el => el.outerHTML),
|
|
224
|
+
[`<p>${'('.repeat(199)}</p>`]);
|
|
225
|
+
assert.deepStrictEqual(
|
|
226
|
+
[...parse('('.repeat(200) + '\n\na').children].map(el => el.outerHTML.replace(/:\w+/, ':rnd')),
|
|
227
|
+
[
|
|
228
|
+
'<h1 id="error:rnd" class="error">Error: Too much recursion.</h1>',
|
|
229
|
+
`<pre class="error" translate="no">${'('.repeat(200)}\n</pre>`,
|
|
230
|
+
'<p>a</p>',
|
|
231
|
+
]);
|
|
225
232
|
});
|
|
226
233
|
|
|
227
234
|
});
|
|
@@ -95,7 +95,7 @@ describe('Unit: parser/block/blockquote', () => {
|
|
|
95
95
|
assert.deepStrictEqual(inspect(parser('!>\n> a')), [['<blockquote><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
|
|
96
96
|
assert.deepStrictEqual(inspect(parser('!>> ## a\n> ## a')), [['<blockquote><blockquote><section><h2>a</h2><ol class="annotations"></ol><ol class="references"></ol></section></blockquote><section><h2>a</h2><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
|
|
97
97
|
assert.deepStrictEqual(inspect(parser('!>> ~ a\n> ~ a')), [['<blockquote><blockquote><section><dl><dt>a</dt><dd></dd></dl><ol class="annotations"></ol><ol class="references"></ol></section></blockquote><section><dl><dt>a</dt><dd></dd></dl><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
|
|
98
|
-
assert.deepStrictEqual(inspect(parser('!>> ~~~figure $fig-a\n>> > \n>>\n~~~\n> ~~~figure $fig-a\n> > \n>\n[#a]\n~~~')), [['<blockquote><blockquote><section><figure data-label="fig-a" data-group="fig" data-number="1"><div
|
|
98
|
+
assert.deepStrictEqual(inspect(parser('!>> ~~~figure $fig-a\n>> > \n>>\n~~~\n> ~~~figure $fig-a\n> > \n>\n[#a]\n~~~')), [['<blockquote><blockquote><section><figure data-label="fig-a" data-group="fig" data-number="1"><div><blockquote></blockquote></div><figcaption><span class="figindex">Fig. 1. </span></figcaption></figure><ol class="annotations"></ol><ol class="references"></ol></section></blockquote><section><figure data-label="fig-a" data-group="fig" data-number="1"><div><blockquote></blockquote></div><figcaption><span class="figindex">Fig. 1. </span><a class="index">a</a></figcaption></figure><ol class="annotations"></ol><ol class="references"></ol></section></blockquote>'], '']);
|
|
99
99
|
assert.deepStrictEqual(inspect(parser('!>> ((a))\n> ((a))')), [['<blockquote><blockquote><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup></p><ol class="annotations"><li>a<sup><a>^1</a></sup></li></ol><ol class="references"></ol></section></blockquote><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup></p><ol class="annotations"><li>a<sup><a>^1</a></sup></li></ol><ol class="references"></ol></section></blockquote>'], '']);
|
|
100
100
|
});
|
|
101
101
|
|
|
@@ -16,7 +16,7 @@ describe('Unit: parser/block/extension/aside', () => {
|
|
|
16
16
|
it('valid', () => {
|
|
17
17
|
assert.deepStrictEqual(inspect(parser('~~~aside\n# 0\n~~~')), [['<aside id="index:0" class="aside"><h1>0</h1><ol class="annotations"></ol><ol class="references"></ol></aside>'], '']);
|
|
18
18
|
assert.deepStrictEqual(inspect(parser('~~~aside\n## 0\n~~~')), [['<aside id="index:0" class="aside"><h2>0</h2><ol class="annotations"></ol><ol class="references"></ol></aside>'], '']);
|
|
19
|
-
assert.deepStrictEqual(inspect(parser('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$fig-a\n> \n~~~')), [['<aside id="index:0" class="aside"><h1>0</h1><figure data-label="$-0.0" data-group="$" hidden="" data-number="0.0"></figure><h2>1</h2><figure data-label="fig-a" data-group="fig" data-number="1.1"><div
|
|
19
|
+
assert.deepStrictEqual(inspect(parser('~~~aside\n# 0\n\n$-0.0\n\n## 1\n\n$fig-a\n> \n~~~')), [['<aside id="index:0" class="aside"><h1>0</h1><figure data-label="$-0.0" data-group="$" hidden="" data-number="0.0"></figure><h2>1</h2><figure data-label="fig-a" data-group="fig" data-number="1.1"><div><blockquote></blockquote></div><figcaption><span class="figindex">Fig. 1.1. </span></figcaption></figure><ol class="annotations"></ol><ol class="references"></ol></aside>'], '']);
|
|
20
20
|
});
|
|
21
21
|
|
|
22
22
|
});
|
|
@@ -19,8 +19,8 @@ describe('Unit: parser/block/extension/example', () => {
|
|
|
19
19
|
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no"></pre><hr><section><ol class="annotations"></ol><ol class="references"></ol></section></aside>'], '']);
|
|
20
20
|
assert.deepStrictEqual(inspect(parser('~~~example/markdown\na\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">a</pre><hr><section><p>a</p><ol class="annotations"></ol><ol class="references"></ol></section></aside>'], '']);
|
|
21
21
|
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n*a\nb*\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">*a\nb*</pre><hr><section><p><em>a<br>b</em></p><ol class="annotations"></ol><ol class="references"></ol></section></aside>'], '']);
|
|
22
|
-
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n$fig-a\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">$fig-a\n!https://host</pre><hr><section><figure data-label="fig-a" data-group="fig" data-number="1"><div
|
|
23
|
-
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n[$fig-a]\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">[$fig-a]\n!https://host</pre><hr><section><figure data-label="fig-a" data-group="fig" data-number="1"><div
|
|
22
|
+
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n$fig-a\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">$fig-a\n!https://host</pre><hr><section><figure data-label="fig-a" data-group="fig" data-number="1"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex">Fig. 1. </span></figcaption></figure><ol class="annotations"></ol><ol class="references"></ol></section></aside>'], '']);
|
|
23
|
+
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n[$fig-a]\n!https://host\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">[$fig-a]\n!https://host</pre><hr><section><figure data-label="fig-a" data-group="fig" data-number="1"><div><a href="https://host" target="_blank"><img class="media" data-src="https://host" alt=""></a></div><figcaption><span class="figindex">Fig. 1. </span></figcaption></figure><ol class="annotations"></ol><ol class="references"></ol></section></aside>'], '']);
|
|
24
24
|
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n## a\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">## a</pre><hr><section><h2>a</h2><ol class="annotations"></ol><ol class="references"></ol></section></aside>'], '']);
|
|
25
25
|
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n~ a\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">~ a</pre><hr><section><dl><dt>a</dt><dd></dd></dl><ol class="annotations"></ol><ol class="references"></ol></section></aside>'], '']);
|
|
26
26
|
assert.deepStrictEqual(inspect(parser('~~~example/markdown\n((a))[[b]]\n~~~')), [['<aside class="example" data-type="markdown"><pre translate="no">((a))[[b]]</pre><hr><section><p><sup class="annotation disabled" title="a"><span hidden="">a</span><a>*1</a></sup><sup class="reference disabled" title="b"><span hidden="">b</span><a>[1]</a></sup></p><ol class="annotations"><li>a<sup><a>^1</a></sup></li></ol><ol class="references"><li>b<sup><a>^1</a></sup></li></ol></section></aside>'], '']);
|