Skip to content
This repository has been archived by the owner on Sep 7, 2021. It is now read-only.

Commit

Permalink
Merge pull request #14 from wbamberg/packaging
Browse files Browse the repository at this point in the history
Simple packaging for HTML elements
  • Loading branch information
wbamberg authored May 13, 2019
2 parents 6861b4f + 46ad957 commit 9d67a91
Show file tree
Hide file tree
Showing 8 changed files with 308 additions and 15 deletions.
18 changes: 5 additions & 13 deletions content/html/elements/video/prose.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
<!-- <short-description> -->
<!-- short-description -->
The **HTML Video element** (**`<video>`**) embeds a media player which
supports video playback into the document.
<!-- </short-description> -->

<!-- <overview> -->
<!-- overview -->
You can use `<video>` for audio content as well, but the [`<audio>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio)
element may provide a more appropriate user experience.

Expand Down Expand Up @@ -53,9 +51,7 @@ A good general source of information on using HTML `<video>` is the
[Video and audio
content](https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content)
beginner's tutorial.
<!-- </overview> -->

<!-- <usage-notes> -->
<!-- usage-notes -->
Usage notes
-----------

Expand Down Expand Up @@ -103,9 +99,7 @@ AddType video/webm .webm

Your web host may provide an easy interface to MIME type configuration
changes for new technologies until a global update naturally occurs.
<!-- </usage-notes> -->

<!-- <accessibility-concerns> -->
<!-- accessibility-concerns -->
Videos should provide both captions and transcripts that accurately
describe its content (see [Adding captions and subtitles to HTML5
video](https://developer.mozilla.org/en-US/docs/Web/Apps/Fundamentals/Audio_and_video_delivery/Adding_captions_and_subtitles_to_HTML5_video)
Expand Down Expand Up @@ -156,9 +150,7 @@ setting](https://developer.mozilla.org/en-US/docs/Web/API/WebVTT_API#Cue_setting
2.0](https://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-av-only-alt.html)
- [Understanding Success Criterion 1.2.2 | W3C Understanding WCAG
2.0](https://www.w3.org/TR/UNDERSTANDING-WCAG20/media-equiv-captions.html)
<!-- </accessibility-concerns> -->

<!-- <see-also> -->
<!-- see-also -->
See also
--------

Expand Down
13 changes: 11 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,27 @@
},
"scripts": {
"lint-md": "remark content",
"build-json": "node scripts/build-json/build-json.js",
"spell-md": "mdspell -a -n --en-us 'content/**/*.md'"
},
"dependencies": {
"gray-matter": "4.0.2",
"jsdom": "^12.2.0",
"js-yaml": "3.13.1",
"marked": "0.6.2",
"markdown-spellcheck": "1.3.1",
"npm": "^6.4.1",
"mdn-browser-compat-data": "0.x",
"npm": "^6.9.0",
"remark-cli": "6.0.1",
"remark-preset-lint-recommended": "3.0.2"
},
"remarkConfig": {
"plugins": [
"remark-preset-lint-recommended",
["remark-lint-list-item-indent", "space"]
[
"remark-lint-list-item-indent",
"space"
]
]
}
}
60 changes: 60 additions & 0 deletions scripts/build-json/build-json.js
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]);
75 changes: 75 additions & 0 deletions scripts/build-json/compose-attributes.js
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
}
48 changes: 48 additions & 0 deletions scripts/build-json/compose-examples.js
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
}
12 changes: 12 additions & 0 deletions scripts/build-json/resolve-bcd.js
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
}
13 changes: 13 additions & 0 deletions scripts/build-json/resolve-contributors.js
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
}
84 changes: 84 additions & 0 deletions scripts/build-json/slice-prose.js
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
}

0 comments on commit 9d67a91

Please sign in to comment.