reffy 11.0.2 → 11.0.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reffy",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.4",
|
|
4
4
|
"description": "W3C/WHATWG spec dependencies exploration companion. Features a short set of tools to study spec references as well as WebIDL term definitions and references found in W3C specifications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -46,9 +46,9 @@
|
|
|
46
46
|
"chai": "4.3.7",
|
|
47
47
|
"mocha": "10.1.0",
|
|
48
48
|
"nock": "13.2.9",
|
|
49
|
-
"respec": "32.
|
|
49
|
+
"respec": "32.4.0",
|
|
50
50
|
"respec-hljs": "2.1.1",
|
|
51
|
-
"rollup": "3.5.
|
|
51
|
+
"rollup": "3.5.1"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"test": "mocha --recursive tests/"
|
|
@@ -240,21 +240,14 @@ export default function () {
|
|
|
240
240
|
// <image> again:
|
|
241
241
|
// https://drafts.csswg.org/css-images-4/#typedef-image
|
|
242
242
|
const isAncestorOf = (ancestor, child) => {
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
res = parents[c]
|
|
248
|
-
?.filter(p => !seen.includes(p))
|
|
249
|
-
?.find(p => checkChild(ancestor, p));
|
|
250
|
-
}
|
|
251
|
-
seen = seen.concat(parents[c]);
|
|
252
|
-
return res;
|
|
253
|
-
}
|
|
254
|
-
return checkChild(child);
|
|
243
|
+
const checkChild = (c, depth) =>
|
|
244
|
+
(depth++ < 10) &&
|
|
245
|
+
(c === ancestor || parents[c]?.find(p => checkChild(p, depth)));
|
|
246
|
+
return checkChild(child, 0);
|
|
255
247
|
};
|
|
256
|
-
const isDeepestConstruct = (name, list) =>
|
|
257
|
-
list.every(p => p === name || !isAncestorOf(name, p));
|
|
248
|
+
const isDeepestConstruct = (name, list) => {
|
|
249
|
+
return list.every(p => p === name || !isAncestorOf(name, p));
|
|
250
|
+
}
|
|
258
251
|
|
|
259
252
|
// We may now associate values with dfns
|
|
260
253
|
for (const value of values) {
|
|
@@ -544,6 +537,40 @@ const parseProductionRule = (rule, { res = [], pureSyntax = false }) => {
|
|
|
544
537
|
};
|
|
545
538
|
|
|
546
539
|
|
|
540
|
+
/**
|
|
541
|
+
* Extract the definition name. If multiple linking texts are possible, the
|
|
542
|
+
* function will select the one that is a "syntax" definition. For instance, it
|
|
543
|
+
* will pick up "<identifier>" for "identifiers|<identifier>" in CSS 2:
|
|
544
|
+
* https://drafts.csswg.org/css2/#value-def-identifier
|
|
545
|
+
*
|
|
546
|
+
* The function throws if it cannot extract an obvious name from the definition.
|
|
547
|
+
* We may want to be smarter about that in the future, but this should really
|
|
548
|
+
* never happen in practice (the above "identifiers" example is the only one
|
|
549
|
+
* CSS value definition so far to have multiple linking texts)
|
|
550
|
+
*/
|
|
551
|
+
const getDfnName = dfn => {
|
|
552
|
+
if (dfn.getAttribute('data-lt')) {
|
|
553
|
+
const names = dfn.getAttribute('data-lt').split('|').map(normalize);
|
|
554
|
+
let name = names.find(n =>
|
|
555
|
+
n.startsWith('<') || // Looks like a "type"
|
|
556
|
+
n.startsWith('@') || // Looks like an "at-rule"
|
|
557
|
+
n.startsWith(':') || // Looks like a "descriptor"
|
|
558
|
+
n.endsWith('()') || // Looks like a "function"
|
|
559
|
+
n === dfn.textContent.trim()); // Looks like the right term
|
|
560
|
+
if (!name) {
|
|
561
|
+
if (names.length > 1) {
|
|
562
|
+
throw new Error(`Found multiple linking texts for dfn without any obvious one: ${names.join(', ')}`);
|
|
563
|
+
}
|
|
564
|
+
name = names[0];
|
|
565
|
+
}
|
|
566
|
+
return name;
|
|
567
|
+
}
|
|
568
|
+
else {
|
|
569
|
+
return dfn.textContent.trim();
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
|
|
573
|
+
|
|
547
574
|
/**
|
|
548
575
|
* Extract the given dfn
|
|
549
576
|
*/
|
|
@@ -553,6 +580,7 @@ const extractTypedDfn = dfn => {
|
|
|
553
580
|
const dfnType = dfn.getAttribute('data-dfn-type');
|
|
554
581
|
const dfnFor = dfn.getAttribute('data-dfn-for');
|
|
555
582
|
const parent = dfn.parentNode.cloneNode(true);
|
|
583
|
+
const fnRegExp = /^([a-zA-Z_][a-zA-Z0-9_\-]+)\([^\)]+\)$/;
|
|
556
584
|
|
|
557
585
|
// Remove note references as in:
|
|
558
586
|
// https://drafts.csswg.org/css-syntax-3/#the-anb-type
|
|
@@ -574,8 +602,17 @@ const extractTypedDfn = dfn => {
|
|
|
574
602
|
// Don't attempt to parse pre tags at this stage, they are tricky to
|
|
575
603
|
// split, we'll parse them as text and map them to the right definitions
|
|
576
604
|
// afterwards.
|
|
577
|
-
|
|
578
|
-
|
|
605
|
+
// That said, we may be looking at a function definition on the right hand
|
|
606
|
+
// side of a production rule, as in the definition of "linear()" in
|
|
607
|
+
// css-easing-2: https://drafts.csswg.org/css-easing-2/#funcdef-linear
|
|
608
|
+
// In such a case, we still want to extract the function parameters
|
|
609
|
+
if (dfn.textContent.trim().match(fnRegExp)) {
|
|
610
|
+
const fn = dfn.textContent.trim().match(fnRegExp)[1];
|
|
611
|
+
res = parseProductionRule(`${fn}() = ${dfn.textContent.trim()}`, { pureSyntax: false });
|
|
612
|
+
}
|
|
613
|
+
else {
|
|
614
|
+
res = { name: getDfnName(dfn) };
|
|
615
|
+
}
|
|
579
616
|
}
|
|
580
617
|
else if (prod) {
|
|
581
618
|
res = parseProductionRule(prod, { pureSyntax: true });
|
|
@@ -585,13 +622,12 @@ const extractTypedDfn = dfn => {
|
|
|
585
622
|
// https://drafts.csswg.org/css-speech-1/#typedef-voice-volume-decibel
|
|
586
623
|
// It may be worth checking but not an error per se.
|
|
587
624
|
console.warn('[reffy]', `Found "=" next to definition of ${dfn.textContent.trim()} but no production rule. Did I miss something?`);
|
|
588
|
-
|
|
589
|
-
res = { name, prose: text.replace(/\s+/g, ' ') };
|
|
625
|
+
res = { name: getDfnName(dfn), prose: text.replace(/\s+/g, ' ') };
|
|
590
626
|
}
|
|
591
627
|
}
|
|
592
|
-
else if (dfn.textContent.trim().match(
|
|
628
|
+
else if (dfn.textContent.trim().match(fnRegExp)) {
|
|
593
629
|
// Definition is "prod(foo bar)", create a "prod() = prod(foo bar)" entry
|
|
594
|
-
const fn = dfn.textContent.trim().match(
|
|
630
|
+
const fn = dfn.textContent.trim().match(fnRegExp)[1];
|
|
595
631
|
res = parseProductionRule(`${fn}() = ${dfn.textContent.trim()}`, { pureSyntax: false });
|
|
596
632
|
}
|
|
597
633
|
else if (parent.nodeName === 'DT') {
|
|
@@ -625,20 +661,23 @@ const extractTypedDfn = dfn => {
|
|
|
625
661
|
}
|
|
626
662
|
});
|
|
627
663
|
|
|
628
|
-
|
|
629
|
-
|
|
664
|
+
res = {
|
|
665
|
+
name: getDfnName(dfn),
|
|
666
|
+
prose: dd.textContent.trim().replace(/\s+/g, ' ')
|
|
667
|
+
};
|
|
630
668
|
}
|
|
631
669
|
}
|
|
632
670
|
else if (parent.nodeName === 'P') {
|
|
633
671
|
// Definition is in regular prose, extract value from prose.
|
|
634
|
-
|
|
635
|
-
|
|
672
|
+
res = {
|
|
673
|
+
name: getDfnName(dfn),
|
|
674
|
+
prose: parent.textContent.trim().replace(/\s+/g, ' ')
|
|
675
|
+
};
|
|
636
676
|
}
|
|
637
677
|
else {
|
|
638
678
|
// Definition is in a heading or a more complex structure, just list the
|
|
639
679
|
// name for now.
|
|
640
|
-
|
|
641
|
-
res = { name };
|
|
680
|
+
res = { name: getDfnName(dfn) };
|
|
642
681
|
}
|
|
643
682
|
|
|
644
683
|
res.type = dfnType;
|
|
@@ -106,17 +106,18 @@ function hasValidType(el) {
|
|
|
106
106
|
return isValid;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
// Return true when definition is not already defined in the list,
|
|
109
|
+
// Return true when exported definition is not already defined in the list,
|
|
110
110
|
// Return false and issue a warning when it is already defined.
|
|
111
|
-
function
|
|
111
|
+
function isNotAlreadyExported(dfn, idx, list) {
|
|
112
112
|
const first = list.find(d => d === dfn ||
|
|
113
|
-
(d.
|
|
113
|
+
(d.access === 'public' && dfn.access === 'public' &&
|
|
114
|
+
d.type === dfn.type &&
|
|
114
115
|
d.linkingText.length === dfn.linkingText.length &&
|
|
115
116
|
d.linkingText.every(lt => dfn.linkingText.find(t => t == lt)) &&
|
|
116
117
|
d.for.length === dfn.for.length &&
|
|
117
118
|
d.for.every(lt => dfn.for.find(t => t === lt))));
|
|
118
119
|
if (first !== dfn) {
|
|
119
|
-
console.warn('[reffy]', `Duplicate dfn found for "${dfn.linkingText[0]}", type="${dfn.type}", for="${dfn.for[0]}"`);
|
|
120
|
+
console.warn('[reffy]', `Duplicate dfn found for "${dfn.linkingText[0]}", type="${dfn.type}", for="${dfn.for[0]}", dupl=${dfn.href}, first=${first.href}`);
|
|
120
121
|
}
|
|
121
122
|
return first === dfn;
|
|
122
123
|
}
|
|
@@ -267,7 +268,7 @@ export default function (spec, idToHeading = {}) {
|
|
|
267
268
|
return !link || (node.textContent.trim() !== link.textContent.trim());
|
|
268
269
|
})
|
|
269
270
|
.map(node => definitionMapper(node, idToHeading, usesDfnDataModel))
|
|
270
|
-
.filter(
|
|
271
|
+
.filter(isNotAlreadyExported);
|
|
271
272
|
}
|
|
272
273
|
|
|
273
274
|
function preProcessEcmascript() {
|