workflow: basic template explorer

This commit is contained in:
Evan You
2019-10-04 13:08:06 -04:00
parent 4d2fa51347
commit 5047bc8dbe
12 changed files with 188 additions and 12 deletions

View File

@@ -20,7 +20,7 @@ import { parse } from 'acorn'
import { walk } from 'estree-walker'
import { TransformContext } from './transform'
import { OPEN_BLOCK, CREATE_BLOCK, MERGE_PROPS } from './runtimeConstants'
import { isString } from '@vue/shared'
import { isString, isFunction } from '@vue/shared'
import { PropsExpression } from './transforms/transformElement'
// cache node requires
@@ -29,12 +29,22 @@ import { PropsExpression } from './transforms/transformElement'
let _parse: typeof parse
let _walk: typeof walk
function loadDep(name: string) {
if (typeof process !== 'undefined' && isFunction(require)) {
return require(name)
} else {
// This is only used when we are building a dev-only build of the compiler
// which runs in the browser but also uses Node deps.
return (window as any)._deps[name]
}
}
export const parseJS: typeof parse = (code: string, options: any) => {
assert(
!__BROWSER__,
`Expression AST analysis can only be performed in non-browser builds.`
)
const parse = _parse || (_parse = require('acorn').parse)
const parse = _parse || (_parse = loadDep('acorn').parse)
return parse(code, options)
}
@@ -43,7 +53,7 @@ export const walkJS: typeof walk = (ast, walker) => {
!__BROWSER__,
`Expression AST analysis can only be performed in non-browser builds.`
)
const walk = _walk || (_walk = require('estree-walker').walk)
const walk = _walk || (_walk = loadDep('estree-walker').walk)
return walk(ast, walker)
}

View File

@@ -1,4 +1,5 @@
{
"name": "@vue/shared",
"version": "3.0.0-alpha.1",
"private": true
}

View File

@@ -0,0 +1,8 @@
## Template Explorer
Live explorer for template compilation output.
To run:
- `yarn dev template-explorer`
- Serve project root over a local HTTP server.

View File

@@ -0,0 +1,43 @@
<link rel="stylesheet" data-name="vs/editor/editor.main" href="../../node_modules/monaco-editor/min/vs/editor/editor.main.css">
<style>
body {
margin: 0;
}
.editor {
position: absolute;
top: 0;
bottom: 0;
box-sizing: border-box;
}
#source {
left: 0;
width: 40%;
}
#output {
left: 40%;
width: 60%;
}
</style>
<div id="source" class="editor"></div>
<div id="output" class="editor"></div>
<script src="../../node_modules/acorn/dist/acorn.js"></script>
<script src="../../node_modules/estree-walker/dist/estree-walker.umd.js"></script>
<script src="../../node_modules/monaco-editor/min/vs/loader.js"></script>
<script src="./dist/template-explorer.global.js"></script>
<script>
window._deps = {
acorn,
'estree-walker': estreeWalker
}
require.config({
paths: {
'vs': '../../node_modules/monaco-editor/min/vs'
}
})
</script>
<script>
require(['vs/editor/editor.main'], init /* injected by build */)
</script>

View File

@@ -0,0 +1,15 @@
{
"name": "@vue/template-explorer",
"version": "3.0.0-alpha.1",
"private": true,
"buildOptions": {
"formats": [
"global"
],
"env": "development",
"enableNonBrowserBranches": true
},
"dependencies": {
"monaco-editor": "^0.18.1"
}
}

View File

@@ -0,0 +1,83 @@
import * as m from 'monaco-editor'
import { compile } from '@vue/compiler-dom'
const self = window as any
self.init = () => {
const monaco = (window as any).monaco as typeof m
const persistedContent =
decodeURIComponent(window.location.hash.slice(1)) ||
`<div>{{ foo + bar }}</div>`
self.compilerOptions = {
mode: 'module',
prefixIdentifiers: true,
hoistStatic: true
}
function compileCode(source: string): string {
console.clear()
try {
const { code, ast } = compile(source, self.compilerOptions)
console.log(ast)
return code
} catch (e) {
console.error(e)
return `/* See console for error */`
}
}
const sharedOptions = {
theme: 'vs-dark',
fontSize: 14,
wordWrap: 'on',
scrollBeyondLastLine: false,
minimap: {
enabled: false
}
} as const
const editor = monaco.editor.create(
document.getElementById('source') as HTMLElement,
{
value: persistedContent,
language: 'html',
...sharedOptions
}
)
const model = editor.getModel()!
model.updateOptions({
tabSize: 2
})
model.onDidChangeContent(() => {
const src = editor.getValue()
window.location.hash = encodeURIComponent(src)
const res = compileCode(src)
if (res) {
output.setValue(res)
}
})
const output = monaco.editor.create(
document.getElementById('output') as HTMLElement,
{
value: compileCode(persistedContent),
language: 'javascript',
readOnly: true,
...sharedOptions
}
)
output.getModel()!.updateOptions({
tabSize: 2
})
window.addEventListener('resize', () => {
editor.layout()
output.layout()
})
}