workflow: basic template explorer
This commit is contained in:
parent
4d2fa51347
commit
5047bc8dbe
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@vue/shared",
|
"name": "@vue/shared",
|
||||||
|
"version": "3.0.0-alpha.1",
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
8
packages/template-explorer/README.md
Normal file
8
packages/template-explorer/README.md
Normal 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.
|
43
packages/template-explorer/index.html
Normal file
43
packages/template-explorer/index.html
Normal 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>
|
15
packages/template-explorer/package.json
Normal file
15
packages/template-explorer/package.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
83
packages/template-explorer/src/index.ts
Normal file
83
packages/template-explorer/src/index.ts
Normal 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()
|
||||||
|
})
|
||||||
|
}
|
@ -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
13
scripts/bootstrap.js
vendored
@ -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,
|
||||||
|
@ -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` : ``) +
|
||||||
|
@ -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!`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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": [
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user