This repository has been archived by the owner on Sep 7, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #14 from wbamberg/packaging
Simple packaging for HTML elements
- Loading branch information
Showing
8 changed files
with
308 additions
and
15 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
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 |
---|---|---|
@@ -0,0 +1,60 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
const yaml = require('js-yaml'); | ||
|
||
const bcd = require('./resolve-bcd'); | ||
const examples = require('./compose-examples'); | ||
const attributes = require('./compose-attributes'); | ||
const prose = require('./slice-prose'); | ||
const contributors = require('./resolve-contributors'); | ||
|
||
const htmlElements = '/content/html/elements'; | ||
|
||
const writeToFile = (propertyName, json) => { | ||
const data = { | ||
html: { | ||
elements: { | ||
[propertyName]: json, | ||
} | ||
} | ||
}; | ||
|
||
const dest = path.join(process.cwd(),'packaged/html/elements', `${propertyName}.json`); | ||
const destDir = path.dirname(dest); | ||
if (!fs.existsSync(destDir)) { | ||
fs.mkdirSync(destDir, { recursive: true }); | ||
} | ||
fs.writeFileSync(dest, `${JSON.stringify(data, null, 2)}`); | ||
}; | ||
|
||
function package(elementName) { | ||
const elementPath = path.join(process.cwd(), htmlElements, elementName); | ||
|
||
if (!fs.existsSync(elementPath)) { | ||
console.error(`Could not find an element called "${elementName}"`); | ||
return; | ||
} | ||
|
||
// open meta.yaml | ||
const meta = yaml.safeLoad(fs.readFileSync(path.join(elementPath, 'meta.yaml'), 'utf8')); | ||
|
||
// initialise some paths for more resources | ||
const examplesPaths = meta.examples.map(relativePath => path.join(elementPath, relativePath)); | ||
const attributesPath = path.join(elementPath, meta.attributes['element-specific']); | ||
const prosePath = path.join(elementPath, 'prose.md'); | ||
const contributorsPath = path.join(elementPath, 'contributors.md'); | ||
|
||
// make the package | ||
const element = {}; | ||
element.title = meta.title; | ||
element.interactive_example_url = meta['interactive-example']; | ||
element.browser_compatibility = bcd.package(meta['browser-compatibility']); | ||
element.examples = examples.package(examplesPaths); | ||
element.attributes = attributes.package(attributesPath); | ||
element.prose = prose.package(prosePath); | ||
element.contributors = contributors.package(contributorsPath); | ||
|
||
writeToFile(elementName, element); | ||
} | ||
|
||
package(process.argv[2]); |
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 |
---|---|---|
@@ -0,0 +1,75 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const yaml = require('js-yaml'); | ||
const matter = require('gray-matter'); | ||
const marked = require('marked'); | ||
const jsdom = require('jsdom'); | ||
const bcd = require('mdn-browser-compat-data'); | ||
|
||
const { JSDOM } = jsdom; | ||
|
||
function extractFromSiblings(node, terminatorTag, contentType) { | ||
let content = ''; | ||
let sib = node.nextSibling; | ||
while (sib && sib.nodeName != terminatorTag) { | ||
if (sib.outerHTML) { | ||
if (contentType === 'html') { | ||
content += sib.outerHTML; | ||
} else if (contentType === 'text') { | ||
content += sib.textContent; | ||
} | ||
} | ||
sib = sib.nextSibling; | ||
} | ||
return content; | ||
} | ||
|
||
function packageValues(heading, dom) { | ||
const values = []; | ||
const valueHeadings = dom.querySelectorAll('h3'); | ||
for (let valueHeading of valueHeadings) { | ||
let value = { | ||
value: valueHeading.textContent, | ||
description: extractFromSiblings(valueHeading, 'H3', 'html') | ||
} | ||
values.push(value); | ||
} | ||
return values; | ||
} | ||
|
||
function packageAttribute(attributePath) { | ||
const attributeMD = fs.readFileSync(attributePath, 'utf8'); | ||
const {data, content} = matter(attributeMD); | ||
const dom = JSDOM.fragment(marked(content)); | ||
const attribute = {}; | ||
|
||
// extract the name property | ||
const name = dom.querySelector('h1'); | ||
attribute.name = name.textContent; | ||
|
||
// extract the description property | ||
attribute.description = extractFromSiblings(name, 'H2', 'html'); | ||
|
||
// extract the type property | ||
const h2Headings = dom.querySelectorAll('h2'); | ||
const typeHeading = (h2Headings.length === 2)? h2Headings[1]: h2Headings[0]; | ||
attribute.type = extractFromSiblings(typeHeading, 'H2', 'text'); | ||
|
||
// extract the values property | ||
if (h2Headings.length === 2) { | ||
valuesHeading = h2Headings[0]; | ||
attribute.values = packageValues(valuesHeading, dom); | ||
} | ||
|
||
return attribute; | ||
} | ||
|
||
function package(root) { | ||
const attributePaths = fs.readdirSync(root).map(relative => path.join(root, relative)); | ||
return attributePaths.map(packageAttribute); | ||
} | ||
|
||
module.exports = { | ||
package | ||
} |
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 |
---|---|---|
@@ -0,0 +1,48 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const matter = require('gray-matter'); | ||
const marked = require('marked'); | ||
|
||
function packageDescription(examplePath) { | ||
const descriptionMD = fs.readFileSync(path.join(examplePath, 'description.md'), 'utf8'); | ||
const {data, content} = matter(descriptionMD); | ||
data.content = marked(content); | ||
return data; | ||
} | ||
|
||
function packageSources(examplePath) { | ||
const exampleSource = {}; | ||
|
||
const jsPath = path.join(examplePath, 'example.js'); | ||
if (fs.existsSync(jsPath)) { | ||
exampleSource.js = fs.readFileSync(jsPath, 'utf8'); | ||
} | ||
|
||
const cssPath = path.join(examplePath, 'example.css'); | ||
if (fs.existsSync(cssPath)) { | ||
exampleSource.css = fs.readFileSync(cssPath, 'utf8'); | ||
} | ||
|
||
const htmlPath = path.join(examplePath, 'example.html'); | ||
if (fs.existsSync(htmlPath)) { | ||
exampleSource.html = fs.readFileSync(htmlPath, 'utf8'); | ||
} | ||
|
||
return exampleSource; | ||
} | ||
|
||
function packageExample(examplePath) { | ||
return { | ||
description: packageDescription(examplePath), | ||
sources: packageSources(examplePath) | ||
} | ||
} | ||
|
||
function package(paths) { | ||
return paths.map(packageExample); | ||
} | ||
|
||
module.exports = { | ||
package | ||
} |
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 |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const bcd = require('mdn-browser-compat-data'); | ||
|
||
function package(query) { | ||
let data = query.split('.').reduce(function(prev, curr) { | ||
return prev ? prev[curr] : undefined | ||
}, bcd); | ||
return data; | ||
} | ||
|
||
module.exports = { | ||
package | ||
} |
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 |
---|---|---|
@@ -0,0 +1,13 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const marked = require('marked'); | ||
|
||
function package(contributorsPath) { | ||
const contributorsMD = fs.readFileSync(contributorsPath, 'utf8'); | ||
return marked(contributorsMD); | ||
} | ||
|
||
module.exports = { | ||
package | ||
} |
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 |
---|---|---|
@@ -0,0 +1,84 @@ | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
|
||
const yaml = require('js-yaml'); | ||
const matter = require('gray-matter'); | ||
const marked = require('marked'); | ||
const jsdom = require('jsdom'); | ||
const bcd = require('mdn-browser-compat-data'); | ||
|
||
const { JSDOM } = jsdom; | ||
const commentNode = 8; | ||
const namedSections = [ | ||
'short-description', | ||
'overview', | ||
'attributes-text', | ||
'usage-notes', | ||
'accessibility-concerns', | ||
'see-also' | ||
]; | ||
|
||
function extractFromSiblings(node, terminatorTag, contentType) { | ||
let content = ''; | ||
let sib = node.nextSibling; | ||
while (sib && sib.nodeName != terminatorTag) { | ||
if (sib.outerHTML) { | ||
if (contentType === 'html') { | ||
content += sib.outerHTML; | ||
} else if (contentType === 'text') { | ||
content += sib.textContent; | ||
} | ||
} | ||
sib = sib.nextSibling; | ||
} | ||
return content; | ||
} | ||
|
||
function packageValues(heading, dom) { | ||
const values = []; | ||
const valueHeadings = dom.querySelectorAll('h3'); | ||
for (let valueHeading of valueHeadings) { | ||
let value = { | ||
value: valueHeading.textContent, | ||
description: extractFromSiblings(valueHeading, 'H3', 'html') | ||
} | ||
values.push(value); | ||
} | ||
return values; | ||
} | ||
|
||
function getSection(node, sections) { | ||
const sectionName = node.textContent.trim(); | ||
const sectionContent = extractFromSiblings(node, '#comment', 'html'); | ||
const extraSections = []; | ||
|
||
if (namedSections.includes(sectionName)) { | ||
sections[sectionName] = sectionContent; | ||
} else { | ||
const additionalSection = { | ||
name: sectionName, | ||
content: sectionContent | ||
}; | ||
sections['additional-sections'].push(additionalSection); | ||
} | ||
} | ||
|
||
function package(prosePath) { | ||
const proseMD = fs.readFileSync(prosePath, 'utf8'); | ||
const dom = JSDOM.fragment(marked(proseMD)); | ||
const sections = { | ||
'additional-sections': [] | ||
}; | ||
let node = dom.firstChild; | ||
while (node) { | ||
if (node.nodeType === commentNode) { | ||
getSection(node, sections); | ||
} | ||
node = node.nextSibling; | ||
} | ||
return sections; | ||
} | ||
|
||
module.exports = { | ||
package | ||
} |