@md-plugins/vite-examples-plugin 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +204 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.mjs +68 -0
- package/package.json +47 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024-present, Jeff Galbraith
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# @md-plugins/vite-examples-plugin
|
|
2
|
+
|
|
3
|
+
A Vite plugin that facilitates handling Vue example files in both development and production modes. The plugin allows you to load and transform example components and their raw source code for usage in your application.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Supports loading Vue example files dynamically during development.
|
|
8
|
+
- Generates import and export statements for Vue example files in production.
|
|
9
|
+
- Easily handles raw and compiled component imports.
|
|
10
|
+
- Enables seamless integration of example files into your project.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
Install the plugin via your preferred package manager:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# npm
|
|
18
|
+
npm install @md-plugins/vite-examples-plugin
|
|
19
|
+
|
|
20
|
+
# yarn
|
|
21
|
+
yarn add @md-plugins/vite-examples-plugin
|
|
22
|
+
|
|
23
|
+
# pnpm
|
|
24
|
+
pnpm add @md-plugins/vite-examples-plugin
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
### Basic Setup with Vite
|
|
30
|
+
|
|
31
|
+
To use the `viteExamplesPlugin`, configure it in your Vite project:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
import { defineConfig } from 'vite';
|
|
35
|
+
import vue from '@vitejs/plugin-vue';
|
|
36
|
+
import { viteExamplesPlugin } from '@md-plugin/vite-examples-plugin';
|
|
37
|
+
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
plugins: [vue(), viteExamplesPlugin('/absolute/path/to/examples')],
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Manual Chunk Splitting with Vite
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
import { defineConfig } from 'vite';
|
|
47
|
+
import vue from '@vitejs/plugin-vue';
|
|
48
|
+
import { viteExamplesPlugin, viteManualChunks } from 'vite-examples-plugin';
|
|
49
|
+
|
|
50
|
+
export default defineConfig({
|
|
51
|
+
plugins: [vue(), viteExamplesPlugin('/absolute/path/to/examples')],
|
|
52
|
+
build: {
|
|
53
|
+
chunkSizeWarningLimit: 650,
|
|
54
|
+
rollupOptions: {
|
|
55
|
+
output: {
|
|
56
|
+
manualChunks: viteManualChunks,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quasar Framework Configuration
|
|
64
|
+
|
|
65
|
+
1. Update `quasar.config.(js|ts)`:
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
import { viteExamplesPlugin } from '@md-plugin/vite-examples-plugin';
|
|
69
|
+
|
|
70
|
+
export default defineConfig((ctx) => {
|
|
71
|
+
// ...
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
build: {
|
|
76
|
+
vitePlugins: [
|
|
77
|
+
viteExamplesPlugin(ctx.appPaths.srcDir + '/examples'),
|
|
78
|
+
// ...
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Manual Chunk Splitting with Quasar
|
|
85
|
+
|
|
86
|
+
```js
|
|
87
|
+
import {
|
|
88
|
+
viteExamplesPlugin,
|
|
89
|
+
viteManualChunks,
|
|
90
|
+
} from '@md-plugins/vite-examples-plugin';
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
build: {
|
|
95
|
+
extendViteConf(viteConf, { isClient }) {
|
|
96
|
+
if (ctx.prod && isClient) {
|
|
97
|
+
if (!viteConf.build) {
|
|
98
|
+
viteConf.build = {}
|
|
99
|
+
}
|
|
100
|
+
viteConf.build.chunkSizeWarningLimit = 650
|
|
101
|
+
viteConf.build.rollupOptions = {
|
|
102
|
+
output: { manualChunks: viteManualChunks },
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## How viteManualChunks Works
|
|
110
|
+
|
|
111
|
+
The `viteManualChunks` function analyzes the module ID and assigns it to a specific chunk:
|
|
112
|
+
|
|
113
|
+
1. **`Vendor Chunk`**: Files from `node_modules` matching libraries like `vue`, `@vue`, `quasar`, and `vue-router` are assigned to the `vendor` chunk.
|
|
114
|
+
|
|
115
|
+
2. **`Examples Chunk`**: Example files matching the pattern `examples:<name>` or located in `src/examples/<name>` are grouped into chunks named `e.<name>`.
|
|
116
|
+
|
|
117
|
+
### Example
|
|
118
|
+
|
|
119
|
+
Given the following files:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
node_modules/vue/index.js
|
|
123
|
+
src/examples/example1/Example1.vue
|
|
124
|
+
src/examples/example2/Example2.vue
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The resulting chunks might look like:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
vendor.js // Contains Vue, Quasar, Vue Router, etc.
|
|
131
|
+
e.example1.js // Contains Example1.vue
|
|
132
|
+
e.example2.js // Contains Example2.vue
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
This helps facilitate loading and chunking in your application for your examples.
|
|
136
|
+
|
|
137
|
+
## Example Folder Structure
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
src/
|
|
141
|
+
examples/
|
|
142
|
+
example1/
|
|
143
|
+
Example1.vue
|
|
144
|
+
example2/
|
|
145
|
+
Example2.vue
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## How It Works
|
|
149
|
+
|
|
150
|
+
The plugin provides two modes of operation based on the environment:
|
|
151
|
+
|
|
152
|
+
### Development Mode
|
|
153
|
+
|
|
154
|
+
During development, the plugin uses Vite's `import.meta.glob` to dynamically load Vue example components and their raw source code:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
export const code = import.meta.glob('/src/examples/example1/*.vue', {
|
|
158
|
+
eager: true,
|
|
159
|
+
});
|
|
160
|
+
export const source = import.meta.glob('/src/examples/example1/*.vue', {
|
|
161
|
+
query: '?raw',
|
|
162
|
+
import: 'default',
|
|
163
|
+
eager: true,
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Production Mode
|
|
168
|
+
|
|
169
|
+
In production, the plugin preloads example components and their raw source code, generating import and export statements:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import Example1 from 'app/src/examples/example1/Example1.vue';
|
|
173
|
+
import RawExample1 from 'app/src/examples/example1/Example1.vue?raw';
|
|
174
|
+
|
|
175
|
+
export { Example1, RawExample1 };
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Development Notes
|
|
179
|
+
|
|
180
|
+
The plugin is structured with the following components:
|
|
181
|
+
|
|
182
|
+
1. `devLoad` Function
|
|
183
|
+
Generates dynamic imports for example files during development.
|
|
184
|
+
|
|
185
|
+
2. `prodLoad` Function
|
|
186
|
+
Creates preloaded import and export statements for example files in production.
|
|
187
|
+
|
|
188
|
+
3. `vitePlugin` Function
|
|
189
|
+
Constructs the Vite plugin with resolveId and load methods.
|
|
190
|
+
|
|
191
|
+
4. `viteExamplesPlugin` Function
|
|
192
|
+
Sets the target folder and initializes the plugin.
|
|
193
|
+
|
|
194
|
+
## Error Handling
|
|
195
|
+
|
|
196
|
+
If the `targetFolder` is not defined when the plugin is initialized, an error will be thrown:
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
throw new Error('targetFolder is not defined');
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
## License
|
|
203
|
+
|
|
204
|
+
This project is licensed under the MIT License. See the [LICENSE](LICENSE.md) file for details.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a Vite plugin for handling Markdown examples.
|
|
3
|
+
*
|
|
4
|
+
* This function sets up the target folder for example files and returns a function
|
|
5
|
+
* that creates the actual Vite plugin. The returned plugin resolves and loads
|
|
6
|
+
* example code based on the production or development environment.
|
|
7
|
+
*
|
|
8
|
+
* @param path - The path to the directory containing the example files.
|
|
9
|
+
* This path will be used as the target folder for resolving examples.
|
|
10
|
+
*
|
|
11
|
+
* @returns A function that creates a Vite plugin. This function takes a boolean
|
|
12
|
+
* parameter indicating whether the build is in production mode and
|
|
13
|
+
* returns the configured Vite plugin object.
|
|
14
|
+
*/
|
|
15
|
+
declare function viteExamplesPlugin(path: string): (isProd: boolean) => {
|
|
16
|
+
name: string;
|
|
17
|
+
enforce: 'pre';
|
|
18
|
+
resolveId(id: string): string | undefined;
|
|
19
|
+
load(id: string): string | undefined;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A function to determine the manual chunk name for a given module ID.
|
|
24
|
+
*
|
|
25
|
+
* @param id - The module ID to analyze.
|
|
26
|
+
* @returns A string representing the chunk name or `undefined`.
|
|
27
|
+
*/
|
|
28
|
+
declare function viteManualChunks(id: string): string | undefined;
|
|
29
|
+
|
|
30
|
+
export { viteExamplesPlugin, viteManualChunks };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a Vite plugin for handling Markdown examples.
|
|
3
|
+
*
|
|
4
|
+
* This function sets up the target folder for example files and returns a function
|
|
5
|
+
* that creates the actual Vite plugin. The returned plugin resolves and loads
|
|
6
|
+
* example code based on the production or development environment.
|
|
7
|
+
*
|
|
8
|
+
* @param path - The path to the directory containing the example files.
|
|
9
|
+
* This path will be used as the target folder for resolving examples.
|
|
10
|
+
*
|
|
11
|
+
* @returns A function that creates a Vite plugin. This function takes a boolean
|
|
12
|
+
* parameter indicating whether the build is in production mode and
|
|
13
|
+
* returns the configured Vite plugin object.
|
|
14
|
+
*/
|
|
15
|
+
declare function viteExamplesPlugin(path: string): (isProd: boolean) => {
|
|
16
|
+
name: string;
|
|
17
|
+
enforce: 'pre';
|
|
18
|
+
resolveId(id: string): string | undefined;
|
|
19
|
+
load(id: string): string | undefined;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* A function to determine the manual chunk name for a given module ID.
|
|
24
|
+
*
|
|
25
|
+
* @param id - The module ID to analyze.
|
|
26
|
+
* @returns A string representing the chunk name or `undefined`.
|
|
27
|
+
*/
|
|
28
|
+
declare function viteManualChunks(id: string): string | undefined;
|
|
29
|
+
|
|
30
|
+
export { viteExamplesPlugin, viteManualChunks };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { join } from 'node:path';
|
|
2
|
+
import { globSync } from 'tinyglobby';
|
|
3
|
+
|
|
4
|
+
const moduleIdRE = /^examples:/;
|
|
5
|
+
const resolvedIdPrefix = "\0examples:";
|
|
6
|
+
let targetFolder = "";
|
|
7
|
+
function devLoad(id) {
|
|
8
|
+
if (id.startsWith(resolvedIdPrefix)) {
|
|
9
|
+
const query = `'/src/examples/${id.substring(id.indexOf(":") + 1)}/*.vue'`;
|
|
10
|
+
return `export const code = import.meta.glob(${query}, { eager: true })
|
|
11
|
+
export const source = import.meta.glob(${query}, { query: '?raw', import: 'default', eager: true })`;
|
|
12
|
+
}
|
|
13
|
+
return void 0;
|
|
14
|
+
}
|
|
15
|
+
function prodLoad(id) {
|
|
16
|
+
if (id.startsWith(resolvedIdPrefix)) {
|
|
17
|
+
const exampleId = id.substring(id.indexOf(":") + 1);
|
|
18
|
+
const files = globSync("*.vue", { cwd: join(targetFolder, exampleId) });
|
|
19
|
+
const importList = files.map(
|
|
20
|
+
(entry) => entry.substring(0, entry.length - 4)
|
|
21
|
+
);
|
|
22
|
+
const importStatements = importList.map(
|
|
23
|
+
(entry) => `import ${entry} from 'app/src/examples/${exampleId}/${entry}.vue'
|
|
24
|
+
import Raw${entry} from 'app/src/examples/${exampleId}/${entry}.vue?raw'`
|
|
25
|
+
).join("\n");
|
|
26
|
+
const exportStatements = importList.map((entry) => `${entry},Raw${entry}`).join(",");
|
|
27
|
+
return importStatements + `
|
|
28
|
+
export {${exportStatements}}`;
|
|
29
|
+
}
|
|
30
|
+
return void 0;
|
|
31
|
+
}
|
|
32
|
+
function vitePlugin(isProd) {
|
|
33
|
+
if (!targetFolder) {
|
|
34
|
+
throw new Error("targetFolder is not defined");
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
name: "markdown-examples",
|
|
38
|
+
enforce: "pre",
|
|
39
|
+
// before vue
|
|
40
|
+
resolveId(id) {
|
|
41
|
+
if (moduleIdRE.test(id)) {
|
|
42
|
+
return "\0" + id;
|
|
43
|
+
}
|
|
44
|
+
return void 0;
|
|
45
|
+
},
|
|
46
|
+
load: isProd ? prodLoad : devLoad
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function viteExamplesPlugin(path) {
|
|
50
|
+
targetFolder = path;
|
|
51
|
+
return vitePlugin;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const vendorRE = /node_modules[\\/](vue|@vue|quasar|vue-router)[\\/](.*)\.(m?js|css|sass)$/;
|
|
55
|
+
const exampleRE = /examples:([a-zA-Z0-9]+)$|src[\\/]examples[\\/]([a-zA-Z0-9-]+)/;
|
|
56
|
+
function viteManualChunks(id) {
|
|
57
|
+
if (vendorRE.test(id)) {
|
|
58
|
+
return "vendor";
|
|
59
|
+
}
|
|
60
|
+
const examplesMatch = exampleRE.exec(id);
|
|
61
|
+
if (examplesMatch !== null) {
|
|
62
|
+
const name = examplesMatch[1] || examplesMatch[2];
|
|
63
|
+
return `e.${name}`;
|
|
64
|
+
}
|
|
65
|
+
return void 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { viteExamplesPlugin, viteManualChunks };
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@md-plugins/vite-examples-plugin",
|
|
3
|
+
"version": "0.1.0-alpha.1",
|
|
4
|
+
"description": "A Vite plugin for @md-plugins for handling imported examples in markdown files.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"markdown-it",
|
|
7
|
+
"quasarframework",
|
|
8
|
+
"vue",
|
|
9
|
+
"utils",
|
|
10
|
+
"vite",
|
|
11
|
+
"vite-plugin"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/md-plugins",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/md-plugins/md-plugins/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/md-plugins/md-plugins.git"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "hawkeye64 <galbraith64@gmail.com>",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./dist/index.d.mts",
|
|
28
|
+
"default": "./dist/index.mjs"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"module": "./dist/index.mjs",
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"files": [
|
|
35
|
+
"./dist"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"tinyglobby": "^0.2.10"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "unbuild",
|
|
45
|
+
"clean": "rm -rf dist"
|
|
46
|
+
}
|
|
47
|
+
}
|