From cb683f95d2e95156b1c2234ffb70fab87547a39d Mon Sep 17 00:00:00 2001 From: Sanyia Saidova Date: Tue, 19 Apr 2022 23:09:44 +0100 Subject: [PATCH 1/4] Creating script to generate exercises in src This would get added to the package.json scripts, which is intended to run when Netlify builds the files --- client/package.json | 7 +- client/public/Exercises/01-stuff.md | 5 + client/public/Exercises/02-more-stuff.md | 5 + client/scripts/blocks-to-categories.json | 23 +++++ client/scripts/generate-exercises.js | 122 +++++++++++++++++++++++ client/src/App.js | 7 +- 6 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 client/public/Exercises/01-stuff.md create mode 100644 client/public/Exercises/02-more-stuff.md create mode 100644 client/scripts/blocks-to-categories.json create mode 100644 client/scripts/generate-exercises.js diff --git a/client/package.json b/client/package.json index 8b0b3e1..ee589a4 100644 --- a/client/package.json +++ b/client/package.json @@ -21,9 +21,10 @@ "web-vitals": "^2.1.4" }, "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", + "gen-exercises": "node ./scripts/generate-exercises.js ", + "start": "npm run gen-exercises && react-scripts start", + "build": "npm run gen-exercises && react-scripts build", + "test": "npm run gen-exercises && react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { diff --git a/client/public/Exercises/01-stuff.md b/client/public/Exercises/01-stuff.md new file mode 100644 index 0000000..e58d853 --- /dev/null +++ b/client/public/Exercises/01-stuff.md @@ -0,0 +1,5 @@ +## Some stuff + +This lesson is about some stuff™️. + +I'm writing some things here things, blah, blah, blah. \ No newline at end of file diff --git a/client/public/Exercises/02-more-stuff.md b/client/public/Exercises/02-more-stuff.md new file mode 100644 index 0000000..058f13e --- /dev/null +++ b/client/public/Exercises/02-more-stuff.md @@ -0,0 +1,5 @@ +## Some more stuff + +This lesson is about some more stuff™️. + +I'm writing some more things here, blah, blah, blah. \ No newline at end of file diff --git a/client/scripts/blocks-to-categories.json b/client/scripts/blocks-to-categories.json new file mode 100644 index 0000000..17dba87 --- /dev/null +++ b/client/scripts/blocks-to-categories.json @@ -0,0 +1,23 @@ +{ + "things": { + "categoryType": "Values", + "blockType": "get_randomWord" + }, + "here": { + "categoryType": "HTML", + "blockType": "on_start" + }, + "blah": { + "categoryType": "Values", + "blockType": "text" + }, + "with element by ID": { + "categoryType": "HTML", + "blockType": "with_element_by_id" + }, + "set content": { + "categoryType": "HTML", + "blockType": "set_content", + "blockxml": " " + } +} \ No newline at end of file diff --git a/client/scripts/generate-exercises.js b/client/scripts/generate-exercises.js new file mode 100644 index 0000000..6e1497c --- /dev/null +++ b/client/scripts/generate-exercises.js @@ -0,0 +1,122 @@ +const fs = require('fs') +const path = require('path'); + +const btcContents = fs.readFileSync(path.join(__dirname, 'blocks-to-categories.json')) +const btcJson = JSON.parse(btcContents) + +function parseToolbox(text) { + const blockPattern = /(\w+)/g + + let blocks = [...text.matchAll(blockPattern)] + .map((block) => block[1]) + + blocks = [...new Set(blocks)] + + let categories = {} + let toolboxContents = [] + + for (let blockName of blocks) { + if (!(blockName in btcJson)) { + console.warn(`${blockName} not defined in blocks-to-categories.json`) + continue + } + + const blockDetails = btcJson[blockName] + const categoryName = blockDetails.categoryType + + const blockEntry = { + kind: 'block', + type: blockDetails.blockType + } + + if ('blockxml' in blockDetails) { blockEntry.blockxml = blockDetails.blockxml } + + if (categoryName in categories) { + categories[categoryName].push(blockEntry) + } else { + categories[categoryName] = [blockEntry] + } + } + + for (let category in categories) { + toolboxContents.push({ + kind: "category", + name: category, + contents: categories[category] + }) + } + + return JSON.stringify({ + kind: "categoryToolbox", + contents: toolboxContents + }, null, 2) +} + +function writeExercisesIndexJs(exerciseInputDir) { + let exercisesFileNames = fs.readdirSync(exerciseInputDir).filter((filename) => filename.endsWith('.md')) + + exercisesFileNames.forEach((filename) => { + const filePath = path.join(exerciseInputDir, filename) + const fileText = fs.readFileSync(filePath, 'utf8') + const filenameNoExt = filename.slice(0, -3) + + const exerciseOutputDir = path.join(__dirname, '..', 'src', 'Exercises', filenameNoExt) + const exerciseMd = path.join(exerciseOutputDir, 'lesson.md') + const exerciseIndexJs = path.join(exerciseOutputDir, 'index.js') + + fs.mkdirSync(exerciseOutputDir, { recursive: true }) + fs.copyFileSync(filePath, exerciseMd) + + const exerciseIndexJsContent = ` +import LessonMarkdown from "../../LessonMarkdown"; +import markdownUrl from "./lesson.md"; + +export function Lesson() { + return ; +} + +export const toolbox = ${parseToolbox(fileText)}` + + fs.writeFileSync(exerciseIndexJs, exerciseIndexJsContent) + }) +} + +function writeRootExercisesIndexJs(exerciseInputDir) { + let exercisesFileNames = fs.readdirSync(exerciseInputDir).filter((filename) => filename.endsWith('.md')) + const exerciseAliases = [] + + let rootIndexJsContent = "" + const rootIndexJs = path.join(__dirname, '..', 'src', 'Exercises', 'index.js') + + exercisesFileNames.forEach((filename) => { + let exerciseNoExt = filename.slice(0,-3) + + // Starting with _ so that the alias is ES6 compatible, in case file name starts with number + let exerciseAlias = `_${exerciseNoExt.replaceAll('-', '_')}` + + exerciseAliases.push(exerciseAlias) + + rootIndexJsContent += `import * as ${exerciseAlias} from "./${exerciseNoExt}"\n` + }) + + rootIndexJsContent += `\n\nexport default ${JSON + .stringify(exerciseAliases, null, 2) + .replaceAll('"', '')}` + + fs.writeFileSync(rootIndexJs, rootIndexJsContent) +} + +function generateExercises() { + const rootDir = path.join(__dirname, '..') + const relExerciseInputDir = './exercises' + + const absExerciseInputDir = path.join(rootDir, './exercises') + + // Create exercises folders and index + writeExercisesIndexJs(absExerciseInputDir) + + // Create root exercises index + writeRootExercisesIndexJs(absExerciseInputDir) +} + +generateExercises() \ No newline at end of file diff --git a/client/src/App.js b/client/src/App.js index ae8ace5..24bc488 100644 --- a/client/src/App.js +++ b/client/src/App.js @@ -7,8 +7,7 @@ import "./Blocks/dom"; import "./Blocks/cyf"; import useBlockly from "./Blockly/useBlockly"; -import * as Exercise1 from "./Exercises/01-stuff"; -import * as Exercise2 from "./Exercises/02-more-stuff"; +import exercises from "./Exercises" import Split from "react-split-grid"; import TextPanel from "./TextPanel/TextPanel"; @@ -16,16 +15,12 @@ import Output from "./Output/Output"; import Header from "./Layout/Header/Header"; import Menu from "./Layout/Menu/Menu"; import Footer from "./Layout/Footer/Footer"; -import Button from "./Button/Button"; import "./App.scss"; import { ReactComponent as Background } from "../src/svgs/Humaaans-Phone.svg"; Blockly.setLocale(locale); -// just left all this and presumed you will pass whatever you decide to do into the text panel -const exercises = [Exercise1, Exercise2]; - function useExercise() { const [exerciseIndex, setExerciseIndex] = useState(0); From 2eb8d28390a56b6e02053ee65cf5048709cea090 Mon Sep 17 00:00:00 2001 From: Sanyia Saidova Date: Mon, 25 Apr 2022 22:29:52 +0100 Subject: [PATCH 2/4] Moving exercises to root of client directory Makes location less confusing, since public directory is supposed to store static assets that get served to the client --- client/{public/Exercises => exercises}/01-stuff.md | 0 client/{public/Exercises => exercises}/02-more-stuff.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename client/{public/Exercises => exercises}/01-stuff.md (100%) rename client/{public/Exercises => exercises}/02-more-stuff.md (100%) diff --git a/client/public/Exercises/01-stuff.md b/client/exercises/01-stuff.md similarity index 100% rename from client/public/Exercises/01-stuff.md rename to client/exercises/01-stuff.md diff --git a/client/public/Exercises/02-more-stuff.md b/client/exercises/02-more-stuff.md similarity index 100% rename from client/public/Exercises/02-more-stuff.md rename to client/exercises/02-more-stuff.md From c5e8dacefaf26d337ed4ef865d05181fcee039fb Mon Sep 17 00:00:00 2001 From: Sanyia Saidova Date: Mon, 25 Apr 2022 23:36:17 +0100 Subject: [PATCH 3/4] Adding another exercise file To test blocks with identifiable Blockly block IDs --- client/exercises/03-test-content.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 client/exercises/03-test-content.md diff --git a/client/exercises/03-test-content.md b/client/exercises/03-test-content.md new file mode 100644 index 0000000..276d72e --- /dev/null +++ b/client/exercises/03-test-content.md @@ -0,0 +1,7 @@ +## Test lesson + +This lesson is about some more stuff™️. + +I'm writing some more things here, with element by ID, blah, blah. + +Something something set content something else \ No newline at end of file From c3ab80f04bbcf17cd7b876952839a4621bf780f0 Mon Sep 17 00:00:00 2001 From: Sanyia Saidova Date: Tue, 19 Apr 2022 23:09:59 +0100 Subject: [PATCH 4/4] Removing src/Exercises folder since it's now being generated Also adding to .gitignore --- .gitignore | 2 + client/src/Exercises/01-stuff/index.js | 46 ---------------- client/src/Exercises/01-stuff/lesson.md | 5 -- client/src/Exercises/02-more-stuff/index.js | 58 -------------------- client/src/Exercises/02-more-stuff/lesson.md | 5 -- 5 files changed, 2 insertions(+), 114 deletions(-) delete mode 100644 client/src/Exercises/01-stuff/index.js delete mode 100644 client/src/Exercises/01-stuff/lesson.md delete mode 100644 client/src/Exercises/02-more-stuff/index.js delete mode 100644 client/src/Exercises/02-more-stuff/lesson.md diff --git a/.gitignore b/.gitignore index 46096f2..46d2bf0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ node_modules package-lock.json .DS_Store +client/src/Exercises +src/Exercises \ No newline at end of file diff --git a/client/src/Exercises/01-stuff/index.js b/client/src/Exercises/01-stuff/index.js deleted file mode 100644 index 155e81e..0000000 --- a/client/src/Exercises/01-stuff/index.js +++ /dev/null @@ -1,46 +0,0 @@ -import LessonMarkdown from "../../LessonMarkdown"; -import markdownUrl from "./lesson.md"; - -export function Lesson() { - return ; -} - -export const toolbox = { - kind: "categoryToolbox", - contents: [ - { - kind: "category", - name: "Values", - contents: [ - { - kind: "block", - type: "text", - }, - { - kind: "block", - type: "get_randomWord", - }, - ], - }, - { - kind: "category", - name: "HTML", - contents: [ - { - kind: "block", - type: "on_start", - }, - { - kind: "block", - type: "with_element_by_id", - }, - { - kind: "block", - type: "set_content", - blockxml: - " ", - }, - ], - }, - ], -}; diff --git a/client/src/Exercises/01-stuff/lesson.md b/client/src/Exercises/01-stuff/lesson.md deleted file mode 100644 index fd1b8ee..0000000 --- a/client/src/Exercises/01-stuff/lesson.md +++ /dev/null @@ -1,5 +0,0 @@ -## Some stuff - -This lesson is about some stuff™️. - -I'm writing some things here, blah, blah, blah. diff --git a/client/src/Exercises/02-more-stuff/index.js b/client/src/Exercises/02-more-stuff/index.js deleted file mode 100644 index 111e3c6..0000000 --- a/client/src/Exercises/02-more-stuff/index.js +++ /dev/null @@ -1,58 +0,0 @@ -import LessonMarkdown from "../../LessonMarkdown"; -import markdownUrl from "./lesson.md"; - -export function Lesson() { - return ; -} - -export const toolbox = { - kind: "categoryToolbox", - contents: [ - { - kind: "category", - name: "Values", - contents: [ - { - kind: "block", - type: "math_number", - }, - { - kind: "block", - type: "text", - }, - { - kind: "block", - type: "colour_picker", - }, - { - kind: "block", - type: "logic_boolean", - }, - ], - }, - { - kind: "category", - name: "HTML", - contents: [ - { - kind: "block", - type: "on_start", - }, - { - kind: "block", - type: "with_element_by_id", - }, - { - kind: "block", - type: "set_content", - blockxml: - " ", - }, - { - kind: "block", - type: "set_attribute", - }, - ], - }, - ], -}; diff --git a/client/src/Exercises/02-more-stuff/lesson.md b/client/src/Exercises/02-more-stuff/lesson.md deleted file mode 100644 index b8863ec..0000000 --- a/client/src/Exercises/02-more-stuff/lesson.md +++ /dev/null @@ -1,5 +0,0 @@ -## Some more stuff - -This lesson is about some more stuff™️. - -I'm writing some more things here, blah, blah, blah.