├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── examples
├── commits.html
├── grid.html
├── markdown.html
├── svg.html
├── todomvc.html
└── tree.html
├── index.html
├── package.json
├── pnpm-lock.yaml
├── scripts
└── release.js
├── src
├── app.ts
├── block.ts
├── context.ts
├── directives
│ ├── bind.ts
│ ├── effect.ts
│ ├── for.ts
│ ├── html.ts
│ ├── if.ts
│ ├── index.ts
│ ├── model.ts
│ ├── on.ts
│ ├── ref.ts
│ ├── show.ts
│ └── text.ts
├── eval.ts
├── index.ts
├── scheduler.ts
├── utils.ts
└── walk.ts
├── tests
├── bind.html
├── cloak.html
├── component.html
├── custom-delimiters.html
├── effect.html
├── for.html
├── html.html
├── if.html
├── model.html
├── multi-mount.html
├── on.html
├── once.html
├── pre.html
├── reactive.html
├── ref.html
├── scope.html
├── show.html
└── text.html
├── tsconfig.json
└── vite.config.ts
/.gitignore:
--------------------------------------------------------------------------------
1 | TODOs.md
2 | node_modules
3 | dist
4 | explorations
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [0.4.1](https://github.com/vuejs/petite-vue/compare/v0.4.0...v0.4.1) (2022-01-18)
2 |
3 | ### Bug Fixes
4 |
5 | - custom delimiters in child contexts ([#90](https://github.com/vuejs/petite-vue/issues/90)) ([1bbd4d1](https://github.com/vuejs/petite-vue/commit/1bbd4d1c00c6c19f2ee6740e728fb274101fc6c9))
6 |
7 | # [0.4.0](https://github.com/vuejs/petite-vue/compare/v0.3.0...v0.4.0) (2021-12-10)
8 |
9 | ### Breaking Changes
10 |
11 | - require vue: prefix for lifecycle hooks ([a981928](https://github.com/vuejs/petite-vue/commit/a9819283f8504a9c2d0cea4d9d122028eba2d10d))
12 |
13 | # [0.3.0](https://github.com/vuejs/petite-vue/compare/v0.2.3...v0.3.0) (2021-09-14)
14 |
15 | ### Bug Fixes
16 |
17 | - fix parsing chained modifiers ([15f75e9](https://github.com/vuejs/petite-vue/commit/15f75e94db3ce1d3630d7ffc10e2db4748d94f3e))
18 | - fix v-cloak on toggle ([#71](https://github.com/vuejs/petite-vue/issues/71)) ([f41981b](https://github.com/vuejs/petite-vue/commit/f41981b32ae4832e58223f55c209fd112dfbede7))
19 | - v-for update on move ([#79](https://github.com/vuejs/petite-vue/issues/79)) ([9af4ea3](https://github.com/vuejs/petite-vue/commit/9af4ea35957053665e586556f7ffb90b9077db26))
20 | - **v-model:** ensure v-model listeners are attached before v-on ([06d3aa7](https://github.com/vuejs/petite-vue/commit/06d3aa79b066410fe4e270b1a9dad65cb8d3fb97)), closes [#65](https://github.com/vuejs/petite-vue/issues/65)
21 |
22 | ### Features
23 |
24 | - bind methods to context ([#74](https://github.com/vuejs/petite-vue/issues/74)) ([167c49d](https://github.com/vuejs/petite-vue/commit/167c49d6940c6f35c6002093d8807ac0e835dcea))
25 | - custom delimiters ([eda903c](https://github.com/vuejs/petite-vue/commit/eda903c0a93fe048219b74b0a44064c87b553ad4))
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2021-present, Yuxi (Evan) You
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.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # petite-vue
2 |
3 | `petite-vue` is an alternative distribution of [Vue](https://vuejs.org) optimized for [progressive enhancement](https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement). It provides the same template syntax and reactivity mental model as standard Vue. However, it is specifically optimized for "sprinkling" a small amount of interactions on an existing HTML page rendered by a server framework. See more details on [how it differs from standard Vue](#comparison-with-standard-vue).
4 |
5 | - Only ~6kb
6 | - Vue-compatible template syntax
7 | - DOM-based, mutates in place
8 | - Driven by `@vue/reactivity`
9 |
10 | ## Status
11 |
12 | - This is pretty new. There are probably bugs and there might still be API changes, so **use at your own risk.** Is it usable though? Very much. Check out the [examples](https://github.com/vuejs/petite-vue/tree/main/examples) to see what it's capable of.
13 |
14 | - The issue list is intentionally disabled because I have higher priority things to focus on for now and don't want to be distracted. If you found a bug, you'll have to either workaround it or submit a PR to fix it yourself. That said, feel free to use the discussions tab to help each other out.
15 |
16 | - Feature requests are unlikely to be accepted at this time - the scope of this project is intentionally kept to a bare minimum.
17 |
18 | ## Usage
19 |
20 | `petite-vue` can be used without a build step. Simply load it from a CDN:
21 |
22 | ```html
23 |
24 |
25 |
26 |
27 | {{ count }}
28 | inc
29 |
30 | ```
31 |
32 | - Use `v-scope` to mark regions on the page that should be controlled by `petite-vue`.
33 | - The `defer` attribute makes the script execute after HTML content is parsed.
34 | - The `init` attribute tells `petite-vue` to automatically query and initialize all elements that have `v-scope` on the page.
35 |
36 | ### Manual Init
37 |
38 | If you don't want the auto init, remove the `init` attribute and move the scripts to end of ``:
39 |
40 | ```html
41 |
42 |
45 | ```
46 |
47 | Or, use the ES module build:
48 |
49 | ```html
50 |
54 | ```
55 |
56 | ### Production CDN URLs
57 |
58 | The short CDN URL is meant for prototyping. For production usage, use a fully resolved CDN URL to avoid resolving and redirect cost:
59 |
60 | - Global build: `https://unpkg.com/petite-vue@0.2.2/dist/petite-vue.iife.js`
61 | - exposes `PetiteVue` global, supports auto init
62 | - ESM build: `https://unpkg.com/petite-vue@0.2.2/dist/petite-vue.es.js`
63 | - Must be used with `
86 |
87 |
88 |
89 |
{{ count }}
90 |
{{ plusOne }}
91 |
increment
92 |
93 | ```
94 |
95 | Note `v-scope` doesn't need to have a value here and simply serves as a hint for `petite-vue` to process the element.
96 |
97 | ### Explicit Mount Target
98 |
99 | You can specify a mount target (selector or element) to limit `petite-vue` to only that region of the page:
100 |
101 | ```js
102 | createApp().mount('#only-this-div')
103 | ```
104 |
105 | This also means you can have multiple `petite-vue` apps to control different regions on the same page:
106 |
107 | ```js
108 | createApp({
109 | // root scope for app one
110 | }).mount('#app1')
111 |
112 | createApp({
113 | // root scope for app two
114 | }).mount('#app2')
115 | ```
116 |
117 | ### Lifecycle Events
118 |
119 | You can listen to the special `vue:mounted` and `vue:unmounted` lifecycle events for each element (the `vue:` prefix is required since v0.4.0):
120 |
121 | ```html
122 |
127 | ```
128 |
129 | ### `v-effect`
130 |
131 | Use `v-effect` to execute **reactive** inline statements:
132 |
133 | ```html
134 |
138 | ```
139 |
140 | The effect uses `count` which is a reactive data source, so it will re-run whenever `count` changes.
141 |
142 | Another example of replacing the `todo-focus` directive found in the original Vue TodoMVC example:
143 |
144 | ```html
145 |
146 | ```
147 |
148 | ### Components
149 |
150 | The concept of "Components" are different in `petite-vue`, as it is much more bare-bones.
151 |
152 | First, reusable scope logic can be created with functions:
153 |
154 | ```html
155 |
174 |
175 |
176 |
{{ count }}
177 |
increment
178 |
179 |
180 |
181 |
{{ count }}
182 |
increment
183 |
184 | ```
185 |
186 | ### Components with Template
187 |
188 | If you also want to reuse a piece of template, you can provide a special `$template` key on a scope object. The value can be the template string, or an ID selector to a `` element:
189 |
190 | ```html
191 |
208 |
209 |
210 | My count is {{ count }}
211 | ++
212 |
213 |
214 |
215 |
216 |
217 | ```
218 |
219 | The `` approach is recommended over inline strings because it is more efficient to clone from a native template element.
220 |
221 | ### Global State Management
222 |
223 | You can use the `reactive` method (re-exported from `@vue/reactivity`) to create global state singletons:
224 |
225 | ```html
226 |
244 |
245 |
246 |
Global {{ store.count }}
247 |
increment
248 |
249 |
Local {{ localCount }}
250 |
increment
251 |
252 | ```
253 |
254 | ### Custom Directives
255 |
256 | Custom directives are also supported but with a different interface:
257 |
258 | ```js
259 | const myDirective = (ctx) => {
260 | // the element the directive is on
261 | ctx.el
262 | // the raw value expression
263 | // e.g. v-my-dir="x" then this would be "x"
264 | ctx.exp
265 | // v-my-dir:foo -> "foo"
266 | ctx.arg
267 | // v-my-dir.mod -> { mod: true }
268 | ctx.modifiers
269 | // evaluate the expression and get its value
270 | ctx.get()
271 | // evaluate arbitrary expression in current scope
272 | ctx.get(`${ctx.exp} + 10`)
273 |
274 | // run reactive effect
275 | ctx.effect(() => {
276 | // this will re-run every time the get() value changes
277 | console.log(ctx.get())
278 | })
279 |
280 | return () => {
281 | // cleanup if the element is unmounted
282 | }
283 | }
284 |
285 | // register the directive
286 | createApp().directive('my-dir', myDirective).mount()
287 | ```
288 |
289 | This is how `v-html` is implemented:
290 |
291 | ```js
292 | const html = ({ el, get, effect }) => {
293 | effect(() => {
294 | el.innerHTML = get()
295 | })
296 | }
297 | ```
298 |
299 | ### Custom Delimiters (0.3+)
300 |
301 | You can use custom delimiters by passing `$delimiters` to your root scope. This is useful when working alongside a server-side templating language that also uses mustaches:
302 |
303 | ```js
304 | createApp({
305 | $delimiters: ['${', '}']
306 | }).mount()
307 | ```
308 |
309 | ## Examples
310 |
311 | Check out the [examples directory](https://github.com/vuejs/petite-vue/tree/main/examples).
312 |
313 | ## Features
314 |
315 | ### `petite-vue` only
316 |
317 | - `v-scope`
318 | - `v-effect`
319 | - `@vue:mounted` & `@vue:unmounted` events
320 |
321 | ### Has Different Behavior
322 |
323 | - In expressions, `$el` points to the current element the directive is bound to (instead of component root element)
324 | - `createApp()` accepts global state instead of a component
325 | - Components are simplified into object-returning functions
326 | - Custom directives have a different interface
327 |
328 | ### Vue Compatible
329 |
330 | - `{{ }}` text bindings (configurable with custom delimiters)
331 | - `v-bind` (including `:` shorthand and class/style special handling)
332 | - `v-on` (including `@` shorthand and all modifiers)
333 | - `v-model` (all input types + non-string `:value` bindings)
334 | - `v-if` / `v-else` / `v-else-if`
335 | - `v-for`
336 | - `v-show`
337 | - `v-html`
338 | - `v-text`
339 | - `v-pre`
340 | - `v-once`
341 | - `v-cloak`
342 | - `reactive()`
343 | - `nextTick()`
344 | - Template refs
345 |
346 | ### Not Supported
347 |
348 | Some features are dropped because they have a relatively low utility/size ratio in the context of progressive enhancement. If you need these features, you should probably just use standard Vue.
349 |
350 | - `ref()`, `computed()` etc.
351 | - Render functions (`petite-vue` has no virtual DOM)
352 | - Reactivity for Collection Types (Map, Set, etc., removed for smaller size)
353 | - Transition, KeepAlive, Teleport, Suspense
354 | - `v-for` deep destructure
355 | - `v-on="object"`
356 | - `v-is` & ``
357 | - `v-bind:style` auto-prefixing
358 |
359 | ## Comparison with standard Vue
360 |
361 | The point of `petite-vue` is not just about being small. It's about using the optimal implementation for the intended use case (progressive enhancement).
362 |
363 | Standard Vue can be used with or without a build step. When using a build setup (e.g. with Single-File Components), we pre-compile all the templates so there's no template processing to be done at runtime. And thanks to tree-shaking, we can ship optional features in standard Vue that doesn't bloat your bundle size when not used. This is the optimal usage of standard Vue, but since it involves a build setup, it is better suited when building SPAs or apps with relatively heavy interactions.
364 |
365 | When using standard Vue without a build step and mounting to in-DOM templates, it is much less optimal because:
366 |
367 | - We have to ship the Vue template compiler to the browser (13kb extra size)
368 | - The compiler will have to retrieve the template string from already instantiated DOM
369 | - The compiler then compiles the string into a JavaScript render function
370 | - Vue then replaces existing DOM templates with new DOM generated from the render function.
371 |
372 | `petite-vue` avoids all this overhead by walking the existing DOM and attaching fine-grained reactive effects to the elements directly. The DOM _is_ the template. This means `petite-vue` is much more efficient in progressive enhancement scenarios.
373 |
374 | This is also how Vue 1 worked. The trade-off here is that this approach is coupled to the DOM and thus not suitable for platform agnostic rendering or JavaScript SSR. We also lose the ability to work with render functions for advanced abstractions. However as you can probably tell, these capabilities are rarely needed in the context of progressive enhancement.
375 |
376 | ## Comparison with Alpine
377 |
378 | `petite-vue` is indeed addressing a similar scope to [Alpine](https://alpinejs.dev), but aims to be (1) even more minimal and (2) more Vue-compatible.
379 |
380 | - `petite-vue` is around half the size of Alpine.
381 |
382 | - `petite-vue` has no transition system (maybe this can be an opt-in plugin).
383 |
384 | - Although Alpine largely resembles Vue's design, there are various cases where the behavior is different from Vue itself. It may also diverge more from Vue in the future. This is good because Alpine shouldn't have to restrict its design to strictly follow Vue - it should have the freedom to develop in a direction that makes sense for its goals.
385 |
386 | In comparison, `petite-vue` will try to align with standard Vue behavior whenever possible so that there is less friction moving to standard Vue if needed. It's intended to be **part of the Vue ecosystem** to cover the progressive enhancement use case where standard Vue is less optimized for nowadays.
387 |
388 | ## Security and CSP
389 |
390 | `petite-vue` evaluates JavaScript expressions in the templates. This means **if** `petite-vue` is mounted on a region of the DOM that contains non-sanitized HTML from user data, it may lead to XSS attacks. **If your page renders user-submitted HTML, you should prefer initializing `petite-vue` using [explicit mount target](#explicit-mount-target) so that it only processes parts that are controlled by you**. You can also sanitize any user-submitted HTML for the `v-scope` attribute.
391 |
392 | `petite-vue` evaluates the expressions using `new Function()`, which may be prohibited in strict CSP settings. There is no plan to provide a CSP build because it involves shipping an expression parser which defeats the purpose of being lightweight. If you have strict CSP requirements, you should probably use standard Vue and pre-compile the templates.
393 |
394 | ## License
395 |
396 | MIT
397 |
--------------------------------------------------------------------------------
/examples/commits.html:
--------------------------------------------------------------------------------
1 |
29 |
30 |
31 |
Latest Vue.js Commits
32 |
33 |
40 | {{ branch }}
41 |
42 |
vuejs/vue@{{ currentBranch }}
43 |
58 |
59 |
60 |
76 |
--------------------------------------------------------------------------------
/examples/grid.html:
--------------------------------------------------------------------------------
1 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
62 | {{ capitalize(key) }}
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {{entry[key]}}
71 |
72 |
73 |
74 |
No matches found.
75 |
76 |
77 |
139 |
--------------------------------------------------------------------------------
/examples/markdown.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
17 |
21 |
22 |
61 |
--------------------------------------------------------------------------------
/examples/svg.html:
--------------------------------------------------------------------------------
1 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {{ label }}
71 |
72 |
73 |
74 |
75 | {{stat.label}}
76 |
77 | {{stat.value}}
78 | X
79 |
80 |
84 |
{{ stats }}
85 |
86 |
87 |
120 |
--------------------------------------------------------------------------------
/examples/todomvc.html:
--------------------------------------------------------------------------------
1 |
5 |
10 |
11 |
134 |
135 |
212 |
--------------------------------------------------------------------------------
/examples/tree.html:
--------------------------------------------------------------------------------
1 |
60 |
61 |
62 |
63 | {{ model.name }}
64 | [{{open ? '-' : '+'}}]
65 |
66 |
70 |
71 |
72 | Double click an item to turn it into a folder.
73 |
76 |
77 |
89 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 | Examples
2 |
10 |
11 | Tests
12 |
30 |
31 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "petite-vue",
3 | "version": "0.4.1",
4 | "description": "5kb subset of Vue optimized for progressive enhancement",
5 | "files": [
6 | "dist"
7 | ],
8 | "main": "dist/petite-vue.umd.js",
9 | "unpkg": "dist/petite-vue.iife.js",
10 | "jsdelivr": "dist/petite-vue.iife.js",
11 | "module": "./dist/petite-vue.es.js",
12 | "exports": {
13 | ".": {
14 | "import": "./dist/petite-vue.es.js",
15 | "require": "./dist/petite-vue.umd.js"
16 | }
17 | },
18 | "types": "./dist/types/index.d.ts",
19 | "scripts": {
20 | "dev": "vite",
21 | "build": "vite build && tsc --emitDeclarationOnly && mv dist/src dist/types",
22 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
23 | "release": "node scripts/release.js"
24 | },
25 | "repository": {
26 | "type": "git",
27 | "url": "git+https://github.com/vuejs/petite-vue.git"
28 | },
29 | "keywords": [
30 | "vue"
31 | ],
32 | "author": "Evan You",
33 | "license": "MIT",
34 | "bugs": {
35 | "url": "https://github.com/vuejs/petite-vue/discussions"
36 | },
37 | "homepage": "https://github.com/vuejs/petite-vue#readme",
38 | "devDependencies": {
39 | "@vue/reactivity": "^3.2.27",
40 | "@vue/shared": "^3.2.27",
41 | "chalk": "^4.1.1",
42 | "conventional-changelog-cli": "^2.1.1",
43 | "enquirer": "^2.3.6",
44 | "execa": "^5.0.0",
45 | "prettier": "^2.3.0",
46 | "semver": "^7.3.5",
47 | "typescript": "^4.4.3",
48 | "vite": "^2.7.12"
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/pnpm-lock.yaml:
--------------------------------------------------------------------------------
1 | lockfileVersion: 5.3
2 |
3 | specifiers:
4 | '@vue/reactivity': ^3.2.27
5 | '@vue/shared': ^3.2.27
6 | chalk: ^4.1.1
7 | conventional-changelog-cli: ^2.1.1
8 | enquirer: ^2.3.6
9 | execa: ^5.0.0
10 | prettier: ^2.3.0
11 | semver: ^7.3.5
12 | typescript: ^4.4.3
13 | vite: ^2.7.12
14 |
15 | devDependencies:
16 | '@vue/reactivity': 3.2.27
17 | '@vue/shared': 3.2.27
18 | chalk: 4.1.2
19 | conventional-changelog-cli: 2.1.1
20 | enquirer: 2.3.6
21 | execa: 5.1.1
22 | prettier: 2.5.1
23 | semver: 7.3.5
24 | typescript: 4.5.3
25 | vite: 2.7.12
26 |
27 | packages:
28 |
29 | /@babel/code-frame/7.16.0:
30 | resolution: {integrity: sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA==}
31 | engines: {node: '>=6.9.0'}
32 | dependencies:
33 | '@babel/highlight': 7.16.0
34 | dev: true
35 |
36 | /@babel/helper-validator-identifier/7.15.7:
37 | resolution: {integrity: sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w==}
38 | engines: {node: '>=6.9.0'}
39 | dev: true
40 |
41 | /@babel/highlight/7.16.0:
42 | resolution: {integrity: sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g==}
43 | engines: {node: '>=6.9.0'}
44 | dependencies:
45 | '@babel/helper-validator-identifier': 7.15.7
46 | chalk: 2.4.2
47 | js-tokens: 4.0.0
48 | dev: true
49 |
50 | /@hutson/parse-repository-url/3.0.2:
51 | resolution: {integrity: sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==}
52 | engines: {node: '>=6.9.0'}
53 | dev: true
54 |
55 | /@types/minimist/1.2.2:
56 | resolution: {integrity: sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==}
57 | dev: true
58 |
59 | /@types/normalize-package-data/2.4.1:
60 | resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==}
61 | dev: true
62 |
63 | /@vue/reactivity/3.2.27:
64 | resolution: {integrity: sha512-QPfIQEJidRGIu/mPexhcB4csp1LEg2Nr+/QE72MnXs/OYDtFErhC9FxIyymkxp/xvAgL5wsnSOuDD6zWF42vRQ==}
65 | dependencies:
66 | '@vue/shared': 3.2.27
67 | dev: true
68 |
69 | /@vue/shared/3.2.27:
70 | resolution: {integrity: sha512-rpAn9k6O08Lvo7ekBIAnkOukX/4EsEQLPrRJBKhIEasMsOI5eX0f6mq1sDUSY7cgAqWw2d7QtP74CWxdXoyKxA==}
71 | dev: true
72 |
73 | /JSONStream/1.3.5:
74 | resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
75 | hasBin: true
76 | dependencies:
77 | jsonparse: 1.3.1
78 | through: 2.3.8
79 | dev: true
80 |
81 | /add-stream/1.0.0:
82 | resolution: {integrity: sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=}
83 | dev: true
84 |
85 | /ansi-colors/4.1.1:
86 | resolution: {integrity: sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==}
87 | engines: {node: '>=6'}
88 | dev: true
89 |
90 | /ansi-regex/5.0.1:
91 | resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
92 | engines: {node: '>=8'}
93 | dev: true
94 |
95 | /ansi-styles/3.2.1:
96 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
97 | engines: {node: '>=4'}
98 | dependencies:
99 | color-convert: 1.9.3
100 | dev: true
101 |
102 | /ansi-styles/4.3.0:
103 | resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
104 | engines: {node: '>=8'}
105 | dependencies:
106 | color-convert: 2.0.1
107 | dev: true
108 |
109 | /array-ify/1.0.0:
110 | resolution: {integrity: sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=}
111 | dev: true
112 |
113 | /arrify/1.0.1:
114 | resolution: {integrity: sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=}
115 | engines: {node: '>=0.10.0'}
116 | dev: true
117 |
118 | /camelcase-keys/6.2.2:
119 | resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==}
120 | engines: {node: '>=8'}
121 | dependencies:
122 | camelcase: 5.3.1
123 | map-obj: 4.3.0
124 | quick-lru: 4.0.1
125 | dev: true
126 |
127 | /camelcase/5.3.1:
128 | resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
129 | engines: {node: '>=6'}
130 | dev: true
131 |
132 | /chalk/2.4.2:
133 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
134 | engines: {node: '>=4'}
135 | dependencies:
136 | ansi-styles: 3.2.1
137 | escape-string-regexp: 1.0.5
138 | supports-color: 5.5.0
139 | dev: true
140 |
141 | /chalk/4.1.2:
142 | resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
143 | engines: {node: '>=10'}
144 | dependencies:
145 | ansi-styles: 4.3.0
146 | supports-color: 7.2.0
147 | dev: true
148 |
149 | /cliui/7.0.4:
150 | resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
151 | dependencies:
152 | string-width: 4.2.3
153 | strip-ansi: 6.0.1
154 | wrap-ansi: 7.0.0
155 | dev: true
156 |
157 | /color-convert/1.9.3:
158 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
159 | dependencies:
160 | color-name: 1.1.3
161 | dev: true
162 |
163 | /color-convert/2.0.1:
164 | resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
165 | engines: {node: '>=7.0.0'}
166 | dependencies:
167 | color-name: 1.1.4
168 | dev: true
169 |
170 | /color-name/1.1.3:
171 | resolution: {integrity: sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=}
172 | dev: true
173 |
174 | /color-name/1.1.4:
175 | resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
176 | dev: true
177 |
178 | /compare-func/2.0.0:
179 | resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==}
180 | dependencies:
181 | array-ify: 1.0.0
182 | dot-prop: 5.3.0
183 | dev: true
184 |
185 | /conventional-changelog-angular/5.0.13:
186 | resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==}
187 | engines: {node: '>=10'}
188 | dependencies:
189 | compare-func: 2.0.0
190 | q: 1.5.1
191 | dev: true
192 |
193 | /conventional-changelog-atom/2.0.8:
194 | resolution: {integrity: sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==}
195 | engines: {node: '>=10'}
196 | dependencies:
197 | q: 1.5.1
198 | dev: true
199 |
200 | /conventional-changelog-cli/2.1.1:
201 | resolution: {integrity: sha512-xMGQdKJ+4XFDDgfX5aK7UNFduvJMbvF5BB+g0OdVhA3rYdYyhctrIE2Al+WYdZeKTdg9YzMWF2iFPT8MupIwng==}
202 | engines: {node: '>=10'}
203 | hasBin: true
204 | dependencies:
205 | add-stream: 1.0.0
206 | conventional-changelog: 3.1.24
207 | lodash: 4.17.21
208 | meow: 8.1.2
209 | tempfile: 3.0.0
210 | dev: true
211 |
212 | /conventional-changelog-codemirror/2.0.8:
213 | resolution: {integrity: sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==}
214 | engines: {node: '>=10'}
215 | dependencies:
216 | q: 1.5.1
217 | dev: true
218 |
219 | /conventional-changelog-conventionalcommits/4.6.1:
220 | resolution: {integrity: sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==}
221 | engines: {node: '>=10'}
222 | dependencies:
223 | compare-func: 2.0.0
224 | lodash: 4.17.21
225 | q: 1.5.1
226 | dev: true
227 |
228 | /conventional-changelog-core/4.2.4:
229 | resolution: {integrity: sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==}
230 | engines: {node: '>=10'}
231 | dependencies:
232 | add-stream: 1.0.0
233 | conventional-changelog-writer: 5.0.0
234 | conventional-commits-parser: 3.2.3
235 | dateformat: 3.0.3
236 | get-pkg-repo: 4.2.1
237 | git-raw-commits: 2.0.10
238 | git-remote-origin-url: 2.0.0
239 | git-semver-tags: 4.1.1
240 | lodash: 4.17.21
241 | normalize-package-data: 3.0.3
242 | q: 1.5.1
243 | read-pkg: 3.0.0
244 | read-pkg-up: 3.0.0
245 | through2: 4.0.2
246 | dev: true
247 |
248 | /conventional-changelog-ember/2.0.9:
249 | resolution: {integrity: sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==}
250 | engines: {node: '>=10'}
251 | dependencies:
252 | q: 1.5.1
253 | dev: true
254 |
255 | /conventional-changelog-eslint/3.0.9:
256 | resolution: {integrity: sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==}
257 | engines: {node: '>=10'}
258 | dependencies:
259 | q: 1.5.1
260 | dev: true
261 |
262 | /conventional-changelog-express/2.0.6:
263 | resolution: {integrity: sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==}
264 | engines: {node: '>=10'}
265 | dependencies:
266 | q: 1.5.1
267 | dev: true
268 |
269 | /conventional-changelog-jquery/3.0.11:
270 | resolution: {integrity: sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==}
271 | engines: {node: '>=10'}
272 | dependencies:
273 | q: 1.5.1
274 | dev: true
275 |
276 | /conventional-changelog-jshint/2.0.9:
277 | resolution: {integrity: sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==}
278 | engines: {node: '>=10'}
279 | dependencies:
280 | compare-func: 2.0.0
281 | q: 1.5.1
282 | dev: true
283 |
284 | /conventional-changelog-preset-loader/2.3.4:
285 | resolution: {integrity: sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==}
286 | engines: {node: '>=10'}
287 | dev: true
288 |
289 | /conventional-changelog-writer/5.0.0:
290 | resolution: {integrity: sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==}
291 | engines: {node: '>=10'}
292 | hasBin: true
293 | dependencies:
294 | conventional-commits-filter: 2.0.7
295 | dateformat: 3.0.3
296 | handlebars: 4.7.7
297 | json-stringify-safe: 5.0.1
298 | lodash: 4.17.21
299 | meow: 8.1.2
300 | semver: 6.3.0
301 | split: 1.0.1
302 | through2: 4.0.2
303 | dev: true
304 |
305 | /conventional-changelog/3.1.24:
306 | resolution: {integrity: sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==}
307 | engines: {node: '>=10'}
308 | dependencies:
309 | conventional-changelog-angular: 5.0.13
310 | conventional-changelog-atom: 2.0.8
311 | conventional-changelog-codemirror: 2.0.8
312 | conventional-changelog-conventionalcommits: 4.6.1
313 | conventional-changelog-core: 4.2.4
314 | conventional-changelog-ember: 2.0.9
315 | conventional-changelog-eslint: 3.0.9
316 | conventional-changelog-express: 2.0.6
317 | conventional-changelog-jquery: 3.0.11
318 | conventional-changelog-jshint: 2.0.9
319 | conventional-changelog-preset-loader: 2.3.4
320 | dev: true
321 |
322 | /conventional-commits-filter/2.0.7:
323 | resolution: {integrity: sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==}
324 | engines: {node: '>=10'}
325 | dependencies:
326 | lodash.ismatch: 4.4.0
327 | modify-values: 1.0.1
328 | dev: true
329 |
330 | /conventional-commits-parser/3.2.3:
331 | resolution: {integrity: sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==}
332 | engines: {node: '>=10'}
333 | hasBin: true
334 | dependencies:
335 | is-text-path: 1.0.1
336 | JSONStream: 1.3.5
337 | lodash: 4.17.21
338 | meow: 8.1.2
339 | split2: 3.2.2
340 | through2: 4.0.2
341 | dev: true
342 |
343 | /core-util-is/1.0.3:
344 | resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
345 | dev: true
346 |
347 | /cross-spawn/7.0.3:
348 | resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
349 | engines: {node: '>= 8'}
350 | dependencies:
351 | path-key: 3.1.1
352 | shebang-command: 2.0.0
353 | which: 2.0.2
354 | dev: true
355 |
356 | /dargs/7.0.0:
357 | resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
358 | engines: {node: '>=8'}
359 | dev: true
360 |
361 | /dateformat/3.0.3:
362 | resolution: {integrity: sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==}
363 | dev: true
364 |
365 | /decamelize-keys/1.1.0:
366 | resolution: {integrity: sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=}
367 | engines: {node: '>=0.10.0'}
368 | dependencies:
369 | decamelize: 1.2.0
370 | map-obj: 1.0.1
371 | dev: true
372 |
373 | /decamelize/1.2.0:
374 | resolution: {integrity: sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=}
375 | engines: {node: '>=0.10.0'}
376 | dev: true
377 |
378 | /dot-prop/5.3.0:
379 | resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
380 | engines: {node: '>=8'}
381 | dependencies:
382 | is-obj: 2.0.0
383 | dev: true
384 |
385 | /emoji-regex/8.0.0:
386 | resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
387 | dev: true
388 |
389 | /enquirer/2.3.6:
390 | resolution: {integrity: sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==}
391 | engines: {node: '>=8.6'}
392 | dependencies:
393 | ansi-colors: 4.1.1
394 | dev: true
395 |
396 | /error-ex/1.3.2:
397 | resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
398 | dependencies:
399 | is-arrayish: 0.2.1
400 | dev: true
401 |
402 | /esbuild-android-arm64/0.13.15:
403 | resolution: {integrity: sha512-m602nft/XXeO8YQPUDVoHfjyRVPdPgjyyXOxZ44MK/agewFFkPa8tUo6lAzSWh5Ui5PB4KR9UIFTSBKh/RrCmg==}
404 | cpu: [arm64]
405 | os: [android]
406 | requiresBuild: true
407 | dev: true
408 | optional: true
409 |
410 | /esbuild-darwin-64/0.13.15:
411 | resolution: {integrity: sha512-ihOQRGs2yyp7t5bArCwnvn2Atr6X4axqPpEdCFPVp7iUj4cVSdisgvEKdNR7yH3JDjW6aQDw40iQFoTqejqxvQ==}
412 | cpu: [x64]
413 | os: [darwin]
414 | requiresBuild: true
415 | dev: true
416 | optional: true
417 |
418 | /esbuild-darwin-arm64/0.13.15:
419 | resolution: {integrity: sha512-i1FZssTVxUqNlJ6cBTj5YQj4imWy3m49RZRnHhLpefFIh0To05ow9DTrXROTE1urGTQCloFUXTX8QfGJy1P8dQ==}
420 | cpu: [arm64]
421 | os: [darwin]
422 | requiresBuild: true
423 | dev: true
424 | optional: true
425 |
426 | /esbuild-freebsd-64/0.13.15:
427 | resolution: {integrity: sha512-G3dLBXUI6lC6Z09/x+WtXBXbOYQZ0E8TDBqvn7aMaOCzryJs8LyVXKY4CPnHFXZAbSwkCbqiPuSQ1+HhrNk7EA==}
428 | cpu: [x64]
429 | os: [freebsd]
430 | requiresBuild: true
431 | dev: true
432 | optional: true
433 |
434 | /esbuild-freebsd-arm64/0.13.15:
435 | resolution: {integrity: sha512-KJx0fzEDf1uhNOZQStV4ujg30WlnwqUASaGSFPhznLM/bbheu9HhqZ6mJJZM32lkyfGJikw0jg7v3S0oAvtvQQ==}
436 | cpu: [arm64]
437 | os: [freebsd]
438 | requiresBuild: true
439 | dev: true
440 | optional: true
441 |
442 | /esbuild-linux-32/0.13.15:
443 | resolution: {integrity: sha512-ZvTBPk0YWCLMCXiFmD5EUtB30zIPvC5Itxz0mdTu/xZBbbHJftQgLWY49wEPSn2T/TxahYCRDWun5smRa0Tu+g==}
444 | cpu: [ia32]
445 | os: [linux]
446 | requiresBuild: true
447 | dev: true
448 | optional: true
449 |
450 | /esbuild-linux-64/0.13.15:
451 | resolution: {integrity: sha512-eCKzkNSLywNeQTRBxJRQ0jxRCl2YWdMB3+PkWFo2BBQYC5mISLIVIjThNtn6HUNqua1pnvgP5xX0nHbZbPj5oA==}
452 | cpu: [x64]
453 | os: [linux]
454 | requiresBuild: true
455 | dev: true
456 | optional: true
457 |
458 | /esbuild-linux-arm/0.13.15:
459 | resolution: {integrity: sha512-wUHttDi/ol0tD8ZgUMDH8Ef7IbDX+/UsWJOXaAyTdkT7Yy9ZBqPg8bgB/Dn3CZ9SBpNieozrPRHm0BGww7W/jA==}
460 | cpu: [arm]
461 | os: [linux]
462 | requiresBuild: true
463 | dev: true
464 | optional: true
465 |
466 | /esbuild-linux-arm64/0.13.15:
467 | resolution: {integrity: sha512-bYpuUlN6qYU9slzr/ltyLTR9YTBS7qUDymO8SV7kjeNext61OdmqFAzuVZom+OLW1HPHseBfJ/JfdSlx8oTUoA==}
468 | cpu: [arm64]
469 | os: [linux]
470 | requiresBuild: true
471 | dev: true
472 | optional: true
473 |
474 | /esbuild-linux-mips64le/0.13.15:
475 | resolution: {integrity: sha512-KlVjIG828uFPyJkO/8gKwy9RbXhCEUeFsCGOJBepUlpa7G8/SeZgncUEz/tOOUJTcWMTmFMtdd3GElGyAtbSWg==}
476 | cpu: [mips64el]
477 | os: [linux]
478 | requiresBuild: true
479 | dev: true
480 | optional: true
481 |
482 | /esbuild-linux-ppc64le/0.13.15:
483 | resolution: {integrity: sha512-h6gYF+OsaqEuBjeesTBtUPw0bmiDu7eAeuc2OEH9S6mV9/jPhPdhOWzdeshb0BskRZxPhxPOjqZ+/OqLcxQwEQ==}
484 | cpu: [ppc64]
485 | os: [linux]
486 | requiresBuild: true
487 | dev: true
488 | optional: true
489 |
490 | /esbuild-netbsd-64/0.13.15:
491 | resolution: {integrity: sha512-3+yE9emwoevLMyvu+iR3rsa+Xwhie7ZEHMGDQ6dkqP/ndFzRHkobHUKTe+NCApSqG5ce2z4rFu+NX/UHnxlh3w==}
492 | cpu: [x64]
493 | os: [netbsd]
494 | requiresBuild: true
495 | dev: true
496 | optional: true
497 |
498 | /esbuild-openbsd-64/0.13.15:
499 | resolution: {integrity: sha512-wTfvtwYJYAFL1fSs8yHIdf5GEE4NkbtbXtjLWjM3Cw8mmQKqsg8kTiqJ9NJQe5NX/5Qlo7Xd9r1yKMMkHllp5g==}
500 | cpu: [x64]
501 | os: [openbsd]
502 | requiresBuild: true
503 | dev: true
504 | optional: true
505 |
506 | /esbuild-sunos-64/0.13.15:
507 | resolution: {integrity: sha512-lbivT9Bx3t1iWWrSnGyBP9ODriEvWDRiweAs69vI+miJoeKwHWOComSRukttbuzjZ8r1q0mQJ8Z7yUsDJ3hKdw==}
508 | cpu: [x64]
509 | os: [sunos]
510 | requiresBuild: true
511 | dev: true
512 | optional: true
513 |
514 | /esbuild-windows-32/0.13.15:
515 | resolution: {integrity: sha512-fDMEf2g3SsJ599MBr50cY5ve5lP1wyVwTe6aLJsM01KtxyKkB4UT+fc5MXQFn3RLrAIAZOG+tHC+yXObpSn7Nw==}
516 | cpu: [ia32]
517 | os: [win32]
518 | requiresBuild: true
519 | dev: true
520 | optional: true
521 |
522 | /esbuild-windows-64/0.13.15:
523 | resolution: {integrity: sha512-9aMsPRGDWCd3bGjUIKG/ZOJPKsiztlxl/Q3C1XDswO6eNX/Jtwu4M+jb6YDH9hRSUflQWX0XKAfWzgy5Wk54JQ==}
524 | cpu: [x64]
525 | os: [win32]
526 | requiresBuild: true
527 | dev: true
528 | optional: true
529 |
530 | /esbuild-windows-arm64/0.13.15:
531 | resolution: {integrity: sha512-zzvyCVVpbwQQATaf3IG8mu1IwGEiDxKkYUdA4FpoCHi1KtPa13jeScYDjlW0Qh+ebWzpKfR2ZwvqAQkSWNcKjA==}
532 | cpu: [arm64]
533 | os: [win32]
534 | requiresBuild: true
535 | dev: true
536 | optional: true
537 |
538 | /esbuild/0.13.15:
539 | resolution: {integrity: sha512-raCxt02HBKv8RJxE8vkTSCXGIyKHdEdGfUmiYb8wnabnaEmHzyW7DCHb5tEN0xU8ryqg5xw54mcwnYkC4x3AIw==}
540 | hasBin: true
541 | requiresBuild: true
542 | optionalDependencies:
543 | esbuild-android-arm64: 0.13.15
544 | esbuild-darwin-64: 0.13.15
545 | esbuild-darwin-arm64: 0.13.15
546 | esbuild-freebsd-64: 0.13.15
547 | esbuild-freebsd-arm64: 0.13.15
548 | esbuild-linux-32: 0.13.15
549 | esbuild-linux-64: 0.13.15
550 | esbuild-linux-arm: 0.13.15
551 | esbuild-linux-arm64: 0.13.15
552 | esbuild-linux-mips64le: 0.13.15
553 | esbuild-linux-ppc64le: 0.13.15
554 | esbuild-netbsd-64: 0.13.15
555 | esbuild-openbsd-64: 0.13.15
556 | esbuild-sunos-64: 0.13.15
557 | esbuild-windows-32: 0.13.15
558 | esbuild-windows-64: 0.13.15
559 | esbuild-windows-arm64: 0.13.15
560 | dev: true
561 |
562 | /escalade/3.1.1:
563 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
564 | engines: {node: '>=6'}
565 | dev: true
566 |
567 | /escape-string-regexp/1.0.5:
568 | resolution: {integrity: sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=}
569 | engines: {node: '>=0.8.0'}
570 | dev: true
571 |
572 | /execa/5.1.1:
573 | resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
574 | engines: {node: '>=10'}
575 | dependencies:
576 | cross-spawn: 7.0.3
577 | get-stream: 6.0.1
578 | human-signals: 2.1.0
579 | is-stream: 2.0.1
580 | merge-stream: 2.0.0
581 | npm-run-path: 4.0.1
582 | onetime: 5.1.2
583 | signal-exit: 3.0.6
584 | strip-final-newline: 2.0.0
585 | dev: true
586 |
587 | /find-up/2.1.0:
588 | resolution: {integrity: sha1-RdG35QbHF93UgndaK3eSCjwMV6c=}
589 | engines: {node: '>=4'}
590 | dependencies:
591 | locate-path: 2.0.0
592 | dev: true
593 |
594 | /find-up/4.1.0:
595 | resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
596 | engines: {node: '>=8'}
597 | dependencies:
598 | locate-path: 5.0.0
599 | path-exists: 4.0.0
600 | dev: true
601 |
602 | /fsevents/2.3.2:
603 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
604 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
605 | os: [darwin]
606 | requiresBuild: true
607 | dev: true
608 | optional: true
609 |
610 | /function-bind/1.1.1:
611 | resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
612 | dev: true
613 |
614 | /get-caller-file/2.0.5:
615 | resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
616 | engines: {node: 6.* || 8.* || >= 10.*}
617 | dev: true
618 |
619 | /get-pkg-repo/4.2.1:
620 | resolution: {integrity: sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==}
621 | engines: {node: '>=6.9.0'}
622 | hasBin: true
623 | dependencies:
624 | '@hutson/parse-repository-url': 3.0.2
625 | hosted-git-info: 4.0.2
626 | through2: 2.0.5
627 | yargs: 16.2.0
628 | dev: true
629 |
630 | /get-stream/6.0.1:
631 | resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
632 | engines: {node: '>=10'}
633 | dev: true
634 |
635 | /git-raw-commits/2.0.10:
636 | resolution: {integrity: sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==}
637 | engines: {node: '>=10'}
638 | hasBin: true
639 | dependencies:
640 | dargs: 7.0.0
641 | lodash: 4.17.21
642 | meow: 8.1.2
643 | split2: 3.2.2
644 | through2: 4.0.2
645 | dev: true
646 |
647 | /git-remote-origin-url/2.0.0:
648 | resolution: {integrity: sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=}
649 | engines: {node: '>=4'}
650 | dependencies:
651 | gitconfiglocal: 1.0.0
652 | pify: 2.3.0
653 | dev: true
654 |
655 | /git-semver-tags/4.1.1:
656 | resolution: {integrity: sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==}
657 | engines: {node: '>=10'}
658 | hasBin: true
659 | dependencies:
660 | meow: 8.1.2
661 | semver: 6.3.0
662 | dev: true
663 |
664 | /gitconfiglocal/1.0.0:
665 | resolution: {integrity: sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=}
666 | dependencies:
667 | ini: 1.3.8
668 | dev: true
669 |
670 | /graceful-fs/4.2.8:
671 | resolution: {integrity: sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==}
672 | dev: true
673 |
674 | /handlebars/4.7.7:
675 | resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==}
676 | engines: {node: '>=0.4.7'}
677 | hasBin: true
678 | dependencies:
679 | minimist: 1.2.5
680 | neo-async: 2.6.2
681 | source-map: 0.6.1
682 | wordwrap: 1.0.0
683 | optionalDependencies:
684 | uglify-js: 3.14.4
685 | dev: true
686 |
687 | /hard-rejection/2.1.0:
688 | resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
689 | engines: {node: '>=6'}
690 | dev: true
691 |
692 | /has-flag/3.0.0:
693 | resolution: {integrity: sha1-tdRU3CGZriJWmfNGfloH87lVuv0=}
694 | engines: {node: '>=4'}
695 | dev: true
696 |
697 | /has-flag/4.0.0:
698 | resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
699 | engines: {node: '>=8'}
700 | dev: true
701 |
702 | /has/1.0.3:
703 | resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
704 | engines: {node: '>= 0.4.0'}
705 | dependencies:
706 | function-bind: 1.1.1
707 | dev: true
708 |
709 | /hosted-git-info/2.8.9:
710 | resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
711 | dev: true
712 |
713 | /hosted-git-info/4.0.2:
714 | resolution: {integrity: sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==}
715 | engines: {node: '>=10'}
716 | dependencies:
717 | lru-cache: 6.0.0
718 | dev: true
719 |
720 | /human-signals/2.1.0:
721 | resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
722 | engines: {node: '>=10.17.0'}
723 | dev: true
724 |
725 | /indent-string/4.0.0:
726 | resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
727 | engines: {node: '>=8'}
728 | dev: true
729 |
730 | /inherits/2.0.4:
731 | resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
732 | dev: true
733 |
734 | /ini/1.3.8:
735 | resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
736 | dev: true
737 |
738 | /is-arrayish/0.2.1:
739 | resolution: {integrity: sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=}
740 | dev: true
741 |
742 | /is-core-module/2.8.0:
743 | resolution: {integrity: sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==}
744 | dependencies:
745 | has: 1.0.3
746 | dev: true
747 |
748 | /is-fullwidth-code-point/3.0.0:
749 | resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
750 | engines: {node: '>=8'}
751 | dev: true
752 |
753 | /is-obj/2.0.0:
754 | resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
755 | engines: {node: '>=8'}
756 | dev: true
757 |
758 | /is-plain-obj/1.1.0:
759 | resolution: {integrity: sha1-caUMhCnfync8kqOQpKA7OfzVHT4=}
760 | engines: {node: '>=0.10.0'}
761 | dev: true
762 |
763 | /is-stream/2.0.1:
764 | resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
765 | engines: {node: '>=8'}
766 | dev: true
767 |
768 | /is-text-path/1.0.1:
769 | resolution: {integrity: sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=}
770 | engines: {node: '>=0.10.0'}
771 | dependencies:
772 | text-extensions: 1.9.0
773 | dev: true
774 |
775 | /isarray/1.0.0:
776 | resolution: {integrity: sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=}
777 | dev: true
778 |
779 | /isexe/2.0.0:
780 | resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=}
781 | dev: true
782 |
783 | /js-tokens/4.0.0:
784 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
785 | dev: true
786 |
787 | /json-parse-better-errors/1.0.2:
788 | resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
789 | dev: true
790 |
791 | /json-parse-even-better-errors/2.3.1:
792 | resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
793 | dev: true
794 |
795 | /json-stringify-safe/5.0.1:
796 | resolution: {integrity: sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=}
797 | dev: true
798 |
799 | /jsonparse/1.3.1:
800 | resolution: {integrity: sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=}
801 | engines: {'0': node >= 0.2.0}
802 | dev: true
803 |
804 | /kind-of/6.0.3:
805 | resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
806 | engines: {node: '>=0.10.0'}
807 | dev: true
808 |
809 | /lines-and-columns/1.2.4:
810 | resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
811 | dev: true
812 |
813 | /load-json-file/4.0.0:
814 | resolution: {integrity: sha1-L19Fq5HjMhYjT9U62rZo607AmTs=}
815 | engines: {node: '>=4'}
816 | dependencies:
817 | graceful-fs: 4.2.8
818 | parse-json: 4.0.0
819 | pify: 3.0.0
820 | strip-bom: 3.0.0
821 | dev: true
822 |
823 | /locate-path/2.0.0:
824 | resolution: {integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=}
825 | engines: {node: '>=4'}
826 | dependencies:
827 | p-locate: 2.0.0
828 | path-exists: 3.0.0
829 | dev: true
830 |
831 | /locate-path/5.0.0:
832 | resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
833 | engines: {node: '>=8'}
834 | dependencies:
835 | p-locate: 4.1.0
836 | dev: true
837 |
838 | /lodash.ismatch/4.4.0:
839 | resolution: {integrity: sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=}
840 | dev: true
841 |
842 | /lodash/4.17.21:
843 | resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
844 | dev: true
845 |
846 | /lru-cache/6.0.0:
847 | resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
848 | engines: {node: '>=10'}
849 | dependencies:
850 | yallist: 4.0.0
851 | dev: true
852 |
853 | /map-obj/1.0.1:
854 | resolution: {integrity: sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=}
855 | engines: {node: '>=0.10.0'}
856 | dev: true
857 |
858 | /map-obj/4.3.0:
859 | resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
860 | engines: {node: '>=8'}
861 | dev: true
862 |
863 | /meow/8.1.2:
864 | resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==}
865 | engines: {node: '>=10'}
866 | dependencies:
867 | '@types/minimist': 1.2.2
868 | camelcase-keys: 6.2.2
869 | decamelize-keys: 1.1.0
870 | hard-rejection: 2.1.0
871 | minimist-options: 4.1.0
872 | normalize-package-data: 3.0.3
873 | read-pkg-up: 7.0.1
874 | redent: 3.0.0
875 | trim-newlines: 3.0.1
876 | type-fest: 0.18.1
877 | yargs-parser: 20.2.9
878 | dev: true
879 |
880 | /merge-stream/2.0.0:
881 | resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
882 | dev: true
883 |
884 | /mimic-fn/2.1.0:
885 | resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
886 | engines: {node: '>=6'}
887 | dev: true
888 |
889 | /min-indent/1.0.1:
890 | resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
891 | engines: {node: '>=4'}
892 | dev: true
893 |
894 | /minimist-options/4.1.0:
895 | resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
896 | engines: {node: '>= 6'}
897 | dependencies:
898 | arrify: 1.0.1
899 | is-plain-obj: 1.1.0
900 | kind-of: 6.0.3
901 | dev: true
902 |
903 | /minimist/1.2.5:
904 | resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==}
905 | dev: true
906 |
907 | /modify-values/1.0.1:
908 | resolution: {integrity: sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==}
909 | engines: {node: '>=0.10.0'}
910 | dev: true
911 |
912 | /nanoid/3.1.30:
913 | resolution: {integrity: sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==}
914 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
915 | hasBin: true
916 | dev: true
917 |
918 | /neo-async/2.6.2:
919 | resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
920 | dev: true
921 |
922 | /normalize-package-data/2.5.0:
923 | resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
924 | dependencies:
925 | hosted-git-info: 2.8.9
926 | resolve: 1.20.0
927 | semver: 5.7.1
928 | validate-npm-package-license: 3.0.4
929 | dev: true
930 |
931 | /normalize-package-data/3.0.3:
932 | resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==}
933 | engines: {node: '>=10'}
934 | dependencies:
935 | hosted-git-info: 4.0.2
936 | is-core-module: 2.8.0
937 | semver: 7.3.5
938 | validate-npm-package-license: 3.0.4
939 | dev: true
940 |
941 | /npm-run-path/4.0.1:
942 | resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
943 | engines: {node: '>=8'}
944 | dependencies:
945 | path-key: 3.1.1
946 | dev: true
947 |
948 | /onetime/5.1.2:
949 | resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
950 | engines: {node: '>=6'}
951 | dependencies:
952 | mimic-fn: 2.1.0
953 | dev: true
954 |
955 | /p-limit/1.3.0:
956 | resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==}
957 | engines: {node: '>=4'}
958 | dependencies:
959 | p-try: 1.0.0
960 | dev: true
961 |
962 | /p-limit/2.3.0:
963 | resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
964 | engines: {node: '>=6'}
965 | dependencies:
966 | p-try: 2.2.0
967 | dev: true
968 |
969 | /p-locate/2.0.0:
970 | resolution: {integrity: sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=}
971 | engines: {node: '>=4'}
972 | dependencies:
973 | p-limit: 1.3.0
974 | dev: true
975 |
976 | /p-locate/4.1.0:
977 | resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
978 | engines: {node: '>=8'}
979 | dependencies:
980 | p-limit: 2.3.0
981 | dev: true
982 |
983 | /p-try/1.0.0:
984 | resolution: {integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=}
985 | engines: {node: '>=4'}
986 | dev: true
987 |
988 | /p-try/2.2.0:
989 | resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
990 | engines: {node: '>=6'}
991 | dev: true
992 |
993 | /parse-json/4.0.0:
994 | resolution: {integrity: sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=}
995 | engines: {node: '>=4'}
996 | dependencies:
997 | error-ex: 1.3.2
998 | json-parse-better-errors: 1.0.2
999 | dev: true
1000 |
1001 | /parse-json/5.2.0:
1002 | resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
1003 | engines: {node: '>=8'}
1004 | dependencies:
1005 | '@babel/code-frame': 7.16.0
1006 | error-ex: 1.3.2
1007 | json-parse-even-better-errors: 2.3.1
1008 | lines-and-columns: 1.2.4
1009 | dev: true
1010 |
1011 | /path-exists/3.0.0:
1012 | resolution: {integrity: sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=}
1013 | engines: {node: '>=4'}
1014 | dev: true
1015 |
1016 | /path-exists/4.0.0:
1017 | resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
1018 | engines: {node: '>=8'}
1019 | dev: true
1020 |
1021 | /path-key/3.1.1:
1022 | resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
1023 | engines: {node: '>=8'}
1024 | dev: true
1025 |
1026 | /path-parse/1.0.7:
1027 | resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
1028 | dev: true
1029 |
1030 | /path-type/3.0.0:
1031 | resolution: {integrity: sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==}
1032 | engines: {node: '>=4'}
1033 | dependencies:
1034 | pify: 3.0.0
1035 | dev: true
1036 |
1037 | /picocolors/1.0.0:
1038 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
1039 | dev: true
1040 |
1041 | /pify/2.3.0:
1042 | resolution: {integrity: sha1-7RQaasBDqEnqWISY59yosVMw6Qw=}
1043 | engines: {node: '>=0.10.0'}
1044 | dev: true
1045 |
1046 | /pify/3.0.0:
1047 | resolution: {integrity: sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=}
1048 | engines: {node: '>=4'}
1049 | dev: true
1050 |
1051 | /postcss/8.4.5:
1052 | resolution: {integrity: sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg==}
1053 | engines: {node: ^10 || ^12 || >=14}
1054 | dependencies:
1055 | nanoid: 3.1.30
1056 | picocolors: 1.0.0
1057 | source-map-js: 1.0.1
1058 | dev: true
1059 |
1060 | /prettier/2.5.1:
1061 | resolution: {integrity: sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==}
1062 | engines: {node: '>=10.13.0'}
1063 | hasBin: true
1064 | dev: true
1065 |
1066 | /process-nextick-args/2.0.1:
1067 | resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
1068 | dev: true
1069 |
1070 | /q/1.5.1:
1071 | resolution: {integrity: sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=}
1072 | engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
1073 | dev: true
1074 |
1075 | /quick-lru/4.0.1:
1076 | resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
1077 | engines: {node: '>=8'}
1078 | dev: true
1079 |
1080 | /read-pkg-up/3.0.0:
1081 | resolution: {integrity: sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=}
1082 | engines: {node: '>=4'}
1083 | dependencies:
1084 | find-up: 2.1.0
1085 | read-pkg: 3.0.0
1086 | dev: true
1087 |
1088 | /read-pkg-up/7.0.1:
1089 | resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
1090 | engines: {node: '>=8'}
1091 | dependencies:
1092 | find-up: 4.1.0
1093 | read-pkg: 5.2.0
1094 | type-fest: 0.8.1
1095 | dev: true
1096 |
1097 | /read-pkg/3.0.0:
1098 | resolution: {integrity: sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=}
1099 | engines: {node: '>=4'}
1100 | dependencies:
1101 | load-json-file: 4.0.0
1102 | normalize-package-data: 2.5.0
1103 | path-type: 3.0.0
1104 | dev: true
1105 |
1106 | /read-pkg/5.2.0:
1107 | resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
1108 | engines: {node: '>=8'}
1109 | dependencies:
1110 | '@types/normalize-package-data': 2.4.1
1111 | normalize-package-data: 2.5.0
1112 | parse-json: 5.2.0
1113 | type-fest: 0.6.0
1114 | dev: true
1115 |
1116 | /readable-stream/2.3.7:
1117 | resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==}
1118 | dependencies:
1119 | core-util-is: 1.0.3
1120 | inherits: 2.0.4
1121 | isarray: 1.0.0
1122 | process-nextick-args: 2.0.1
1123 | safe-buffer: 5.1.2
1124 | string_decoder: 1.1.1
1125 | util-deprecate: 1.0.2
1126 | dev: true
1127 |
1128 | /readable-stream/3.6.0:
1129 | resolution: {integrity: sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==}
1130 | engines: {node: '>= 6'}
1131 | dependencies:
1132 | inherits: 2.0.4
1133 | string_decoder: 1.3.0
1134 | util-deprecate: 1.0.2
1135 | dev: true
1136 |
1137 | /redent/3.0.0:
1138 | resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
1139 | engines: {node: '>=8'}
1140 | dependencies:
1141 | indent-string: 4.0.0
1142 | strip-indent: 3.0.0
1143 | dev: true
1144 |
1145 | /require-directory/2.1.1:
1146 | resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=}
1147 | engines: {node: '>=0.10.0'}
1148 | dev: true
1149 |
1150 | /resolve/1.20.0:
1151 | resolution: {integrity: sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==}
1152 | dependencies:
1153 | is-core-module: 2.8.0
1154 | path-parse: 1.0.7
1155 | dev: true
1156 |
1157 | /rollup/2.61.0:
1158 | resolution: {integrity: sha512-teQ+T1mUYbyvGyUavCodiyA9hD4DxwYZJwr/qehZGhs1Z49vsmzelMVYMxGU4ZhGRKxYPupHuz5yzm/wj7VpWA==}
1159 | engines: {node: '>=10.0.0'}
1160 | hasBin: true
1161 | optionalDependencies:
1162 | fsevents: 2.3.2
1163 | dev: true
1164 |
1165 | /safe-buffer/5.1.2:
1166 | resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
1167 | dev: true
1168 |
1169 | /safe-buffer/5.2.1:
1170 | resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
1171 | dev: true
1172 |
1173 | /semver/5.7.1:
1174 | resolution: {integrity: sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==}
1175 | hasBin: true
1176 | dev: true
1177 |
1178 | /semver/6.3.0:
1179 | resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==}
1180 | hasBin: true
1181 | dev: true
1182 |
1183 | /semver/7.3.5:
1184 | resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==}
1185 | engines: {node: '>=10'}
1186 | hasBin: true
1187 | dependencies:
1188 | lru-cache: 6.0.0
1189 | dev: true
1190 |
1191 | /shebang-command/2.0.0:
1192 | resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
1193 | engines: {node: '>=8'}
1194 | dependencies:
1195 | shebang-regex: 3.0.0
1196 | dev: true
1197 |
1198 | /shebang-regex/3.0.0:
1199 | resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
1200 | engines: {node: '>=8'}
1201 | dev: true
1202 |
1203 | /signal-exit/3.0.6:
1204 | resolution: {integrity: sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==}
1205 | dev: true
1206 |
1207 | /source-map-js/1.0.1:
1208 | resolution: {integrity: sha512-4+TN2b3tqOCd/kaGRJ/sTYA0tR0mdXx26ipdolxcwtJVqEnqNYvlCAt1q3ypy4QMlYus+Zh34RNtYLoq2oQ4IA==}
1209 | engines: {node: '>=0.10.0'}
1210 | dev: true
1211 |
1212 | /source-map/0.6.1:
1213 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
1214 | engines: {node: '>=0.10.0'}
1215 | dev: true
1216 |
1217 | /spdx-correct/3.1.1:
1218 | resolution: {integrity: sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==}
1219 | dependencies:
1220 | spdx-expression-parse: 3.0.1
1221 | spdx-license-ids: 3.0.11
1222 | dev: true
1223 |
1224 | /spdx-exceptions/2.3.0:
1225 | resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==}
1226 | dev: true
1227 |
1228 | /spdx-expression-parse/3.0.1:
1229 | resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
1230 | dependencies:
1231 | spdx-exceptions: 2.3.0
1232 | spdx-license-ids: 3.0.11
1233 | dev: true
1234 |
1235 | /spdx-license-ids/3.0.11:
1236 | resolution: {integrity: sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==}
1237 | dev: true
1238 |
1239 | /split/1.0.1:
1240 | resolution: {integrity: sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==}
1241 | dependencies:
1242 | through: 2.3.8
1243 | dev: true
1244 |
1245 | /split2/3.2.2:
1246 | resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==}
1247 | dependencies:
1248 | readable-stream: 3.6.0
1249 | dev: true
1250 |
1251 | /string-width/4.2.3:
1252 | resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
1253 | engines: {node: '>=8'}
1254 | dependencies:
1255 | emoji-regex: 8.0.0
1256 | is-fullwidth-code-point: 3.0.0
1257 | strip-ansi: 6.0.1
1258 | dev: true
1259 |
1260 | /string_decoder/1.1.1:
1261 | resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
1262 | dependencies:
1263 | safe-buffer: 5.1.2
1264 | dev: true
1265 |
1266 | /string_decoder/1.3.0:
1267 | resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
1268 | dependencies:
1269 | safe-buffer: 5.2.1
1270 | dev: true
1271 |
1272 | /strip-ansi/6.0.1:
1273 | resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
1274 | engines: {node: '>=8'}
1275 | dependencies:
1276 | ansi-regex: 5.0.1
1277 | dev: true
1278 |
1279 | /strip-bom/3.0.0:
1280 | resolution: {integrity: sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=}
1281 | engines: {node: '>=4'}
1282 | dev: true
1283 |
1284 | /strip-final-newline/2.0.0:
1285 | resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
1286 | engines: {node: '>=6'}
1287 | dev: true
1288 |
1289 | /strip-indent/3.0.0:
1290 | resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
1291 | engines: {node: '>=8'}
1292 | dependencies:
1293 | min-indent: 1.0.1
1294 | dev: true
1295 |
1296 | /supports-color/5.5.0:
1297 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
1298 | engines: {node: '>=4'}
1299 | dependencies:
1300 | has-flag: 3.0.0
1301 | dev: true
1302 |
1303 | /supports-color/7.2.0:
1304 | resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
1305 | engines: {node: '>=8'}
1306 | dependencies:
1307 | has-flag: 4.0.0
1308 | dev: true
1309 |
1310 | /temp-dir/2.0.0:
1311 | resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==}
1312 | engines: {node: '>=8'}
1313 | dev: true
1314 |
1315 | /tempfile/3.0.0:
1316 | resolution: {integrity: sha512-uNFCg478XovRi85iD42egu+eSFUmmka750Jy7L5tfHI5hQKKtbPnxaSaXAbBqCDYrw3wx4tXjKwci4/QmsZJxw==}
1317 | engines: {node: '>=8'}
1318 | dependencies:
1319 | temp-dir: 2.0.0
1320 | uuid: 3.4.0
1321 | dev: true
1322 |
1323 | /text-extensions/1.9.0:
1324 | resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==}
1325 | engines: {node: '>=0.10'}
1326 | dev: true
1327 |
1328 | /through/2.3.8:
1329 | resolution: {integrity: sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=}
1330 | dev: true
1331 |
1332 | /through2/2.0.5:
1333 | resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==}
1334 | dependencies:
1335 | readable-stream: 2.3.7
1336 | xtend: 4.0.2
1337 | dev: true
1338 |
1339 | /through2/4.0.2:
1340 | resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
1341 | dependencies:
1342 | readable-stream: 3.6.0
1343 | dev: true
1344 |
1345 | /trim-newlines/3.0.1:
1346 | resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==}
1347 | engines: {node: '>=8'}
1348 | dev: true
1349 |
1350 | /type-fest/0.18.1:
1351 | resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==}
1352 | engines: {node: '>=10'}
1353 | dev: true
1354 |
1355 | /type-fest/0.6.0:
1356 | resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
1357 | engines: {node: '>=8'}
1358 | dev: true
1359 |
1360 | /type-fest/0.8.1:
1361 | resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
1362 | engines: {node: '>=8'}
1363 | dev: true
1364 |
1365 | /typescript/4.5.3:
1366 | resolution: {integrity: sha512-eVYaEHALSt+s9LbvgEv4Ef+Tdq7hBiIZgii12xXJnukryt3pMgJf6aKhoCZ3FWQsu6sydEnkg11fYXLzhLBjeQ==}
1367 | engines: {node: '>=4.2.0'}
1368 | hasBin: true
1369 | dev: true
1370 |
1371 | /uglify-js/3.14.4:
1372 | resolution: {integrity: sha512-AbiSR44J0GoCeV81+oxcy/jDOElO2Bx3d0MfQCUShq7JRXaM4KtQopZsq2vFv8bCq2yMaGrw1FgygUd03RyRDA==}
1373 | engines: {node: '>=0.8.0'}
1374 | hasBin: true
1375 | requiresBuild: true
1376 | dev: true
1377 | optional: true
1378 |
1379 | /util-deprecate/1.0.2:
1380 | resolution: {integrity: sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=}
1381 | dev: true
1382 |
1383 | /uuid/3.4.0:
1384 | resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==}
1385 | deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.
1386 | hasBin: true
1387 | dev: true
1388 |
1389 | /validate-npm-package-license/3.0.4:
1390 | resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
1391 | dependencies:
1392 | spdx-correct: 3.1.1
1393 | spdx-expression-parse: 3.0.1
1394 | dev: true
1395 |
1396 | /vite/2.7.12:
1397 | resolution: {integrity: sha512-KvPYToRQWhRfBeVkyhkZ5hASuHQkqZUUdUcE3xyYtq5oYEPIJ0h9LWiWTO6v990glmSac2cEPeYeXzpX5Z6qKQ==}
1398 | engines: {node: '>=12.2.0'}
1399 | hasBin: true
1400 | peerDependencies:
1401 | less: '*'
1402 | sass: '*'
1403 | stylus: '*'
1404 | peerDependenciesMeta:
1405 | less:
1406 | optional: true
1407 | sass:
1408 | optional: true
1409 | stylus:
1410 | optional: true
1411 | dependencies:
1412 | esbuild: 0.13.15
1413 | postcss: 8.4.5
1414 | resolve: 1.20.0
1415 | rollup: 2.61.0
1416 | optionalDependencies:
1417 | fsevents: 2.3.2
1418 | dev: true
1419 |
1420 | /which/2.0.2:
1421 | resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
1422 | engines: {node: '>= 8'}
1423 | hasBin: true
1424 | dependencies:
1425 | isexe: 2.0.0
1426 | dev: true
1427 |
1428 | /wordwrap/1.0.0:
1429 | resolution: {integrity: sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=}
1430 | dev: true
1431 |
1432 | /wrap-ansi/7.0.0:
1433 | resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
1434 | engines: {node: '>=10'}
1435 | dependencies:
1436 | ansi-styles: 4.3.0
1437 | string-width: 4.2.3
1438 | strip-ansi: 6.0.1
1439 | dev: true
1440 |
1441 | /xtend/4.0.2:
1442 | resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
1443 | engines: {node: '>=0.4'}
1444 | dev: true
1445 |
1446 | /y18n/5.0.8:
1447 | resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
1448 | engines: {node: '>=10'}
1449 | dev: true
1450 |
1451 | /yallist/4.0.0:
1452 | resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
1453 | dev: true
1454 |
1455 | /yargs-parser/20.2.9:
1456 | resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
1457 | engines: {node: '>=10'}
1458 | dev: true
1459 |
1460 | /yargs/16.2.0:
1461 | resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
1462 | engines: {node: '>=10'}
1463 | dependencies:
1464 | cliui: 7.0.4
1465 | escalade: 3.1.1
1466 | get-caller-file: 2.0.5
1467 | require-directory: 2.1.1
1468 | string-width: 4.2.3
1469 | y18n: 5.0.8
1470 | yargs-parser: 20.2.9
1471 | dev: true
1472 |
--------------------------------------------------------------------------------
/scripts/release.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const chalk = require('chalk')
4 | const semver = require('semver')
5 | const { prompt } = require('enquirer')
6 | const execa = require('execa')
7 | const currentVersion = require('../package.json').version
8 |
9 | const versionIncrements = ['patch', 'minor', 'major']
10 |
11 | const inc = (i) => semver.inc(currentVersion, i)
12 | const run = (bin, args, opts = {}) =>
13 | execa(bin, args, { stdio: 'inherit', ...opts })
14 | const step = (msg) => console.log(chalk.cyan(msg))
15 |
16 | async function main() {
17 | let targetVersion
18 |
19 | const { release } = await prompt({
20 | type: 'select',
21 | name: 'release',
22 | message: 'Select release type',
23 | choices: versionIncrements.map((i) => `${i} (${inc(i)})`).concat(['custom'])
24 | })
25 |
26 | if (release === 'custom') {
27 | targetVersion = (
28 | await prompt({
29 | type: 'input',
30 | name: 'version',
31 | message: 'Input custom version',
32 | initial: currentVersion
33 | })
34 | ).version
35 | } else {
36 | targetVersion = release.match(/\((.*)\)/)[1]
37 | }
38 |
39 | if (!semver.valid(targetVersion)) {
40 | throw new Error(`Invalid target version: ${targetVersion}`)
41 | }
42 |
43 | const { yes: tagOk } = await prompt({
44 | type: 'confirm',
45 | name: 'yes',
46 | message: `Releasing v${targetVersion}. Confirm?`
47 | })
48 |
49 | if (!tagOk) {
50 | return
51 | }
52 |
53 | // Update the package version.
54 | step('\nUpdating the package version...')
55 | updatePackage(targetVersion)
56 |
57 | // Build the package.
58 | step('\nBuilding the package...')
59 | await run('yarn', ['build'])
60 |
61 | // Generate the changelog.
62 | step('\nGenerating the changelog...')
63 | await run('yarn', ['changelog'])
64 | await run('yarn', ['prettier', '--write', 'CHANGELOG.md'])
65 |
66 | const { yes: changelogOk } = await prompt({
67 | type: 'confirm',
68 | name: 'yes',
69 | message: `Changelog generated. Does it look good?`
70 | })
71 |
72 | if (!changelogOk) {
73 | return
74 | }
75 |
76 | // Commit changes to the Git and create a tag.
77 | step('\nCommitting changes...')
78 | await run('git', ['add', 'CHANGELOG.md', 'package.json'])
79 | await run('git', ['commit', '-m', `release: v${targetVersion}`])
80 | await run('git', ['tag', `v${targetVersion}`])
81 |
82 | // Publish the package.
83 | step('\nPublishing the package...')
84 | await run('yarn', [
85 | 'publish',
86 | '--new-version',
87 | targetVersion,
88 | '--no-commit-hooks',
89 | '--no-git-tag-version'
90 | ])
91 |
92 | // Push to GitHub.
93 | step('\nPushing to GitHub...')
94 | await run('git', ['push', 'origin', `refs/tags/v${targetVersion}`])
95 | await run('git', ['push'])
96 | }
97 |
98 | function updatePackage(version) {
99 | const pkgPath = path.resolve(path.resolve(__dirname, '..'), 'package.json')
100 | const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'))
101 |
102 | pkg.version = version
103 |
104 | fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n')
105 | }
106 |
107 | main().catch((err) => console.error(err))
108 |
--------------------------------------------------------------------------------
/src/app.ts:
--------------------------------------------------------------------------------
1 | import { reactive } from '@vue/reactivity'
2 | import { Block } from './block'
3 | import { Directive } from './directives'
4 | import { bindContextMethods, createContext } from './context'
5 | import { toDisplayString } from './directives/text'
6 | import { nextTick } from './scheduler'
7 |
8 | const escapeRegex = (str: string) =>
9 | str.replace(/[-.*+?^${}()|[\]\/\\]/g, '\\$&')
10 |
11 | export const createApp = (initialData?: any) => {
12 | // root context
13 | const ctx = createContext()
14 | if (initialData) {
15 | ctx.scope = reactive(initialData)
16 | bindContextMethods(ctx.scope)
17 |
18 | // handle custom delimiters
19 | if (initialData.$delimiters) {
20 | const [open, close] = (ctx.delimiters = initialData.$delimiters)
21 | ctx.delimitersRE = new RegExp(
22 | escapeRegex(open) + '([^]+?)' + escapeRegex(close),
23 | 'g'
24 | )
25 | }
26 | }
27 |
28 | // global internal helpers
29 | ctx.scope.$s = toDisplayString
30 | ctx.scope.$nextTick = nextTick
31 | ctx.scope.$refs = Object.create(null)
32 |
33 | let rootBlocks: Block[]
34 |
35 | return {
36 | directive(name: string, def?: Directive) {
37 | if (def) {
38 | ctx.dirs[name] = def
39 | return this
40 | } else {
41 | return ctx.dirs[name]
42 | }
43 | },
44 |
45 | mount(el?: string | Element | null) {
46 | if (typeof el === 'string') {
47 | el = document.querySelector(el)
48 | if (!el) {
49 | import.meta.env.DEV &&
50 | console.error(`selector ${el} has no matching element.`)
51 | return
52 | }
53 | }
54 |
55 | el = el || document.documentElement
56 | let roots: Element[]
57 | if (el.hasAttribute('v-scope')) {
58 | roots = [el]
59 | } else {
60 | roots = [...el.querySelectorAll(`[v-scope]`)].filter(
61 | (root) => !root.matches(`[v-scope] [v-scope]`)
62 | )
63 | }
64 | if (!roots.length) {
65 | roots = [el]
66 | }
67 |
68 | if (
69 | import.meta.env.DEV &&
70 | roots.length === 1 &&
71 | roots[0] === document.documentElement
72 | ) {
73 | console.warn(
74 | `Mounting on documentElement - this is non-optimal as petite-vue ` +
75 | `will be forced to crawl the entire page's DOM. ` +
76 | `Consider explicitly marking elements controlled by petite-vue ` +
77 | `with \`v-scope\`.`
78 | )
79 | }
80 |
81 | rootBlocks = roots.map((el) => new Block(el, ctx, true))
82 | return this
83 | },
84 |
85 | unmount() {
86 | rootBlocks.forEach((block) => block.teardown())
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/block.ts:
--------------------------------------------------------------------------------
1 | import { Context, createContext } from './context'
2 | import { walk } from './walk'
3 | import { remove } from '@vue/shared'
4 | import { stop } from '@vue/reactivity'
5 |
6 | export class Block {
7 | template: Element | DocumentFragment
8 | ctx: Context
9 | key?: any
10 | parentCtx?: Context
11 |
12 | isFragment: boolean
13 | start?: Text
14 | end?: Text
15 |
16 | get el() {
17 | return this.start || (this.template as Element)
18 | }
19 |
20 | constructor(template: Element, parentCtx: Context, isRoot = false) {
21 | this.isFragment = template instanceof HTMLTemplateElement
22 |
23 | if (isRoot) {
24 | this.template = template
25 | } else if (this.isFragment) {
26 | this.template = (template as HTMLTemplateElement).content.cloneNode(
27 | true
28 | ) as DocumentFragment
29 | } else {
30 | this.template = template.cloneNode(true) as Element
31 | }
32 |
33 | if (isRoot) {
34 | this.ctx = parentCtx
35 | } else {
36 | // create child context
37 | this.parentCtx = parentCtx
38 | parentCtx.blocks.push(this)
39 | this.ctx = createContext(parentCtx)
40 | }
41 |
42 | walk(this.template, this.ctx)
43 | }
44 |
45 | insert(parent: Element, anchor: Node | null = null) {
46 | if (this.isFragment) {
47 | if (this.start) {
48 | // already inserted, moving
49 | let node: Node | null = this.start
50 | let next: Node | null
51 | while (node) {
52 | next = node.nextSibling
53 | parent.insertBefore(node, anchor)
54 | if (node === this.end) break
55 | node = next
56 | }
57 | } else {
58 | this.start = new Text('')
59 | this.end = new Text('')
60 | parent.insertBefore(this.end, anchor)
61 | parent.insertBefore(this.start, this.end)
62 | parent.insertBefore(this.template, this.end)
63 | }
64 | } else {
65 | parent.insertBefore(this.template, anchor)
66 | }
67 | }
68 |
69 | remove() {
70 | if (this.parentCtx) {
71 | remove(this.parentCtx.blocks, this)
72 | }
73 | if (this.start) {
74 | const parent = this.start.parentNode!
75 | let node: Node | null = this.start
76 | let next: Node | null
77 | while (node) {
78 | next = node.nextSibling
79 | parent.removeChild(node)
80 | if (node === this.end) break
81 | node = next
82 | }
83 | } else {
84 | this.template.parentNode!.removeChild(this.template)
85 | }
86 | this.teardown()
87 | }
88 |
89 | teardown() {
90 | this.ctx.blocks.forEach((child) => {
91 | child.teardown()
92 | })
93 | this.ctx.effects.forEach(stop)
94 | this.ctx.cleanups.forEach((fn) => fn())
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/context.ts:
--------------------------------------------------------------------------------
1 | import {
2 | effect as rawEffect,
3 | reactive,
4 | ReactiveEffectRunner
5 | } from '@vue/reactivity'
6 | import { Block } from './block'
7 | import { Directive } from './directives'
8 | import { queueJob } from './scheduler'
9 | import { inOnce } from './walk'
10 | export interface Context {
11 | key?: any
12 | scope: Record
13 | dirs: Record
14 | blocks: Block[]
15 | effect: typeof rawEffect
16 | effects: ReactiveEffectRunner[]
17 | cleanups: (() => void)[]
18 | delimiters: [string, string]
19 | delimitersRE: RegExp
20 | }
21 |
22 | export const createContext = (parent?: Context): Context => {
23 | const ctx: Context = {
24 | delimiters: ['{{', '}}'],
25 | delimitersRE: /\{\{([^]+?)\}\}/g,
26 | ...parent,
27 | scope: parent ? parent.scope : reactive({}),
28 | dirs: parent ? parent.dirs : {},
29 | effects: [],
30 | blocks: [],
31 | cleanups: [],
32 | effect: (fn) => {
33 | if (inOnce) {
34 | queueJob(fn)
35 | return fn as any
36 | }
37 | const e: ReactiveEffectRunner = rawEffect(fn, {
38 | scheduler: () => queueJob(e)
39 | })
40 | ctx.effects.push(e)
41 | return e
42 | }
43 | }
44 | return ctx
45 | }
46 |
47 | export const createScopedContext = (ctx: Context, data = {}): Context => {
48 | const parentScope = ctx.scope
49 | const mergedScope = Object.create(parentScope)
50 | Object.defineProperties(mergedScope, Object.getOwnPropertyDescriptors(data))
51 | mergedScope.$refs = Object.create(parentScope.$refs)
52 | const reactiveProxy = reactive(
53 | new Proxy(mergedScope, {
54 | set(target, key, val, receiver) {
55 | // when setting a property that doesn't exist on current scope,
56 | // do not create it on the current scope and fallback to parent scope.
57 | if (receiver === reactiveProxy && !target.hasOwnProperty(key)) {
58 | return Reflect.set(parentScope, key, val)
59 | }
60 | return Reflect.set(target, key, val, receiver)
61 | }
62 | })
63 | )
64 |
65 | bindContextMethods(reactiveProxy)
66 | return {
67 | ...ctx,
68 | scope: reactiveProxy
69 | }
70 | }
71 |
72 | export const bindContextMethods = (scope: Record) => {
73 | for (const key of Object.keys(scope)) {
74 | if (typeof scope[key] === 'function') {
75 | scope[key] = scope[key].bind(scope)
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/directives/bind.ts:
--------------------------------------------------------------------------------
1 | import { Directive } from '.'
2 | import {
3 | normalizeClass,
4 | normalizeStyle,
5 | isString,
6 | isArray,
7 | hyphenate,
8 | camelize
9 | } from '@vue/shared'
10 |
11 | const forceAttrRE = /^(spellcheck|draggable|form|list|type)$/
12 |
13 | export const bind: Directive = ({
14 | el,
15 | get,
16 | effect,
17 | arg,
18 | modifiers
19 | }) => {
20 | let prevValue: any
21 |
22 | // record static class
23 | if (arg === 'class') {
24 | el._class = el.className
25 | }
26 |
27 | effect(() => {
28 | let value = get()
29 | if (arg) {
30 | if (modifiers?.camel) {
31 | arg = camelize(arg)
32 | }
33 | setProp(el, arg, value, prevValue)
34 | } else {
35 | for (const key in value) {
36 | setProp(el, key, value[key], prevValue && prevValue[key])
37 | }
38 | for (const key in prevValue) {
39 | if (!value || !(key in value)) {
40 | setProp(el, key, null)
41 | }
42 | }
43 | }
44 | prevValue = value
45 | })
46 | }
47 |
48 | const setProp = (
49 | el: Element & { _class?: string },
50 | key: string,
51 | value: any,
52 | prevValue?: any
53 | ) => {
54 | if (key === 'class') {
55 | el.setAttribute(
56 | 'class',
57 | normalizeClass(el._class ? [el._class, value] : value) || ''
58 | )
59 | } else if (key === 'style') {
60 | value = normalizeStyle(value)
61 | const { style } = el as HTMLElement
62 | if (!value) {
63 | el.removeAttribute('style')
64 | } else if (isString(value)) {
65 | if (value !== prevValue) style.cssText = value
66 | } else {
67 | for (const key in value) {
68 | setStyle(style, key, value[key])
69 | }
70 | if (prevValue && !isString(prevValue)) {
71 | for (const key in prevValue) {
72 | if (value[key] == null) {
73 | setStyle(style, key, '')
74 | }
75 | }
76 | }
77 | }
78 | } else if (
79 | !(el instanceof SVGElement) &&
80 | key in el &&
81 | !forceAttrRE.test(key)
82 | ) {
83 | // @ts-ignore
84 | el[key] = value
85 | if (key === 'value') {
86 | // @ts-ignore
87 | el._value = value
88 | }
89 | } else {
90 | // special case for with
91 | // :true-value & :false-value
92 | // store value as dom properties since non-string values will be
93 | // stringified.
94 | if (key === 'true-value') {
95 | ;(el as any)._trueValue = value
96 | } else if (key === 'false-value') {
97 | ;(el as any)._falseValue = value
98 | } else if (value != null) {
99 | el.setAttribute(key, value)
100 | } else {
101 | el.removeAttribute(key)
102 | }
103 | }
104 | }
105 |
106 | const importantRE = /\s*!important$/
107 |
108 | const setStyle = (
109 | style: CSSStyleDeclaration,
110 | name: string,
111 | val: string | string[]
112 | ) => {
113 | if (isArray(val)) {
114 | val.forEach((v) => setStyle(style, name, v))
115 | } else {
116 | if (name.startsWith('--')) {
117 | // custom property definition
118 | style.setProperty(name, val)
119 | } else {
120 | if (importantRE.test(val)) {
121 | // !important
122 | style.setProperty(
123 | hyphenate(name),
124 | val.replace(importantRE, ''),
125 | 'important'
126 | )
127 | } else {
128 | style[name as any] = val
129 | }
130 | }
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/directives/effect.ts:
--------------------------------------------------------------------------------
1 | import { Directive } from '.'
2 | import { execute } from '../eval'
3 | import { nextTick } from '../scheduler'
4 |
5 | export const effect: Directive = ({ el, ctx, exp, effect }) => {
6 | nextTick(() => effect(() => execute(ctx.scope, exp, el)))
7 | }
8 |
--------------------------------------------------------------------------------
/src/directives/for.ts:
--------------------------------------------------------------------------------
1 | import { isArray, isObject } from '@vue/shared'
2 | import { Block } from '../block'
3 | import { evaluate } from '../eval'
4 | import { Context, createScopedContext } from '../context'
5 |
6 | const forAliasRE = /([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/
7 | const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
8 | const stripParensRE = /^\(|\)$/g
9 | const destructureRE = /^[{[]\s*((?:[\w_$]+\s*,?\s*)+)[\]}]$/
10 |
11 | type KeyToIndexMap = Map
12 |
13 | export const _for = (el: Element, exp: string, ctx: Context) => {
14 | const inMatch = exp.match(forAliasRE)
15 | if (!inMatch) {
16 | import.meta.env.DEV && console.warn(`invalid v-for expression: ${exp}`)
17 | return
18 | }
19 |
20 | const nextNode = el.nextSibling
21 |
22 | const parent = el.parentElement!
23 | const anchor = new Text('')
24 | parent.insertBefore(anchor, el)
25 | parent.removeChild(el)
26 |
27 | const sourceExp = inMatch[2].trim()
28 | let valueExp = inMatch[1].trim().replace(stripParensRE, '').trim()
29 | let destructureBindings: string[] | undefined
30 | let isArrayDestructure = false
31 | let indexExp: string | undefined
32 | let objIndexExp: string | undefined
33 |
34 | let keyAttr = 'key'
35 | let keyExp =
36 | el.getAttribute(keyAttr) ||
37 | el.getAttribute((keyAttr = ':key')) ||
38 | el.getAttribute((keyAttr = 'v-bind:key'))
39 | if (keyExp) {
40 | el.removeAttribute(keyAttr)
41 | if (keyAttr === 'key') keyExp = JSON.stringify(keyExp)
42 | }
43 |
44 | let match
45 | if ((match = valueExp.match(forIteratorRE))) {
46 | valueExp = valueExp.replace(forIteratorRE, '').trim()
47 | indexExp = match[1].trim()
48 | if (match[2]) {
49 | objIndexExp = match[2].trim()
50 | }
51 | }
52 |
53 | if ((match = valueExp.match(destructureRE))) {
54 | destructureBindings = match[1].split(',').map((s) => s.trim())
55 | isArrayDestructure = valueExp[0] === '['
56 | }
57 |
58 | let mounted = false
59 | let blocks: Block[]
60 | let childCtxs: Context[]
61 | let keyToIndexMap: Map
62 |
63 | const createChildContexts = (source: unknown): [Context[], KeyToIndexMap] => {
64 | const map: KeyToIndexMap = new Map()
65 | const ctxs: Context[] = []
66 |
67 | if (isArray(source)) {
68 | for (let i = 0; i < source.length; i++) {
69 | ctxs.push(createChildContext(map, source[i], i))
70 | }
71 | } else if (typeof source === 'number') {
72 | for (let i = 0; i < source; i++) {
73 | ctxs.push(createChildContext(map, i + 1, i))
74 | }
75 | } else if (isObject(source)) {
76 | let i = 0
77 | for (const key in source) {
78 | ctxs.push(createChildContext(map, source[key], i++, key))
79 | }
80 | }
81 |
82 | return [ctxs, map]
83 | }
84 |
85 | const createChildContext = (
86 | map: KeyToIndexMap,
87 | value: any,
88 | index: number,
89 | objKey?: string
90 | ): Context => {
91 | const data: any = {}
92 | if (destructureBindings) {
93 | destructureBindings.forEach(
94 | (b, i) => (data[b] = value[isArrayDestructure ? i : b])
95 | )
96 | } else {
97 | data[valueExp] = value
98 | }
99 | if (objKey) {
100 | indexExp && (data[indexExp] = objKey)
101 | objIndexExp && (data[objIndexExp] = index)
102 | } else {
103 | indexExp && (data[indexExp] = index)
104 | }
105 | const childCtx = createScopedContext(ctx, data)
106 | const key = keyExp ? evaluate(childCtx.scope, keyExp) : index
107 | map.set(key, index)
108 | childCtx.key = key
109 | return childCtx
110 | }
111 |
112 | const mountBlock = (ctx: Context, ref: Node) => {
113 | const block = new Block(el, ctx)
114 | block.key = ctx.key
115 | block.insert(parent, ref)
116 | return block
117 | }
118 |
119 | ctx.effect(() => {
120 | const source = evaluate(ctx.scope, sourceExp)
121 | const prevKeyToIndexMap = keyToIndexMap
122 | ;[childCtxs, keyToIndexMap] = createChildContexts(source)
123 | if (!mounted) {
124 | blocks = childCtxs.map((s) => mountBlock(s, anchor))
125 | mounted = true
126 | } else {
127 | for (let i = 0; i < blocks.length; i++) {
128 | if (!keyToIndexMap.has(blocks[i].key)) {
129 | blocks[i].remove()
130 | }
131 | }
132 |
133 | const nextBlocks: Block[] = []
134 | let i = childCtxs.length
135 | let nextBlock: Block | undefined
136 | let prevMovedBlock: Block | undefined
137 | while (i--) {
138 | const childCtx = childCtxs[i]
139 | const oldIndex = prevKeyToIndexMap.get(childCtx.key)
140 | let block
141 | if (oldIndex == null) {
142 | // new
143 | block = mountBlock(
144 | childCtx,
145 | nextBlock ? nextBlock.el : anchor
146 | )
147 | } else {
148 | // update
149 | block = blocks[oldIndex]
150 | Object.assign(block.ctx.scope, childCtx.scope)
151 | if (oldIndex !== i) {
152 | // moved
153 | if (
154 | blocks[oldIndex + 1] !== nextBlock ||
155 | // If the next has moved, it must move too
156 | prevMovedBlock === nextBlock
157 | ) {
158 | prevMovedBlock = block
159 | block.insert(parent, nextBlock ? nextBlock.el : anchor)
160 | }
161 | }
162 | }
163 | nextBlocks.unshift(nextBlock = block)
164 | }
165 | blocks = nextBlocks
166 | }
167 | })
168 |
169 | return nextNode
170 | }
171 |
--------------------------------------------------------------------------------
/src/directives/html.ts:
--------------------------------------------------------------------------------
1 | import { Directive } from '.'
2 |
3 | export const html: Directive = ({ el, get, effect }) => {
4 | effect(() => {
5 | el.innerHTML = get()
6 | })
7 | }
8 |
--------------------------------------------------------------------------------
/src/directives/if.ts:
--------------------------------------------------------------------------------
1 | import { Block } from '../block'
2 | import { evaluate } from '../eval'
3 | import { checkAttr } from '../utils'
4 | import { Context } from '../context'
5 |
6 | interface Branch {
7 | exp?: string | null
8 | el: Element
9 | }
10 |
11 | export const _if = (el: Element, exp: string, ctx: Context) => {
12 | if (import.meta.env.DEV && !exp.trim()) {
13 | console.warn(`v-if expression cannot be empty.`)
14 | }
15 |
16 | const parent = el.parentElement!
17 | const anchor = new Comment('v-if')
18 | parent.insertBefore(anchor, el)
19 |
20 | const branches: Branch[] = [
21 | {
22 | exp,
23 | el
24 | }
25 | ]
26 |
27 | // locate else branch
28 | let elseEl: Element | null
29 | let elseExp: string | null
30 | while ((elseEl = el.nextElementSibling)) {
31 | elseExp = null
32 | if (
33 | checkAttr(elseEl, 'v-else') === '' ||
34 | (elseExp = checkAttr(elseEl, 'v-else-if'))
35 | ) {
36 | parent.removeChild(elseEl)
37 | branches.push({ exp: elseExp, el: elseEl })
38 | } else {
39 | break
40 | }
41 | }
42 |
43 | const nextNode = el.nextSibling
44 | parent.removeChild(el)
45 |
46 | let block: Block | undefined
47 | let activeBranchIndex: number = -1
48 |
49 | const removeActiveBlock = () => {
50 | if (block) {
51 | parent.insertBefore(anchor, block.el)
52 | block.remove()
53 | block = undefined
54 | }
55 | }
56 |
57 | ctx.effect(() => {
58 | for (let i = 0; i < branches.length; i++) {
59 | const { exp, el } = branches[i]
60 | if (!exp || evaluate(ctx.scope, exp)) {
61 | if (i !== activeBranchIndex) {
62 | removeActiveBlock()
63 | block = new Block(el, ctx)
64 | block.insert(parent, anchor)
65 | parent.removeChild(anchor)
66 | activeBranchIndex = i
67 | }
68 | return
69 | }
70 | }
71 | // no matched branch.
72 | activeBranchIndex = -1
73 | removeActiveBlock()
74 | })
75 |
76 | return nextNode
77 | }
78 |
--------------------------------------------------------------------------------
/src/directives/index.ts:
--------------------------------------------------------------------------------
1 | import { Context } from '../context'
2 | import { effect as rawEffect } from '@vue/reactivity'
3 | import { bind } from './bind'
4 | import { on } from './on'
5 | import { show } from './show'
6 | import { text } from './text'
7 | import { html } from './html'
8 | import { model } from './model'
9 | import { effect } from './effect'
10 |
11 | export interface Directive {
12 | (ctx: DirectiveContext): (() => void) | void
13 | }
14 |
15 | export interface DirectiveContext {
16 | el: T
17 | get: (exp?: string) => any
18 | effect: typeof rawEffect
19 | exp: string
20 | arg?: string
21 | modifiers?: Record
22 | ctx: Context
23 | }
24 |
25 | export const builtInDirectives: Record> = {
26 | bind,
27 | on,
28 | show,
29 | text,
30 | html,
31 | model,
32 | effect
33 | }
34 |
--------------------------------------------------------------------------------
/src/directives/model.ts:
--------------------------------------------------------------------------------
1 | import { isArray, looseEqual, looseIndexOf, toNumber } from '@vue/shared'
2 | import { Directive } from '.'
3 | import { listen } from '../utils'
4 |
5 | export const model: Directive<
6 | HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement
7 | > = ({ el, exp, get, effect, modifiers }) => {
8 | const type = el.type
9 | const assign = get(`(val) => { ${exp} = val }`)
10 | const { trim, number = type === 'number' } = modifiers || {}
11 |
12 | if (el.tagName === 'SELECT') {
13 | const sel = el as HTMLSelectElement
14 | listen(el, 'change', () => {
15 | const selectedVal = Array.prototype.filter
16 | .call(sel.options, (o: HTMLOptionElement) => o.selected)
17 | .map((o: HTMLOptionElement) =>
18 | number ? toNumber(getValue(o)) : getValue(o)
19 | )
20 | assign(sel.multiple ? selectedVal : selectedVal[0])
21 | })
22 | effect(() => {
23 | const value = get()
24 | const isMultiple = sel.multiple
25 | for (let i = 0, l = sel.options.length; i < l; i++) {
26 | const option = sel.options[i]
27 | const optionValue = getValue(option)
28 | if (isMultiple) {
29 | if (isArray(value)) {
30 | option.selected = looseIndexOf(value, optionValue) > -1
31 | } else {
32 | option.selected = value.has(optionValue)
33 | }
34 | } else {
35 | if (looseEqual(getValue(option), value)) {
36 | if (sel.selectedIndex !== i) sel.selectedIndex = i
37 | return
38 | }
39 | }
40 | }
41 | if (!isMultiple && sel.selectedIndex !== -1) {
42 | sel.selectedIndex = -1
43 | }
44 | })
45 | } else if (type === 'checkbox') {
46 | listen(el, 'change', () => {
47 | const modelValue = get()
48 | const checked = (el as HTMLInputElement).checked
49 | if (isArray(modelValue)) {
50 | const elementValue = getValue(el)
51 | const index = looseIndexOf(modelValue, elementValue)
52 | const found = index !== -1
53 | if (checked && !found) {
54 | assign(modelValue.concat(elementValue))
55 | } else if (!checked && found) {
56 | const filtered = [...modelValue]
57 | filtered.splice(index, 1)
58 | assign(filtered)
59 | }
60 | } else {
61 | assign(getCheckboxValue(el as HTMLInputElement, checked))
62 | }
63 | })
64 |
65 | let oldValue: any
66 | effect(() => {
67 | const value = get()
68 | if (isArray(value)) {
69 | ;(el as HTMLInputElement).checked =
70 | looseIndexOf(value, getValue(el)) > -1
71 | } else if (value !== oldValue) {
72 | ;(el as HTMLInputElement).checked = looseEqual(
73 | value,
74 | getCheckboxValue(el as HTMLInputElement, true)
75 | )
76 | }
77 | oldValue = value
78 | })
79 | } else if (type === 'radio') {
80 | listen(el, 'change', () => {
81 | assign(getValue(el))
82 | })
83 | let oldValue: any
84 | effect(() => {
85 | const value = get()
86 | if (value !== oldValue) {
87 | ;(el as HTMLInputElement).checked = looseEqual(value, getValue(el))
88 | }
89 | })
90 | } else {
91 | // text-like
92 | const resolveValue = (val: string) => {
93 | if (trim) return val.trim()
94 | if (number) return toNumber(val)
95 | return val
96 | }
97 |
98 | listen(el, 'compositionstart', onCompositionStart)
99 | listen(el, 'compositionend', onCompositionEnd)
100 | listen(el, modifiers?.lazy ? 'change' : 'input', () => {
101 | if ((el as any).composing) return
102 | assign(resolveValue(el.value))
103 | })
104 | if (trim) {
105 | listen(el, 'change', () => {
106 | el.value = el.value.trim()
107 | })
108 | }
109 |
110 | effect(() => {
111 | if ((el as any).composing) {
112 | return
113 | }
114 | const curVal = el.value
115 | const newVal = get()
116 | if (document.activeElement === el && resolveValue(curVal) === newVal) {
117 | return
118 | }
119 | if (curVal !== newVal) {
120 | el.value = newVal
121 | }
122 | })
123 | }
124 | }
125 |
126 | const getValue = (el: any) => ('_value' in el ? el._value : el.value)
127 |
128 | // retrieve raw value for true-value and false-value set via :true-value or :false-value bindings
129 | const getCheckboxValue = (
130 | el: HTMLInputElement & { _trueValue?: any; _falseValue?: any },
131 | checked: boolean
132 | ) => {
133 | const key = checked ? '_trueValue' : '_falseValue'
134 | return key in el ? el[key] : checked
135 | }
136 |
137 | const onCompositionStart = (e: Event) => {
138 | ;(e.target as any).composing = true
139 | }
140 |
141 | const onCompositionEnd = (e: Event) => {
142 | const target = e.target as any
143 | if (target.composing) {
144 | target.composing = false
145 | trigger(target, 'input')
146 | }
147 | }
148 |
149 | const trigger = (el: HTMLElement, type: string) => {
150 | const e = document.createEvent('HTMLEvents')
151 | e.initEvent(type, true, true)
152 | el.dispatchEvent(e)
153 | }
154 |
--------------------------------------------------------------------------------
/src/directives/on.ts:
--------------------------------------------------------------------------------
1 | import { Directive } from '.'
2 | import { hyphenate } from '@vue/shared'
3 | import { listen } from '../utils'
4 | import { nextTick } from '../scheduler'
5 |
6 | // same as vue 2
7 | const simplePathRE =
8 | /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/
9 |
10 | const systemModifiers = ['ctrl', 'shift', 'alt', 'meta']
11 |
12 | type KeyedEvent = KeyboardEvent | MouseEvent | TouchEvent
13 |
14 | const modifierGuards: Record<
15 | string,
16 | (e: Event, modifiers: Record) => void | boolean
17 | > = {
18 | stop: (e) => e.stopPropagation(),
19 | prevent: (e) => e.preventDefault(),
20 | self: (e) => e.target !== e.currentTarget,
21 | ctrl: (e) => !(e as KeyedEvent).ctrlKey,
22 | shift: (e) => !(e as KeyedEvent).shiftKey,
23 | alt: (e) => !(e as KeyedEvent).altKey,
24 | meta: (e) => !(e as KeyedEvent).metaKey,
25 | left: (e) => 'button' in e && (e as MouseEvent).button !== 0,
26 | middle: (e) => 'button' in e && (e as MouseEvent).button !== 1,
27 | right: (e) => 'button' in e && (e as MouseEvent).button !== 2,
28 | exact: (e, modifiers) =>
29 | systemModifiers.some((m) => (e as any)[`${m}Key`] && !modifiers[m])
30 | }
31 |
32 | export const on: Directive = ({ el, get, exp, arg, modifiers }) => {
33 | if (!arg) {
34 | if (import.meta.env.DEV) {
35 | console.error(`v-on="obj" syntax is not supported in petite-vue.`)
36 | }
37 | return
38 | }
39 |
40 | let handler = simplePathRE.test(exp)
41 | ? get(`(e => ${exp}(e))`)
42 | : get(`($event => { ${exp} })`)
43 |
44 | // special lifecycle events
45 | if (import.meta.env.DEV && (arg === 'mounted' || arg === 'unmounted')) {
46 | console.error(
47 | `mounted and unmounted hooks now need to be prefixed with vue: ` +
48 | `- use @vue:${arg}="handler" instead.`
49 | )
50 | }
51 | if (arg === 'vue:mounted') {
52 | nextTick(handler)
53 | return
54 | } else if (arg === 'vue:unmounted') {
55 | return () => handler()
56 | }
57 |
58 | if (modifiers) {
59 | // map modifiers
60 | if (arg === 'click') {
61 | if (modifiers.right) arg = 'contextmenu'
62 | if (modifiers.middle) arg = 'mouseup'
63 | }
64 |
65 | const raw = handler
66 | handler = (e: Event) => {
67 | if ('key' in e && !(hyphenate((e as KeyboardEvent).key) in modifiers)) {
68 | return
69 | }
70 | for (const key in modifiers) {
71 | const guard = modifierGuards[key]
72 | if (guard && guard(e, modifiers)) {
73 | return
74 | }
75 | }
76 | return raw(e)
77 | }
78 | }
79 |
80 | listen(el, arg, handler, modifiers)
81 | }
82 |
--------------------------------------------------------------------------------
/src/directives/ref.ts:
--------------------------------------------------------------------------------
1 | import { Directive } from '.'
2 |
3 | export const ref: Directive = ({
4 | el,
5 | ctx: {
6 | scope: { $refs }
7 | },
8 | get,
9 | effect
10 | }) => {
11 | let prevRef: any
12 | effect(() => {
13 | const ref = get()
14 | $refs[ref] = el
15 | if (prevRef && ref !== prevRef) {
16 | delete $refs[prevRef]
17 | }
18 | prevRef = ref
19 | })
20 | return () => {
21 | prevRef && delete $refs[prevRef]
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/directives/show.ts:
--------------------------------------------------------------------------------
1 | import { Directive } from '.'
2 |
3 | export const show: Directive = ({ el, get, effect }) => {
4 | const initialDisplay = el.style.display
5 | effect(() => {
6 | el.style.display = get() ? initialDisplay : 'none'
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/src/directives/text.ts:
--------------------------------------------------------------------------------
1 | import { isObject } from '@vue/shared'
2 | import { Directive } from '.'
3 |
4 | export const text: Directive = ({ el, get, effect }) => {
5 | effect(() => {
6 | el.textContent = toDisplayString(get())
7 | })
8 | }
9 |
10 | export const toDisplayString = (value: any) =>
11 | value == null
12 | ? ''
13 | : isObject(value)
14 | ? JSON.stringify(value, null, 2)
15 | : String(value)
16 |
--------------------------------------------------------------------------------
/src/eval.ts:
--------------------------------------------------------------------------------
1 | const evalCache: Record = Object.create(null)
2 |
3 | export const evaluate = (scope: any, exp: string, el?: Node) =>
4 | execute(scope, `return(${exp})`, el)
5 |
6 | export const execute = (scope: any, exp: string, el?: Node) => {
7 | const fn = evalCache[exp] || (evalCache[exp] = toFunction(exp))
8 | try {
9 | return fn(scope, el)
10 | } catch (e) {
11 | if (import.meta.env.DEV) {
12 | console.warn(`Error when evaluating expression "${exp}":`)
13 | }
14 | console.error(e)
15 | }
16 | }
17 |
18 | const toFunction = (exp: string): Function => {
19 | try {
20 | return new Function(`$data`, `$el`, `with($data){${exp}}`)
21 | } catch (e) {
22 | console.error(`${(e as Error).message} in expression: ${exp}`)
23 | return () => {}
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export { createApp } from './app'
2 | export { nextTick } from './scheduler'
3 | export { reactive } from '@vue/reactivity'
4 |
5 | import { createApp } from './app'
6 |
7 | const s = document.currentScript
8 | if (s && s.hasAttribute('init')) {
9 | createApp().mount()
10 | }
11 |
--------------------------------------------------------------------------------
/src/scheduler.ts:
--------------------------------------------------------------------------------
1 | let queued = false
2 | const queue: Function[] = []
3 | const p = Promise.resolve()
4 |
5 | export const nextTick = (fn: () => void) => p.then(fn)
6 |
7 | export const queueJob = (job: Function) => {
8 | if (!queue.includes(job)) queue.push(job)
9 | if (!queued) {
10 | queued = true
11 | nextTick(flushJobs)
12 | }
13 | }
14 |
15 | const flushJobs = () => {
16 | for (const job of queue) {
17 | job()
18 | }
19 | queue.length = 0
20 | queued = false
21 | }
22 |
--------------------------------------------------------------------------------
/src/utils.ts:
--------------------------------------------------------------------------------
1 | export const checkAttr = (el: Element, name: string): string | null => {
2 | const val = el.getAttribute(name)
3 | if (val != null) el.removeAttribute(name)
4 | return val
5 | }
6 |
7 | export const listen = (
8 | el: Element,
9 | event: string,
10 | handler: any,
11 | options?: any
12 | ) => {
13 | el.addEventListener(event, handler, options)
14 | }
15 |
--------------------------------------------------------------------------------
/src/walk.ts:
--------------------------------------------------------------------------------
1 | import { builtInDirectives, Directive } from './directives'
2 | import { _if } from './directives/if'
3 | import { _for } from './directives/for'
4 | import { bind } from './directives/bind'
5 | import { on } from './directives/on'
6 | import { text } from './directives/text'
7 | import { evaluate } from './eval'
8 | import { checkAttr } from './utils'
9 | import { ref } from './directives/ref'
10 | import { Context, createScopedContext } from './context'
11 |
12 | const dirRE = /^(?:v-|:|@)/
13 | const modifierRE = /\.([\w-]+)/g
14 |
15 | export let inOnce = false
16 |
17 | export const walk = (node: Node, ctx: Context): ChildNode | null | void => {
18 | const type = node.nodeType
19 | if (type === 1) {
20 | // Element
21 | const el = node as Element
22 | if (el.hasAttribute('v-pre')) {
23 | return
24 | }
25 |
26 | checkAttr(el, 'v-cloak')
27 |
28 | let exp: string | null
29 |
30 | // v-if
31 | if ((exp = checkAttr(el, 'v-if'))) {
32 | return _if(el, exp, ctx)
33 | }
34 |
35 | // v-for
36 | if ((exp = checkAttr(el, 'v-for'))) {
37 | return _for(el, exp, ctx)
38 | }
39 |
40 | // v-scope
41 | if ((exp = checkAttr(el, 'v-scope')) || exp === '') {
42 | const scope = exp ? evaluate(ctx.scope, exp) : {}
43 | ctx = createScopedContext(ctx, scope)
44 | if (scope.$template) {
45 | resolveTemplate(el, scope.$template)
46 | }
47 | }
48 |
49 | // v-once
50 | const hasVOnce = checkAttr(el, 'v-once') != null
51 | if (hasVOnce) {
52 | inOnce = true
53 | }
54 |
55 | // ref
56 | if ((exp = checkAttr(el, 'ref'))) {
57 | applyDirective(el, ref, `"${exp}"`, ctx)
58 | }
59 |
60 | // process children first before self attrs
61 | walkChildren(el, ctx)
62 |
63 | // other directives
64 | const deferred: [string, string][] = []
65 | for (const { name, value } of [...el.attributes]) {
66 | if (dirRE.test(name) && name !== 'v-cloak') {
67 | if (name === 'v-model') {
68 | // defer v-model since it relies on :value bindings to be processed
69 | // first, but also before v-on listeners (#73)
70 | deferred.unshift([name, value])
71 | } else if (name[0] === '@' || /^v-on\b/.test(name)) {
72 | deferred.push([name, value])
73 | } else {
74 | processDirective(el, name, value, ctx)
75 | }
76 | }
77 | }
78 | for (const [name, value] of deferred) {
79 | processDirective(el, name, value, ctx)
80 | }
81 |
82 | if (hasVOnce) {
83 | inOnce = false
84 | }
85 | } else if (type === 3) {
86 | // Text
87 | const data = (node as Text).data
88 | if (data.includes(ctx.delimiters[0])) {
89 | let segments: string[] = []
90 | let lastIndex = 0
91 | let match
92 | while ((match = ctx.delimitersRE.exec(data))) {
93 | const leading = data.slice(lastIndex, match.index)
94 | if (leading) segments.push(JSON.stringify(leading))
95 | segments.push(`$s(${match[1]})`)
96 | lastIndex = match.index + match[0].length
97 | }
98 | if (lastIndex < data.length) {
99 | segments.push(JSON.stringify(data.slice(lastIndex)))
100 | }
101 | applyDirective(node, text, segments.join('+'), ctx)
102 | }
103 | } else if (type === 11) {
104 | walkChildren(node as DocumentFragment, ctx)
105 | }
106 | }
107 |
108 | const walkChildren = (node: Element | DocumentFragment, ctx: Context) => {
109 | let child = node.firstChild
110 | while (child) {
111 | child = walk(child, ctx) || child.nextSibling
112 | }
113 | }
114 |
115 | const processDirective = (
116 | el: Element,
117 | raw: string,
118 | exp: string,
119 | ctx: Context
120 | ) => {
121 | let dir: Directive
122 | let arg: string | undefined
123 | let modifiers: Record | undefined
124 |
125 | // modifiers
126 | raw = raw.replace(modifierRE, (_, m) => {
127 | ;(modifiers || (modifiers = {}))[m] = true
128 | return ''
129 | })
130 |
131 | if (raw[0] === ':') {
132 | dir = bind
133 | arg = raw.slice(1)
134 | } else if (raw[0] === '@') {
135 | dir = on
136 | arg = raw.slice(1)
137 | } else {
138 | const argIndex = raw.indexOf(':')
139 | const dirName = argIndex > 0 ? raw.slice(2, argIndex) : raw.slice(2)
140 | dir = builtInDirectives[dirName] || ctx.dirs[dirName]
141 | arg = argIndex > 0 ? raw.slice(argIndex + 1) : undefined
142 | }
143 | if (dir) {
144 | if (dir === bind && arg === 'ref') dir = ref
145 | applyDirective(el, dir, exp, ctx, arg, modifiers)
146 | el.removeAttribute(raw)
147 | } else if (import.meta.env.DEV) {
148 | console.error(`unknown custom directive ${raw}.`)
149 | }
150 | }
151 |
152 | const applyDirective = (
153 | el: Node,
154 | dir: Directive,
155 | exp: string,
156 | ctx: Context,
157 | arg?: string,
158 | modifiers?: Record
159 | ) => {
160 | const get = (e = exp) => evaluate(ctx.scope, e, el)
161 | const cleanup = dir({
162 | el,
163 | get,
164 | effect: ctx.effect,
165 | ctx,
166 | exp,
167 | arg,
168 | modifiers
169 | })
170 | if (cleanup) {
171 | ctx.cleanups.push(cleanup)
172 | }
173 | }
174 |
175 | const resolveTemplate = (el: Element, template: string) => {
176 | if (template[0] === '#') {
177 | const templateEl = document.querySelector(template)
178 | if (import.meta.env.DEV && !templateEl) {
179 | console.error(
180 | `template selector ${template} has no matching element.`
181 | )
182 | }
183 | el.appendChild((templateEl as HTMLTemplateElement).content.cloneNode(true))
184 | return
185 | }
186 | el.innerHTML = template
187 | }
188 |
--------------------------------------------------------------------------------
/tests/bind.html:
--------------------------------------------------------------------------------
1 |
18 |
19 |
34 |
35 |
36 |
simple binding - this should be green
37 |
38 | class binding - this should be red and bold
39 |
40 |
41 | style binding - this should be blue and bold
42 |
43 |
object binding - this should be orange
44 |
45 |
--------------------------------------------------------------------------------
/tests/cloak.html:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
{{ msg }}
11 |
toggle
12 |
13 |
14 |
--------------------------------------------------------------------------------
/tests/component.html:
--------------------------------------------------------------------------------
1 |
18 |
19 |
20 | {{ count }} {{ plusOne }}
21 | ++
22 |
23 |
24 |
--------------------------------------------------------------------------------
/tests/custom-delimiters.html:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
count is ${ count }!
10 |
increase
11 |
12 |
${ i }
13 |
14 |
${ count }
15 |
16 |
--------------------------------------------------------------------------------
/tests/effect.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
10 |
--------------------------------------------------------------------------------
/tests/for.html:
--------------------------------------------------------------------------------
1 |
20 |
21 |
22 |
add
23 |
reverse
24 |
pop
25 |
splice
26 |
31 |
32 |
37 |
38 |
--------------------------------------------------------------------------------
/tests/html.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/tests/if.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
toggle
9 |
toggle else
10 |
ok
11 |
else if
12 |
else
13 |
14 |
--------------------------------------------------------------------------------
/tests/model.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
20 |
{{ $data }}
21 |
Text Input
22 | {{ text }}
23 |
24 |
25 |
TextArea
26 | {{ text }}
27 |
28 |
29 |
Checkbox
30 |
31 |
{{ checked }}
32 |
33 |
Checkbox w/ Array
34 |
one
35 |
two
36 |
actual number
39 |
{{ arr }}
40 |
41 |
Checkbox w/ true-value / false-value
42 |
48 |
{{ checkToggle }}
49 |
50 |
Radio
51 |
one
52 |
two
53 |
three
56 |
{{ radioSelected }}
57 |
58 |
Select
59 |
60 | one
61 | two
62 | three
63 |
64 |
{{ selected }}
65 |
66 |
--------------------------------------------------------------------------------
/tests/multi-mount.html:
--------------------------------------------------------------------------------
1 |
21 |
22 |
23 | Global count {{ store.count }}
24 | Local count {{ count }}
25 |
26 |
27 |
28 | Global count {{ store.count }}
29 | Local count {{ count }}
30 |
--------------------------------------------------------------------------------
/tests/on.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
13 |
16 | right click
17 | middle click
18 | click once
19 |
20 |
--------------------------------------------------------------------------------
/tests/once.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | {{ count }}
8 |
9 |
Once
10 | {{ count }}
11 |
12 | {{ i }}
13 |
14 |
15 |
++
16 |
17 |
--------------------------------------------------------------------------------
/tests/pre.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
{{ count }}
8 |
{{ count }}
9 |
increment
10 |
--------------------------------------------------------------------------------
/tests/reactive.html:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
Global {{ store.count }}
22 |
increment
23 |
24 |
Local {{ localCount }}
25 |
increment
26 |
--------------------------------------------------------------------------------
/tests/ref.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
12 |
Accessing root el: id is {{ $refs.root.id }}
13 |
14 |
15 |
Span with dynamic ref
16 |
dynamicRef is {{ dynamicRef }}
17 |
18 | change dynamicRef
19 |
20 |
toggle
21 |
22 |
23 |
nested scope ref
24 |
27 | log nested scope refs
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/tests/scope.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 | {{ msg }} Change one
8 |
9 |
10 |
11 |
{{ $data }}
12 | {{ msg }} {{ outer }}
13 |
Change two
14 |
Change outer
15 |
16 |
{{ $data }}
17 | {{ msg }} {{ inner }} {{ outer }}
18 |
Change three
19 |
Change inner
20 |
Change outer
21 |
22 |
23 | change outer
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/tests/show.html:
--------------------------------------------------------------------------------
1 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/tests/text.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
10 |
11 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": ".",
4 | "outDir": "dist",
5 | "declaration": true,
6 | "sourceMap": false,
7 | "target": "esnext",
8 | "module": "esnext",
9 | "moduleResolution": "node",
10 | "allowJs": false,
11 | "strict": true,
12 | "noUnusedLocals": true,
13 | "rootDir": ".",
14 | "types": ["vite/client"]
15 | },
16 | "include": [
17 | "src"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import { resolve } from 'path'
3 |
4 | export default defineConfig({
5 | esbuild: {
6 | minify: true
7 | },
8 | build: {
9 | target: 'esnext',
10 | minify: 'terser',
11 | lib: {
12 | entry: resolve(__dirname, 'src/index.ts'),
13 | name: 'PetiteVue',
14 | formats: ['es', 'umd', 'iife']
15 | },
16 | rollupOptions: {
17 | plugins: [
18 | {
19 | name: 'remove-collection-handlers',
20 | transform(code, id) {
21 | if (id.endsWith('reactivity.esm-bundler.js')) {
22 | return code
23 | .replace(`mutableCollectionHandlers,`, `null,`)
24 | .replace(`readonlyCollectionHandlers,`, `null,`)
25 | }
26 | }
27 | }
28 | ]
29 | }
30 | }
31 | })
32 |
--------------------------------------------------------------------------------