-
Notifications
You must be signed in to change notification settings - Fork 63
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
do not leave emu-import / emu-biblio in the generated DOM (#624)
- Loading branch information
Showing
8 changed files
with
94 additions
and
98 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,84 +1,64 @@ | ||
import type Spec from './Spec'; | ||
|
||
import Builder from './Builder'; | ||
import * as utils from './utils'; | ||
import * as path from 'path'; | ||
import type { JSDOM } from 'jsdom'; | ||
|
||
export default class Import extends Builder { | ||
/** @internal */ public importLocation: string; | ||
/** @internal */ public relativeRoot: string; | ||
/** @internal */ public source: string; | ||
export type Import = { | ||
importLocation: string; | ||
relativeRoot: string; | ||
source: string; | ||
}; | ||
|
||
constructor( | ||
spec: Spec, | ||
node: HTMLElement, | ||
importLocation: string, | ||
relativeRoot: string, | ||
source: string, | ||
) { | ||
super(spec, node); | ||
this.importLocation = importLocation; | ||
this.relativeRoot = relativeRoot; | ||
this.source = source; | ||
} | ||
export async function buildImports(spec: Spec, importNode: EmuImportElement, root: string) { | ||
const href = importNode.getAttribute('href'); | ||
if (!href) throw new Error('Import missing href attribute.'); | ||
const importPath = path.join(root, href); | ||
const relativeRoot = path.dirname(importPath); | ||
|
||
static async build(spec: Spec, node: EmuImportElement, root: string) { | ||
const href = node.getAttribute('href'); | ||
if (!href) throw new Error('Import missing href attribute.'); | ||
const importPath = path.join(root, href); | ||
const relativeRoot = path.dirname(importPath); | ||
const html = await spec.fetch(importPath); | ||
|
||
const html = await spec.fetch(importPath); | ||
spec.imports.push({ importLocation: importPath, relativeRoot, source: html }); | ||
|
||
const imp = new Import(spec, node, importPath, relativeRoot, html); | ||
spec.imports.push(imp); | ||
const importDom = utils.htmlToDom(html); | ||
importNode.dom = importDom; | ||
importNode.source = html; | ||
importNode.importPath = importPath; | ||
|
||
const importDom = utils.htmlToDom(html); | ||
node.dom = importDom; | ||
node.source = html; | ||
node.importPath = importPath; | ||
const importDoc = importDom.window.document; | ||
|
||
const importDoc = importDom.window.document; | ||
const nodes = importDoc.body.childNodes; | ||
const frag = spec.doc.createDocumentFragment(); | ||
// clone this list so we can walk it after the replaceWith call | ||
const importedNodes = [...importDoc.body.childNodes]; | ||
const frag = spec.doc.createDocumentFragment(); | ||
|
||
for (let i = 0; i < nodes.length; i++) { | ||
const node = nodes[i]; | ||
const importedNode = spec.doc.adoptNode(node); | ||
frag.appendChild(importedNode); | ||
} | ||
for (let i = 0; i < importedNodes.length; i++) { | ||
const importedNode = spec.doc.adoptNode(importedNodes[i]); | ||
importedNodes[i] = importedNode; | ||
frag.appendChild(importedNode); | ||
|
||
const children = frag.childElementCount; | ||
node.appendChild(frag); | ||
spec.topLevelImportedNodes.set(importedNode, importNode); | ||
} | ||
|
||
// This is a bit gross. | ||
// We want to do this check after adopting the elements into the main DOM, so the location-finding infrastructure works | ||
// But `appendChild(documentFragment)` both empties out the original fragment and returns it. | ||
// So we have to remember how many child elements we are adding and walk over each of them manually. | ||
for (let i = node.children.length - children; i < node.children.length; ++i) { | ||
const child = node.children[i]; | ||
const biblios = [ | ||
...child.querySelectorAll('emu-biblio'), | ||
...(child.tagName === 'EMU-BIBLIO' ? [child] : []), | ||
importNode.replaceWith(frag); | ||
|
||
for (let i = 0; i < importedNodes.length; i++) { | ||
const importedNode = importedNodes[i]; | ||
if (importedNode.nodeType === 1 /* Node.ELEMENT_NODE */) { | ||
const importedImports = [ | ||
...(importedNode as HTMLElement).querySelectorAll('emu-import'), | ||
// we have to do this because querySelectorAll can't return its `this` | ||
...((importedNode as HTMLElement).tagName === 'EMU-IMPORT' ? [importedNode] : []), | ||
]; | ||
for (const biblio of biblios) { | ||
spec.warn({ | ||
type: 'node', | ||
node: biblio, | ||
ruleId: 'biblio-in-import', | ||
message: 'emu-biblio elements cannot be used within emu-imports', | ||
}); | ||
for (const childImport of importedImports) { | ||
await buildImports(spec, childImport as EmuImportElement, relativeRoot); | ||
} | ||
} | ||
|
||
return imp; | ||
} | ||
} | ||
|
||
export interface EmuImportElement extends HTMLElement { | ||
href: string; | ||
dom?: JSDOM; | ||
dom: JSDOM; | ||
source?: string; | ||
importPath?: string; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters