@diplodoc/transform 4.70.0 → 4.70.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/dist/css/_yfm-only.css.map +1 -1
- package/dist/css/_yfm-only.min.css.map +1 -1
- package/dist/css/base.css.map +1 -1
- package/dist/css/base.min.css.map +1 -1
- package/dist/css/print.css.map +1 -1
- package/dist/css/yfm.css.map +1 -1
- package/dist/css/yfm.min.css.map +1 -1
- package/lib/plugins/term/index.js +106 -2
- package/lib/plugins/term/index.js.map +1 -1
- package/package.json +1 -1
- package/src/transform/plugins/term/index.ts +138 -2
|
@@ -122,6 +122,120 @@ function termInlineRule(state: StateInline, silent: boolean): boolean {
|
|
|
122
122
|
return true;
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
+
const RAW_CODE_TOKEN_TYPES = new Set(['fence', 'code_block', 'yfm_page-constructor']);
|
|
126
|
+
|
|
127
|
+
function collectRawTermMatches(content: string, reg: RegExp, out: Set<string>) {
|
|
128
|
+
reg.lastIndex = 0;
|
|
129
|
+
let match: RegExpExecArray | null;
|
|
130
|
+
|
|
131
|
+
while ((match = reg.exec(content))) {
|
|
132
|
+
out.add(':' + match[3]);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function collectTermsFromRawContent(tokens: Token[], reg: RegExp, out: Set<string>) {
|
|
137
|
+
for (const token of tokens) {
|
|
138
|
+
if (RAW_CODE_TOKEN_TYPES.has(token.type) && token.content) {
|
|
139
|
+
collectRawTermMatches(token.content, reg, out);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (token.type === 'inline' && token.children) {
|
|
143
|
+
for (const child of token.children) {
|
|
144
|
+
if (child.type === 'code_inline' && child.content) {
|
|
145
|
+
collectRawTermMatches(child.content, reg, out);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function collectTermKeysFromInlineChildren(children: Token[], out: Set<string>) {
|
|
153
|
+
for (const child of children) {
|
|
154
|
+
if (child.type === 'term_open') {
|
|
155
|
+
const key = child.attrGet('term-key');
|
|
156
|
+
|
|
157
|
+
if (key) {
|
|
158
|
+
out.add(key);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function collectTermsFromContent(tokens: Token[], out: Set<string>) {
|
|
165
|
+
let inDfn = false;
|
|
166
|
+
|
|
167
|
+
for (const token of tokens) {
|
|
168
|
+
if (token.type === 'dfn_open') {
|
|
169
|
+
inDfn = true;
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (token.type === 'dfn_close') {
|
|
174
|
+
inDfn = false;
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (!inDfn && token.type === 'inline' && token.children) {
|
|
179
|
+
collectTermKeysFromInlineChildren(token.children, out);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function collectTermsFromDfns(tokens: Token[], out: Set<string>, referencedDfns: Set<string>) {
|
|
185
|
+
let inReferencedDfn = false;
|
|
186
|
+
|
|
187
|
+
for (const token of tokens) {
|
|
188
|
+
if (token.type === 'dfn_open') {
|
|
189
|
+
const key = (token.attrGet('id') || '').replace(/_element$/, '');
|
|
190
|
+
|
|
191
|
+
inReferencedDfn = Boolean(key) && referencedDfns.has(key);
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (token.type === 'dfn_close') {
|
|
196
|
+
inReferencedDfn = false;
|
|
197
|
+
continue;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
if (inReferencedDfn && token.type === 'inline' && token.children) {
|
|
201
|
+
collectTermKeysFromInlineChildren(token.children, out);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function findDfnCloseIdx(tokens: Token[], from: number) {
|
|
207
|
+
let endIdx = from;
|
|
208
|
+
|
|
209
|
+
while (endIdx < tokens.length && tokens[endIdx].type !== 'dfn_close') {
|
|
210
|
+
endIdx++;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return endIdx;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function removeUnreferencedDefinitions(tokens: Token[], referencedTerms: Set<string>) {
|
|
217
|
+
let idx = 0;
|
|
218
|
+
|
|
219
|
+
while (idx < tokens.length) {
|
|
220
|
+
const tok = tokens[idx];
|
|
221
|
+
|
|
222
|
+
if (tok.type === 'dfn_open') {
|
|
223
|
+
const termKey = (tok.attrGet('id') || '').replace(/_element$/, '');
|
|
224
|
+
|
|
225
|
+
if (termKey && !referencedTerms.has(termKey)) {
|
|
226
|
+
const endIdx = findDfnCloseIdx(tokens, idx + 1);
|
|
227
|
+
|
|
228
|
+
if (endIdx < tokens.length) {
|
|
229
|
+
tokens.splice(idx, endIdx - idx + 1);
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
idx++;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
125
239
|
const term: MarkdownItPluginCb = (md, options) => {
|
|
126
240
|
const escapeRE = md.utils.escapeRE;
|
|
127
241
|
const arrayReplaceAt = md.utils.arrayReplaceAt;
|
|
@@ -150,13 +264,27 @@ const term: MarkdownItPluginCb = (md, options) => {
|
|
|
150
264
|
return;
|
|
151
265
|
}
|
|
152
266
|
|
|
153
|
-
const
|
|
154
|
-
|
|
267
|
+
const termKeys = Object.keys(state.env.terms);
|
|
268
|
+
|
|
269
|
+
if (!termKeys.length) {
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const referencedTerms = new Set<string>();
|
|
274
|
+
|
|
275
|
+
const regTerms = termKeys
|
|
276
|
+
.map((el) => el.slice(1))
|
|
155
277
|
.map(escapeRE)
|
|
156
278
|
.join('|');
|
|
157
279
|
const regText = '\\[([^\\[]+)\\](\\(\\*(' + regTerms + ')\\))';
|
|
158
280
|
const reg = new RegExp(regText, 'g');
|
|
159
281
|
|
|
282
|
+
collectTermsFromRawContent(blockTokens, reg, referencedTerms);
|
|
283
|
+
collectTermsFromContent(blockTokens, referencedTerms);
|
|
284
|
+
|
|
285
|
+
// Collect terms transitively referenced inside definitions of referenced terms.
|
|
286
|
+
collectTermsFromDfns(blockTokens, referencedTerms, referencedTerms);
|
|
287
|
+
|
|
160
288
|
for (j = 0, l = blockTokens.length; j < l; j++) {
|
|
161
289
|
if (blockTokens[j].type === 'heading_open') {
|
|
162
290
|
while (blockTokens[j].type !== 'heading_close') {
|
|
@@ -210,6 +338,8 @@ const term: MarkdownItPluginCb = (md, options) => {
|
|
|
210
338
|
const termTitle = termMatch[1];
|
|
211
339
|
const termKey = termMatch[3];
|
|
212
340
|
|
|
341
|
+
referencedTerms.add(':' + termKey);
|
|
342
|
+
|
|
213
343
|
if (termMatch.index > 0 || termMatch[1].length > 0) {
|
|
214
344
|
token = new state.Token('text', '', 0);
|
|
215
345
|
token.content = text.slice(pos, termMatch.index);
|
|
@@ -244,6 +374,12 @@ const term: MarkdownItPluginCb = (md, options) => {
|
|
|
244
374
|
blockTokens[j].children = tokens = arrayReplaceAt(tokens, i, nodes);
|
|
245
375
|
}
|
|
246
376
|
}
|
|
377
|
+
|
|
378
|
+
// Remove definitions without any reference on the page
|
|
379
|
+
// Skip during linting to allow lint rules to check term definitions
|
|
380
|
+
if (!isLintRun) {
|
|
381
|
+
removeUnreferencedDefinitions(state.tokens, referencedTerms);
|
|
382
|
+
}
|
|
247
383
|
}
|
|
248
384
|
|
|
249
385
|
md.block.ruler.before('reference', 'termDefinitions', termDefinitions(md, options), {
|