1+ import * as fs from "fs" ;
2+ import * as path from "path" ;
3+ import fetch from "node-fetch" ;
4+ // import { JSDOM } from "jsdom";
5+
6+
7+
8+ interface IDLSource {
9+ url : string ;
10+ title : string ;
11+ deprecated ?: boolean ;
12+ local ?: boolean ;
13+ }
14+
15+ // const idlSelector = [
16+ // "pre.idl:not(.extract):not(.example)", // bikeshed and ReSpec
17+ // "pre.code code.idl-code", // Web Cryptography
18+ // "pre:not(.extract) code.idl", // HTML
19+ // "#permission-registry + pre.highlight" // Permissions
20+ // ].join(",");
21+
22+ // const cssPropSelector = [
23+ // ".propdef dfn", // CSS Fonts, SVG
24+ // ".propdef-title", // SVG Paint Servers
25+ // "dfn.css[data-dfn-type=property]"
26+ // ].join(",");
27+
28+
29+ async function fetchIDLs ( ) {
30+ const idlSources = ( require ( "../inputfiles/idlSources.json" ) as IDLSource [ ] ) ;
31+ await Promise . all ( idlSources . map ( async source => {
32+ if ( source . local ) {
33+ return ;
34+ }
35+ await fetchIDL ( source ) ;
36+ // fs.writeFileSync(path.join(__dirname, `../inputfiles/idl/${source.title}.widl`), idl + '\n');
37+ // if (comments) {
38+ // fs.writeFileSync(path.join(__dirname, `../inputfiles/idl/${source.title}.commentmap.json`), comments + '\n');
39+ // }
40+ } ) ) . then (
41+ ( ) => {
42+ console . log ( ) ;
43+ console . log ( deprecatedSet ) ;
44+ }
45+ ) ;
46+ }
47+
48+ const tmpLocalFolder = path . join ( __dirname , "localIdlSource" ) ;
49+ const deprecatedSet = new Set < string > ( ) ;
50+ // ['https://www.w3.org/TR/css-color-3/', 'https://www.w3.org/TR/credential-management-1/', 'https://www.w3.org/TR/css-text-decor-3/', 'https://w3c.github.io/media-playback-quality/', 'https://www.w3.org/TR/css-text-3/', 'https://drafts.csswg.org/css-images-3/', 'https://www.w3.org/TR/secure-contexts/', 'https://www.w3.org/TR/SVG2/types.html', 'https://html.spec.whatwg.org/multipage/obsolete.html', 'https://notifications.spec.whatwg.org/', 'https://www.w3.org/TR/SVG2/text.html', 'https://fetch.spec.whatwg.org/', 'https://html.spec.whatwg.org/multipage/webappapis.html', 'https://dom.spec.whatwg.org/', 'https://drafts.fxtf.org/css-masking-1/', 'https://www.w3.org/TR/filter-effects-1/', 'https://drafts.csswg.org/cssom/', 'https://w3c.github.io/webrtc-pc/', 'https://webaudio.github.io/web-audio-api/', 'https://heycam.github.io/webidl/', 'https://www.w3.org/TR/SVG2/pservers.html', 'https://www.w3.org/TR/uievents/']
51+ async function fetchIDL ( source : IDLSource ) {
52+
53+ if ( ! fs . existsSync ( tmpLocalFolder ) ) {
54+ fs . mkdirSync ( tmpLocalFolder ) ;
55+ }
56+
57+ if ( source . url . endsWith ( ".idl" ) ) {
58+ return ;
59+ }
60+
61+ const localFile = path . join ( tmpLocalFolder , source . title ) ;
62+ let webPageContent : string ;
63+ if ( fs . existsSync ( localFile ) ) {
64+ webPageContent = fs . readFileSync ( localFile , { encoding : "utf-8" } ) ;
65+ }
66+ else {
67+ const response = await fetch ( source . url ) ;
68+ webPageContent = await response . text ( ) ;
69+ fs . writeFileSync ( localFile , webPageContent ) ;
70+ }
71+ if ( webPageContent . toLowerCase ( ) . includes ( "deprecated" ) ) {
72+ deprecatedSet . add ( source . url ) ;
73+ }
74+ // const dom = JSDOM.fragment(
75+ // ""// webPageContent
76+ // );
77+
78+ }
79+
80+ // function extractIDL(dom: DocumentFragment) {
81+ // const elements = Array.from(dom.querySelectorAll(idlSelector))
82+ // .filter(el => {
83+ // if (el.parentElement && el.parentElement.classList.contains("example")) {
84+ // return false;
85+ // }
86+ // const previous = el.previousElementSibling;
87+ // if (!previous) {
88+ // return true;
89+ // }
90+ // return !previous.classList.contains("atrisk") && !previous.textContent!.includes("IDL Index");
91+ // });
92+ // return elements.map(element => trimCommonIndentation(element.textContent!).trim()).join('\n\n');
93+ // }
94+
95+ // function extractCSSDefinitions(dom: DocumentFragment) {
96+ // const properties = Array.from(dom.querySelectorAll(cssPropSelector))
97+ // .map(element => element.textContent!.trim());
98+
99+ // if (!properties.length) {
100+ // return "";
101+ // }
102+
103+ // return `partial interface CSSStyleDeclaration {${
104+ // properties.map(property => `\n [CEReactions] attribute [LegacyNullToEmptyString] CSSOMString ${
105+ // hyphenToCamelCase(property)
106+ // };`).join("")
107+ // }\n };`;
108+ // }
109+
110+ // function hyphenToCamelCase(name: string) {
111+ // const camel = name
112+ // .replace(/^-(\w)/, (_, c) => c)
113+ // .replace(/-(\w)/g, (_, c) => c.toUpperCase());
114+ // return camel === "float" ? "_float" : camel;
115+ // }
116+
117+ // function processComments(dom: DocumentFragment) {
118+ // const elements = [...dom.querySelectorAll("dl.domintro")];
119+ // if (!elements.length) {
120+ // return undefined;
121+ // }
122+
123+ // const result: Record<string, string> = {};
124+ // for (const element of elements) {
125+ // for (const { dt, dd } of generateDescriptionPairs(element)) {
126+ // elements.push(...importNestedList(dd));
127+ // const comment = dd
128+ // .map(desc => {
129+ // desc.normalize();
130+ // convertChildPre(desc);
131+ // return innerText(desc).replace(/’/g, "'");
132+ // })
133+ // .filter(text => text)
134+ // .join("\n\n");
135+ // for (const key of dt.map(term => getKey(term.innerHTML))) {
136+ // if (!key) {
137+ // continue;
138+ // }
139+ // const retargeted = retargetCommentKey(key, dom);
140+ // // prefer the first description
141+ // if (!result[retargeted]) {
142+ // result[retargeted] = comment;
143+ // }
144+ // }
145+ // }
146+ // }
147+ // if (!Object.keys(result).length) {
148+ // return undefined;
149+ // }
150+ // return JSON.stringify(result, undefined, 4);
151+ // }
152+
153+ // function convertChildPre(e: Element) {
154+ // for (const pre of e.querySelectorAll("pre")) {
155+ // const code = pre.querySelector(":scope > code") as HTMLElement;
156+ // if (!code) {
157+ // continue;
158+ // }
159+ // const text = innerText(code, {
160+ // getComputedStyle(_: Element) {
161+ // return { whiteSpace: "pre" } as CSSStyleDeclaration;
162+ // }
163+ // });
164+ // pre.textContent = "```\n" + text + "\n```";
165+ // }
166+ // }
167+
168+ // function getKey(s: string) {
169+ // const keyRegexp = /#dom-([a-zA-Z0-9-_]+)/i;
170+ // const match = s.match(keyRegexp);
171+ // if (match) {
172+ // return match[1];
173+ // }
174+ // return undefined;
175+ // }
176+
177+ // function* generateDescriptionPairs(domIntro: Element) {
178+ // const dt: HTMLElement[] = [];
179+ // const dd: HTMLElement[] = [];
180+ // let element = domIntro.firstElementChild;
181+ // while (element) {
182+ // switch (element.localName) {
183+ // case "dt":
184+ // if (dd.length) {
185+ // yield { dt: [...dt], dd: [...dd] };
186+ // dt.length = dd.length = 0;
187+ // }
188+ // dt.push(element as HTMLElement)
189+ // break;
190+ // case "dd":
191+ // dd.push(element as HTMLElement)
192+ // break;
193+ // default:
194+ // debugger;
195+ // }
196+ // element = element.nextElementSibling;
197+ // }
198+ // if (dd.length) {
199+ // yield { dt: [...dt], dd: [...dd] };
200+ // }
201+ // }
202+
203+ // function* importNestedList(elements: Element[]) {
204+ // for (const element of elements) {
205+ // for (const dl of element.getElementsByTagName("dl")) {
206+ // dl.remove();
207+ // yield dl;
208+ // }
209+ // }
210+ // }
211+
212+ // /**
213+ // * Specifications tends to keep existing keys even after a member relocation
214+ // * so that external links can be stable and won't broken.
215+ // */
216+ // function retargetCommentKey(key: string, dom: DocumentFragment) {
217+ // const [parent, member] = key.split(/-/g);
218+ // if (!member) {
219+ // return parent;
220+ // }
221+ // const dfn = dom.getElementById(`dom-${key}`);
222+ // if (!dfn || !dfn.dataset.dfnFor) {
223+ // // The optional third word is for overloads and can be safely ignored.
224+ // return `${parent}-${member}`;
225+ // }
226+ // return `${dfn.dataset.dfnFor.toLowerCase()}-${member}`;
227+ // }
228+
229+ // /**
230+ // * Remove common indentation:
231+ // * <pre>
232+ // * typedef Type = "type";
233+ // *
234+ // * dictionary Dictionary {
235+ // * "member"
236+ // * };
237+ // * </pre>
238+ // * Here the textContent has 6 common preceding whitespaces that can be unindented.
239+ // */
240+ // function trimCommonIndentation(text: string) {
241+ // const lines = text.split("\n");
242+ // if (!lines[0].trim()) {
243+ // lines.shift();
244+ // }
245+ // if (!lines[lines.length - 1].trim()) {
246+ // lines.pop();
247+ // }
248+ // const commonIndentation = Math.min(...lines.filter(line => line.trim()).map(getIndentation));
249+ // return lines.map(line => line.slice(commonIndentation)).join("\n");
250+ // }
251+
252+ // /** Count preceding whitespaces */
253+ // function getIndentation(line: string) {
254+ // let count = 0;
255+ // for (const ch of line) {
256+ // if (ch !== " ") {
257+ // break;
258+ // }
259+ // count++;
260+ // }
261+ // return count;
262+ // }
263+
264+ fetchIDLs ( ) ;
0 commit comments