diff --git a/public/consolidated/_index.json b/public/consolidated/_index.json index fb8c7e77..c5640dd3 100644 --- a/public/consolidated/_index.json +++ b/public/consolidated/_index.json @@ -1,58 +1,72 @@ [ { - "lang": "C", - "icon": "/icons/c.svg" + "name": "C", + "icon": "/icons/c.svg", + "subLanguages": [] }, { - "lang": "CPP", - "icon": "/icons/cpp.svg" + "name": "CPP", + "icon": "/icons/cpp.svg", + "subLanguages": [] }, { - "lang": "CSHARP", - "icon": "/icons/csharp.svg" + "name": "CSHARP", + "icon": "/icons/csharp.svg", + "subLanguages": [] }, { - "lang": "CSS", - "icon": "/icons/css.svg" + "name": "CSS", + "icon": "/icons/css.svg", + "subLanguages": [] }, { - "lang": "HASKELL", - "icon": "/icons/haskell.svg" + "name": "HASKELL", + "icon": "/icons/haskell.svg", + "subLanguages": [] }, { - "lang": "HTML", - "icon": "/icons/html.svg" + "name": "HTML", + "icon": "/icons/html.svg", + "subLanguages": [] }, { - "lang": "JAVA", - "icon": "/icons/java.svg" + "name": "JAVA", + "icon": "/icons/java.svg", + "subLanguages": [] }, { - "lang": "JAVASCRIPT", - "icon": "/icons/javascript.svg" + "name": "JAVASCRIPT", + "icon": "/icons/javascript.svg", + "subLanguages": [] }, { - "lang": "PYTHON", - "icon": "/icons/python.svg" + "name": "PYTHON", + "icon": "/icons/python.svg", + "subLanguages": [] }, { - "lang": "REGEX", - "icon": "/icons/regex.svg" + "name": "REGEX", + "icon": "/icons/regex.svg", + "subLanguages": [] }, { - "lang": "RUBY", - "icon": "/icons/ruby.svg" + "name": "RUBY", + "icon": "/icons/ruby.svg", + "subLanguages": [] }, { - "lang": "RUST", - "icon": "/icons/rust.svg" + "name": "RUST", + "icon": "/icons/rust.svg", + "subLanguages": [] }, { - "lang": "SCSS", - "icon": "/icons/scss.svg" + "name": "SCSS", + "icon": "/icons/scss.svg", + "subLanguages": [] }, { - "lang": "TYPESCRIPT", - "icon": "/icons/typescript.svg" + "name": "TYPESCRIPT", + "icon": "/icons/typescript.svg", + "subLanguages": [] } ] \ No newline at end of file diff --git a/public/consolidated/c.json b/public/consolidated/c.json index a9258611..2343c989 100644 --- a/public/consolidated/c.json +++ b/public/consolidated/c.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -16,7 +16,7 @@ ] }, { - "categoryName": "Mathematical Functions", + "name": "Mathematical Functions", "snippets": [ { "title": "Factorial Function", diff --git a/public/consolidated/cpp.json b/public/consolidated/cpp.json index 6427f04f..75698cc0 100644 --- a/public/consolidated/cpp.json +++ b/public/consolidated/cpp.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -16,7 +16,7 @@ ] }, { - "categoryName": "Data Structure Conversion", + "name": "Data Structure Conversion", "snippets": [ { "title": "Vector to Queue", @@ -33,7 +33,7 @@ ] }, { - "categoryName": "Debuging", + "name": "Debugging", "snippets": [ { "title": "Vector Print", @@ -50,7 +50,7 @@ ] }, { - "categoryName": "Math And Numbers", + "name": "Math And Numbers", "snippets": [ { "title": "Check Prime Number", @@ -66,7 +66,7 @@ ] }, { - "categoryName": "String Manipulation", + "name": "String Manipulation", "snippets": [ { "title": "Reverse String", diff --git a/public/consolidated/csharp.json b/public/consolidated/csharp.json index 63ff0ec1..fbd87ed4 100644 --- a/public/consolidated/csharp.json +++ b/public/consolidated/csharp.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -16,7 +16,7 @@ ] }, { - "categoryName": "Guid Utilities", + "name": "Guid Utilities", "snippets": [ { "title": "Generate GUID", @@ -43,7 +43,7 @@ ] }, { - "categoryName": "Jwt Utilities", + "name": "Jwt Utilities", "snippets": [ { "title": "Decode JWT", @@ -70,7 +70,7 @@ ] }, { - "categoryName": "List Utilities", + "name": "List Utilities", "snippets": [ { "title": "Swap items at index", @@ -86,7 +86,7 @@ ] }, { - "categoryName": "String Utilities", + "name": "String Utilities", "snippets": [ { "title": "Capitalize first letter", diff --git a/public/consolidated/css.json b/public/consolidated/css.json index b759c611..359088c9 100644 --- a/public/consolidated/css.json +++ b/public/consolidated/css.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Buttons", + "name": "Buttons", "snippets": [ { "title": "3D Button Effect", @@ -42,7 +42,7 @@ ] }, { - "categoryName": "Effects", + "name": "Effects", "snippets": [ { "title": "Blur Background", @@ -83,7 +83,7 @@ ] }, { - "categoryName": "Layouts", + "name": "Layouts", "snippets": [ { "title": "CSS Reset", @@ -146,7 +146,7 @@ ] }, { - "categoryName": "Typography", + "name": "Typography", "snippets": [ { "title": "Letter Spacing", diff --git a/public/consolidated/haskell.json b/public/consolidated/haskell.json index b4a97f3c..d199bba5 100644 --- a/public/consolidated/haskell.json +++ b/public/consolidated/haskell.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Array Manipulation", + "name": "Array Manipulation", "snippets": [ { "title": "Binary Search", @@ -41,7 +41,7 @@ ] }, { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -58,7 +58,7 @@ ] }, { - "categoryName": "File Handling", + "name": "File Handling", "snippets": [ { "title": "Find Files in Directory by Type", @@ -89,7 +89,7 @@ ] }, { - "categoryName": "Monads", + "name": "Monads", "snippets": [ { "title": "Either Monad for Error Handling", @@ -141,7 +141,7 @@ ] }, { - "categoryName": "String Manipulation", + "name": "String Manipulation", "snippets": [ { "title": "CamelCase to snake_case", diff --git a/public/consolidated/html.json b/public/consolidated/html.json index f7635148..1509d6d5 100644 --- a/public/consolidated/html.json +++ b/public/consolidated/html.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Basic Layouts", + "name": "Basic Layouts", "snippets": [ { "title": "Grid Layout with Navigation", diff --git a/public/consolidated/java.json b/public/consolidated/java.json index f00ab589..3a36e17d 100644 --- a/public/consolidated/java.json +++ b/public/consolidated/java.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello-World", diff --git a/public/consolidated/javascript.json b/public/consolidated/javascript.json index 2e8c8f97..1b49645a 100644 --- a/public/consolidated/javascript.json +++ b/public/consolidated/javascript.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Array Manipulation", + "name": "Array Manipulation", "snippets": [ { "title": "Partition Array", @@ -62,7 +62,7 @@ ] }, { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -78,7 +78,7 @@ ] }, { - "categoryName": "Color Manipulation", + "name": "Color Manipulation", "snippets": [ { "title": "RGB to Hex Color", @@ -94,7 +94,7 @@ ] }, { - "categoryName": "Date And Time", + "name": "Date And Time", "snippets": [ { "title": "Check Leap Year", @@ -191,7 +191,7 @@ ] }, { - "categoryName": "Dom Manipulation", + "name": "Dom Manipulation", "snippets": [ { "title": "Change Element Style", @@ -218,7 +218,7 @@ ] }, { - "categoryName": "Function Utilities", + "name": "Function Utilities", "snippets": [ { "title": "Compose Functions", @@ -327,7 +327,7 @@ ] }, { - "categoryName": "Local Storage", + "name": "Local Storage", "snippets": [ { "title": "Add Item to localStorage", @@ -365,7 +365,7 @@ ] }, { - "categoryName": "Mathematical Functions", + "name": "Mathematical Functions", "snippets": [ { "title": "Greatest Common Divisor", @@ -381,7 +381,7 @@ ] }, { - "categoryName": "Number Formatting", + "name": "Number Formatting", "snippets": [ { "title": "Convert Number to Currency", @@ -463,7 +463,7 @@ ] }, { - "categoryName": "Object Manipulation", + "name": "Object Manipulation", "snippets": [ { "title": "Check if Object is Empty", @@ -628,7 +628,7 @@ ] }, { - "categoryName": "String Manipulation", + "name": "String Manipulation", "snippets": [ { "title": "Capitalize String", diff --git a/public/consolidated/python.json b/public/consolidated/python.json index 953272b8..8acadcfc 100644 --- a/public/consolidated/python.json +++ b/public/consolidated/python.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -16,7 +16,7 @@ ] }, { - "categoryName": "Datetime Utilities", + "name": "Datetime Utilities", "snippets": [ { "title": "Calculate Date Difference in Milliseconds", @@ -99,7 +99,7 @@ ] }, { - "categoryName": "Error Handling", + "name": "Error Handling", "snippets": [ { "title": "Create Custom Exception Type", @@ -128,7 +128,7 @@ ] }, { - "categoryName": "File Handling", + "name": "File Handling", "snippets": [ { "title": "Find Files", @@ -180,7 +180,7 @@ ] }, { - "categoryName": "Json Manipulation", + "name": "Json Manipulation", "snippets": [ { "title": "Filter JSON Data", @@ -257,7 +257,7 @@ ] }, { - "categoryName": "List Manipulation", + "name": "List Manipulation", "snippets": [ { "title": "Find Duplicates in a List", @@ -342,7 +342,7 @@ ] }, { - "categoryName": "Math And Numbers", + "name": "Math And Numbers", "snippets": [ { "title": "Calculate Compound Interest", @@ -435,7 +435,7 @@ ] }, { - "categoryName": "Sqlite Database", + "name": "Sqlite Database", "snippets": [ { "title": "Create SQLite Database Table", @@ -485,7 +485,7 @@ ] }, { - "categoryName": "String Manipulation", + "name": "String Manipulation", "snippets": [ { "title": "Capitalize Words", diff --git a/public/consolidated/regex.json b/public/consolidated/regex.json index 2d8330c7..201f84ae 100644 --- a/public/consolidated/regex.json +++ b/public/consolidated/regex.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Miscellaneous", + "name": "Miscellaneous", "snippets": [ { "title": "Hexadecimal Color", @@ -47,7 +47,7 @@ ] }, { - "categoryName": "Validation pattern", + "name": "Validation pattern", "snippets": [ { "title": "Email Address", diff --git a/public/consolidated/ruby.json b/public/consolidated/ruby.json index 5d1da9f7..90a66a2c 100644 --- a/public/consolidated/ruby.json +++ b/public/consolidated/ruby.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Array Manipulation", + "name": "Array Manipulation", "snippets": [ { "title": "Binary Search", @@ -40,7 +40,7 @@ ] }, { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -57,7 +57,7 @@ ] }, { - "categoryName": "Error Handling", + "name": "Error Handling", "snippets": [ { "title": "Custom Error Class", @@ -73,7 +73,7 @@ ] }, { - "categoryName": "Math And Numbers", + "name": "Math And Numbers", "snippets": [ { "title": "Calculate Compound Interest", @@ -128,7 +128,7 @@ ] }, { - "categoryName": "String Manipulation", + "name": "String Manipulation", "snippets": [ { "title": "Capitalize Words", diff --git a/public/consolidated/rust.json b/public/consolidated/rust.json index 4a150d77..d3bd8f67 100644 --- a/public/consolidated/rust.json +++ b/public/consolidated/rust.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Basics", + "name": "Basics", "snippets": [ { "title": "Hello, World!", @@ -16,7 +16,7 @@ ] }, { - "categoryName": "File Handling", + "name": "File Handling", "snippets": [ { "title": "Find Files", @@ -43,7 +43,7 @@ ] }, { - "categoryName": "String Manipulation", + "name": "String Manipulation", "snippets": [ { "title": "Capitalize String", diff --git a/public/consolidated/scss.json b/public/consolidated/scss.json index dd8414b1..f64d083b 100644 --- a/public/consolidated/scss.json +++ b/public/consolidated/scss.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Animations", + "name": "Animations", "snippets": [ { "title": "Fade In Animation", @@ -29,7 +29,7 @@ ] }, { - "categoryName": "Borders Shadows", + "name": "Borders Shadows", "snippets": [ { "title": "Border Radius Helper", @@ -58,7 +58,7 @@ ] }, { - "categoryName": "Components", + "name": "Components", "snippets": [ { "title": "Primary Button", @@ -75,7 +75,7 @@ ] }, { - "categoryName": "Layouts", + "name": "Layouts", "snippets": [ { "title": "Aspect Ratio", @@ -130,7 +130,7 @@ ] }, { - "categoryName": "Typography", + "name": "Typography", "snippets": [ { "title": "Font Import Helper", @@ -184,7 +184,7 @@ ] }, { - "categoryName": "Utilities", + "name": "Utilities", "snippets": [ { "title": "Clearfix", diff --git a/public/consolidated/typescript.json b/public/consolidated/typescript.json index 98a0680b..1d3ece20 100644 --- a/public/consolidated/typescript.json +++ b/public/consolidated/typescript.json @@ -1,6 +1,6 @@ [ { - "categoryName": "Helper Types", + "name": "Helper Types", "snippets": [ { "title": "Exclusive Types", diff --git a/src/components/LanguageSelector.tsx b/src/components/LanguageSelector.tsx index ae30b12f..d8e208fe 100644 --- a/src/components/LanguageSelector.tsx +++ b/src/components/LanguageSelector.tsx @@ -79,7 +79,7 @@ const LanguageSelector = () => { >
- {language.lang || "Select a language"} + {language.name || "Select a language"}
@@ -92,18 +92,18 @@ const LanguageSelector = () => { > {fetchedLanguages.map((lang, index) => (
  • handleSelect(lang)} className={`selector__item ${ - language.lang === lang.lang ? "selected" : "" + language.name === lang.name ? "selected" : "" } ${focusedIndex === index ? "focused" : ""}`} - aria-selected={language.lang === lang.lang} + aria-selected={language.name === lang.name} >
  • ))} diff --git a/src/components/SnippetList.tsx b/src/components/SnippetList.tsx index 1b96925b..8868b9f1 100644 --- a/src/components/SnippetList.tsx +++ b/src/components/SnippetList.tsx @@ -37,7 +37,7 @@ const SnippetList = () => { {fetchedSnippets.map((snippet, idx) => { - const uniqueId = `${language.lang}-${snippet.title}`; + const uniqueId = `${language.name}-${snippet.title}`; return ( { whileTap={{ scale: 0.98 }} >
    - {language.lang} + {language.name}

    {snippet.title}

    @@ -87,7 +87,7 @@ const SnippetList = () => { )}
    diff --git a/src/contexts/AppContext.tsx b/src/contexts/AppContext.tsx index 78fc86ea..30dd366e 100644 --- a/src/contexts/AppContext.tsx +++ b/src/contexts/AppContext.tsx @@ -4,8 +4,9 @@ import { AppState, LanguageType, SnippetType } from "@types"; // tokens const defaultLanguage: LanguageType = { - lang: "JAVASCRIPT", + name: "JAVASCRIPT", icon: "/icons/javascript.svg", + subIndexes: [], }; // TODO: add custom loading and error handling diff --git a/src/hooks/useCategories.ts b/src/hooks/useCategories.ts index ac55a7d5..4bd00685 100644 --- a/src/hooks/useCategories.ts +++ b/src/hooks/useCategories.ts @@ -1,24 +1,19 @@ import { useMemo } from "react"; import { useAppContext } from "@contexts/AppContext"; -import { SnippetType } from "@types"; +import { CategoryType } from "@types"; import { slugify } from "@utils/slugify"; import { useFetch } from "./useFetch"; -type CategoryData = { - categoryName: string; - snippets: SnippetType[]; -}; - export const useCategories = () => { const { language } = useAppContext(); - const { data, loading, error } = useFetch( - `/consolidated/${slugify(language.lang)}.json` + const { data, loading, error } = useFetch( + `/consolidated/${slugify(language.name)}.json` ); const fetchedCategories = useMemo(() => { - return data ? data.map((item) => item.categoryName) : []; + return data ? data.map((item) => item.name) : []; }, [data]); return { fetchedCategories, loading, error }; diff --git a/src/hooks/useSnippets.ts b/src/hooks/useSnippets.ts index 1ceb0dd5..a9d85499 100644 --- a/src/hooks/useSnippets.ts +++ b/src/hooks/useSnippets.ts @@ -1,22 +1,17 @@ import { useAppContext } from "@contexts/AppContext"; -import { SnippetType } from "@types"; +import { CategoryType } from "@types"; import { slugify } from "@utils/slugify"; import { useFetch } from "./useFetch"; -type CategoryData = { - categoryName: string; - snippets: SnippetType[]; -}; - export const useSnippets = () => { const { language, category } = useAppContext(); - const { data, loading, error } = useFetch( - `/consolidated/${slugify(language.lang)}.json` + const { data, loading, error } = useFetch( + `/consolidated/${slugify(language.name)}.json` ); const fetchedSnippets = data - ? data.find((item) => item.categoryName === category)?.snippets + ? data.find((item) => item.name === category)?.snippets : []; return { fetchedSnippets, loading, error }; diff --git a/src/types/index.ts b/src/types/index.ts index b4eac550..9f6c4fb2 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,10 +1,14 @@ export type LanguageType = { - lang: string; + name: string; icon: string; + subIndexes: { + name: string; + icon: string; + }[]; }; export type CategoryType = { - categoryName: string; + name: string; snippets: SnippetType[]; }; diff --git a/utils/consolidateSnippets.js b/utils/consolidateSnippets.js index 6a7673a1..aeaea0ce 100644 --- a/utils/consolidateSnippets.js +++ b/utils/consolidateSnippets.js @@ -1,5 +1,5 @@ import { exit } from 'process'; -import { parseAllSnippets, reverseSlugify } from './snippetParser.js'; +import { parseAllSnippets, reverseSlugify, slugify } from './snippetParser.js'; import { join } from 'path'; import { copyFileSync, writeFileSync } from 'fs'; @@ -8,21 +8,39 @@ const indexPath = join(dataPath, '_index.json'); const iconPath = 'public/icons/'; const snippetsPath = 'snippets/'; -const [ errored, snippets ] = parseAllSnippets(); +const [ errored, languages ] = parseAllSnippets(); if(errored) exit(1); const index = []; -for(const [language, categories] of Object.entries(snippets)) { - const languageIconPath = join(snippetsPath, language, 'icon.svg'); +for(const language of languages) { + copyFileSync(language.icon, join(iconPath, `${slugify(language.name)}.svg`)); - copyFileSync(languageIconPath, join(iconPath, `${language}.svg`)); + const subIndexes = []; - index.push({ lang: reverseSlugify(language).toUpperCase(), icon: `/icons/${language}.svg` }); + for(const subLanguage of language.subLanguages) { + const joinedName = `${slugify(language.name)}--${slugify(subLanguage.name)}`; + const iconName = `${joinedName}.svg`; + const subLanguageFilePath = join(dataPath, `${joinedName}.json`); + + copyFileSync(subLanguage.icon, join(iconPath, iconName)); + subIndexes.push({ + name: subLanguage.name.toUpperCase(), + icon: `/icons/${iconName}`, + }); + + writeFileSync(subLanguageFilePath, JSON.stringify(subLanguage.categories, null, 4)); + } + + index.push({ + name: language.name.toUpperCase(), + icon: `/icons/${slugify(language.name)}.svg`, + subLanguages: subIndexes, + }); - const languageFilePath = join(dataPath, `${language}.json`); + const languageFilePath = join(dataPath, `${slugify(language.name)}.json`); - writeFileSync(languageFilePath, JSON.stringify(categories, null, 4)); + writeFileSync(languageFilePath, JSON.stringify(language.categories, null, 4)); } writeFileSync(indexPath, JSON.stringify(index, null, 4)); \ No newline at end of file diff --git a/utils/snippetParser.js b/utils/snippetParser.js index 0989ab5e..e7b502f8 100644 --- a/utils/snippetParser.js +++ b/utils/snippetParser.js @@ -31,13 +31,13 @@ const crlfRegex = /\r\n/gm; const propertyRegex = /^\s+([a-zA-Z]+):\s*(.+)/; const headerEndCodeStartRegex = /^\s*---\s*```.*\n/; const codeRegex = /^(.+)```/s -function parseSnippet(snippetPath, name, text) { - if(crlfRegex.exec(text) !== null) return raise('Found CRLF line endings instead of LF line endings', snippetPath); +function parseSnippet(path, name, text) { + if(crlfRegex.exec(text) !== null) return raise('Found CRLF line endings instead of LF line endings', path); let cursor = 0; const fromCursor = () => text.substring(cursor); - if(!fromCursor().trim().startsWith('---')) return raise('Missing header start delimiter \'---\'', snippetPath); + if(!fromCursor().trim().startsWith('---')) return raise('Missing header start delimiter \'---\'', path); cursor += 3; const properties = {}; @@ -47,19 +47,19 @@ function parseSnippet(snippetPath, name, text) { properties[match[1].toLowerCase()] = match[2]; } - if(!('title' in properties)) return raise(`Missing 'title' property`, snippetPath); - if(!('description' in properties)) return raise(`Missing 'description' property`, snippetPath); - if(!('author' in properties)) return raise(`Missing 'author' property`, snippetPath); - if(!('tags' in properties)) return raise(`Missing 'tags' property`, snippetPath); + if(!('title' in properties)) return raise(`Missing 'title' property`, path); + if(!('description' in properties)) return raise(`Missing 'description' property`, path); + if(!('author' in properties)) return raise(`Missing 'author' property`, path); + if(!('tags' in properties)) return raise(`Missing 'tags' property`, path); - if(slugify(properties.title) !== name) return raise(`slugifyed 'title' property doesn't match snippet file name`, snippetPath); + if(slugify(properties.title) !== name) return raise(`slugifyed 'title' property doesn't match snippet file name`, path); match = headerEndCodeStartRegex.exec(fromCursor()); - if(match === null) return raise('Missing header end \'---\' or code start \'```\'', snippetPath); + if(match === null) return raise('Missing header end \'---\' or code start \'```\'', path); cursor += match[0].length; match = codeRegex.exec(fromCursor()); - if(match === null) return raise('Missing code block end \'```\'', snippetPath); + if(match === null) return raise('Missing code block end \'```\'', path); const code = match[1]; return { @@ -72,43 +72,63 @@ function parseSnippet(snippetPath, name, text) { } } +function parseCategory(path, name) { + const snippets = []; + + for(const snippet of readdirSync(path)) { + const snippetPath = join(path, snippet); + const snippetContent = readFileSync(snippetPath).toString(); + const snippetFileName = snippet.slice(0, -3); + + const snippetData = parseSnippet(snippetPath, snippetFileName, snippetContent); + if(!snippetData) continue; + snippets.push(snippetData); + } + + return { + name: reverseSlugify(name), + snippets, + }; +} + +function parseLanguage(path, name, subLanguageOf = null) { + const iconPath = join(path, 'icon.svg'); + + if(!existsSync(iconPath)) return raise(`icon for '${subLanguageOf ? `${subLanguageOf}/` : '' }${name}' is missing`); + + const categories = []; + const subLanguages = []; + + for(const category of readdirSync(path)) { + if(category === 'icon.svg') continue; + const categoryPath = join(path, category); + + if(category.startsWith('[') && category.endsWith(']')) { + if(subLanguageOf !== null) { + return raise('Cannot have more than two level of language nesting'); + } + subLanguages.push(parseLanguage(categoryPath, category.slice(1, -1), name)); + }else { + categories.push(parseCategory(categoryPath, category)); + } + } + + return { + name: reverseSlugify(name), + icon: iconPath, + categories, subLanguages, + } +} + const snippetPath = "snippets/"; export function parseAllSnippets() { - const snippets = {}; + const languages = []; for(const language of readdirSync(snippetPath)) { const languagePath = join(snippetPath, language); - - const languageIconPath = join(languagePath, 'icon.svg'); - - if(!existsSync(languageIconPath)) { - raise(`icon for '${language}' is missing`); - continue; - } - - const categories = []; - for(const category of readdirSync(languagePath)) { - if(category === 'icon.svg') continue; - const categoryPath = join(languagePath, category); - - const categorySnippets = []; - for(const snippet of readdirSync(categoryPath)) { - const snippetPath = join(categoryPath, snippet); - const snippetContent = readFileSync(snippetPath).toString(); - const snippetFileName = snippet.slice(0, -3); - - const snippetData = parseSnippet(snippetPath, snippetFileName, snippetContent); - if(!snippetData) continue; - categorySnippets.push(snippetData); - } - categories.push({ - categoryName: reverseSlugify(category), - snippets: categorySnippets, - }); - } - snippets[language] = categories; + languages.push(parseLanguage(languagePath, language)); } - return [ errored, snippets ]; + return [ errored, languages ]; }