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 { walk } from 'estree-walker'
import { TransformContext } from './transform' import { TransformContext } from './transform'
import { OPEN_BLOCK, CREATE_BLOCK, MERGE_PROPS } from './runtimeConstants' 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' import { PropsExpression } from './transforms/transformElement'
// cache node requires // cache node requires
@ -29,12 +29,22 @@ import { PropsExpression } from './transforms/transformElement'
let _parse: typeof parse let _parse: typeof parse
let _walk: typeof walk 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) => { export const parseJS: typeof parse = (code: string, options: any) => {
assert( assert(
!__BROWSER__, !__BROWSER__,
`Expression AST analysis can only be performed in non-browser builds.` `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) return parse(code, options)
} }
@ -43,7 +53,7 @@ export const walkJS: typeof walk = (ast, walker) => {
!__BROWSER__, !__BROWSER__,
`Expression AST analysis can only be performed in non-browser builds.` `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) return walk(ast, walker)
} }

View File

@ -1,4 +1,5 @@
{ {
"name": "@vue/shared", "name": "@vue/shared",
"version": "3.0.0-alpha.1",
"private": true "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()
})
}

View File

@ -119,7 +119,8 @@ function createConfig(output, plugins = []) {
createReplacePlugin( createReplacePlugin(
isProductionBuild, isProductionBuild,
isBunlderESMBuild, isBunlderESMBuild,
isGlobalBuild || isBrowserESMBuild (isGlobalBuild || isBrowserESMBuild) &&
!packageOptions.enableNonBrowserBranches
), ),
...plugins ...plugins
], ],

13
scripts/bootstrap.js vendored
View File

@ -9,16 +9,21 @@ const packagesDir = path.resolve(__dirname, '../packages')
const files = fs.readdirSync(packagesDir) const files = fs.readdirSync(packagesDir)
files.forEach(shortName => { files.forEach(shortName => {
if (shortName === 'shared') {
return
}
if (!fs.statSync(path.join(packagesDir, shortName)).isDirectory()) { if (!fs.statSync(path.join(packagesDir, shortName)).isDirectory()) {
return return
} }
const name = shortName === `vue` ? shortName : `@vue/${shortName}` const name = shortName === `vue` ? shortName : `@vue/${shortName}`
const pkgPath = path.join(packagesDir, shortName, `package.json`) const pkgPath = path.join(packagesDir, shortName, `package.json`)
if (args.force || !fs.existsSync(pkgPath)) { const pkgExists = fs.existsSync(pkgPath)
if (pkgExists) {
const pkg = require(pkgPath)
if (pkg.private) {
return
}
}
if (args.force || !pkgExists) {
const json = { const json = {
name, name,
version: baseVersion, version: baseVersion,

View File

@ -51,12 +51,16 @@ async function build(target) {
await fs.remove(`${pkgDir}/dist`) await fs.remove(`${pkgDir}/dist`)
const env =
(pkg.buildOptions && pkg.buildOptions.env) ||
(devOnly ? 'development' : 'production')
await execa( await execa(
'rollup', 'rollup',
[ [
'-c', '-c',
'--environment', '--environment',
`NODE_ENV:${devOnly ? 'development' : 'production'},` + `NODE_ENV:${env},` +
`TARGET:${target}` + `TARGET:${target}` +
(formats ? `,FORMATS:${formats}` : ``) + (formats ? `,FORMATS:${formats}` : ``) +
(args.types ? `,TYPES:true` : ``) + (args.types ? `,TYPES:true` : ``) +

View File

@ -5,7 +5,7 @@ const targets = (exports.targets = fs.readdirSync('packages').filter(f => {
return false return false
} }
const pkg = require(`../packages/${f}/package.json`) const pkg = require(`../packages/${f}/package.json`)
if (pkg.private) { if (pkg.private && !pkg.buildOptions) {
return false return false
} }
return true return true
@ -26,6 +26,6 @@ exports.fuzzyMatchTarget = (partialTargets, includeAllMatching) => {
if (matched.length) { if (matched.length) {
return matched return matched
} else { } else {
throw new Error(`Target ${partialTarget} not found!`) throw new Error(`Target ${partialTargets} not found!`)
} }
} }

View File

@ -27,7 +27,8 @@
"@vue/reactivity": ["packages/reactivity/src"], "@vue/reactivity": ["packages/reactivity/src"],
"@vue/compiler-core": ["packages/compiler-core/src"], "@vue/compiler-core": ["packages/compiler-core/src"],
"@vue/compiler-dom": ["packages/compiler-dom/src"], "@vue/compiler-dom": ["packages/compiler-dom/src"],
"@vue/server-renderer": ["packages/server-renderer/src"] "@vue/server-renderer": ["packages/server-renderer/src"],
"@vue/template-explorer": ["packages/template-explorer/src"]
} }
}, },
"include": [ "include": [

View File

@ -4932,6 +4932,11 @@ modify-values@^1.0.0:
resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
monaco-editor@^0.18.1:
version "0.18.1"
resolved "https://registry.yarnpkg.com/monaco-editor/-/monaco-editor-0.18.1.tgz#ced7c305a23109875feeaf395a504b91f6358cfc"
integrity sha512-fmL+RFZ2Hrezy+X/5ZczQW51LUmvzfcqOurnkCIRFTyjdVjzR7JvENzI6+VKBJzJdPh6EYL4RoWl92b2Hrk9fw==
move-concurrently@^1.0.1: move-concurrently@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"