workflow: sfc playground
This commit is contained in:
parent
2424768808
commit
f76ddc5ac3
@ -56,7 +56,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
// Private package, browser only + no syntax restrictions
|
// Private package, browser only + no syntax restrictions
|
||||||
{
|
{
|
||||||
files: ['packages/template-explorer/**'],
|
files: ['packages/template-explorer/**', 'packages/sfc-playground/**'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||||
'no-restricted-syntax': 'off'
|
'no-restricted-syntax': 'off'
|
||||||
|
@ -69,7 +69,7 @@
|
|||||||
"rollup": "~2.38.5",
|
"rollup": "~2.38.5",
|
||||||
"rollup-plugin-node-builtins": "^2.1.2",
|
"rollup-plugin-node-builtins": "^2.1.2",
|
||||||
"rollup-plugin-node-globals": "^1.4.0",
|
"rollup-plugin-node-globals": "^1.4.0",
|
||||||
"rollup-plugin-node-polyfills": "^0.2.1",
|
"rollup-plugin-polyfill-node": "^0.6.2",
|
||||||
"rollup-plugin-terser": "^7.0.2",
|
"rollup-plugin-terser": "^7.0.2",
|
||||||
"rollup-plugin-typescript2": "^0.27.2",
|
"rollup-plugin-typescript2": "^0.27.2",
|
||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"version": "3.0.9",
|
"version": "3.0.9",
|
||||||
"description": "@vue/compiler-sfc",
|
"description": "@vue/compiler-sfc",
|
||||||
"main": "dist/compiler-sfc.cjs.js",
|
"main": "dist/compiler-sfc.cjs.js",
|
||||||
|
"module": "dist/compiler-sfc.esm-browser.js",
|
||||||
"types": "dist/compiler-sfc.d.ts",
|
"types": "dist/compiler-sfc.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
"dist"
|
"dist"
|
||||||
@ -11,7 +12,7 @@
|
|||||||
"name": "VueCompilerSFC",
|
"name": "VueCompilerSFC",
|
||||||
"formats": [
|
"formats": [
|
||||||
"cjs",
|
"cjs",
|
||||||
"global"
|
"esm-browser"
|
||||||
],
|
],
|
||||||
"prod": false,
|
"prod": false,
|
||||||
"enableNonBrowserBranches": true
|
"enableNonBrowserBranches": true
|
||||||
|
@ -1367,7 +1367,7 @@ function markScopeIdentifier(
|
|||||||
* but with some subtle differences as this needs to handle a wider range of
|
* but with some subtle differences as this needs to handle a wider range of
|
||||||
* possible syntax.
|
* possible syntax.
|
||||||
*/
|
*/
|
||||||
function walkIdentifiers(
|
export function walkIdentifiers(
|
||||||
root: Node,
|
root: Node,
|
||||||
onIdentifier: (node: Identifier, parent: Node, parentStack: Node[]) => void
|
onIdentifier: (node: Identifier, parent: Node, parentStack: Node[]) => void
|
||||||
) {
|
) {
|
||||||
|
@ -6,6 +6,12 @@ export { compileScript } from './compileScript'
|
|||||||
export { rewriteDefault } from './rewriteDefault'
|
export { rewriteDefault } from './rewriteDefault'
|
||||||
export { generateCodeFrame } from '@vue/compiler-core'
|
export { generateCodeFrame } from '@vue/compiler-core'
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
export { parse as babelParse } from '@babel/parser'
|
||||||
|
export { walkIdentifiers } from './compileScript'
|
||||||
|
import MagicString from 'magic-string'
|
||||||
|
export { MagicString }
|
||||||
|
|
||||||
// Types
|
// Types
|
||||||
export {
|
export {
|
||||||
SFCParseOptions,
|
SFCParseOptions,
|
||||||
|
@ -16,6 +16,10 @@ export function warn(msg: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function warnExperimental(feature: string, rfcId: number) {
|
export function warnExperimental(feature: string, rfcId: number) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
return
|
||||||
|
}
|
||||||
warnOnce(
|
warnOnce(
|
||||||
`${feature} is still an experimental proposal.\n` +
|
`${feature} is still an experimental proposal.\n` +
|
||||||
`Follow its status at https://github.com/vuejs/rfcs/pull/${rfcId}.`
|
`Follow its status at https://github.com/vuejs/rfcs/pull/${rfcId}.`
|
||||||
|
7
packages/global.d.ts
vendored
7
packages/global.d.ts
vendored
@ -22,3 +22,10 @@ declare namespace jest {
|
|||||||
toHaveBeenWarnedTimes(n: number): R
|
toHaveBeenWarnedTimes(n: number): R
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '*.vue' {
|
||||||
|
|
||||||
|
}
|
||||||
|
declare module '*?raw' {
|
||||||
|
|
||||||
|
}
|
||||||
|
19
packages/sfc-playground/index.html
Normal file
19
packages/sfc-playground/index.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Vue SFC Playground</title>
|
||||||
|
|
||||||
|
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Source+Code+Pro&display=swap" rel="stylesheet">
|
||||||
|
|
||||||
|
<!-- process shim for @vue/compiler-sfc dependency -->
|
||||||
|
<script>window.process = { env: {} }</script>
|
||||||
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
packages/sfc-playground/package.json
Normal file
23
packages/sfc-playground/package.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "@vue/sfc-playground",
|
||||||
|
"version": "3.0.9",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"serve": "vite preview"
|
||||||
|
},
|
||||||
|
"buildOptions": {
|
||||||
|
"formats": [
|
||||||
|
"global"
|
||||||
|
],
|
||||||
|
"env": "development",
|
||||||
|
"enableNonBrowserBranches": true
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/codemirror": "^0.0.108",
|
||||||
|
"@vitejs/plugin-vue": "^1.2.0",
|
||||||
|
"codemirror": "^5.60.0",
|
||||||
|
"vite": "^2.1.3"
|
||||||
|
}
|
||||||
|
}
|
37
packages/sfc-playground/src/App.vue
Normal file
37
packages/sfc-playground/src/App.vue
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<template>
|
||||||
|
<Header />
|
||||||
|
<div class="wrapper">
|
||||||
|
<SplitPane>
|
||||||
|
<template #left>
|
||||||
|
<Editor />
|
||||||
|
</template>
|
||||||
|
<template #right>
|
||||||
|
<Output />
|
||||||
|
</template>
|
||||||
|
</SplitPane>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Header from './Header.vue'
|
||||||
|
import SplitPane from './SplitPane.vue'
|
||||||
|
import Editor from './editor/Editor.vue'
|
||||||
|
import Output from './output/Output.vue'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
|
||||||
|
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||||
|
color: #444;
|
||||||
|
margin: 0;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
--nav-height: 50px;
|
||||||
|
--font-code: 'Source Code Pro', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
height: calc(100vh - var(--nav-height));
|
||||||
|
}
|
||||||
|
</style>
|
23
packages/sfc-playground/src/Header.vue
Normal file
23
packages/sfc-playground/src/Header.vue
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<template>
|
||||||
|
<nav>
|
||||||
|
<h1>Vue SFC Playground</h1>
|
||||||
|
</nav>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
nav {
|
||||||
|
height: var(--nav-height);
|
||||||
|
box-sizing: border-box;
|
||||||
|
padding: 0 1em;
|
||||||
|
background-color: #fff;
|
||||||
|
box-shadow: 0 0 4px rgba(0, 0, 0, 0.33);
|
||||||
|
position: relative;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
line-height: var(--nav-height);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
</style>
|
66
packages/sfc-playground/src/Message.vue
Normal file
66
packages/sfc-playground/src/Message.vue
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<Transition name="fade">
|
||||||
|
<pre v-if="err || warn"
|
||||||
|
class="msg"
|
||||||
|
:class="err ? 'err' : 'warn'">{{ formatMessage(err || warn) }}</pre>
|
||||||
|
</Transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { defineProps } from 'vue'
|
||||||
|
import type { CompilerError } from '@vue/compiler-sfc'
|
||||||
|
|
||||||
|
defineProps(['err', 'warn'])
|
||||||
|
|
||||||
|
function formatMessage(err: string | Error): string {
|
||||||
|
if (typeof err === 'string') {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
let msg = err.message
|
||||||
|
const loc = (err as CompilerError).loc
|
||||||
|
if (loc && loc.start) {
|
||||||
|
msg = `(${loc.start.line}:${loc.start.column}) ` + msg
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.msg {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 8px;
|
||||||
|
right: 8px;
|
||||||
|
z-index: 10;
|
||||||
|
padding: 14px 20px;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
border-radius: 6px;
|
||||||
|
font-family: var(--font-code);
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg.err {
|
||||||
|
color: red;
|
||||||
|
border-color: red;
|
||||||
|
background-color: #ffd7d7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.msg.warn {
|
||||||
|
--color: rgb(105, 95, 27);
|
||||||
|
color: var(--color);
|
||||||
|
border-color: var(--color);
|
||||||
|
background-color: rgb(247, 240, 205);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-active,
|
||||||
|
.fade-leave-active {
|
||||||
|
transition: all 0.15s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fade-enter-from,
|
||||||
|
.fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translate(0, 10px);
|
||||||
|
}
|
||||||
|
</style>
|
91
packages/sfc-playground/src/SplitPane.vue
Normal file
91
packages/sfc-playground/src/SplitPane.vue
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
ref="container"
|
||||||
|
class="split-pane"
|
||||||
|
:class="{ dragging: state.dragging }"
|
||||||
|
@mousemove="dragMove"
|
||||||
|
@mouseup="dragEnd"
|
||||||
|
@mouseleave="dragEnd"
|
||||||
|
>
|
||||||
|
<div class="left" :style="{ width: boundSplit() + '%' }">
|
||||||
|
<slot name="left" />
|
||||||
|
<div class="dragger" @mousedown.prevent="dragStart" />
|
||||||
|
</div>
|
||||||
|
<div class="right" :style="{ width: (100 - boundSplit()) + '%' }">
|
||||||
|
<slot name="right" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive } from 'vue'
|
||||||
|
|
||||||
|
const container = ref()
|
||||||
|
|
||||||
|
const state = reactive({
|
||||||
|
dragging: false,
|
||||||
|
split: 50
|
||||||
|
})
|
||||||
|
|
||||||
|
function boundSplit() {
|
||||||
|
const { split } = state
|
||||||
|
return split < 20
|
||||||
|
? 20
|
||||||
|
: split > 80
|
||||||
|
? 80
|
||||||
|
: split
|
||||||
|
}
|
||||||
|
|
||||||
|
let startPosition = 0
|
||||||
|
let startSplit = 0
|
||||||
|
|
||||||
|
function dragStart(e: MouseEvent) {
|
||||||
|
state.dragging = true
|
||||||
|
startPosition = e.pageX
|
||||||
|
startSplit = boundSplit()
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragMove(e: MouseEvent) {
|
||||||
|
if (state.dragging) {
|
||||||
|
const position = e.pageX
|
||||||
|
const totalSize = container.value.offsetWidth
|
||||||
|
const dp = position - startPosition
|
||||||
|
state.split = startSplit + ~~(dp / totalSize * 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function dragEnd() {
|
||||||
|
state.dragging = false
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.split-pane {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.split-pane.dragging {
|
||||||
|
cursor: ew-resize;
|
||||||
|
}
|
||||||
|
.dragging .left,
|
||||||
|
.dragging .right {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.left,
|
||||||
|
.right {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.left {
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
.dragger {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 99;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: -5px;
|
||||||
|
width: 10px;
|
||||||
|
cursor: ew-resize;
|
||||||
|
}
|
||||||
|
</style>
|
76
packages/sfc-playground/src/codemirror/CodeMirror.vue
Normal file
76
packages/sfc-playground/src/codemirror/CodeMirror.vue
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<template>
|
||||||
|
<div class="editor" ref="el"></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted, defineProps, defineEmit, watchEffect } from 'vue'
|
||||||
|
import { debounce } from '../utils'
|
||||||
|
import CodeMirror from './codemirror'
|
||||||
|
|
||||||
|
const el = ref()
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
mode: {
|
||||||
|
type: String,
|
||||||
|
default: 'htmlmixed'
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
readonly: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emit = defineEmit(['change'])
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const addonOptions = {
|
||||||
|
autoCloseBrackets: true,
|
||||||
|
autoCloseTags: true,
|
||||||
|
foldGutter: true,
|
||||||
|
gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter']
|
||||||
|
}
|
||||||
|
|
||||||
|
const editor = CodeMirror(el.value!, {
|
||||||
|
value: '',
|
||||||
|
mode: props.mode,
|
||||||
|
readOnly: props.readonly,
|
||||||
|
tabSize: 2,
|
||||||
|
lineWrapping: true,
|
||||||
|
lineNumbers: true,
|
||||||
|
...addonOptions
|
||||||
|
})
|
||||||
|
|
||||||
|
editor.on('change', () => {
|
||||||
|
emit('change', editor.getValue())
|
||||||
|
})
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
editor.setValue(props.value)
|
||||||
|
})
|
||||||
|
watchEffect(() => {
|
||||||
|
editor.setOption('mode', props.mode)
|
||||||
|
})
|
||||||
|
|
||||||
|
window.addEventListener('resize', debounce(() => {
|
||||||
|
editor.refresh()
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.editor {
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
font-family: "Source Code Pro", monospace;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
506
packages/sfc-playground/src/codemirror/codemirror.css
Normal file
506
packages/sfc-playground/src/codemirror/codemirror.css
Normal file
@ -0,0 +1,506 @@
|
|||||||
|
/* BASICS */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
--base: #545281;
|
||||||
|
--comment: hsl(210, 25%, 60%);
|
||||||
|
--keyword: #af4ab1;
|
||||||
|
--variable: #0055d1;
|
||||||
|
--function: #c25205;
|
||||||
|
--string: #2ba46d;
|
||||||
|
--number: #c25205;
|
||||||
|
--tags: #dd0000;
|
||||||
|
--qualifier: #ff6032;
|
||||||
|
--important: var(--string);
|
||||||
|
|
||||||
|
direction: ltr;
|
||||||
|
font-family: var(--font-code);
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PADDING */
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
padding: 4px 0; /* Vertical padding around content */
|
||||||
|
}
|
||||||
|
.CodeMirror pre {
|
||||||
|
padding: 0 4px; /* Horizontal padding of content */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scrollbar-filler,
|
||||||
|
.CodeMirror-gutter-filler {
|
||||||
|
background-color: white; /* The little square between H and V scrollbars */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GUTTER */
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
border-right: 1px solid #ddd;
|
||||||
|
background-color: transparent;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
padding: 0 3px 0 5px;
|
||||||
|
min-width: 20px;
|
||||||
|
text-align: right;
|
||||||
|
color: var(--comment);
|
||||||
|
white-space: nowrap;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-guttermarker {
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.CodeMirror-guttermarker-subtle {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FOLD GUTTER */
|
||||||
|
|
||||||
|
.CodeMirror-foldmarker {
|
||||||
|
color: #414141;
|
||||||
|
text-shadow: #ff9966 1px 1px 2px, #ff9966 -1px -1px 2px, #ff9966 1px -1px 2px,
|
||||||
|
#ff9966 -1px 1px 2px;
|
||||||
|
font-family: arial;
|
||||||
|
line-height: 0.3;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.CodeMirror-foldgutter {
|
||||||
|
width: 0.7em;
|
||||||
|
}
|
||||||
|
.CodeMirror-foldgutter-open,
|
||||||
|
.CodeMirror-foldgutter-folded {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.CodeMirror-foldgutter-open:after,
|
||||||
|
.CodeMirror-foldgutter-folded:after {
|
||||||
|
content: '>';
|
||||||
|
font-size: 0.8em;
|
||||||
|
opacity: 0.8;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
display: inline-block;
|
||||||
|
top: -0.1em;
|
||||||
|
position: relative;
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
.CodeMirror-foldgutter-folded:after {
|
||||||
|
transform: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CURSOR */
|
||||||
|
|
||||||
|
.CodeMirror-cursor {
|
||||||
|
border-left: 1px solid black;
|
||||||
|
border-right: none;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
/* Shown when moving in bi-directional text */
|
||||||
|
.CodeMirror div.CodeMirror-secondarycursor {
|
||||||
|
border-left: 1px solid silver;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor .CodeMirror-cursor {
|
||||||
|
width: auto;
|
||||||
|
border: 0 !important;
|
||||||
|
background: #7e7;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor div.CodeMirror-cursors {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.cm-fat-cursor-mark {
|
||||||
|
background-color: rgba(20, 255, 20, 0.5);
|
||||||
|
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||||
|
-moz-animation: blink 1.06s steps(1) infinite;
|
||||||
|
animation: blink 1.06s steps(1) infinite;
|
||||||
|
}
|
||||||
|
.cm-animate-fat-cursor {
|
||||||
|
width: auto;
|
||||||
|
border: 0;
|
||||||
|
-webkit-animation: blink 1.06s steps(1) infinite;
|
||||||
|
-moz-animation: blink 1.06s steps(1) infinite;
|
||||||
|
animation: blink 1.06s steps(1) infinite;
|
||||||
|
background-color: #7e7;
|
||||||
|
}
|
||||||
|
@-moz-keyframes blink {
|
||||||
|
0% {
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-webkit-keyframes blink {
|
||||||
|
0% {
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@keyframes blink {
|
||||||
|
0% {
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-tab {
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-rulers {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: -50px;
|
||||||
|
bottom: -20px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.CodeMirror-ruler {
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEFAULT THEME */
|
||||||
|
.cm-s-default.CodeMirror {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-header {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-quote {
|
||||||
|
color: #090;
|
||||||
|
}
|
||||||
|
.cm-negative {
|
||||||
|
color: #d44;
|
||||||
|
}
|
||||||
|
.cm-positive {
|
||||||
|
color: #292;
|
||||||
|
}
|
||||||
|
.cm-header,
|
||||||
|
.cm-strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.cm-em {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
.cm-link {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
.cm-strikethrough {
|
||||||
|
text-decoration: line-through;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-s-default .cm-atom,
|
||||||
|
.cm-s-default .cm-def,
|
||||||
|
.cm-s-default .cm-property,
|
||||||
|
.cm-s-default .cm-variable-2,
|
||||||
|
.cm-s-default .cm-variable-3,
|
||||||
|
.cm-s-default .cm-punctuation {
|
||||||
|
color: var(--base);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-hr,
|
||||||
|
.cm-s-default .cm-comment {
|
||||||
|
color: var(--comment);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-attribute,
|
||||||
|
.cm-s-default .cm-keyword {
|
||||||
|
color: var(--keyword);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-variable {
|
||||||
|
color: var(--variable);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-bracket,
|
||||||
|
.cm-s-default .cm-tag {
|
||||||
|
color: var(--tags);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-number {
|
||||||
|
color: var(--number);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-string,
|
||||||
|
.cm-s-default .cm-string-2 {
|
||||||
|
color: var(--string);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-type {
|
||||||
|
color: #085;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-meta {
|
||||||
|
color: #555;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-qualifier {
|
||||||
|
color: var(--qualifier);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-builtin {
|
||||||
|
color: #7539ff;
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-link {
|
||||||
|
color: var(--flash);
|
||||||
|
}
|
||||||
|
.cm-s-default .cm-error {
|
||||||
|
color: #ff008c;
|
||||||
|
}
|
||||||
|
.cm-invalidchar {
|
||||||
|
color: #ff008c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-composing {
|
||||||
|
border-bottom: 2px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default styles for common addons */
|
||||||
|
|
||||||
|
div.CodeMirror span.CodeMirror-matchingbracket {
|
||||||
|
color: #0b0;
|
||||||
|
}
|
||||||
|
div.CodeMirror span.CodeMirror-nonmatchingbracket {
|
||||||
|
color: #a22;
|
||||||
|
}
|
||||||
|
.CodeMirror-matchingtag {
|
||||||
|
background: rgba(255, 150, 0, 0.3);
|
||||||
|
}
|
||||||
|
.CodeMirror-activeline-background {
|
||||||
|
background: #e8f2ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* STOP */
|
||||||
|
|
||||||
|
/* The rest of this file contains styles related to the mechanics of
|
||||||
|
the editor. You probably shouldn't touch them. */
|
||||||
|
|
||||||
|
.CodeMirror {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
background: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-scroll {
|
||||||
|
overflow: scroll !important; /* Things will break if this is overridden */
|
||||||
|
/* 30px is the magic margin used to hide the element's real scrollbars */
|
||||||
|
/* See overflow: hidden in .CodeMirror */
|
||||||
|
margin-bottom: -30px;
|
||||||
|
margin-right: -30px;
|
||||||
|
padding-bottom: 30px;
|
||||||
|
height: 100%;
|
||||||
|
outline: none; /* Prevent dragging from highlighting the element */
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.CodeMirror-sizer {
|
||||||
|
position: relative;
|
||||||
|
border-right: 30px solid transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The fake, visible scrollbars. Used to force redraw during scrolling
|
||||||
|
before actual scrolling happens, thus preventing shaking and
|
||||||
|
flickering artifacts. */
|
||||||
|
.CodeMirror-vscrollbar,
|
||||||
|
.CodeMirror-hscrollbar,
|
||||||
|
.CodeMirror-scrollbar-filler,
|
||||||
|
.CodeMirror-gutter-filler {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 6;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-vscrollbar {
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-hscrollbar {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
overflow-x: scroll;
|
||||||
|
}
|
||||||
|
.CodeMirror-scrollbar-filler {
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-filler {
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-gutters {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
min-height: 100%;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter {
|
||||||
|
white-space: normal;
|
||||||
|
height: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
margin-bottom: -30px;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 4;
|
||||||
|
background: none !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-background {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-elt {
|
||||||
|
position: absolute;
|
||||||
|
cursor: default;
|
||||||
|
z-index: 4;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper ::selection {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.CodeMirror-gutter-wrapper ::-moz-selection {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-lines {
|
||||||
|
cursor: text;
|
||||||
|
min-height: 1px; /* prevents collapsing before first draw */
|
||||||
|
}
|
||||||
|
.CodeMirror pre {
|
||||||
|
/* Reset some styles that the rest of the page might have set */
|
||||||
|
-moz-border-radius: 0;
|
||||||
|
-webkit-border-radius: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
border-width: 0;
|
||||||
|
background: transparent;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
|
margin: 0;
|
||||||
|
white-space: pre;
|
||||||
|
word-wrap: normal;
|
||||||
|
line-height: inherit;
|
||||||
|
color: inherit;
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
overflow: visible;
|
||||||
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
-webkit-font-variant-ligatures: contextual;
|
||||||
|
font-variant-ligatures: contextual;
|
||||||
|
}
|
||||||
|
.CodeMirror-wrap pre {
|
||||||
|
word-wrap: break-word;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-break: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linebackground {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-linewidget {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 0.1px; /* Force widget margins to stay inside of the container */
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-rtl pre {
|
||||||
|
direction: rtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-code {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force content-box sizing for the elements where we expect it */
|
||||||
|
.CodeMirror-scroll,
|
||||||
|
.CodeMirror-sizer,
|
||||||
|
.CodeMirror-gutter,
|
||||||
|
.CodeMirror-gutters,
|
||||||
|
.CodeMirror-linenumber {
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-measure {
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-cursor {
|
||||||
|
position: absolute;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
.CodeMirror-measure pre {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
position: relative;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
div.CodeMirror-dragcursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-focused div.CodeMirror-cursors {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.CodeMirror-selected {
|
||||||
|
background: #d9d9d9;
|
||||||
|
}
|
||||||
|
.CodeMirror-focused .CodeMirror-selected {
|
||||||
|
background: #d7d4f0;
|
||||||
|
}
|
||||||
|
.CodeMirror-crosshair {
|
||||||
|
cursor: crosshair;
|
||||||
|
}
|
||||||
|
.CodeMirror-line::selection,
|
||||||
|
.CodeMirror-line > span::selection,
|
||||||
|
.CodeMirror-line > span > span::selection {
|
||||||
|
background: #d7d4f0;
|
||||||
|
}
|
||||||
|
.CodeMirror-line::-moz-selection,
|
||||||
|
.CodeMirror-line > span::-moz-selection,
|
||||||
|
.CodeMirror-line > span > span::-moz-selection {
|
||||||
|
background: #d7d4f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cm-searching {
|
||||||
|
background-color: #ffa;
|
||||||
|
background-color: rgba(255, 255, 0, 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used to force a border model for a node */
|
||||||
|
.cm-force-border {
|
||||||
|
padding-right: 0.1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media print {
|
||||||
|
/* Hide the cursor when printing */
|
||||||
|
.CodeMirror div.CodeMirror-cursors {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See issue #2901 */
|
||||||
|
.cm-tab-wrap-hack:after {
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Help users use markselection to safely style text background */
|
||||||
|
span.CodeMirror-selectedtext {
|
||||||
|
background: none;
|
||||||
|
}
|
19
packages/sfc-playground/src/codemirror/codemirror.ts
Normal file
19
packages/sfc-playground/src/codemirror/codemirror.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import CodeMirror from 'codemirror'
|
||||||
|
import './codemirror.css'
|
||||||
|
|
||||||
|
// modes
|
||||||
|
import 'codemirror/mode/javascript/javascript.js'
|
||||||
|
import 'codemirror/mode/css/css.js'
|
||||||
|
import 'codemirror/mode/htmlmixed/htmlmixed.js'
|
||||||
|
|
||||||
|
// addons
|
||||||
|
import 'codemirror/addon/edit/closebrackets.js'
|
||||||
|
import 'codemirror/addon/edit/closetag.js'
|
||||||
|
import 'codemirror/addon/comment/comment.js'
|
||||||
|
import 'codemirror/addon/fold/foldcode.js'
|
||||||
|
import 'codemirror/addon/fold/foldgutter.js'
|
||||||
|
import 'codemirror/addon/fold/brace-fold.js'
|
||||||
|
import 'codemirror/addon/fold/indent-fold.js'
|
||||||
|
import 'codemirror/addon/fold/comment-fold.js'
|
||||||
|
|
||||||
|
export default CodeMirror
|
17
packages/sfc-playground/src/editor/Editor.vue
Normal file
17
packages/sfc-playground/src/editor/Editor.vue
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<template>
|
||||||
|
<CodeMirror @change="onChange" :value="initialCode" />
|
||||||
|
<Message :err="store.errors[0]" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import CodeMirror from '../codemirror/CodeMirror.vue'
|
||||||
|
import Message from '../Message.vue'
|
||||||
|
import { store } from '../store'
|
||||||
|
import { debounce } from '../utils'
|
||||||
|
|
||||||
|
const onChange = debounce((code: string) => {
|
||||||
|
store.code = code
|
||||||
|
}, 250)
|
||||||
|
|
||||||
|
const initialCode = store.code
|
||||||
|
</script>
|
4
packages/sfc-playground/src/main.ts
Normal file
4
packages/sfc-playground/src/main.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { createApp } from 'vue'
|
||||||
|
import App from './App.vue'
|
||||||
|
|
||||||
|
createApp(App).mount('#app')
|
57
packages/sfc-playground/src/output/Output.vue
Normal file
57
packages/sfc-playground/src/output/Output.vue
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
<template>
|
||||||
|
<div class="tab-buttons">
|
||||||
|
<button v-for="m of modes" :class="{ active: mode === m }" @click="mode = m">{{ m }}</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="output-container">
|
||||||
|
<Preview v-if="mode === 'preview'" :code="store.compiled.executed" />
|
||||||
|
<CodeMirror
|
||||||
|
v-else
|
||||||
|
readonly
|
||||||
|
:mode="mode === 'css' ? 'css' : 'javascript'"
|
||||||
|
:value="store.compiled[mode]"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Preview from './Preview.vue'
|
||||||
|
import CodeMirror from '../codemirror/CodeMirror.vue'
|
||||||
|
import { store } from '../store'
|
||||||
|
import { ref } from 'vue'
|
||||||
|
|
||||||
|
type Modes = 'preview' | 'executed' | 'js' | 'css' | 'template'
|
||||||
|
|
||||||
|
const modes: Modes[] = ['preview', 'js', 'css', 'template', 'executed']
|
||||||
|
const mode = ref<Modes>('preview')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.output-container {
|
||||||
|
height: calc(100% - 35px);
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.tab-buttons {
|
||||||
|
box-sizing: border-box;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.tab-buttons button {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 13px;
|
||||||
|
font-family: 'Source Code Pro', monospace;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
padding: 8px 16px 6px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
cursor: pointer;
|
||||||
|
color: #999;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.active {
|
||||||
|
color: #42b983;
|
||||||
|
border-bottom: 3px solid #42b983;
|
||||||
|
}
|
||||||
|
</style>
|
108
packages/sfc-playground/src/output/Preview.vue
Normal file
108
packages/sfc-playground/src/output/Preview.vue
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
<template>
|
||||||
|
<iframe
|
||||||
|
id="preview"
|
||||||
|
ref="iframe"
|
||||||
|
sandbox="allow-forms allow-modals allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-top-navigation-by-user-activation"
|
||||||
|
:srcdoc="srcdoc"
|
||||||
|
></iframe>
|
||||||
|
<Message :err="runtimeError" />
|
||||||
|
<Message v-if="!runtimeError" :warn="runtimeWarning" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import Message from '../Message.vue'
|
||||||
|
import { ref, onMounted, onUnmounted, watchEffect, defineProps } from 'vue'
|
||||||
|
import srcdoc from './srcdoc.html?raw'
|
||||||
|
import { PreviewProxy } from './PreviewProxy'
|
||||||
|
import { sandboxVueURL } from '../store'
|
||||||
|
|
||||||
|
const props = defineProps<{ code: string }>()
|
||||||
|
|
||||||
|
const iframe = ref()
|
||||||
|
const runtimeError = ref()
|
||||||
|
const runtimeWarning = ref()
|
||||||
|
|
||||||
|
let proxy: PreviewProxy
|
||||||
|
|
||||||
|
async function updatePreview() {
|
||||||
|
if (!props.code?.trim()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
proxy.eval(`
|
||||||
|
${props.code}
|
||||||
|
|
||||||
|
if (window.vueApp) {
|
||||||
|
window.vueApp.unmount()
|
||||||
|
}
|
||||||
|
const container = document.getElementById('app')
|
||||||
|
container.innerHTML = ''
|
||||||
|
|
||||||
|
import { createApp as _createApp } from "${sandboxVueURL}"
|
||||||
|
const app = window.vueApp = _createApp(__comp)
|
||||||
|
|
||||||
|
app.config.errorHandler = e => console.error(e)
|
||||||
|
|
||||||
|
app.mount(container)
|
||||||
|
`)
|
||||||
|
} catch (e) {
|
||||||
|
runtimeError.value = e.message
|
||||||
|
return
|
||||||
|
}
|
||||||
|
runtimeError.value = null
|
||||||
|
runtimeWarning.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
proxy = new PreviewProxy(iframe.value, {
|
||||||
|
on_fetch_progress: (progress: any) => {
|
||||||
|
// pending_imports = progress;
|
||||||
|
},
|
||||||
|
on_error: (event: any) => {
|
||||||
|
// push_logs({ level: 'error', args: [event.value] });
|
||||||
|
runtimeError.value = event.value
|
||||||
|
},
|
||||||
|
on_unhandled_rejection: (event: any) => {
|
||||||
|
let error = event.value
|
||||||
|
if (typeof error === 'string') error = { message: error }
|
||||||
|
runtimeError.value = 'Uncaught (in promise): ' + error.message
|
||||||
|
},
|
||||||
|
on_console: (log: any) => {
|
||||||
|
if (log.level === 'error') {
|
||||||
|
runtimeError.value = log.args.join('')
|
||||||
|
} else if (log.level === 'warn') {
|
||||||
|
if (log.args[0].toString().includes('[Vue warn]')) {
|
||||||
|
runtimeWarning.value = log.args.join('').replace(/\[Vue warn\]:/, '').trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on_console_group: (action: any) => {
|
||||||
|
// group_logs(action.label, false);
|
||||||
|
},
|
||||||
|
on_console_group_end: () => {
|
||||||
|
// ungroup_logs();
|
||||||
|
},
|
||||||
|
on_console_group_collapsed: (action: any) => {
|
||||||
|
// group_logs(action.label, true);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
iframe.value.addEventListener('load', () => {
|
||||||
|
proxy.handle_links();
|
||||||
|
watchEffect(updatePreview)
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
proxy.destroy()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
iframe {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: none;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
96
packages/sfc-playground/src/output/PreviewProxy.ts
Normal file
96
packages/sfc-playground/src/output/PreviewProxy.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
// ReplProxy and srcdoc implementation from Svelte REPL
|
||||||
|
// MIT License https://github.com/sveltejs/svelte-repl/blob/master/LICENSE
|
||||||
|
|
||||||
|
let uid = 1
|
||||||
|
|
||||||
|
export class PreviewProxy {
|
||||||
|
iframe: HTMLIFrameElement
|
||||||
|
handlers: Record<string, Function>
|
||||||
|
pending_cmds: Map<
|
||||||
|
number,
|
||||||
|
{ resolve: (value: unknown) => void; reject: (reason?: any) => void }
|
||||||
|
>
|
||||||
|
handle_event: (e: any) => void
|
||||||
|
|
||||||
|
constructor(iframe: HTMLIFrameElement, handlers: Record<string, Function>) {
|
||||||
|
this.iframe = iframe
|
||||||
|
this.handlers = handlers
|
||||||
|
|
||||||
|
this.pending_cmds = new Map()
|
||||||
|
|
||||||
|
this.handle_event = e => this.handle_repl_message(e)
|
||||||
|
window.addEventListener('message', this.handle_event, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
destroy() {
|
||||||
|
window.removeEventListener('message', this.handle_event)
|
||||||
|
}
|
||||||
|
|
||||||
|
iframe_command(action: string, args: any) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const cmd_id = uid++
|
||||||
|
|
||||||
|
this.pending_cmds.set(cmd_id, { resolve, reject })
|
||||||
|
|
||||||
|
this.iframe.contentWindow!.postMessage({ action, cmd_id, args }, '*')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_command_message(cmd_data: any) {
|
||||||
|
let action = cmd_data.action
|
||||||
|
let id = cmd_data.cmd_id
|
||||||
|
let handler = this.pending_cmds.get(id)
|
||||||
|
|
||||||
|
if (handler) {
|
||||||
|
this.pending_cmds.delete(id)
|
||||||
|
if (action === 'cmd_error') {
|
||||||
|
let { message, stack } = cmd_data
|
||||||
|
let e = new Error(message)
|
||||||
|
e.stack = stack
|
||||||
|
handler.reject(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'cmd_ok') {
|
||||||
|
handler.resolve(cmd_data.args)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('command not found', id, cmd_data, [
|
||||||
|
...this.pending_cmds.keys()
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_repl_message(event: any) {
|
||||||
|
if (event.source !== this.iframe.contentWindow) return
|
||||||
|
|
||||||
|
const { action, args } = event.data
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case 'cmd_error':
|
||||||
|
case 'cmd_ok':
|
||||||
|
return this.handle_command_message(event.data)
|
||||||
|
case 'fetch_progress':
|
||||||
|
return this.handlers.on_fetch_progress(args.remaining)
|
||||||
|
case 'error':
|
||||||
|
return this.handlers.on_error(event.data)
|
||||||
|
case 'unhandledrejection':
|
||||||
|
return this.handlers.on_unhandled_rejection(event.data)
|
||||||
|
case 'console':
|
||||||
|
return this.handlers.on_console(event.data)
|
||||||
|
case 'console_group':
|
||||||
|
return this.handlers.on_console_group(event.data)
|
||||||
|
case 'console_group_collapsed':
|
||||||
|
return this.handlers.on_console_group_collapsed(event.data)
|
||||||
|
case 'console_group_end':
|
||||||
|
return this.handlers.on_console_group_end(event.data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eval(script: string) {
|
||||||
|
return this.iframe_command('eval', { script })
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_links() {
|
||||||
|
return this.iframe_command('catch_clicks', {})
|
||||||
|
}
|
||||||
|
}
|
201
packages/sfc-playground/src/output/srcdoc.html
Normal file
201
packages/sfc-playground/src/output/srcdoc.html
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
|
||||||
|
Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style id="__sfc-styles"></style>
|
||||||
|
<script>
|
||||||
|
(function(){
|
||||||
|
let scriptEl
|
||||||
|
|
||||||
|
function handle_message(ev) {
|
||||||
|
let { action, cmd_id } = ev.data;
|
||||||
|
const send_message = (payload) => parent.postMessage( { ...payload }, ev.origin);
|
||||||
|
const send_reply = (payload) => send_message({ ...payload, cmd_id });
|
||||||
|
const send_ok = () => send_reply({ action: 'cmd_ok' });
|
||||||
|
const send_error = (message, stack) => send_reply({ action: 'cmd_error', message, stack });
|
||||||
|
|
||||||
|
if (action === 'eval') {
|
||||||
|
try {
|
||||||
|
if (scriptEl) {
|
||||||
|
document.head.removeChild(scriptEl)
|
||||||
|
}
|
||||||
|
scriptEl = document.createElement('script')
|
||||||
|
scriptEl.setAttribute('type', 'module')
|
||||||
|
scriptEl.innerHTML = ev.data.args.script
|
||||||
|
document.head.appendChild(scriptEl)
|
||||||
|
send_ok();
|
||||||
|
} catch (e) {
|
||||||
|
send_error(e.message, e.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action === 'catch_clicks') {
|
||||||
|
try {
|
||||||
|
const top_origin = ev.origin;
|
||||||
|
document.body.addEventListener('click', event => {
|
||||||
|
if (event.which !== 1) return;
|
||||||
|
if (event.metaKey || event.ctrlKey || event.shiftKey) return;
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
|
|
||||||
|
// ensure target is a link
|
||||||
|
let el = event.target;
|
||||||
|
while (el && el.nodeName !== 'A') el = el.parentNode;
|
||||||
|
if (!el || el.nodeName !== 'A') return;
|
||||||
|
|
||||||
|
if (el.hasAttribute('download') || el.getAttribute('rel') === 'external' || el.target) return;
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (el.href.startsWith(top_origin)) {
|
||||||
|
const url = new URL(el.href);
|
||||||
|
if (url.hash[0] === '#') {
|
||||||
|
window.location.hash = url.hash;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.open(el.href, '_blank');
|
||||||
|
});
|
||||||
|
send_ok();
|
||||||
|
} catch(e) {
|
||||||
|
send_error(e.message, e.stack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener('message', handle_message, false);
|
||||||
|
|
||||||
|
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||||
|
parent.postMessage({ action: 'error', value: error }, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("unhandledrejection", event => {
|
||||||
|
parent.postMessage({ action: 'unhandledrejection', value: event.reason }, '*');
|
||||||
|
});
|
||||||
|
}).call(this);
|
||||||
|
|
||||||
|
let previous = { level: null, args: null };
|
||||||
|
|
||||||
|
['clear', 'log', 'info', 'dir', 'warn', 'error', 'table'].forEach((level) => {
|
||||||
|
const original = console[level];
|
||||||
|
console[level] = (...args) => {
|
||||||
|
if (String(args[0]).includes('You are running a development build of Vue')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const stringifiedArgs = stringify(args);
|
||||||
|
if (
|
||||||
|
previous.level === level &&
|
||||||
|
previous.args &&
|
||||||
|
previous.args === stringifiedArgs
|
||||||
|
) {
|
||||||
|
parent.postMessage({ action: 'console', level, duplicate: true }, '*');
|
||||||
|
} else {
|
||||||
|
previous = { level, args: stringifiedArgs };
|
||||||
|
|
||||||
|
try {
|
||||||
|
parent.postMessage({ action: 'console', level, args }, '*');
|
||||||
|
} catch (err) {
|
||||||
|
parent.postMessage({ action: 'console', level: 'unclonable' }, '*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
original(...args);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
[
|
||||||
|
{ method: 'group', action: 'console_group' },
|
||||||
|
{ method: 'groupEnd', action: 'console_group_end' },
|
||||||
|
{ method: 'groupCollapsed', action: 'console_group_collapsed' },
|
||||||
|
].forEach((group_action) => {
|
||||||
|
const original = console[group_action.method];
|
||||||
|
console[group_action.method] = (label) => {
|
||||||
|
parent.postMessage({ action: group_action.action, label }, '*');
|
||||||
|
|
||||||
|
original(label);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const timers = new Map();
|
||||||
|
const original_time = console.time;
|
||||||
|
const original_timelog = console.timeLog;
|
||||||
|
const original_timeend = console.timeEnd;
|
||||||
|
|
||||||
|
console.time = (label = 'default') => {
|
||||||
|
original_time(label);
|
||||||
|
timers.set(label, performance.now());
|
||||||
|
}
|
||||||
|
console.timeLog = (label = 'default') => {
|
||||||
|
original_timelog(label);
|
||||||
|
const now = performance.now();
|
||||||
|
if (timers.has(label)) {
|
||||||
|
parent.postMessage({ action: 'console', level: 'system-log', args: [`${label}: ${now - timers.get(label)}ms`] }, '*');
|
||||||
|
} else {
|
||||||
|
parent.postMessage({ action: 'console', level: 'system-warn', args: [`Timer '${label}' does not exist`] }, '*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.timeEnd = (label = 'default') => {
|
||||||
|
original_timeend(label);
|
||||||
|
const now = performance.now();
|
||||||
|
if (timers.has(label)) {
|
||||||
|
parent.postMessage({ action: 'console', level: 'system-log', args: [`${label}: ${now - timers.get(label)}ms`] }, '*');
|
||||||
|
} else {
|
||||||
|
parent.postMessage({ action: 'console', level: 'system-warn', args: [`Timer '${label}' does not exist`] }, '*');
|
||||||
|
}
|
||||||
|
timers.delete(label);
|
||||||
|
};
|
||||||
|
|
||||||
|
const original_assert = console.assert;
|
||||||
|
console.assert = (condition, ...args) => {
|
||||||
|
if (condition) {
|
||||||
|
const stack = new Error().stack;
|
||||||
|
parent.postMessage({ action: 'console', level: 'assert', args, stack }, '*');
|
||||||
|
}
|
||||||
|
original_assert(condition, ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
const counter = new Map();
|
||||||
|
const original_count = console.count;
|
||||||
|
const original_countreset = console.countReset;
|
||||||
|
|
||||||
|
console.count = (label = 'default') => {
|
||||||
|
counter.set(label, (counter.get(label) || 0) + 1);
|
||||||
|
parent.postMessage({ action: 'console', level: 'system-log', args: `${label}: ${counter.get(label)}` }, '*');
|
||||||
|
original_count(label);
|
||||||
|
};
|
||||||
|
|
||||||
|
console.countReset = (label = 'default') => {
|
||||||
|
if (counter.has(label)) {
|
||||||
|
counter.set(label, 0);
|
||||||
|
} else {
|
||||||
|
parent.postMessage({ action: 'console', level: 'system-warn', args: `Count for '${label}' does not exist` }, '*');
|
||||||
|
}
|
||||||
|
original_countreset(label);
|
||||||
|
};
|
||||||
|
|
||||||
|
const original_trace = console.trace;
|
||||||
|
|
||||||
|
console.trace = (...args) => {
|
||||||
|
const stack = new Error().stack;
|
||||||
|
parent.postMessage({ action: 'console', level: 'trace', args, stack }, '*');
|
||||||
|
original_trace(...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
function stringify(args) {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(args);
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
168
packages/sfc-playground/src/store.ts
Normal file
168
packages/sfc-playground/src/store.ts
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
import { reactive, watchEffect } from 'vue'
|
||||||
|
import {
|
||||||
|
parse,
|
||||||
|
compileTemplate,
|
||||||
|
compileStyleAsync,
|
||||||
|
compileScript,
|
||||||
|
rewriteDefault,
|
||||||
|
CompilerError
|
||||||
|
} from '@vue/compiler-sfc'
|
||||||
|
|
||||||
|
const storeKey = 'sfc-code'
|
||||||
|
const saved = localStorage.getItem(storeKey) || ''
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
export const sandboxVueURL = import.meta.env.PROD
|
||||||
|
? '/vue.runtime.esm-browser.js' // to be copied on build
|
||||||
|
: '/src/vue-dev-proxy'
|
||||||
|
|
||||||
|
export const store = reactive({
|
||||||
|
code: saved,
|
||||||
|
compiled: {
|
||||||
|
executed: '',
|
||||||
|
js: '',
|
||||||
|
css: '',
|
||||||
|
template: ''
|
||||||
|
},
|
||||||
|
errors: [] as (string | CompilerError | SyntaxError)[]
|
||||||
|
})
|
||||||
|
|
||||||
|
const filename = 'Playground.vue'
|
||||||
|
const id = 'scope-id'
|
||||||
|
const compIdentifier = `__comp`
|
||||||
|
|
||||||
|
watchEffect(async () => {
|
||||||
|
const { code, compiled } = store
|
||||||
|
if (!code.trim()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
localStorage.setItem(storeKey, code)
|
||||||
|
|
||||||
|
const { errors, descriptor } = parse(code, { filename, sourceMap: true })
|
||||||
|
if (errors.length) {
|
||||||
|
store.errors = errors
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasScoped = descriptor.styles.some(s => s.scoped)
|
||||||
|
let finalCode = ''
|
||||||
|
|
||||||
|
if (
|
||||||
|
(descriptor.script && descriptor.script.lang) ||
|
||||||
|
(descriptor.scriptSetup && descriptor.scriptSetup.lang) ||
|
||||||
|
descriptor.styles.some(s => s.lang) ||
|
||||||
|
(descriptor.template && descriptor.template.lang)
|
||||||
|
) {
|
||||||
|
store.errors = [
|
||||||
|
'lang="x" pre-processors are not supported in the in-browser playground.'
|
||||||
|
]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// script
|
||||||
|
if (descriptor.script || descriptor.scriptSetup) {
|
||||||
|
try {
|
||||||
|
const compiledScript = compileScript(descriptor, {
|
||||||
|
id,
|
||||||
|
refSugar: true,
|
||||||
|
inlineTemplate: true
|
||||||
|
})
|
||||||
|
compiled.js = compiledScript.content.trim()
|
||||||
|
finalCode +=
|
||||||
|
`\n` +
|
||||||
|
rewriteDefault(
|
||||||
|
rewriteVueImports(compiledScript.content),
|
||||||
|
compIdentifier
|
||||||
|
)
|
||||||
|
} catch (e) {
|
||||||
|
store.errors = [e]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
compiled.js = ''
|
||||||
|
finalCode += `\nconst ${compIdentifier} = {}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// template
|
||||||
|
if (descriptor.template && !descriptor.scriptSetup) {
|
||||||
|
const templateResult = compileTemplate({
|
||||||
|
source: descriptor.template.content,
|
||||||
|
filename,
|
||||||
|
id,
|
||||||
|
scoped: hasScoped,
|
||||||
|
slotted: descriptor.slotted,
|
||||||
|
isProd: false
|
||||||
|
})
|
||||||
|
if (templateResult.errors.length) {
|
||||||
|
store.errors = templateResult.errors
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
compiled.template = templateResult.code.trim()
|
||||||
|
finalCode += rewriteVueImports(templateResult.code).replace(
|
||||||
|
/\nexport (function|const) render/,
|
||||||
|
'$1 render'
|
||||||
|
)
|
||||||
|
finalCode += `\n${compIdentifier}.render = render`
|
||||||
|
} else {
|
||||||
|
compiled.template = descriptor.scriptSetup
|
||||||
|
? '/* inlined in JS (script setup) */'
|
||||||
|
: '/* no template present */'
|
||||||
|
}
|
||||||
|
if (hasScoped) {
|
||||||
|
finalCode += `\n${compIdentifier}.__scopeId = ${JSON.stringify(
|
||||||
|
`data-v-${id}`
|
||||||
|
)}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// styles
|
||||||
|
let css = ''
|
||||||
|
for (const style of descriptor.styles) {
|
||||||
|
if (style.module) {
|
||||||
|
// TODO error
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
const styleResult = await compileStyleAsync({
|
||||||
|
source: style.content,
|
||||||
|
filename,
|
||||||
|
id,
|
||||||
|
scoped: style.scoped,
|
||||||
|
modules: !!style.module
|
||||||
|
})
|
||||||
|
if (styleResult.errors.length) {
|
||||||
|
// postcss uses pathToFileURL which isn't polyfilled in the browser
|
||||||
|
// ignore these errors for now
|
||||||
|
if (!styleResult.errors[0].message.includes('pathToFileURL')) {
|
||||||
|
store.errors = styleResult.errors
|
||||||
|
}
|
||||||
|
// proceed even if css compile errors
|
||||||
|
} else {
|
||||||
|
css += styleResult.code + '\n'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (css) {
|
||||||
|
compiled.css = css.trim()
|
||||||
|
finalCode += `\ndocument.getElementById('__sfc-styles').innerHTML = ${JSON.stringify(
|
||||||
|
css
|
||||||
|
)}`
|
||||||
|
} else {
|
||||||
|
compiled.css = ''
|
||||||
|
}
|
||||||
|
|
||||||
|
store.errors = []
|
||||||
|
if (finalCode) {
|
||||||
|
compiled.executed =
|
||||||
|
`/* Exact code being executed in the preview iframe (different from production bundler output) */\n` +
|
||||||
|
finalCode
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// TODO use proper parser
|
||||||
|
function rewriteVueImports(code: string): string {
|
||||||
|
return code.replace(
|
||||||
|
/\b(import \{.*?\}\s+from\s+)(?:"vue"|'vue')/g,
|
||||||
|
`$1"${sandboxVueURL}"`
|
||||||
|
)
|
||||||
|
}
|
9
packages/sfc-playground/src/utils.ts
Normal file
9
packages/sfc-playground/src/utils.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
export function debounce(fn: Function, n = 100) {
|
||||||
|
let handle: any
|
||||||
|
return (...args: any[]) => {
|
||||||
|
if (handle) clearTimeout(handle)
|
||||||
|
handle = setTimeout(() => {
|
||||||
|
fn(...args)
|
||||||
|
}, n)
|
||||||
|
}
|
||||||
|
}
|
2
packages/sfc-playground/src/vue-dev-proxy.ts
Normal file
2
packages/sfc-playground/src/vue-dev-proxy.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
// serve vue to the iframe sandbox during dev.
|
||||||
|
export * from 'vue'
|
34
packages/sfc-playground/vite.config.ts
Normal file
34
packages/sfc-playground/vite.config.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
import { defineConfig, Plugin } from 'vite'
|
||||||
|
import vue from '@vitejs/plugin-vue'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue(), copyVuePlugin()],
|
||||||
|
optimizeDeps: {
|
||||||
|
exclude: ['consolidate']
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
function copyVuePlugin(): Plugin {
|
||||||
|
return {
|
||||||
|
name: 'copy-vue',
|
||||||
|
generateBundle(_opts, bundle) {
|
||||||
|
const filePath = path.resolve(
|
||||||
|
__dirname,
|
||||||
|
'../vue/dist/vue.runtime.esm-browser.js'
|
||||||
|
)
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
throw new Error(
|
||||||
|
`vue.runtime.esm-browser.js not built. ` +
|
||||||
|
`Run "yarn build vue -f esm-browser" first.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
this.emitFile({
|
||||||
|
type: 'asset',
|
||||||
|
fileName: 'vue.runtime.esm-browser.js',
|
||||||
|
source: fs.readFileSync(filePath, 'utf-8')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -142,7 +142,7 @@ function createConfig(format, output, plugins = []) {
|
|||||||
require('@rollup/plugin-commonjs')({
|
require('@rollup/plugin-commonjs')({
|
||||||
sourceMap: false
|
sourceMap: false
|
||||||
}),
|
}),
|
||||||
require('rollup-plugin-node-polyfills')(),
|
require('rollup-plugin-polyfill-node')(),
|
||||||
require('@rollup/plugin-node-resolve').nodeResolve()
|
require('@rollup/plugin-node-resolve').nodeResolve()
|
||||||
]
|
]
|
||||||
: []
|
: []
|
||||||
|
93
yarn.lock
93
yarn.lock
@ -572,6 +572,15 @@
|
|||||||
magic-string "^0.25.7"
|
magic-string "^0.25.7"
|
||||||
resolve "^1.17.0"
|
resolve "^1.17.0"
|
||||||
|
|
||||||
|
"@rollup/plugin-inject@^4.0.0":
|
||||||
|
version "4.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-inject/-/plugin-inject-4.0.2.tgz#55b21bb244a07675f7fdde577db929c82fc17395"
|
||||||
|
integrity sha512-TSLMA8waJ7Dmgmoc8JfPnwUwVZgLjjIAM6MqeIFqPO2ODK36JqE0Cf2F54UTgCUuW8da93Mvoj75a6KAVWgylw==
|
||||||
|
dependencies:
|
||||||
|
"@rollup/pluginutils" "^3.0.4"
|
||||||
|
estree-walker "^1.0.1"
|
||||||
|
magic-string "^0.25.5"
|
||||||
|
|
||||||
"@rollup/plugin-json@^4.0.0":
|
"@rollup/plugin-json@^4.0.0":
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3"
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3"
|
||||||
@ -599,7 +608,7 @@
|
|||||||
"@rollup/pluginutils" "^3.1.0"
|
"@rollup/pluginutils" "^3.1.0"
|
||||||
magic-string "^0.25.7"
|
magic-string "^0.25.7"
|
||||||
|
|
||||||
"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
|
"@rollup/pluginutils@^3.0.4", "@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
|
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
|
||||||
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
|
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
|
||||||
@ -698,6 +707,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.33.tgz#d79c020f283bd50bd76101d7d300313c107325fc"
|
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.33.tgz#d79c020f283bd50bd76101d7d300313c107325fc"
|
||||||
integrity sha512-ndEo1xvnYeHxm7I/5sF6tBvnsA4Tdi3zj1keRKRs12SP+2ye2A27NDJ1B6PqkfMbGAcT+mqQVqbZRIrhfOp5PQ==
|
integrity sha512-ndEo1xvnYeHxm7I/5sF6tBvnsA4Tdi3zj1keRKRs12SP+2ye2A27NDJ1B6PqkfMbGAcT+mqQVqbZRIrhfOp5PQ==
|
||||||
|
|
||||||
|
"@types/codemirror@^0.0.108":
|
||||||
|
version "0.0.108"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/codemirror/-/codemirror-0.0.108.tgz#e640422b666bf49251b384c390cdeb2362585bde"
|
||||||
|
integrity sha512-3FGFcus0P7C2UOGCNUVENqObEb4SFk+S8Dnxq7K6aIsLVs/vDtlangl3PEO0ykaKXyK56swVF6Nho7VsA44uhw==
|
||||||
|
dependencies:
|
||||||
|
"@types/tern" "*"
|
||||||
|
|
||||||
"@types/consolidate@^0.14.0":
|
"@types/consolidate@^0.14.0":
|
||||||
version "0.14.0"
|
version "0.14.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/consolidate/-/consolidate-0.14.0.tgz#856735b3a1421513bd12b9bdd588923bec773bff"
|
resolved "https://registry.yarnpkg.com/@types/consolidate/-/consolidate-0.14.0.tgz#856735b3a1421513bd12b9bdd588923bec773bff"
|
||||||
@ -814,6 +830,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
|
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
|
||||||
integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==
|
integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw==
|
||||||
|
|
||||||
|
"@types/tern@*":
|
||||||
|
version "0.23.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/tern/-/tern-0.23.3.tgz#4b54538f04a88c9ff79de1f6f94f575a7f339460"
|
||||||
|
integrity sha512-imDtS4TAoTcXk0g7u4kkWqedB3E4qpjXzCpD2LU5M5NAXHzCDsypyvXSaG7mM8DKYkCRa7tFp4tS/lp/Wo7Q3w==
|
||||||
|
dependencies:
|
||||||
|
"@types/estree" "*"
|
||||||
|
|
||||||
"@types/yargs-parser@*":
|
"@types/yargs-parser@*":
|
||||||
version "20.2.0"
|
version "20.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9"
|
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9"
|
||||||
@ -870,6 +893,11 @@
|
|||||||
"@typescript-eslint/types" "4.19.0"
|
"@typescript-eslint/types" "4.19.0"
|
||||||
eslint-visitor-keys "^2.0.0"
|
eslint-visitor-keys "^2.0.0"
|
||||||
|
|
||||||
|
"@vitejs/plugin-vue@^1.2.0":
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-1.2.0.tgz#f0a92470b74761f90afc8cda204fa3bec9df09f4"
|
||||||
|
integrity sha512-IhSJfJH6IDNEAnhr91+2vhLLe/1SqkA/2BP19jwtn54DGI+cNbZIxiPhHIdKUpdRo0QwErOh6Jy1Maxk2uVo7A==
|
||||||
|
|
||||||
"@zeit/schemas@2.6.0":
|
"@zeit/schemas@2.6.0":
|
||||||
version "2.6.0"
|
version "2.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3"
|
resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3"
|
||||||
@ -1696,6 +1724,11 @@ co@^4.6.0:
|
|||||||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||||
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
|
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
|
||||||
|
|
||||||
|
codemirror@^5.60.0:
|
||||||
|
version "5.60.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-5.60.0.tgz#00a8cfd287d5d8737ceb73987f04aee2fe5860da"
|
||||||
|
integrity sha512-AEL7LhFOlxPlCL8IdTcJDblJm8yrAGib7I+DErJPdZd4l6imx8IMgKK3RblVgBQqz3TZJR4oknQ03bz+uNjBYA==
|
||||||
|
|
||||||
collect-v8-coverage@^1.0.0:
|
collect-v8-coverage@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
|
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
|
||||||
@ -1733,7 +1766,7 @@ color-name@~1.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
|
||||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||||
|
|
||||||
colorette@^1.2.1:
|
colorette@^1.2.1, colorette@^1.2.2:
|
||||||
version "1.2.2"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94"
|
||||||
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==
|
||||||
@ -2419,6 +2452,11 @@ es-to-primitive@^1.2.1:
|
|||||||
is-date-object "^1.0.1"
|
is-date-object "^1.0.1"
|
||||||
is-symbol "^1.0.2"
|
is-symbol "^1.0.2"
|
||||||
|
|
||||||
|
esbuild@^0.9.3:
|
||||||
|
version "0.9.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.9.7.tgz#ea0d639cbe4b88ec25fbed4d6ff00c8d788ef70b"
|
||||||
|
integrity sha512-VtUf6aQ89VTmMLKrWHYG50uByMF4JQlVysb8dmg6cOgW8JnFCipmz7p+HNBl+RR3LLCuBxFGVauAe2wfnF9bLg==
|
||||||
|
|
||||||
escalade@^3.1.1:
|
escalade@^3.1.1:
|
||||||
version "3.1.1"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||||
@ -4617,7 +4655,7 @@ magic-string@^0.22.5:
|
|||||||
dependencies:
|
dependencies:
|
||||||
vlq "^0.2.2"
|
vlq "^0.2.2"
|
||||||
|
|
||||||
magic-string@^0.25.3, magic-string@^0.25.7:
|
magic-string@^0.25.5, magic-string@^0.25.7:
|
||||||
version "0.25.7"
|
version "0.25.7"
|
||||||
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
|
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
|
||||||
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
|
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
|
||||||
@ -5460,6 +5498,15 @@ postcss@^8.1.10:
|
|||||||
nanoid "^3.1.20"
|
nanoid "^3.1.20"
|
||||||
source-map "^0.6.1"
|
source-map "^0.6.1"
|
||||||
|
|
||||||
|
postcss@^8.2.1:
|
||||||
|
version "8.2.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.8.tgz#0b90f9382efda424c4f0f69a2ead6f6830d08ece"
|
||||||
|
integrity sha512-1F0Xb2T21xET7oQV9eKuctbM9S7BC0fetoHCc4H13z0PT6haiRLP4T0ZY4XWh7iLP0usgqykT6p9B2RtOf4FPw==
|
||||||
|
dependencies:
|
||||||
|
colorette "^1.2.2"
|
||||||
|
nanoid "^3.1.20"
|
||||||
|
source-map "^0.6.1"
|
||||||
|
|
||||||
prelude-ls@^1.2.1:
|
prelude-ls@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
|
||||||
@ -6053,15 +6100,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
|
|||||||
hash-base "^3.0.0"
|
hash-base "^3.0.0"
|
||||||
inherits "^2.0.1"
|
inherits "^2.0.1"
|
||||||
|
|
||||||
rollup-plugin-inject@^3.0.0:
|
|
||||||
version "3.0.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-inject/-/rollup-plugin-inject-3.0.2.tgz#e4233855bfba6c0c12a312fd6649dff9a13ee9f4"
|
|
||||||
integrity sha512-ptg9PQwzs3orn4jkgXJ74bfs5vYz1NCZlSQMBUA0wKcGp5i5pA1AO3fOUEte8enhGUC+iapTCzEWw2jEFFUO/w==
|
|
||||||
dependencies:
|
|
||||||
estree-walker "^0.6.1"
|
|
||||||
magic-string "^0.25.3"
|
|
||||||
rollup-pluginutils "^2.8.1"
|
|
||||||
|
|
||||||
rollup-plugin-node-builtins@^2.1.2:
|
rollup-plugin-node-builtins@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz#24a1fed4a43257b6b64371d8abc6ce1ab14597e9"
|
resolved "https://registry.yarnpkg.com/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz#24a1fed4a43257b6b64371d8abc6ce1ab14597e9"
|
||||||
@ -6084,12 +6122,12 @@ rollup-plugin-node-globals@^1.4.0:
|
|||||||
process-es6 "^0.11.6"
|
process-es6 "^0.11.6"
|
||||||
rollup-pluginutils "^2.3.1"
|
rollup-pluginutils "^2.3.1"
|
||||||
|
|
||||||
rollup-plugin-node-polyfills@^0.2.1:
|
rollup-plugin-polyfill-node@^0.6.2:
|
||||||
version "0.2.1"
|
version "0.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-node-polyfills/-/rollup-plugin-node-polyfills-0.2.1.tgz#53092a2744837164d5b8a28812ba5f3ff61109fd"
|
resolved "https://registry.yarnpkg.com/rollup-plugin-polyfill-node/-/rollup-plugin-polyfill-node-0.6.2.tgz#dea62e00f5cc2c174e4b4654b5daab79b1a92fc3"
|
||||||
integrity sha512-4kCrKPTJ6sK4/gLL/U5QzVT8cxJcofO0OU74tnB19F40cmuAKSzH5/siithxlofFEjwvw1YAhPmbvGNA6jEroA==
|
integrity sha512-gMCVuR0zsKq0jdBn8pSXN1Ejsc458k2QsFFvQdbHoM0Pot5hEnck+pBP/FDwFS6uAi77pD3rDTytsaUStsOMlA==
|
||||||
dependencies:
|
dependencies:
|
||||||
rollup-plugin-inject "^3.0.0"
|
"@rollup/plugin-inject" "^4.0.0"
|
||||||
|
|
||||||
rollup-plugin-terser@^7.0.2:
|
rollup-plugin-terser@^7.0.2:
|
||||||
version "7.0.2"
|
version "7.0.2"
|
||||||
@ -6112,13 +6150,20 @@ rollup-plugin-typescript2@^0.27.2:
|
|||||||
resolve "1.17.0"
|
resolve "1.17.0"
|
||||||
tslib "2.0.1"
|
tslib "2.0.1"
|
||||||
|
|
||||||
rollup-pluginutils@^2.3.1, rollup-pluginutils@^2.8.1:
|
rollup-pluginutils@^2.3.1:
|
||||||
version "2.8.2"
|
version "2.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
|
resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz#72f2af0748b592364dbd3389e600e5a9444a351e"
|
||||||
integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
|
integrity sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
estree-walker "^0.6.1"
|
estree-walker "^0.6.1"
|
||||||
|
|
||||||
|
rollup@^2.38.5:
|
||||||
|
version "2.43.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.43.0.tgz#05d1ed0bbb37080a63e68c530a84d34f61ceb56a"
|
||||||
|
integrity sha512-FRsYGqlo1iF/w3bv319iStAK0hyhhwon35Cbo7sGUoXaOpsZFy6Lel7UoGb5bNDE4OsoWjMH94WiVvpOM26l3g==
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.3.1"
|
||||||
|
|
||||||
rollup@~2.38.5:
|
rollup@~2.38.5:
|
||||||
version "2.38.5"
|
version "2.38.5"
|
||||||
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.38.5.tgz#be41ad4fe0c103a8794377afceb5f22b8f603d6a"
|
resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.38.5.tgz#be41ad4fe0c103a8794377afceb5f22b8f603d6a"
|
||||||
@ -7141,6 +7186,18 @@ verror@1.10.0:
|
|||||||
core-util-is "1.0.2"
|
core-util-is "1.0.2"
|
||||||
extsprintf "^1.2.0"
|
extsprintf "^1.2.0"
|
||||||
|
|
||||||
|
vite@^2.1.3:
|
||||||
|
version "2.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/vite/-/vite-2.1.3.tgz#a31a844d26d3846b5a78f06970d1ea1f8a442955"
|
||||||
|
integrity sha512-bUzArZIUwADVJS/3ywCr4KKFn3a7izs4M87ZDlAlY2V34E4g1kH6p3sVNAh8/IXCn/56fwgMh3rRavPUW7qEQQ==
|
||||||
|
dependencies:
|
||||||
|
esbuild "^0.9.3"
|
||||||
|
postcss "^8.2.1"
|
||||||
|
resolve "^1.19.0"
|
||||||
|
rollup "^2.38.5"
|
||||||
|
optionalDependencies:
|
||||||
|
fsevents "~2.3.1"
|
||||||
|
|
||||||
vlq@^0.2.2:
|
vlq@^0.2.2:
|
||||||
version "0.2.3"
|
version "0.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
|
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.3.tgz#8f3e4328cf63b1540c0d67e1b2778386f8975b26"
|
||||||
|
Loading…
Reference in New Issue
Block a user