setupin 3.0.0 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -16
- package/README.zh-CN.md +98 -16
- package/dist/main.js +46 -42
- package/dist/main.prod.js +94 -97
- package/package.json +1 -2
- package/dist/main.d.mts +0 -954
- package/dist/main.d.ts +0 -954
package/README.md
CHANGED
|
@@ -10,32 +10,111 @@
|
|
|
10
10
|
<a href="https://bundlephobia.com/package/setupin"><img src="https://img.shields.io/bundlephobia/minzip/setupin"></a>
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
## 😏
|
|
13
|
+
## 😏 What is a setupin?
|
|
14
14
|
|
|
15
|
-
**setupin** allows you to write Vue's [\<script **setup
|
|
15
|
+
**setupin** allows you to write Vue's [\<script **setup**>](https://vuejs.org/api/sfc-script-setup.html)**in** HTML.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
> Offer a friendly environment for beginners to easily grasp the core usage of Vue.
|
|
19
|
-
2. **Simple development**
|
|
20
|
-
> Provide a convenient way to rapidly develop small webpage without complex configurations.
|
|
21
|
-
3. **Quick experience**
|
|
22
|
-
> Allow users to quickly experiment with Vue's new features in HTML and feel its charm.
|
|
17
|
+
Using the [vue/compiler-sfc](https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme), which compiled at runtime for esm vue code format, and dynamic execution.
|
|
23
18
|
|
|
24
|
-
## 🤯
|
|
19
|
+
## 🤯 Code comparison
|
|
25
20
|
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
<h4 align=center>esm.html</h4>
|
|
22
|
+
It's a little more complicated
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<!DOCTYPE html>
|
|
26
|
+
<html lang="en">
|
|
27
|
+
<head>
|
|
28
|
+
<meta charset="UTF-8">
|
|
29
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
30
|
+
<title>esm</title>
|
|
31
|
+
<style>
|
|
32
|
+
button {
|
|
33
|
+
font-size: larger;
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
36
|
+
</head>
|
|
37
|
+
<body>
|
|
38
|
+
<div id="app">
|
|
39
|
+
<button @click="count++">{{ count }}</button>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<script type="module">
|
|
43
|
+
import { createApp, defineComponent, ref } from 'https://unpkg.com/vue/dist/vue.esm-browser.js';
|
|
44
|
+
const App = defineComponent(() => {
|
|
45
|
+
const count = ref(0);
|
|
46
|
+
return {
|
|
47
|
+
count
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
createApp(App).mount('#app')
|
|
51
|
+
</script>
|
|
52
|
+
</body>
|
|
53
|
+
</html>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
<h4 align=center>setup.vue</h4>
|
|
57
|
+
Cannot run directly in the browser
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<script setup>
|
|
61
|
+
import { ref } from 'vue'
|
|
62
|
+
const count = ref(0)
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<template>
|
|
66
|
+
<button @click="count++">{{ count }}</button>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<style>
|
|
70
|
+
button {
|
|
71
|
+
font-size: larger;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
<h4 align=center>setupin.html</h4>
|
|
77
|
+
unit as one
|
|
30
78
|
|
|
31
|
-
|
|
79
|
+
```html
|
|
80
|
+
<head>
|
|
81
|
+
<meta charset="UTF-8">
|
|
82
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
83
|
+
<title>setupin</title>
|
|
84
|
+
<script src="https://unpkg.com/setupin"></script>
|
|
85
|
+
</head>
|
|
86
|
+
|
|
87
|
+
<script setup>
|
|
88
|
+
import { ref } from 'vue'
|
|
89
|
+
const count = ref(0)
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<template>
|
|
93
|
+
<button @click="count++">{{ count }}</button>
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<style>
|
|
97
|
+
button {
|
|
98
|
+
font-size: larger;
|
|
99
|
+
}
|
|
100
|
+
</style>
|
|
101
|
+
```
|
|
32
102
|
|
|
103
|
+
It's exactly the same as [\<script setup>](https://vuejs.org/api/sfc-script-setup.html) except for the \<head>
|
|
33
104
|
## 🤓 Characteristics
|
|
34
105
|
|
|
35
|
-
- [x] supports esm import syntax
|
|
36
106
|
- [x] [top-level await](https://vuejs.org/api/sfc-script-setup.html#top-level-await)
|
|
37
107
|
- [x] [sfc css features](https://vuejs.org/api/sfc-css-features.html)
|
|
38
|
-
- [
|
|
108
|
+
- [ ] Split [component](https://vuejs.org/guide/essentials/component-basics.html)
|
|
109
|
+
|
|
110
|
+
## 🤔 Why setupin
|
|
111
|
+
|
|
112
|
+
1. **Easy to learn**
|
|
113
|
+
Offer a friendly environment for beginners to easily grasp the core usage of Vue.
|
|
114
|
+
2. **Simple development**
|
|
115
|
+
Provide a convenient way to rapidly develop small webpage without complex configurations.
|
|
116
|
+
3. **Quick experience**
|
|
117
|
+
Allow users to quickly experiment with Vue's new features in HTML and feel its charm.
|
|
39
118
|
|
|
40
119
|
## 😝 Playground
|
|
41
120
|
|
package/README.zh-CN.md
CHANGED
|
@@ -10,32 +10,114 @@
|
|
|
10
10
|
<a href="https://bundlephobia.com/package/setupin"><img src="https://img.shields.io/bundlephobia/minzip/setupin"></a>
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
|
-
## 😏
|
|
13
|
+
## 😏 setupin 是什么?
|
|
14
14
|
|
|
15
|
-
**setupin** 允许你在 HTML 中编写 Vue 的 [\<script setup
|
|
15
|
+
**setupin** 允许你在 HTML 中编写 Vue 的 [\<script setup>](https://cn.vuejs.org/api/sfc-script-setup.html)语法。
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
> 为初学者提供一个友好的环境,帮助他们轻松上手 Vue 的核心用法。
|
|
19
|
-
2. **简易开发**
|
|
20
|
-
> 提供便捷的方式,助力快速开发小网页,无需繁琐的配置。
|
|
21
|
-
3. **快速体验**
|
|
22
|
-
> 让用户可以快速在 HTML 中尝试 Vue 的新特性,感受其魅力。
|
|
17
|
+
利用[vue/compiler-sfc](https://github.com/vuejs/core/tree/main/packages/compiler-sfc#readme),在运行时编译为esm格式的vue代码,并动态执行。
|
|
23
18
|
|
|
24
|
-
## 🤯
|
|
19
|
+
## 🤯 代码对比
|
|
25
20
|
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
21
|
+
<h4 align=center>esm.html</h4>
|
|
22
|
+
写法略微复杂
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<!DOCTYPE html>
|
|
26
|
+
<html lang="en">
|
|
27
|
+
<head>
|
|
28
|
+
<meta charset="UTF-8">
|
|
29
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
30
|
+
<title>esm</title>
|
|
31
|
+
<style>
|
|
32
|
+
button {
|
|
33
|
+
font-size: larger;
|
|
34
|
+
}
|
|
35
|
+
</style>
|
|
36
|
+
</head>
|
|
37
|
+
<body>
|
|
38
|
+
<div id="app">
|
|
39
|
+
<button @click="count++">{{ count }}</button>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<script type="module">
|
|
43
|
+
import { createApp, defineComponent, ref } from 'https://unpkg.com/vue/dist/vue.esm-browser.js';
|
|
44
|
+
const App = defineComponent(() => {
|
|
45
|
+
const count = ref(0);
|
|
46
|
+
return {
|
|
47
|
+
count
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
createApp(App).mount('#app')
|
|
51
|
+
</script>
|
|
52
|
+
</body>
|
|
53
|
+
</html>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
<h4 align=center>setup.vue</h4>
|
|
57
|
+
无法直接在浏览器运行
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<script setup>
|
|
61
|
+
import { ref } from 'vue'
|
|
62
|
+
const count = ref(0)
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<template>
|
|
66
|
+
<button @click="count++">{{ count }}</button>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<style>
|
|
70
|
+
button {
|
|
71
|
+
font-size: larger;
|
|
72
|
+
}
|
|
73
|
+
</style>
|
|
74
|
+
```
|
|
30
75
|
|
|
31
|
-
|
|
76
|
+
<h4 align=center>setupin.html</h4>
|
|
77
|
+
合二为一
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<head>
|
|
81
|
+
<meta charset="UTF-8">
|
|
82
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
83
|
+
<title>setupin</title>
|
|
84
|
+
<script src="https://unpkg.com/setupin"></script>
|
|
85
|
+
</head>
|
|
86
|
+
|
|
87
|
+
<script setup>
|
|
88
|
+
import { ref } from 'vue'
|
|
89
|
+
const count = ref(0)
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<template>
|
|
93
|
+
<button @click="count++">{{ count }}</button>
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<style>
|
|
97
|
+
button {
|
|
98
|
+
font-size: larger;
|
|
99
|
+
}
|
|
100
|
+
</style>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
除了\<head>之外和[\<script setup>](https://cn.vuejs.org/api/sfc-script-setup.html)写法完全一致
|
|
32
104
|
|
|
33
105
|
## 🤓 特性
|
|
34
106
|
|
|
35
|
-
- [x] 支持 esm import 语法
|
|
36
107
|
- [x] [顶层 await](https://cn.vuejs.org/api/sfc-script-setup.html#top-level-await)
|
|
37
108
|
- [x] [CSS 功能](https://cn.vuejs.org/api/sfc-css-features)
|
|
38
|
-
- [
|
|
109
|
+
- [ ] 拆分 [组件](https://cn.vuejs.org/guide/essentials/component-basics.html)
|
|
110
|
+
|
|
111
|
+
## 🤔 为什么选择 setupin
|
|
112
|
+
|
|
113
|
+
1. **便于学习**
|
|
114
|
+
为初学者提供一个友好的环境,帮助他们轻松上手 Vue 的核心用法。
|
|
115
|
+
|
|
116
|
+
2. **简易开发**
|
|
117
|
+
提供便捷的方式,助力快速开发小网页,无需繁琐的配置。
|
|
118
|
+
|
|
119
|
+
3. **快速体验**
|
|
120
|
+
让用户可以快速在 HTML 中尝试 Vue 的新特性,感受其魅力。
|
|
39
121
|
|
|
40
122
|
## 😝 演练场
|
|
41
123
|
|
package/dist/main.js
CHANGED
|
@@ -51,26 +51,25 @@ var __async = (__this, __arguments, generator) => {
|
|
|
51
51
|
};
|
|
52
52
|
(function() {
|
|
53
53
|
"use strict";
|
|
54
|
-
const ASCII_LOGO = "/***************************************\r\n** _ _ **\r\n** ___ ___| |_ _ _ _ __ (_)_ __ **\r\n** / __|/ _ \\ __| | | | '_ \\| | '_ \\ **\r\n** \\__ \\ __/ |_| |_| | |_/ | | | | | **\r\n** |___/\\___|\\__|\\__,_| .__/|_|_| |_| **\r\n** |_| **\r\n***************************************/\r\n";
|
|
54
|
+
const ASCII_LOGO = "\r\n/***************************************\r\n** _ _ **\r\n** ___ ___| |_ _ _ _ __ (_)_ __ **\r\n** / __|/ _ \\ __| | | | '_ \\| | '_ \\ **\r\n** \\__ \\ __/ |_| |_| | |_/ | | | | | **\r\n** |___/\\___|\\__|\\__,_| .__/|_|_| |_| **\r\n** |_| **\r\n***************************************/\r\n";
|
|
55
55
|
const APP_VAR_NAME = "APP$";
|
|
56
56
|
const REPO_NAME = "setupin";
|
|
57
|
-
const IMPORTS_JSON = JSON.stringify({ imports: { vue: "https://unpkg.com/vue/dist/vue.runtime.esm-browser.js" } });
|
|
57
|
+
const IMPORTS_JSON = JSON.stringify({ imports: { vue: "https://unpkg.com/vue@latest/dist/vue.runtime.esm-browser.js" } });
|
|
58
58
|
const INIT_CODE = `
|
|
59
|
-
<script>
|
|
60
59
|
${ASCII_LOGO}
|
|
61
60
|
import * as Vue from "vue";
|
|
62
|
-
let ${APP_VAR_NAME} =
|
|
63
|
-
<\/script>
|
|
61
|
+
let ${APP_VAR_NAME} = Object.create(null);
|
|
64
62
|
`;
|
|
65
63
|
const CREATE_APP_CODE = `
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
Vue.createApp(Vue.defineComponent(
|
|
65
|
+
String(${APP_VAR_NAME}.setup).startsWith('async')
|
|
66
|
+
? () => () =>
|
|
67
|
+
Vue.h(Vue.Suspense, null, {
|
|
68
|
+
default: Vue.h(${APP_VAR_NAME}),
|
|
69
|
+
fallback: Vue.h('div', 'Loading...'),
|
|
70
|
+
})
|
|
71
|
+
: ${APP_VAR_NAME}
|
|
72
|
+
)).mount(document.body)
|
|
74
73
|
`;
|
|
75
74
|
/**
|
|
76
75
|
* @vue/compiler-sfc v3.5.12
|
|
@@ -45876,22 +45875,24 @@ ${exposeCall}`
|
|
|
45876
45875
|
const id = REPO_NAME;
|
|
45877
45876
|
function compilerSfc(source) {
|
|
45878
45877
|
var _a2, _b2;
|
|
45879
|
-
const sfcParseResult = parse$2(
|
|
45878
|
+
const sfcParseResult = parse$2(source, { filename });
|
|
45880
45879
|
sfcParseResult.errors.forEach((e) => {
|
|
45881
45880
|
console.warn(e);
|
|
45882
45881
|
});
|
|
45883
|
-
const sfcScriptBlock = compileScript(sfcParseResult.descriptor, { id });
|
|
45882
|
+
const sfcScriptBlock = compileScript(sfcParseResult.descriptor, { id, isProd: false });
|
|
45884
45883
|
const sfcTemplateCompileResults = compileTemplate({
|
|
45885
45884
|
id,
|
|
45886
45885
|
filename,
|
|
45887
|
-
source: (_b2 = (_a2 = sfcParseResult.descriptor.template) == null ? void 0 : _a2.content) != null ? _b2 : ""
|
|
45886
|
+
source: (_b2 = (_a2 = sfcParseResult.descriptor.template) == null ? void 0 : _a2.content) != null ? _b2 : "",
|
|
45887
|
+
isProd: false
|
|
45888
45888
|
});
|
|
45889
45889
|
const sfcStyleCompileResultsList = sfcParseResult.descriptor.styles.map((style) => {
|
|
45890
45890
|
return compileStyle({
|
|
45891
45891
|
id,
|
|
45892
45892
|
filename,
|
|
45893
45893
|
source: style.content,
|
|
45894
|
-
scoped: style.scoped
|
|
45894
|
+
scoped: style.scoped,
|
|
45895
|
+
isProd: false
|
|
45895
45896
|
});
|
|
45896
45897
|
});
|
|
45897
45898
|
return {
|
|
@@ -45902,7 +45903,7 @@ ${exposeCall}`
|
|
|
45902
45903
|
}
|
|
45903
45904
|
function createDom(row, inner) {
|
|
45904
45905
|
var _a2;
|
|
45905
|
-
const container2 = document.createElement("
|
|
45906
|
+
const container2 = document.createElement("body");
|
|
45906
45907
|
container2.insertAdjacentHTML("afterbegin", row);
|
|
45907
45908
|
const sample = container2.firstElementChild;
|
|
45908
45909
|
const dom = document.createElement(sample.tagName);
|
|
@@ -45911,9 +45912,7 @@ ${exposeCall}`
|
|
|
45911
45912
|
dom.setAttribute(n2, (_a2 = sample.getAttribute(n2)) != null ? _a2 : "");
|
|
45912
45913
|
}
|
|
45913
45914
|
return {
|
|
45914
|
-
mount(el)
|
|
45915
|
-
el.appendChild(dom);
|
|
45916
|
-
}
|
|
45915
|
+
mount: (el) => el.appendChild(dom)
|
|
45917
45916
|
};
|
|
45918
45917
|
}
|
|
45919
45918
|
function watchRoot(handler) {
|
|
@@ -45937,13 +45936,18 @@ ${exposeCall}`
|
|
|
45937
45936
|
}
|
|
45938
45937
|
function awaitCompileSfc(handler) {
|
|
45939
45938
|
return __async(this, null, function* () {
|
|
45940
|
-
const
|
|
45941
|
-
if (
|
|
45942
|
-
|
|
45943
|
-
|
|
45944
|
-
|
|
45939
|
+
const clientCodeList = yield watchRoot((node2, clientCodeList2) => {
|
|
45940
|
+
if (!/^(?:script|template|style)$/.test(node2.localName))
|
|
45941
|
+
return;
|
|
45942
|
+
if (node2.hasAttribute("src"))
|
|
45943
|
+
return;
|
|
45944
|
+
clientCodeList2.push(node2.outerHTML);
|
|
45945
|
+
node2.localName === "style" ? node2.onload = node2.remove : node2.remove();
|
|
45945
45946
|
});
|
|
45946
|
-
const
|
|
45947
|
+
const hasScript = clientCodeList.some((code) => code.slice(1, 7) === "script");
|
|
45948
|
+
if (!hasScript)
|
|
45949
|
+
clientCodeList.push("<script>/* empty script */<\/script>");
|
|
45950
|
+
const { sfcScriptBlock, sfcTemplateCompileResults, sfcStyleCompileResultsList } = compilerSfc(clientCodeList.join("\n"));
|
|
45947
45951
|
handler(sfcStyleCompileResultsList, sfcScriptBlock, sfcTemplateCompileResults);
|
|
45948
45952
|
});
|
|
45949
45953
|
}
|
|
@@ -45952,27 +45956,27 @@ ${exposeCall}`
|
|
|
45952
45956
|
}
|
|
45953
45957
|
function generateEsmCode(sfcScriptBlock, sfcTemplateCompileResults) {
|
|
45954
45958
|
return `
|
|
45959
|
+
${INIT_CODE}
|
|
45955
45960
|
${_scriptTransform(sfcScriptBlock)}
|
|
45956
45961
|
${_templateTransform(sfcTemplateCompileResults)}
|
|
45957
|
-
|
|
45958
|
-
else{${CREATE_APP_CODE}}
|
|
45962
|
+
${CREATE_APP_CODE}
|
|
45959
45963
|
`;
|
|
45964
|
+
function _scriptTransform(sfcScriptBlock2) {
|
|
45965
|
+
const s = new MagicString(sfcScriptBlock2.content);
|
|
45966
|
+
s.replace("export default", `${APP_VAR_NAME} =`);
|
|
45967
|
+
s.replace("Object.defineProperty(__returned__,", "// ");
|
|
45968
|
+
return s.toString();
|
|
45969
|
+
}
|
|
45970
|
+
function _templateTransform(sfcTemplateCompileResults2) {
|
|
45971
|
+
const t = new MagicString(sfcTemplateCompileResults2.code);
|
|
45972
|
+
t.replace("export function render", `${APP_VAR_NAME}.render = function`);
|
|
45973
|
+
return t.toString();
|
|
45974
|
+
}
|
|
45960
45975
|
}
|
|
45961
|
-
|
|
45962
|
-
const s = new MagicString(sfcScriptBlock.content);
|
|
45963
|
-
s.replace("export default", `${APP_VAR_NAME} =`);
|
|
45964
|
-
s.replace("Object.defineProperty(__returned__,", "// ");
|
|
45965
|
-
return s.toString();
|
|
45966
|
-
}
|
|
45967
|
-
function _templateTransform(sfcTemplateCompileResults) {
|
|
45968
|
-
const t = new MagicString(sfcTemplateCompileResults.code);
|
|
45969
|
-
t.replace("export function render", `${APP_VAR_NAME}.render = function`);
|
|
45970
|
-
return t.toString();
|
|
45971
|
-
}
|
|
45972
|
-
awaitCompileSfc((compiledStyles, ...compiledSetupAndRender) => {
|
|
45976
|
+
awaitCompileSfc((compiledStyleList, ...compiledSetupAndRender) => {
|
|
45973
45977
|
_toHead(`<script ${REPO_NAME} type="importmap">${IMPORTS_JSON}<\/script>`);
|
|
45974
45978
|
_toHead(`<script ${REPO_NAME} type="module">`, generateEsmCode(...compiledSetupAndRender));
|
|
45975
|
-
_toHead(`<style ${REPO_NAME}>`, generateStyleCode(
|
|
45979
|
+
_toHead(`<style ${REPO_NAME}>`, generateStyleCode(compiledStyleList));
|
|
45976
45980
|
});
|
|
45977
45981
|
function _toHead(...args) {
|
|
45978
45982
|
createDom(...args).mount(document.head);
|