From 9c396c1a3ed741fd69e70a4ffd4f708517e40697 Mon Sep 17 00:00:00 2001 From: Niedziolka Michal Date: Wed, 20 Jul 2022 12:56:51 +0200 Subject: [PATCH] Adds height-data.json --- .bobconfigrc | 3 +- lib/heightBuilder.js | 93 ++++++++++++++++++++++++++++++++++++++++++++ lib/mdn-bob.js | 5 +++ lib/processor.js | 41 ++++++++++++++++--- 4 files changed, 136 insertions(+), 6 deletions(-) create mode 100644 lib/heightBuilder.js diff --git a/.bobconfigrc b/.bobconfigrc index 52705310a..d5ed2e0c0 100644 --- a/.bobconfigrc +++ b/.bobconfigrc @@ -11,5 +11,6 @@ "examplesMediaDest": "./docs/media/", "fontsMediaDest": "./docs/media/fonts/", "metaGlob": "./live-examples/**/meta.json", - "pagesDir": "./docs/pages/" + "pagesDir": "./docs/pages/", + "heightData": "./docs/height-data.json" } diff --git a/lib/heightBuilder.js b/lib/heightBuilder.js new file mode 100644 index 000000000..724f57fda --- /dev/null +++ b/lib/heightBuilder.js @@ -0,0 +1,93 @@ +const fse = require("fs-extra"); +const glob = require("glob"); + +const getConfig = require("./config"); +const processor = require("./processor"); + +const config = getConfig(); + +/** + * Converts content of meta.json into array of height data, which are objects containing 'path' and 'height' of an interactive example + * Any examples for which height couldn't be determined are skipped + * @param metaContent - Content of meta.json as an JS object + * @return {{path: string, height: String}[]} array of height data + */ +function getPagesHeightData(metaContent) { + const pageArray = Object.values(metaContent.pages); + const allHeights = pageArray.flatMap(p => getPageHeightData(p)); + return allHeights.filter(p => p !== undefined); +} + +/** + * Returns object holding 'path' and 'height' of interactive example provided as an argument in form of an object which can be found in meta.json files + * 'path' is relative path to interactive example file name, for example: pages/css/function-calc.html + * 'height' is YARI class name used for setting height of that interactive example + * @param page - Object describing single interactive example + * @return {{path: string, height: String}|undefined} height data - object holding 'path' and 'height' of interactive example + */ +function getPageHeightData(page) { + const height = getPageHeight(page); + if(height !== undefined) { + return { + 'path': `pages/${page.type}/${page.fileName}`, + 'height': height + } + } else { + return undefined; + } +} + +/** + * Returns YARI class name used for setting height of interactive example provided as an argument in form of an object which can be found in meta.json files + * @param page - Object describing single interactive example + * @return {String|undefined} height - YARI class name used for setting height of interactive example + */ +function getPageHeight(page) { + if(page.height !== undefined) { + return page.height; + } + + switch(page.type) { + case 'css': + return '';// All examples have the same height + case 'tabbed': + case 'webapi-tabbed': + console.error(`MDN-BOB: (heightBuilder.js) Missing height property for ${page.fileName}`); + return undefined; + case 'js': + // Yari expects those values for JS editor: 'shorter', '', 'taller' + return processor.getJSPageHeight(page.exampleCode); + case 'wat': + // Yari expects those values for WAT editor: 'tabbed-shorter', 'tabbed-standard', 'tabbed-taller' + return 'tabbed-' + processor.getWatPageHeight(page.watExampleCode); + default: + console.error(`MDN-BOB: (heightBuilder.js) Unsupported page type ${page.type}`); + return undefined; + } +} + +/** + * Builds height-data.json containing array of objects with path and height properties, which can be used for setting height of interactive example + */ +function buildHeightData() { + return new Promise((resolve) => { + const metaJSONArray = glob.sync(config.metaGlob, {}); + const heightData = []; + + for (const metaJson of metaJSONArray) { + const file = fse.readJsonSync(metaJson); + + const metaHeights = getPagesHeightData(file); + heightData.push(...metaHeights); + } + + const jsonData = JSON.stringify(heightData, null, 4); + fse.outputFileSync(config.heightData, jsonData); + + resolve("MDN-BOB: Height Data was successfully constructed"); + }); +} + +module.exports = { + buildHeightData, +}; diff --git a/lib/mdn-bob.js b/lib/mdn-bob.js index 41fa11dba..8460896d9 100755 --- a/lib/mdn-bob.js +++ b/lib/mdn-bob.js @@ -5,6 +5,7 @@ const fse = require('fs-extra'); const bundler = require('./bundler'); const getConfig = require('./config'); const pageBuilder = require('./pageBuilder'); +const heightBuilder = require('./heightBuilder') const utils = require('./utils'); /** @@ -39,6 +40,10 @@ function init() { console.info(result); return utils.removeJSBundles(); }) + .then(result => { + console.info(result); + return heightBuilder.buildHeightData(); + }) .then(result => { console.info(result); console.info('MDN-BOB: Build completed successfully'); diff --git a/lib/processor.js b/lib/processor.js index 349b797e2..c7d5183ce 100644 --- a/lib/processor.js +++ b/lib/processor.js @@ -106,11 +106,20 @@ function getJSExampleHeightByLineCount(lineCount) { * @returns {String} jsExample - The example wrapped into code tag */ function preprocessJSExample(exampleCode) { - const lineCount = (exampleCode.match(/\n/g) || []).length + 1; - const height = getJSExampleHeightByLineCount(lineCount); + const height = getHeightByLineCount(exampleCode, getJSExampleHeightByLineCount); return `
${exampleCode}
`; } +/** + * Returns BOB class name used for setting height for JavaScript interactive example present at provided path + * @param {String} sourcePath - Path to JS example source code. For example: 'pages/tabbed/header.html' + * @return {String} height - BOB class name used for setting height + */ +function getJSPageHeight(sourcePath) { + const exampleCode = fse.readFileSync(sourcePath, 'utf8'); + return getHeightByLineCount(exampleCode, getJSExampleHeightByLineCount); +} + /** * Returns the height of the example block based on the line count * @param {Number} lineCount - Count of lines in the source code @@ -135,8 +144,7 @@ function getWatExampleHeightByLineCount(lineCount) { * @returns {String} jsExample - The examples wrapped into code tag */ function preprocessWatExample(watCode, jsCode) { - const lineCount = (watCode.match(/\n/g) || []).length + 1; - const height = getWatExampleHeightByLineCount(lineCount); + const height = getHeightByLineCount(watCode, getWatExampleHeightByLineCount); return `
${watCode}
${jsCode}
@@ -144,7 +152,28 @@ function preprocessWatExample(watCode, jsCode) { } /** - * Process JS example which has written in HTML. + * Returns BOB class name used for setting height for WAT interactive example present at provided path + * @param {String} sourcePath - Path to WAT example source code. For example: 'pages/tabbed/header.html' + * @return {Number} height - BOB class name used for setting height + */ +function getWatPageHeight(watSrc) { + const watCode = fse.readFileSync(watSrc, 'utf8'); + return getHeightByLineCount(watCode, getWatExampleHeightByLineCount); +} + +/** + * Counts amount of lines in provided source code, executes provided function with that amount as an argument and returns result of that function + * @param {String} sourceCode + * @param {Function} linesToHeightFunc - function accepting amount of lines as an argument and returning BOB class name used for setting height + * @return {String} - BOB class name used for setting height + */ +function getHeightByLineCount(sourceCode, linesToHeightFunc) { + const lineCount = (sourceCode.match(/\n/g) || []).length + 1; + return linesToHeightFunc(lineCount); +} + +/** + * Process JS example which has written in HTML. * @param {String} exampleCode - The example source code itself * @param {String} path - path of the example code * @@ -198,4 +227,6 @@ module.exports = { processInclude, processExampleCode, processWat, + getJSPageHeight, + getWatPageHeight };