From e72c827c570c3c1904eb031f160b902bdd43044d Mon Sep 17 00:00:00 2001 From: emmadal Date: Tue, 19 Oct 2021 02:44:54 +0000 Subject: [PATCH 1/7] Parse markdown and generate JSON file for exercises --- dev/build.js | 5 ++- dev/exo-parser.js | 98 +++++++++++++++++++++++++++++++++++++++++++++++ dev/server.js | 6 ++- package.json | 1 + 4 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 dev/exo-parser.js diff --git a/dev/build.js b/dev/build.js index 25befb35..976cb775 100644 --- a/dev/build.js +++ b/dev/build.js @@ -4,6 +4,7 @@ import { parse, join } from 'path' import * as esbuild from 'esbuild' import { rootDir, DEV, time } from './utils.js' +import { generateExoFile } from './exo-parser.js' const getHash = async head => { if (!head.startsWith('ref:')) return { hash: head.trim(), branch: 'detached' } @@ -12,7 +13,7 @@ const getHash = async head => { const hash = await readFile(join(rootDir, '.git', ...parts), 'utf8') return { hash: hash.trim(), branch } } - + try { const head = await readFile(join(rootDir, '.git/HEAD'), 'utf8') const { hash, branch } = await getHash(head) @@ -62,6 +63,8 @@ const generate = async (file = 'index') => { templates[key]?.replace(//gm, replace) || ``) + await generateExoFile() + return readTemplate(file) } diff --git a/dev/exo-parser.js b/dev/exo-parser.js new file mode 100644 index 00000000..36d0fd88 --- /dev/null +++ b/dev/exo-parser.js @@ -0,0 +1,98 @@ +import { readFile, readdir, writeFile, mkdir, rename } from 'fs/promises' +import { fromMarkdown } from 'mdast-util-from-markdown' +import { fileURLToPath } from 'url' +import { join, dirname } from 'path' + +// returns a flatten array of all the children +const children = (n) => + n.children ? [n, ...n.children.flatMap(children)] : [n] + +const getTrimValue = (n) => n.value?.trim() +const textContent = (n) => + children(n).map(getTrimValue).filter(Boolean).join(' ') || '' + +const isH1 = (node) => node.type === 'heading' && node.depth === 1 +const isH2 = (node) => node.type === 'heading' && node.depth === 2 +const isH3 = (node) => node.type === 'heading' && node.depth === 3 +const text = (node) => node.type === 'paragraph' +const isList = (node) => node.type === 'list' + +const parseContent = (nodeList) => { + const content = { description: '' } + let mode, + test = text + for (const node of nodeList) { + if (!content.title && isH1(node)) { + content.title = textContent(node) + } else if (isH2(node)) { + mode = textContent(node).toLowerCase() + content[mode] = [] + } else if (mode === 'notions') { + if (isList(node)) { + let ul = node.children + .flatMap((e) => e.children) + .flatMap((v) => v.children) + .map((k) => k.value) + content.notions = ul + } + } else if (mode === 'instructions') { + if (text(node)) { + let p = node.children.map((e) => e.value) + content.instructions = p.join('') + } + } else if (mode === 'tests') { + if (isH3(node)) { + test = { name: textContent(node) } + content.tests.push(test) + } else if (test && node.type === 'code') { + test.code = textContent(node) + test.lang = node.lang + } else { + console.warn('ignored node', node) + } + } else if (mode) { + // any other mode is stored in raw tree + content[mode].push(node) + } else { + // before any mode is set, we are writing the description + content.description += textContent(node) + } + } + return content +} + +const dirList = await readdir('js-introduction') +const entries = await Promise.all( + dirList.map(async (name) => { + const file = await readFile(join('js-introduction/', name)) + const root = fromMarkdown(file) + return [name, parseContent(root.children)] + }), +) + +export const generateExoFile = async () => { + dirList.map(async (filename) => { + const data = Object.fromEntries(entries)[`${filename}`] + + await Promise.all([ + // Create each exercise json file from a markdown file + writeFile(`${filename.split('.md')[0]}.json`, JSON.stringify(data)), + + mkdir(join(fileURLToPath(dirname(import.meta.url)), '../exoBundle'), { + recursive: true, + }), + ]) + }) + + const rootFile = await ( + await readdir('./') + ).filter((file) => file.includes('exercise.json')) + + rootFile.map(async (file) => { + // Move each exercise json file in exo directory bundle + await rename( + join(fileURLToPath(dirname(import.meta.url)), `../${file}`), + join(fileURLToPath(dirname(import.meta.url)), `../exoBundle/${file}`), + ) + }) +} diff --git a/dev/server.js b/dev/server.js index 0f1d5bb5..00e16d05 100644 --- a/dev/server.js +++ b/dev/server.js @@ -3,6 +3,7 @@ import { readFile, writeFile } from 'fs/promises' import { join } from 'path' import { rootDir } from './utils.js' +import { generateExoFile } from './exo-parser.js' // Start esbuild's server on a random local port const { generate, serve } = await import('./build.js') @@ -53,4 +54,7 @@ createServer(async (req, res) => { // Apply headers from the worker sendResponse({ body, options, res }) -}).listen(PORT, () => console.log(`Dev server ready on ${process.env.DOMAIN}`)) +}).listen(PORT, async () => { + await generateExoFile() + console.log(`Dev server ready on ${process.env.DOMAIN}`) +}) diff --git a/package.json b/package.json index 703b4077..15b3c6c8 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "esbuild": "^0.11.2", "fast-toml": "^0.5.4", + "mdast-util-from-markdown": "^1.0.4", "preact": "^10.5.13" } } From 20affb84da2ebed7e47a627c61a9cd0cd1f61d46 Mon Sep 17 00:00:00 2001 From: emmadal Date: Thu, 21 Oct 2021 15:34:29 +0000 Subject: [PATCH 2/7] continue to fix suggestion in the old PR --- dev/build.js | 21 ++++++++++--- dev/exo-parser.js | 76 +++++++++++++++++++---------------------------- dev/server.js | 8 +++-- 3 files changed, 52 insertions(+), 53 deletions(-) diff --git a/dev/build.js b/dev/build.js index 976cb775..c08d4afe 100644 --- a/dev/build.js +++ b/dev/build.js @@ -1,10 +1,11 @@ import { readFile, readdir, writeFile, mkdir } from 'fs/promises' import { parse, join } from 'path' +import { fromMarkdown } from 'mdast-util-from-markdown' import * as esbuild from 'esbuild' import { rootDir, DEV, time } from './utils.js' -import { generateExoFile } from './exo-parser.js' +import { parseContent } from './exo-parser.js' const getHash = async head => { if (!head.startsWith('ref:')) return { hash: head.trim(), branch: 'detached' } @@ -24,6 +25,21 @@ try { process.env.HASH = `unk@${now.toString(36)}` } +export const exoJsDir = async () => + await readdir(join(rootDir, 'js-introduction')) + +export const readJSExo = async () => { + const dirList = await exoJsDir() + const entries = await Promise.all( + dirList.map(async (name) => { + const file = await readFile(join(rootDir, 'js-introduction', name)) + const root = fromMarkdown(file) + return [name, parseContent(root.children)] + }), + ) + return entries +} + const templateDir = join(rootDir, 'template') const readEntry = async ({ name, ext, base }) => [ name, @@ -62,9 +78,6 @@ const generate = async (file = 'index') => { (cache[key] = templates[key]?.replace(//gm, replace) || ``) - - await generateExoFile() - return readTemplate(file) } diff --git a/dev/exo-parser.js b/dev/exo-parser.js index 36d0fd88..29ff1f4c 100644 --- a/dev/exo-parser.js +++ b/dev/exo-parser.js @@ -1,12 +1,15 @@ -import { readFile, readdir, writeFile, mkdir, rename } from 'fs/promises' -import { fromMarkdown } from 'mdast-util-from-markdown' -import { fileURLToPath } from 'url' -import { join, dirname } from 'path' +import { readdir, writeFile, mkdir, rename } from 'fs/promises' +import { join } from 'path' +import { readJSExo, exoJsDir } from './build.js' +import { rootDir } from './utils.js' // returns a flatten array of all the children const children = (n) => n.children ? [n, ...n.children.flatMap(children)] : [n] +const moveFile = async (file) => + await rename(join(rootDir, file), join(rootDir, 'exoBundle', file)) + const getTrimValue = (n) => n.value?.trim() const textContent = (n) => children(n).map(getTrimValue).filter(Boolean).join(' ') || '' @@ -14,13 +17,15 @@ const textContent = (n) => const isH1 = (node) => node.type === 'heading' && node.depth === 1 const isH2 = (node) => node.type === 'heading' && node.depth === 2 const isH3 = (node) => node.type === 'heading' && node.depth === 3 -const text = (node) => node.type === 'paragraph' -const isList = (node) => node.type === 'list' +const isP = (node) => node.type === 'paragraph' || node.type === 'text' +const isCODE = (node) => node.type === 'code' || node.type === 'inlineCode' +const isBLOCK = (node) => node.type === 'blockquote' +const isLI = (node) => node.type === 'list' -const parseContent = (nodeList) => { +export const parseContent = (nodeList) => { const content = { description: '' } let mode, - test = text + test = isP for (const node of nodeList) { if (!content.title && isH1(node)) { content.title = textContent(node) @@ -28,23 +33,20 @@ const parseContent = (nodeList) => { mode = textContent(node).toLowerCase() content[mode] = [] } else if (mode === 'notions') { - if (isList(node)) { - let ul = node.children - .flatMap((e) => e.children) - .flatMap((v) => v.children) - .map((k) => k.value) - content.notions = ul + if (isLI(node)) { + content.notions = children(node).map(getTrimValue).filter(Boolean) } } else if (mode === 'instructions') { - if (text(node)) { - let p = node.children.map((e) => e.value) - content.instructions = p.join('') + if (isP(node) || isLI(node)) { + content.instructions = + children(node).map(getTrimValue).filter(Boolean).join(' ') } + } else if (mode === 'tests') { if (isH3(node)) { test = { name: textContent(node) } content.tests.push(test) - } else if (test && node.type === 'code') { + } else if (test && isCODE(node)) { test.code = textContent(node) test.lang = node.lang } else { @@ -55,44 +57,26 @@ const parseContent = (nodeList) => { content[mode].push(node) } else { // before any mode is set, we are writing the description - content.description += textContent(node) + content.description += `${textContent(node).trim()}\n` } } return content } -const dirList = await readdir('js-introduction') -const entries = await Promise.all( - dirList.map(async (name) => { - const file = await readFile(join('js-introduction/', name)) - const root = fromMarkdown(file) - return [name, parseContent(root.children)] - }), -) - -export const generateExoFile = async () => { +export const getJsonExoFile = async () => { + const dirList = await exoJsDir() + const entries = await readJSExo() dirList.map(async (filename) => { - const data = Object.fromEntries(entries)[`${filename}`] - + const data = Object.fromEntries(entries)[filename] await Promise.all([ // Create each exercise json file from a markdown file writeFile(`${filename.split('.md')[0]}.json`, JSON.stringify(data)), - - mkdir(join(fileURLToPath(dirname(import.meta.url)), '../exoBundle'), { - recursive: true, - }), + mkdir(join(rootDir, 'exoBundle'), { recursive: true }), ]) }) - const rootFile = await ( - await readdir('./') - ).filter((file) => file.includes('exercise.json')) - - rootFile.map(async (file) => { - // Move each exercise json file in exo directory bundle - await rename( - join(fileURLToPath(dirname(import.meta.url)), `../${file}`), - join(fileURLToPath(dirname(import.meta.url)), `../exoBundle/${file}`), - ) - }) + // read root directory and move each exo json file into exoBundle directory + await (await readdir(rootDir)) + .filter((file) => file.includes('exercise.json')) + .map(moveFile) } diff --git a/dev/server.js b/dev/server.js index 00e16d05..46e0b91a 100644 --- a/dev/server.js +++ b/dev/server.js @@ -3,7 +3,7 @@ import { readFile, writeFile } from 'fs/promises' import { join } from 'path' import { rootDir } from './utils.js' -import { generateExoFile } from './exo-parser.js' +import { getJsonExoFile } from './exo-parser.js' // Start esbuild's server on a random local port const { generate, serve } = await import('./build.js') @@ -13,6 +13,9 @@ const { host: hostname, port } = await serve() const PORT = process.env.PORT || port + 1 process.env.DOMAIN = process.env.DOMAIN || `http://localhost:${PORT}` +// generate bundle for js-introduction exercise +await getJsonExoFile() + // run tests await (await import('./test-runner.js')).run() @@ -54,7 +57,6 @@ createServer(async (req, res) => { // Apply headers from the worker sendResponse({ body, options, res }) -}).listen(PORT, async () => { - await generateExoFile() +}).listen(PORT, () => { console.log(`Dev server ready on ${process.env.DOMAIN}`) }) From 090ccf6f83b2f56d4ccf85a72611e6167a6da736 Mon Sep 17 00:00:00 2001 From: emmadal Date: Thu, 21 Oct 2021 16:26:02 +0000 Subject: [PATCH 3/7] directory name for windows compatibility --- dev/build.js | 3 ++- dev/exo-parser.js | 23 ++++++++++++++--------- dev/server.js | 4 ++-- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/dev/build.js b/dev/build.js index c08d4afe..866c99e5 100644 --- a/dev/build.js +++ b/dev/build.js @@ -5,7 +5,7 @@ import { fromMarkdown } from 'mdast-util-from-markdown' import * as esbuild from 'esbuild' import { rootDir, DEV, time } from './utils.js' -import { parseContent } from './exo-parser.js' +import { parseContent, generateJSONExo } from './exo-parser.js' const getHash = async head => { if (!head.startsWith('ref:')) return { hash: head.trim(), branch: 'detached' } @@ -68,6 +68,7 @@ const config = { const serve = () => esbuild.serve({ servedir }, config) const generate = async (file = 'index') => { + await generateJSONExo() const content = await readdir(templateDir) const entries = await Promise.all(content.map(parse).map(readEntry)) const templates = Object.fromEntries(entries) diff --git a/dev/exo-parser.js b/dev/exo-parser.js index 29ff1f4c..d1709475 100644 --- a/dev/exo-parser.js +++ b/dev/exo-parser.js @@ -8,7 +8,7 @@ const children = (n) => n.children ? [n, ...n.children.flatMap(children)] : [n] const moveFile = async (file) => - await rename(join(rootDir, file), join(rootDir, 'exoBundle', file)) + await rename(join(rootDir, file), join(rootDir, 'exobundle', file)) const getTrimValue = (n) => n.value?.trim() const textContent = (n) => @@ -22,6 +22,8 @@ const isCODE = (node) => node.type === 'code' || node.type === 'inlineCode' const isBLOCK = (node) => node.type === 'blockquote' const isLI = (node) => node.type === 'list' +const contentRootDir = await readdir(rootDir) + export const parseContent = (nodeList) => { const content = { description: '' } let mode, @@ -38,10 +40,11 @@ export const parseContent = (nodeList) => { } } else if (mode === 'instructions') { if (isP(node) || isLI(node)) { - content.instructions = - children(node).map(getTrimValue).filter(Boolean).join(' ') + content.instructions = children(node) + .map(getTrimValue) + .filter(Boolean) + .join(' ') } - } else if (mode === 'tests') { if (isH3(node)) { test = { name: textContent(node) } @@ -63,7 +66,7 @@ export const parseContent = (nodeList) => { return content } -export const getJsonExoFile = async () => { +export const generateJSONExo = async () => { const dirList = await exoJsDir() const entries = await readJSExo() dirList.map(async (filename) => { @@ -71,12 +74,14 @@ export const getJsonExoFile = async () => { await Promise.all([ // Create each exercise json file from a markdown file writeFile(`${filename.split('.md')[0]}.json`, JSON.stringify(data)), - mkdir(join(rootDir, 'exoBundle'), { recursive: true }), + mkdir(join(rootDir, 'exobundle'), { recursive: true }), ]) }) // read root directory and move each exo json file into exoBundle directory - await (await readdir(rootDir)) - .filter((file) => file.includes('exercise.json')) - .map(moveFile) + return await Promise.all( + contentRootDir + .filter((file) => file.includes('exercise.json')) + .map(moveFile), + ) } diff --git a/dev/server.js b/dev/server.js index 46e0b91a..a9ed7b96 100644 --- a/dev/server.js +++ b/dev/server.js @@ -3,7 +3,7 @@ import { readFile, writeFile } from 'fs/promises' import { join } from 'path' import { rootDir } from './utils.js' -import { getJsonExoFile } from './exo-parser.js' +import { generateJSONExo } from './exo-parser.js' // Start esbuild's server on a random local port const { generate, serve } = await import('./build.js') @@ -14,7 +14,7 @@ const PORT = process.env.PORT || port + 1 process.env.DOMAIN = process.env.DOMAIN || `http://localhost:${PORT}` // generate bundle for js-introduction exercise -await getJsonExoFile() +await generateJSONExo() // run tests await (await import('./test-runner.js')).run() From 64a0e3755360968450262c4e505c9092834edd78 Mon Sep 17 00:00:00 2001 From: emmadal Date: Tue, 26 Oct 2021 19:50:14 +0000 Subject: [PATCH 4/7] fix recents commentaries --- dev/build.js | 3 +++ dev/exo-parser.js | 30 +++++++++--------------------- dev/server.js | 4 ---- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/dev/build.js b/dev/build.js index 866c99e5..e5d2ac45 100644 --- a/dev/build.js +++ b/dev/build.js @@ -28,6 +28,9 @@ try { export const exoJsDir = async () => await readdir(join(rootDir, 'js-introduction')) +export const bundleJSONDir = async (dirName) => + await mkdir(join(rootDir, dirName), { recursive: true }) + export const readJSExo = async () => { const dirList = await exoJsDir() const entries = await Promise.all( diff --git a/dev/exo-parser.js b/dev/exo-parser.js index d1709475..e54ab375 100644 --- a/dev/exo-parser.js +++ b/dev/exo-parser.js @@ -1,15 +1,12 @@ -import { readdir, writeFile, mkdir, rename } from 'fs/promises' +import { readdir, writeFile, rename } from 'fs/promises' import { join } from 'path' -import { readJSExo, exoJsDir } from './build.js' +import { readJSExo, exoJsDir, bundleJSONDir } from './build.js' import { rootDir } from './utils.js' // returns a flatten array of all the children const children = (n) => n.children ? [n, ...n.children.flatMap(children)] : [n] -const moveFile = async (file) => - await rename(join(rootDir, file), join(rootDir, 'exobundle', file)) - const getTrimValue = (n) => n.value?.trim() const textContent = (n) => children(n).map(getTrimValue).filter(Boolean).join(' ') || '' @@ -19,11 +16,8 @@ const isH2 = (node) => node.type === 'heading' && node.depth === 2 const isH3 = (node) => node.type === 'heading' && node.depth === 3 const isP = (node) => node.type === 'paragraph' || node.type === 'text' const isCODE = (node) => node.type === 'code' || node.type === 'inlineCode' -const isBLOCK = (node) => node.type === 'blockquote' const isLI = (node) => node.type === 'list' -const contentRootDir = await readdir(rootDir) - export const parseContent = (nodeList) => { const content = { description: '' } let mode, @@ -69,19 +63,13 @@ export const parseContent = (nodeList) => { export const generateJSONExo = async () => { const dirList = await exoJsDir() const entries = await readJSExo() - dirList.map(async (filename) => { - const data = Object.fromEntries(entries)[filename] - await Promise.all([ - // Create each exercise json file from a markdown file - writeFile(`${filename.split('.md')[0]}.json`, JSON.stringify(data)), - mkdir(join(rootDir, 'exobundle'), { recursive: true }), - ]) + const exobundle = await bundleJSONDir('exobundle') + dirList.map(async (file) => { + const data = Object.fromEntries(entries)[file] + await writeFile(`${file.split('.md')[0]}.json`, JSON.stringify(data)) }) - // read root directory and move each exo json file into exoBundle directory - return await Promise.all( - contentRootDir - .filter((file) => file.includes('exercise.json')) - .map(moveFile), - ) + await (await readdir(rootDir)) + .filter((filename) => filename.includes('exercise.json')) + .map((e) => rename(join(rootDir, e), join(exobundle, e))) } diff --git a/dev/server.js b/dev/server.js index a9ed7b96..df9a4bbd 100644 --- a/dev/server.js +++ b/dev/server.js @@ -3,7 +3,6 @@ import { readFile, writeFile } from 'fs/promises' import { join } from 'path' import { rootDir } from './utils.js' -import { generateJSONExo } from './exo-parser.js' // Start esbuild's server on a random local port const { generate, serve } = await import('./build.js') @@ -13,9 +12,6 @@ const { host: hostname, port } = await serve() const PORT = process.env.PORT || port + 1 process.env.DOMAIN = process.env.DOMAIN || `http://localhost:${PORT}` -// generate bundle for js-introduction exercise -await generateJSONExo() - // run tests await (await import('./test-runner.js')).run() From bd3d8446a4daba9d89b5ccb5ce160fd48108755f Mon Sep 17 00:00:00 2001 From: emmadal Date: Tue, 26 Oct 2021 20:37:08 +0000 Subject: [PATCH 5/7] remove unusable await --- dev/build.js | 7 +++---- dev/exo-parser.js | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/dev/build.js b/dev/build.js index e5d2ac45..ca3209c3 100644 --- a/dev/build.js +++ b/dev/build.js @@ -25,11 +25,10 @@ try { process.env.HASH = `unk@${now.toString(36)}` } -export const exoJsDir = async () => - await readdir(join(rootDir, 'js-introduction')) +export const exoJsDir = () => readdir(join(rootDir, 'js-introduction')) -export const bundleJSONDir = async (dirName) => - await mkdir(join(rootDir, dirName), { recursive: true }) +export const bundleJSONDir = (dirName) => + mkdir(join(rootDir, dirName), { recursive: true }) export const readJSExo = async () => { const dirList = await exoJsDir() diff --git a/dev/exo-parser.js b/dev/exo-parser.js index e54ab375..06effb65 100644 --- a/dev/exo-parser.js +++ b/dev/exo-parser.js @@ -73,3 +73,5 @@ export const generateJSONExo = async () => { .filter((filename) => filename.includes('exercise.json')) .map((e) => rename(join(rootDir, e), join(exobundle, e))) } + +await generateJSONExo() From 2a28b85cd909f2e38d1536ff0f3d0586b298c9f2 Mon Sep 17 00:00:00 2001 From: emmadal Date: Wed, 27 Oct 2021 09:04:18 +0000 Subject: [PATCH 6/7] remove generate json function --- dev/exo-parser.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/dev/exo-parser.js b/dev/exo-parser.js index 06effb65..e54ab375 100644 --- a/dev/exo-parser.js +++ b/dev/exo-parser.js @@ -73,5 +73,3 @@ export const generateJSONExo = async () => { .filter((filename) => filename.includes('exercise.json')) .map((e) => rename(join(rootDir, e), join(exobundle, e))) } - -await generateJSONExo() From 0842a279d7356455164570eba32289a5cf0f3fee Mon Sep 17 00:00:00 2001 From: Clement Denis Date: Sun, 31 Oct 2021 13:45:50 +0000 Subject: [PATCH 7/7] dev/build: rework content markdown parser --- dev/build.js | 24 +++++++----------------- dev/exo-parser.js | 34 ++++++++++++++++++++-------------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/dev/build.js b/dev/build.js index ca3209c3..b80abf62 100644 --- a/dev/build.js +++ b/dev/build.js @@ -1,13 +1,12 @@ import { readFile, readdir, writeFile, mkdir } from 'fs/promises' import { parse, join } from 'path' -import { fromMarkdown } from 'mdast-util-from-markdown' import * as esbuild from 'esbuild' import { rootDir, DEV, time } from './utils.js' -import { parseContent, generateJSONExo } from './exo-parser.js' +import { generateContentJSON } from './exo-parser.js' -const getHash = async head => { +const getHash = async (head) => { if (!head.startsWith('ref:')) return { hash: head.trim(), branch: 'detached' } const parts = head.split(' ')[1].trim().split('/') const branch = parts[parts.length - 1] @@ -20,7 +19,10 @@ try { const { hash, branch } = await getHash(head) process.env.HASH = `${branch}@${hash.trim()}` } catch (err) { - console.warn('Unable to load git commit version, fallback to time based hash', err) + console.warn( + 'Unable to load git commit version, fallback to time based hash', + err, + ) const now = Math.floor((Date.now() - 16e11) / 1000) process.env.HASH = `unk@${now.toString(36)}` } @@ -30,18 +32,6 @@ export const exoJsDir = () => readdir(join(rootDir, 'js-introduction')) export const bundleJSONDir = (dirName) => mkdir(join(rootDir, dirName), { recursive: true }) -export const readJSExo = async () => { - const dirList = await exoJsDir() - const entries = await Promise.all( - dirList.map(async (name) => { - const file = await readFile(join(rootDir, 'js-introduction', name)) - const root = fromMarkdown(file) - return [name, parseContent(root.children)] - }), - ) - return entries -} - const templateDir = join(rootDir, 'template') const readEntry = async ({ name, ext, base }) => [ name, @@ -70,7 +60,7 @@ const config = { const serve = () => esbuild.serve({ servedir }, config) const generate = async (file = 'index') => { - await generateJSONExo() + await generateContentJSON('js-introduction', 'public') const content = await readdir(templateDir) const entries = await Promise.all(content.map(parse).map(readEntry)) const templates = Object.fromEntries(entries) diff --git a/dev/exo-parser.js b/dev/exo-parser.js index e54ab375..5d126146 100644 --- a/dev/exo-parser.js +++ b/dev/exo-parser.js @@ -1,6 +1,8 @@ -import { readdir, writeFile, rename } from 'fs/promises' -import { join } from 'path' -import { readJSExo, exoJsDir, bundleJSONDir } from './build.js' +import { readdir, writeFile, readFile, mkdir } from 'fs/promises' +import { join, parse as pathParse } from 'path' + +import { fromMarkdown } from 'mdast-util-from-markdown' + import { rootDir } from './utils.js' // returns a flatten array of all the children @@ -18,7 +20,7 @@ const isP = (node) => node.type === 'paragraph' || node.type === 'text' const isCODE = (node) => node.type === 'code' || node.type === 'inlineCode' const isLI = (node) => node.type === 'list' -export const parseContent = (nodeList) => { +const parseContent = (nodeList) => { const content = { description: '' } let mode, test = isP @@ -60,16 +62,20 @@ export const parseContent = (nodeList) => { return content } -export const generateJSONExo = async () => { - const dirList = await exoJsDir() - const entries = await readJSExo() - const exobundle = await bundleJSONDir('exobundle') - dirList.map(async (file) => { - const data = Object.fromEntries(entries)[file] - await writeFile(`${file.split('.md')[0]}.json`, JSON.stringify(data)) +const readdirParse = async (path) => + (await readdir(join(path))).map((file) => pathParse(join(path, file))) + +export const generateContentJSON = async (input, ouput) => { + const dirList = await readdirParse(join(rootDir, input)) + const contentProcessing = dirList.map(async ({ dir, base, name }) => { + const content = await readFile(join(dir, base)) + const root = fromMarkdown(content) + const parsed = parseContent(root.children) + const outDir = join(rootDir, ouput, dir.slice(rootDir.length)) + await mkdir(outDir, { recursive: true }) + await writeFile(join(outDir, `${name}.json`), JSON.stringify(parsed)) + return [name, parsed] }) - await (await readdir(rootDir)) - .filter((filename) => filename.includes('exercise.json')) - .map((e) => rename(join(rootDir, e), join(exobundle, e))) + return Object.fromEntries(await Promise.all(contentProcessing)) }