Skip to content

Commit

Permalink
Expose htmlProse when available
Browse files Browse the repository at this point in the history
  • Loading branch information
dontcallmedom committed Feb 13, 2024
1 parent 5337541 commit b2a2c96
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 15 deletions.
79 changes: 64 additions & 15 deletions _tools/generate-pages.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
const fs = require("fs/promises");
const html = require('escape-html-template-tag');
const {safe} = html;
const {JSDOM} = require("jsdom");

const { expandCrawlResult } = require('reffy/src/lib/util');

Expand All @@ -8,6 +10,8 @@ const aliasIndex = new Map();
const linksIndex = new Map();
const letters = new Map();

let results;

const typeInfo = {
"grammar": {
human: "grammar",
Expand Down Expand Up @@ -195,6 +199,33 @@ function sortByArea([relatedTerm1, relatedTermId1], [relatedTerm2, relatedTermId
return typeInfo[type1].area.localeCompare(typeInfo[type2].area) || type1.localeCompare(type2) || relatedTerm1.localeCompare(relatedTerm2);
}

function findDfn(link) {
console.log("searching for " + link + " in " + results.length + " specs");
for (const spec of results) {
const dfn = spec.dfns?.find(d => d.href === link);
if (dfn) return {dfn, spec};
}
}

function substituteProseLinks(html) {
// TODO: how reliably can we assume that the html can be put inside a <div>?
const frag = JSDOM.fragment("<div>" + html + "</div>");
frag.querySelectorAll('a[href^="https://"]').forEach(link => {
const dfnData = findDfn(link.href);
if (dfnData) {
const {dfn, spec} = dfnData;
const term = cleanTerm(dfn.linkingText[0], dfn.type);
const termId = generateTermId(dfn, spec);
console.log(link.href, term, termId);
const dfnLink = getLink(term, termId);
if (dfnLink) {
link.href = dfnLink;
}
}
});
return frag.firstChild.innerHTML;
}

function getScopingTermId(type, _for, displayTerm, dfns) {
function returnIfFound(candidates, matches) {
if (matches.length === 1) {
Expand Down Expand Up @@ -413,10 +444,23 @@ ${content}`);
}


function generateTermId(dfn, spec) {
if (dfn.for.length === 0) {
if (typeInfo[dfn.type]?.exclusiveNamespace) {
return `@@${dfn.type}`;
} else {
return `${spec.series.shortname}%%${dfn.type}`;
}
} else {
// by convention, we use the first 'for' by alphabetical order
return `${dfn.for.sort()[0]}@${dfn.type}`;
}
}

(async function() {
const jsonIndex = await fs.readFile("./webref/ed/index.json", "utf-8");
const index = JSON.parse(jsonIndex);
const {results} = await expandCrawlResult(index, './webref/ed/', ['dfns', 'links']);
results = (await expandCrawlResult(index, './webref/ed/', ['dfns', 'links'])).results;
for (const spec of results) {
for (const dfn of (spec.dfns || [])) {
if (dfn.access === "private") continue;
Expand All @@ -425,22 +469,14 @@ ${content}`);
const term = cleanTerm(dfn.linkingText[0], dfn.type);
const displayTerm = dfn.linkingText[0].replace(/^"/, '').replace(/"$/, '');
const termEntry = termIndex.get(term) ?? {};
let termId;
const termId = generateTermId(dfn, spec);
let prefixes = [];
if (dfn.for.length === 0) {
if (typeInfo[dfn.type]?.exclusiveNamespace) {
termId = `@@${dfn.type}`;
} else {
termId = `${spec.series.shortname}%%${dfn.type}`;
}
} else {
if (dfn.for.length) {
if (dfn.type === "constructor" && term !== 'constructor()') {
prefixes = ['new '];
} else if (['method', 'const', 'attribute', 'dict-member'].includes(dfn.type)) {
prefixes = dfn.for.map(_for => `${_for}.`);
}
// by convention, we use the first 'for' by alphabetical order
termId = `${dfn.for.sort()[0]}@${dfn.type}`;
}
const subtermEntry = termEntry[termId] ?? {shortname: spec.series.shortname, type: dfn.type, _for: dfn.for, dfns: [], prefixes: [], refs: [], related: [], displayTerm, sortTerm: `${displayTerm}-${prefixes[0] ?? ''}`};
subtermEntry.dfns.push({...dfn, spec: spec.shortTitle});
Expand Down Expand Up @@ -510,16 +546,29 @@ ${content}`);
<p class=legend>Color key: <code class=webidl>WebIDL</code> <code class='css'>CSS</code> <code class='markup'>Markup</code> <code class='http'>HTTP</code></p>
<dl>
${letters.get(entry).sort((a,b) => a.toLowerCase().localeCompare(b.toLowerCase())).map(term => {
return html`${Object.keys(termIndex.get(term)).sort((a,b) => termIndex.get(term)[a].sortTerm.localeCompare(termIndex.get(term)[b].sortTerm))
.map(termId => {
const {displayTerm, type, _for, dfns, prefixes, refs, related} = termIndex.get(term)[termId];
let definitionContent = ``;
const withProse = dfns.some(d => d.htmlProse && d.access === "public");
if (!withProse) {
definitionContent = html.join(dfns.map(dfn => {
return html`<strong title='${displayTerm} is defined in ${dfn.spec}'><a href=${dfn.href}>${dfn.spec}</a></strong> `;
}), ', ');
} else if (dfns.length === 1) {
const dfn = dfns[0];
definitionContent = html`<strong title='${displayTerm} is defined in ${dfn.spec}'><a href=${dfn.href}>${dfn.spec}</a></strong>: ${safe(substituteProseLinks(dfn.htmlProse))}`;
} else {
definitionContent = html`<ul> ${html.join(dfns.map(dfn => {
return html`<li><strong title='${displayTerm} is defined in ${dfn.spec}'><a href=${dfn.href}>${dfn.spec}</a></strong>${dfn.htmlProse? html`: ${safe(substituteProseLinks(dfn.htmlProse))}` : ""}</li>`;
}), '')}`;
}
const definitionList = html`<dd>Defined in ${definitionContent}</dd>`;
const webidlpedia = ['interface', 'dictionary', 'enum', 'typedef'].includes(type) ? html`<dd>see also <a href='https://dontcallmedom.github.io/webidlpedia/names/${displayTerm}.html' title='${displayTerm} entry on WebIDLpedia'>WebIDLPedia</a></dd>` : '';
return html`<dt id="${displayTerm}@@${termId}">${composeDisplayName(displayTerm, type, _for, prefixes[0] || '', dfns, termId)}</dt>
${prefixes.slice(1).map(p => html`<dt>${composeDisplayName(displayTerm, type, _for, p, dfns, termId)}</dt>`)}
<dd>Defined in ${html.join(dfns.map(dfn => {
return html`
<strong title='${displayTerm} is defined in ${dfn.spec}'><a href=${dfn.href}>${dfn.spec}</a></strong> `;
}), ', ')}</dd>
${definitionList}
${refs.length ? html`<dd>Referenced in ${html.join(refs.map(ref => {
return html`
<a href=${ref.url} title='${displayTerm} is referenced by ${ref.title}'>${ref.title}</a>`;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"dependencies": {
"escape-html-template-tag": "^1.2.0",
"jsdom": "^24.0.0",
"node-fetch": "^2.6.1",
"reffy": "^6.0.0",
"vnu-jar": "^20.6.30"
Expand Down

0 comments on commit b2a2c96

Please sign in to comment.