Skip to content

Commit 0afac3b

Browse files
committed
11Jul24 dynamically generate examples in folders
1 parent 8afdef9 commit 0afac3b

File tree

20 files changed

+270
-69
lines changed

20 files changed

+270
-69
lines changed

src/ReplFactory.js

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,6 @@
11
// createReplComponent.js
22
import { defineComponent, h } from "vue";
3-
import ReplWrapper from "@/components/ReplWrapper.vue"; // Adjust the path accordingly
4-
5-
// Props
6-
import DeclaringPropsAppVue from "@/views/props/declaringprops/DeclaringPropsView.vue?raw";
7-
import DeclaringPropsNestedVue from "@/views/props/declaringprops/NestedView.vue?raw";
8-
9-
import DefaultValuesAppVue from "@/views/props/defaultvalues/DefaultValuesView.vue?raw";
10-
import DefaultValuesNestedVue from "@/views/props/defaultvalues/NestedView.vue?raw";
11-
12-
import SpreadPropsAppVue from "@/views/props/spreadprops/SpreadPropsView.vue?raw";
13-
import SpreadPropsNestedVue from "@/views/props/spreadprops/InfoView.vue?raw";
14-
15-
3+
import ReplWrapper from "@/components/ReplWrapper.vue";
164

175
export function createReplComponent(codeString, files = {}) {
186
return defineComponent({
@@ -22,15 +10,4 @@ export function createReplComponent(codeString, files = {}) {
2210
});
2311
}
2412

25-
// Props
26-
export const DeclaringPropsVue = createReplComponent(DeclaringPropsAppVue, {
27-
"NestedView.vue": DeclaringPropsNestedVue,
28-
});
29-
export const DefaultValuesVue = createReplComponent(DefaultValuesAppVue, {
30-
"NestedView.vue": DefaultValuesNestedVue,
31-
});
32-
export const SpreadPropsVue = createReplComponent(SpreadPropsAppVue, {
33-
"InfoView.vue": SpreadPropsNestedVue,
34-
});
35-
3613

src/components/ReplWrapper.vue

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import CodeMirror from "@vue/repl/codemirror-editor";
66
const props = defineProps({
77
codeString: {
88
type: String,
9-
required: true,
9+
required: false,
10+
default: ""
1011
},
1112
files: {
1213
type: Object,
@@ -15,12 +16,19 @@ const props = defineProps({
1516
});
1617
1718
const store = new useStore({});
19+
if (props.codeString) {
20+
store.setFiles({
21+
...store.getFiles(),
22+
"App.vue": props.codeString,
23+
...props.files,
24+
});
25+
} else {
26+
store.setFiles({
27+
...store.getFiles(),
28+
...props.files,
29+
});
30+
}
1831
19-
store.setFiles({
20-
...store.getFiles(),
21-
"App.vue": props.codeString,
22-
...props.files,
23-
});
2432
</script>
2533

2634
<template>

src/components/RouterButton.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ const props = defineProps({
1515
1616
const route = useRoute();
1717
const isSelected = computed(() => {
18-
console.log(props.toPath)
19-
2018
return route.path === props.toPath
2119
});
2220
</script>

src/exampleButtons.js

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,15 @@ import { IntroductionButtonExamples } from "@/factory/IntroductionFactory.js";
33
import { StyleButtonExamples } from "@/factory/StylesFactory.js";
44
import { RenderingButtonExamples } from "@/factory/RenderingFactory.js";
55
import { EventHandlingButtonExamples } from "@/factory/EventHandlingFactory.js";
6-
7-
const propExamples = {
8-
name: "Props",
9-
examples: [
10-
{
11-
name: "Declaring Props",
12-
path: "/declaringprops",
13-
},
14-
{
15-
name: "Default Values",
16-
path: "/defaultvalues",
17-
},
18-
{
19-
name: "Spread Props",
20-
path: "/spreadprops",
21-
},
22-
],
23-
link: "https://vuejs.org/guide/components/props.html",
24-
};
25-
6+
import {OthersButtonExamples} from "@/factory/OthersFactory.js";
7+
import {PropsButtonExamples} from "@/factory/PropsFactory.js";
268

279
export const ALL_EXAMPLES = [
2810
IntroductionButtonExamples,
2911
ReactivityButtonExamples,
3012
StyleButtonExamples,
3113
RenderingButtonExamples,
3214
EventHandlingButtonExamples,
33-
propExamples,
15+
PropsButtonExamples,
16+
OthersButtonExamples,
3417
];

src/factory/OthersFactory.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import {
2+
createExample,
3+
createRouterObj,
4+
createRouterObjAdvanced,
5+
extractUniqueFolderNames,
6+
organizeFilesByFolder,
7+
sortExamples
8+
} from "@/util.js";
9+
import { createReplComponent } from "@/ReplFactory.js";
10+
11+
const path = "/src/views/others/";
12+
13+
// Import single file components
14+
const singleFileComponents = import.meta.glob('/src/views/others/*.vue', {
15+
eager: true,
16+
query: "?raw",
17+
import: "default",
18+
});
19+
20+
// Generate examples and router objects for single file components
21+
let exampleList = Object.keys(singleFileComponents).map(key => {
22+
const filename = key.replace(path, "").replace(".vue", "");
23+
return createExample(filename);
24+
});
25+
26+
let othersRouterList = exampleList.map(({ name }) => createRouterObj(name, singleFileComponents, path));
27+
28+
// Import components from folders
29+
const folderComponents = import.meta.glob('/src/views/others/*/*.vue', {
30+
eager: true,
31+
query: "?raw",
32+
import: "default",
33+
});
34+
35+
// Extract folder names and generate examples for them
36+
const folderNames = extractUniqueFolderNames(folderComponents);
37+
exampleList = [...exampleList, ...folderNames.map(createExample)];
38+
39+
// Organize folder components and generate router objects
40+
const organizedFolders = organizeFilesByFolder(folderComponents);
41+
Object.entries(organizedFolders).forEach(([folderName, folderFiles]) => {
42+
// Rename `${folderName}.vue` to `App.vue` if exists
43+
const folderVue = `${folderName}.vue`;
44+
if (folderFiles[folderVue]) {
45+
folderFiles["App.vue"] = folderFiles[folderVue];
46+
delete folderFiles[folderVue];
47+
}
48+
const component = createReplComponent(null, folderFiles);
49+
othersRouterList.push(createRouterObjAdvanced(folderName, component));
50+
});
51+
52+
// Sort examples if needed
53+
const orderedList = [];
54+
exampleList = sortExamples(orderedList, exampleList);
55+
56+
export const OthersButtonExamples = {
57+
name: "Others",
58+
examples: exampleList,
59+
link: "https://vuejs.org/guide/essentials/class-and-style.html",
60+
};
61+
62+
export { othersRouterList };

src/factory/PropsFactory.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import {generateButtonExamplesAndRouterList} from "@/factoryUtil.js";
2+
3+
const path = "/src/views/props/";
4+
const sectionName = "Props";
5+
const link = "https://vuejs.org/guide/components/props.html";
6+
7+
const singleFileComponents = import.meta.glob('/src/views/props/*.vue', {
8+
eager: true,
9+
query: "?raw",
10+
import: "default",
11+
});
12+
13+
const folderComponents = import.meta.glob('/src/views/props/*/*.vue', {
14+
eager: true,
15+
query: "?raw",
16+
import: "default",
17+
});
18+
19+
20+
const {
21+
ButtonExamples: PropsButtonExamples,
22+
RouterList: PropsRouterList
23+
} = generateButtonExamplesAndRouterList(path, singleFileComponents,
24+
folderComponents, sectionName, link);
25+
26+
27+
export { PropsButtonExamples, PropsRouterList };
28+

src/factoryUtil.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {
2+
createExample,
3+
createRouterObj,
4+
createRouterObjAdvanced,
5+
extractUniqueFolderNames,
6+
organizeFilesByFolder,
7+
sortExamples
8+
} from "@/util.js";
9+
import { createReplComponent } from "@/ReplFactory.js";
10+
11+
/**
12+
* Generates button examples and router list for a given path.
13+
*
14+
* @param {string} basePath - The base path to the Vue components.
15+
* @param {string[]} orderedList - An optional array to sort the examples.
16+
* @param {string} sectionName - The name of the section.
17+
* @returns {{ ButtonExamples: Object, RouterList: Object[] }}
18+
*/
19+
export function generateButtonExamplesAndRouterList(basePath,
20+
singleFileComponents,
21+
folderComponents,
22+
sectionName,
23+
link,
24+
orderedList = []) {
25+
26+
27+
// Generate examples and router objects for single file components
28+
let exampleList = Object.keys(singleFileComponents).map(key => {
29+
const filename = key.replace(basePath, "").replace(".vue", "");
30+
return createExample(filename);
31+
});
32+
33+
let routerList = exampleList.map(({ name }) => createRouterObj(name, singleFileComponents, basePath));
34+
35+
// Extract folder names and generate examples for them
36+
const folderNames = extractUniqueFolderNames(folderComponents);
37+
exampleList = [...exampleList, ...folderNames.map(createExample)];
38+
39+
// Organize folder components and generate router objects
40+
const organizedFolders = organizeFilesByFolder(folderComponents);
41+
Object.entries(organizedFolders).forEach(([folderName, folderFiles]) => {
42+
// Rename `${folderName}.vue` to `App.vue` if exists
43+
const folderVue = `${folderName}.vue`;
44+
if (folderFiles[folderVue]) {
45+
folderFiles["App.vue"] = folderFiles[folderVue];
46+
delete folderFiles[folderVue];
47+
}
48+
const component = createReplComponent(null, folderFiles);
49+
routerList.push(createRouterObjAdvanced(folderName, component));
50+
});
51+
52+
// Sort examples if an ordered list is provided
53+
exampleList = sortExamples(orderedList, exampleList);
54+
55+
return {
56+
ButtonExamples: {
57+
name: sectionName,
58+
examples: exampleList,
59+
link: link
60+
},
61+
RouterList: routerList,
62+
};
63+
}

src/router/index.js

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import {createRouter, createWebHistory} from "vue-router";
2-
import {DeclaringPropsVue, DefaultValuesVue, SpreadPropsVue,} from "@/ReplFactory.js";
32
import {ReactivityRouterList} from "@/factory/ReativityFactory.js";
43
import {IntroductionRouterList} from "@/factory/IntroductionFactory.js";
54
import {StyleRouterList} from "@/factory/StylesFactory.js";
65
import {RenderingRouterList} from "@/factory/RenderingFactory.js";
76
import {EventHandlingRouterList} from "@/factory/EventHandlingFactory.js";
87
import TestView from "@/views/TestView.vue";
8+
import {othersRouterList} from "@/factory/OthersFactory.js";
9+
import {PropsRouterList} from "@/factory/PropsFactory.js";
910

1011
const router = createRouter({
1112
history: createWebHistory(import.meta.env.BASE_URL),
@@ -14,21 +15,6 @@ const router = createRouter({
1415
path: "/",
1516
redirect: "/HelloWorld",
1617
},
17-
{
18-
path: "/declaringprops",
19-
name: "declaringprops",
20-
component: DeclaringPropsVue,
21-
},
22-
{
23-
path: "/defaultvalues",
24-
name: "defaultvalues",
25-
component: DefaultValuesVue,
26-
},
27-
{
28-
path: "/spreadprops",
29-
name: "spreadprops",
30-
component: SpreadPropsVue,
31-
},
3218
{
3319
path: "/test",
3420
name: "testme",
@@ -40,6 +26,8 @@ const router = createRouter({
4026
...StyleRouterList,
4127
...RenderingRouterList,
4228
...EventHandlingRouterList,
29+
...PropsRouterList,
30+
...othersRouterList,
4331
],
4432
});
4533

src/util.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,48 @@ export const sortExamples = (orderedList, exampleList) => {
3737
return orderedList.indexOf(a.name) - orderedList.indexOf(b.name);
3838
});
3939
};
40+
41+
/**
42+
* Extracts unique folder names from a given object's keys, where each key represents a file path.
43+
* This function assumes that the file paths are structured such that the folder name is the second-to-last segment
44+
* when the path is split by "/".
45+
*
46+
* @param {Object} filesObject - An object with keys as file paths.
47+
* @returns {string[]} An array of unique folder names extracted from the file paths.
48+
*/
49+
export const extractUniqueFolderNames = (filesObject) => {
50+
const folderNames = new Set();
51+
for (const key in filesObject) {
52+
const folderName = key.split("/").slice(-2)[0];
53+
folderNames.add(folderName);
54+
}
55+
return [...folderNames];
56+
};
57+
58+
59+
/**
60+
* Organizes files into a structured object based on their folder paths.
61+
*
62+
* This function takes an object where keys represent file paths and values represent file contents.
63+
* It then organizes these files into a nested object structure, where each key is a folder name,
64+
* and its value is an object containing file names (as keys) and their contents (as values).
65+
*
66+
* @param {Object} filesObject - The object containing file paths as keys and file contents as values.
67+
* @returns {Object} An organized object with folder names as keys and objects of file names and contents as values.
68+
*/
69+
export const organizeFilesByFolder = (filesObject) => {
70+
const organized = {};
71+
for (const [path, content] of Object.entries(filesObject)) {
72+
const parts = path.split('/');
73+
const fileName = parts.pop(); // Get the file name
74+
const folderName = parts.pop(); // Get the folder name
75+
76+
if (!organized[folderName]) {
77+
organized[folderName] = {}; // Initialize the folder object if it doesn't exist
78+
}
79+
80+
organized[folderName][fileName] = content; // Add the file object to the folder
81+
};
82+
83+
return organized;
84+
};
File renamed without changes.

0 commit comments

Comments
 (0)