reffy 11.0.2 → 11.0.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "reffy",
|
|
3
|
-
"version": "11.0.
|
|
3
|
+
"version": "11.0.3",
|
|
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,7 +46,7 @@
|
|
|
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
51
|
"rollup": "3.5.0"
|
|
52
52
|
},
|
|
@@ -544,6 +544,39 @@ const parseProductionRule = (rule, { res = [], pureSyntax = false }) => {
|
|
|
544
544
|
};
|
|
545
545
|
|
|
546
546
|
|
|
547
|
+
/**
|
|
548
|
+
* Extract the definition name. If multiple linking texts are possible, the
|
|
549
|
+
* function will select the one that is a "syntax" definition. For instance, it
|
|
550
|
+
* will pick up "<identifier>" for "identifiers|<identifier>" in CSS 2:
|
|
551
|
+
* https://drafts.csswg.org/css2/#value-def-identifier
|
|
552
|
+
*
|
|
553
|
+
* The function throws if it cannot extract an obvious name from the definition.
|
|
554
|
+
* We may want to be smarter about that in the future, but this should really
|
|
555
|
+
* never happen in practice (the above "identifiers" example is the only one
|
|
556
|
+
* CSS value definition so far to have multiple linking texts)
|
|
557
|
+
*/
|
|
558
|
+
const getDfnName = dfn => {
|
|
559
|
+
if (dfn.getAttribute('data-lt')) {
|
|
560
|
+
const names = dfn.getAttribute('data-lt').split('|').map(normalize);
|
|
561
|
+
let name = names.find(n =>
|
|
562
|
+
n.startsWith('<') || // Looks like a "type"
|
|
563
|
+
n.startsWith('@') || // Looks like an "at-rule"
|
|
564
|
+
n.startsWith(':') || // Looks like a "descriptor"
|
|
565
|
+
n.endsWith('()')); // Looks like a "function"
|
|
566
|
+
if (!name) {
|
|
567
|
+
if (names.length > 1) {
|
|
568
|
+
throw new Error(`Found multiple linking texts for dfn without any obvious one: ${names.join(', ')}`);
|
|
569
|
+
}
|
|
570
|
+
name = names[0];
|
|
571
|
+
}
|
|
572
|
+
return name;
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
return dfn.textContent.trim();
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
|
|
547
580
|
/**
|
|
548
581
|
* Extract the given dfn
|
|
549
582
|
*/
|
|
@@ -553,6 +586,7 @@ const extractTypedDfn = dfn => {
|
|
|
553
586
|
const dfnType = dfn.getAttribute('data-dfn-type');
|
|
554
587
|
const dfnFor = dfn.getAttribute('data-dfn-for');
|
|
555
588
|
const parent = dfn.parentNode.cloneNode(true);
|
|
589
|
+
const fnRegExp = /^([a-zA-Z_][a-zA-Z0-9_\-]+)\([^\)]+\)$/;
|
|
556
590
|
|
|
557
591
|
// Remove note references as in:
|
|
558
592
|
// https://drafts.csswg.org/css-syntax-3/#the-anb-type
|
|
@@ -574,8 +608,17 @@ const extractTypedDfn = dfn => {
|
|
|
574
608
|
// Don't attempt to parse pre tags at this stage, they are tricky to
|
|
575
609
|
// split, we'll parse them as text and map them to the right definitions
|
|
576
610
|
// afterwards.
|
|
577
|
-
|
|
578
|
-
|
|
611
|
+
// That said, we may be looking at a function definition on the right hand
|
|
612
|
+
// side of a production rule, as in the definition of "linear()" in
|
|
613
|
+
// css-easing-2: https://drafts.csswg.org/css-easing-2/#funcdef-linear
|
|
614
|
+
// In such a case, we still want to extract the function parameters
|
|
615
|
+
if (dfn.textContent.trim().match(fnRegExp)) {
|
|
616
|
+
const fn = dfn.textContent.trim().match(fnRegExp)[1];
|
|
617
|
+
res = parseProductionRule(`${fn}() = ${dfn.textContent.trim()}`, { pureSyntax: false });
|
|
618
|
+
}
|
|
619
|
+
else {
|
|
620
|
+
res = { name: getDfnName(dfn) };
|
|
621
|
+
}
|
|
579
622
|
}
|
|
580
623
|
else if (prod) {
|
|
581
624
|
res = parseProductionRule(prod, { pureSyntax: true });
|
|
@@ -585,13 +628,12 @@ const extractTypedDfn = dfn => {
|
|
|
585
628
|
// https://drafts.csswg.org/css-speech-1/#typedef-voice-volume-decibel
|
|
586
629
|
// It may be worth checking but not an error per se.
|
|
587
630
|
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, ' ') };
|
|
631
|
+
res = { name: getDfnName(dfn), prose: text.replace(/\s+/g, ' ') };
|
|
590
632
|
}
|
|
591
633
|
}
|
|
592
|
-
else if (dfn.textContent.trim().match(
|
|
634
|
+
else if (dfn.textContent.trim().match(fnRegExp)) {
|
|
593
635
|
// Definition is "prod(foo bar)", create a "prod() = prod(foo bar)" entry
|
|
594
|
-
const fn = dfn.textContent.trim().match(
|
|
636
|
+
const fn = dfn.textContent.trim().match(fnRegExp)[1];
|
|
595
637
|
res = parseProductionRule(`${fn}() = ${dfn.textContent.trim()}`, { pureSyntax: false });
|
|
596
638
|
}
|
|
597
639
|
else if (parent.nodeName === 'DT') {
|
|
@@ -625,20 +667,23 @@ const extractTypedDfn = dfn => {
|
|
|
625
667
|
}
|
|
626
668
|
});
|
|
627
669
|
|
|
628
|
-
|
|
629
|
-
|
|
670
|
+
res = {
|
|
671
|
+
name: getDfnName(dfn),
|
|
672
|
+
prose: dd.textContent.trim().replace(/\s+/g, ' ')
|
|
673
|
+
};
|
|
630
674
|
}
|
|
631
675
|
}
|
|
632
676
|
else if (parent.nodeName === 'P') {
|
|
633
677
|
// Definition is in regular prose, extract value from prose.
|
|
634
|
-
|
|
635
|
-
|
|
678
|
+
res = {
|
|
679
|
+
name: getDfnName(dfn),
|
|
680
|
+
prose: parent.textContent.trim().replace(/\s+/g, ' ')
|
|
681
|
+
};
|
|
636
682
|
}
|
|
637
683
|
else {
|
|
638
684
|
// Definition is in a heading or a more complex structure, just list the
|
|
639
685
|
// name for now.
|
|
640
|
-
|
|
641
|
-
res = { name };
|
|
686
|
+
res = { name: getDfnName(dfn) };
|
|
642
687
|
}
|
|
643
688
|
|
|
644
689
|
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() {
|