diff --git a/src/compiler/codegen.js b/src/compiler/codegen.js new file mode 100644 index 0000000..0fd9ee0 --- /dev/null +++ b/src/compiler/codegen.js @@ -0,0 +1,5 @@ +export function generate(ast) { + return ` + console.log('hello world') + ` +} diff --git a/src/compiler/compile.js b/src/compiler/compile.js new file mode 100644 index 0000000..587b164 --- /dev/null +++ b/src/compiler/compile.js @@ -0,0 +1,7 @@ +import { generate } from './codegen' +import { baseParse } from './parse' + +export function compile(template) { + const ast = baseParse(template) + return generate(ast) +} diff --git a/src/examples/commits.html b/src/examples/commits.html new file mode 100644 index 0000000..2f597e8 --- /dev/null +++ b/src/examples/commits.html @@ -0,0 +1,88 @@ + + +
+

Latest MiniVue.js Commits

+ + + + +

leaon4/mini-vue3@{{ currentBranch.value }}

+ +
+ + + + diff --git a/src/examples/grid.html b/src/examples/grid.html new file mode 100644 index 0000000..4e79939 --- /dev/null +++ b/src/examples/grid.html @@ -0,0 +1,188 @@ + + + + + + + + +
+ + + +
+ + + + diff --git a/src/examples/index.html b/src/examples/index.html new file mode 100644 index 0000000..3460609 --- /dev/null +++ b/src/examples/index.html @@ -0,0 +1,22 @@ + + + + + + + Expamels + + + +

Expamels

+ + + diff --git a/src/examples/markdown.html b/src/examples/markdown.html new file mode 100644 index 0000000..770efc5 --- /dev/null +++ b/src/examples/markdown.html @@ -0,0 +1,71 @@ + + + + +
+ +
+
+ + + + diff --git a/src/examples/package-lock.json b/src/examples/package-lock.json new file mode 100644 index 0000000..0e19ce0 --- /dev/null +++ b/src/examples/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "examples", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.nlark.com/lodash/download/lodash-4.17.21.tgz?cache=0&sync_timestamp=1618910518249&other_urls=https%3A%2F%2Fregistry.nlark.com%2Flodash%2Fdownload%2Flodash-4.17.21.tgz", + "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw=" + }, + "marked": { + "version": "2.1.3", + "resolved": "https://registry.nlark.com/marked/download/marked-2.1.3.tgz", + "integrity": "sha1-vQF872Qxck/Usn4GV/XOsUv/N1M=" + }, + "monaco-editor": { + "version": "0.26.1", + "resolved": "https://registry.nlark.com/monaco-editor/download/monaco-editor-0.26.1.tgz", + "integrity": "sha1-YrtfZYvJU3n4q7ZLFHYyvRwBnXM=" + }, + "prettier": { + "version": "2.3.2", + "resolved": "https://registry.nlark.com/prettier/download/prettier-2.3.2.tgz?cache=0&sync_timestamp=1624696479455&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fprettier%2Fdownload%2Fprettier-2.3.2.tgz", + "integrity": "sha1-7ygKBewlNxLkhiM9tcbyNEHnNC0=" + } + } +} diff --git a/src/examples/package.json b/src/examples/package.json new file mode 100644 index 0000000..9f09cb0 --- /dev/null +++ b/src/examples/package.json @@ -0,0 +1,16 @@ +{ + "name": "examples", + "version": "1.0.0", + "description": "", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "lodash": "^4.17.21", + "marked": "^2.1.3", + "monaco-editor": "^0.26.1", + "prettier": "^2.3.2" + } +} diff --git a/src/examples/template-explorer/index.html b/src/examples/template-explorer/index.html new file mode 100644 index 0000000..902f59e --- /dev/null +++ b/src/examples/template-explorer/index.html @@ -0,0 +1,46 @@ + + + + + + + Mini-Vue3 Template Explorer + + + + + + +
+
+ + + + + + + + + + diff --git a/src/examples/template-explorer/index.js b/src/examples/template-explorer/index.js new file mode 100644 index 0000000..d1f55b3 --- /dev/null +++ b/src/examples/template-explorer/index.js @@ -0,0 +1,208 @@ +// eslint-disable-next-line no-undef +const { effect, compile } = MiniVue; + +const sharedEditorOptions = { + fontSize: 14, + scrollBeyondLastLine: false, + renderWhitespace: 'selection', + minimap: { + enabled: false, + }, +}; + +window.init = () => { + const monaco = window.monaco; + + // eslint-disable-next-line no-undef + monaco.editor.defineTheme('my-theme', theme); + monaco.editor.setTheme('my-theme'); + + const persistedState = JSON.parse( + decodeURIComponent(window.location.hash.slice(1)) || + localStorage.getItem('state') || + `{}` + ); + + let lastSuccessfulCode; + let lastSuccessfulMap; + function compileCode(source) { + console.clear(); + try { + const errors = []; + const compileFn = (source) => { + // eslint-disable-next-line no-undef + return format(compile(source)); + }; + const start = performance.now(); + const code = compileFn(source); + console.log(`Compiled in ${(performance.now() - start).toFixed(2)}ms.`); + monaco.editor.setModelMarkers( + editor.getModel(), + `@vue/compiler-dom`, + errors.filter((e) => e.loc).map(formatError) + ); + lastSuccessfulCode = code; + } catch (e) { + lastSuccessfulCode = `/* ERROR: ${e.message} (see console for more info) */`; + console.error(e); + } + return lastSuccessfulCode; + } + + function formatError(err) { + return { + message: `Vue template compilation error: ${err.message}`, + code: String(err.code), + }; + } + + function reCompile() { + const src = editor.getValue(); + // every time we re-compile, persist current state + const state = JSON.stringify({ + src, + }); + localStorage.setItem('state', state); + window.location.hash = encodeURIComponent(state); + const res = compileCode(src); + if (res) { + output.setValue(res); + output.trigger('editor', 'editor.action.formatDocument'); + } + } + + const editor = monaco.editor.create(document.getElementById('source'), { + value: persistedState.src || `
Hello World!
`, + language: 'html', + ...sharedEditorOptions, + wordWrap: 'bounded', + }); + + editor.getModel().updateOptions({ + tabSize: 2, + }); + + const output = (window.output = monaco.editor.create( + document.getElementById('output'), + { + value: '', + language: 'javascript', + // readOnly: true, + ...sharedEditorOptions, + } + )); + output.getModel().updateOptions({ + tabSize: 2, + }); + + // handle resize + window.addEventListener('resize', () => { + editor.layout(); + output.layout(); + }); + + // update compile output when input changes + editor.onDidChangeModelContent(debounce(reCompile)); + + // highlight output code + let prevOutputDecos = []; + function clearOutputDecos() { + prevOutputDecos = output.deltaDecorations(prevOutputDecos, []); + } + + editor.onDidChangeCursorPosition( + debounce((e) => { + clearEditorDecos(); + if (lastSuccessfulMap) { + const pos = lastSuccessfulMap.generatedPositionFor({ + source: 'ExampleTemplate.vue', + line: e.position.lineNumber, + column: e.position.column - 1, + }); + if (pos.line != null && pos.column != null) { + prevOutputDecos = output.deltaDecorations(prevOutputDecos, [ + { + range: new monaco.Range( + pos.line, + pos.column + 1, + pos.line, + pos.lastColumn ? pos.lastColumn + 2 : pos.column + 2 + ), + options: { + inlineClassName: `highlight`, + }, + }, + ]); + output.revealPositionInCenter({ + lineNumber: pos.line, + column: pos.column + 1, + }); + } else { + clearOutputDecos(); + } + } + }, 100) + ); + + let previousEditorDecos = []; + function clearEditorDecos() { + previousEditorDecos = editor.deltaDecorations(previousEditorDecos, []); + } + + output.onDidChangeCursorPosition( + debounce((e) => { + clearOutputDecos(); + if (lastSuccessfulMap) { + const pos = lastSuccessfulMap.originalPositionFor({ + line: e.position.lineNumber, + column: e.position.column - 1, + }); + if ( + pos.line != null && + pos.column != null && + !( + // ignore mock location + (pos.line === 1 && pos.column === 0) + ) + ) { + const translatedPos = { + column: pos.column + 1, + lineNumber: pos.line, + }; + previousEditorDecos = editor.deltaDecorations(previousEditorDecos, [ + { + range: new monaco.Range( + pos.line, + pos.column + 1, + pos.line, + pos.column + 1 + ), + options: { + isWholeLine: true, + className: `highlight`, + }, + }, + ]); + editor.revealPositionInCenter(translatedPos); + } else { + clearEditorDecos(); + } + } + }, 100) + ); + + effect(reCompile); +}; + +function debounce(fn, delay = 300) { + let prevTimer = null; + return (...args) => { + if (prevTimer) { + clearTimeout(prevTimer); + } + prevTimer = window.setTimeout(() => { + fn(...args); + prevTimer = null; + }, delay); + }; +} diff --git a/src/examples/template-explorer/style.css b/src/examples/template-explorer/style.css new file mode 100644 index 0000000..888c135 --- /dev/null +++ b/src/examples/template-explorer/style.css @@ -0,0 +1,95 @@ +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, + Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; + --bg: #1d1f21; + --border: #333; +} + +#header { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 60px; + box-sizing: border-box; + background-color: var(--bg); + border-bottom: 1px solid var(--border); + padding: 0.3em 1.6em; + color: #fff; + z-index: 1; +} + +h1 { + font-size: 18px; + display: inline-block; + margin-right: 15px; +} + +#options-wrapper { + position: absolute; + top: 20px; + right: 10px; +} + +#options-wrapper:hover #options { + display: block; +} + +#options-label { + cursor: pointer; + text-align: right; + padding-right: 10px; + font-weight: bold; +} + +#options { + display: none; + margin-top: 15px; + list-style-type: none; + background-color: var(--bg); + border: 1px solid var(--border); + padding: 15px 30px; +} + +#options li { + margin: 8px 0; +} + +#header a { + font-weight: 600; + color: rgb(101, 163, 221); +} + +#header .label { + font-weight: bold; +} + +#header input { + margin-right: 6px; +} + +#header label { + color: #999; +} + +.editor { + position: absolute; + top: 60px; + bottom: 0; + box-sizing: border-box; +} + +#source { + left: 0; + width: 45%; +} + +#output { + left: 45%; + width: 55%; +} + +.highlight { + background-color: rgba(46, 120, 190, 0.5); +} diff --git a/src/examples/template-explorer/theme.js b/src/examples/template-explorer/theme.js new file mode 100644 index 0000000..2123d85 --- /dev/null +++ b/src/examples/template-explorer/theme.js @@ -0,0 +1,244 @@ +window.theme = { + base: 'vs-dark', + inherit: true, + rules: [ + { + foreground: 'de935f', + token: 'number', + }, + { + foreground: '969896', + token: 'comment', + }, + { + foreground: 'ced1cf', + token: 'keyword.operator.class', + }, + { + foreground: 'ced1cf', + token: 'constant.other', + }, + { + foreground: 'ced1cf', + token: 'source.php.embedded.line', + }, + { + foreground: 'cc6666', + token: 'variable', + }, + { + foreground: 'cc6666', + token: 'support.other.variable', + }, + { + foreground: 'cc6666', + token: 'string.other.link', + }, + { + foreground: 'cc6666', + token: 'string.regexp', + }, + { + foreground: 'cc6666', + token: 'entity.name.tag', + }, + { + foreground: 'cc6666', + token: 'entity.other.attribute-name', + }, + { + foreground: 'cc6666', + token: 'meta.tag', + }, + { + foreground: 'cc6666', + token: 'declaration.tag', + }, + { + foreground: 'cc6666', + token: 'markup.deleted.git_gutter', + }, + { + foreground: 'de935f', + token: 'constant.numeric', + }, + { + foreground: 'de935f', + token: 'constant.language', + }, + { + foreground: 'de935f', + token: 'support.constant', + }, + { + foreground: 'de935f', + token: 'constant.character', + }, + { + foreground: 'de935f', + token: 'variable.parameter', + }, + { + foreground: 'de935f', + token: 'punctuation.section.embedded', + }, + { + foreground: 'de935f', + token: 'keyword.other.unit', + }, + { + foreground: 'f0c674', + token: 'entity.name.class', + }, + { + foreground: 'f0c674', + token: 'entity.name.type.class', + }, + { + foreground: 'f0c674', + token: 'support.type', + }, + { + foreground: 'f0c674', + token: 'support.class', + }, + { + foreground: 'b5bd68', + token: 'string', + }, + { + foreground: 'b5bd68', + token: 'constant.other.symbol', + }, + { + foreground: 'b5bd68', + token: 'entity.other.inherited-class', + }, + { + foreground: 'b5bd68', + token: 'markup.heading', + }, + { + foreground: 'b5bd68', + token: 'markup.inserted.git_gutter', + }, + { + foreground: '8abeb7', + token: 'keyword.operator', + }, + { + foreground: '8abeb7', + token: 'constant.other.color', + }, + { + foreground: '81a2be', + token: 'entity.name.function', + }, + { + foreground: '81a2be', + token: 'meta.function-call', + }, + { + foreground: '81a2be', + token: 'support.function', + }, + { + foreground: '81a2be', + token: 'keyword.other.special-method', + }, + { + foreground: '81a2be', + token: 'meta.block-level', + }, + { + foreground: '81a2be', + token: 'markup.changed.git_gutter', + }, + { + foreground: 'b294bb', + token: 'keyword', + }, + { + foreground: 'b294bb', + token: 'storage', + }, + { + foreground: 'b294bb', + token: 'storage.type', + }, + { + foreground: 'b294bb', + token: 'entity.name.tag.css', + }, + { + foreground: 'ced2cf', + background: 'df5f5f', + token: 'invalid', + }, + { + foreground: 'ced2cf', + background: '82a3bf', + token: 'meta.separator', + }, + { + foreground: 'ced2cf', + background: 'b798bf', + token: 'invalid.deprecated', + }, + { + foreground: 'ffffff', + token: 'markup.inserted.diff', + }, + { + foreground: 'ffffff', + token: 'markup.deleted.diff', + }, + { + foreground: 'ffffff', + token: 'meta.diff.header.to-file', + }, + { + foreground: 'ffffff', + token: 'meta.diff.header.from-file', + }, + { + foreground: '718c00', + token: 'markup.inserted.diff', + }, + { + foreground: '718c00', + token: 'meta.diff.header.to-file', + }, + { + foreground: 'c82829', + token: 'markup.deleted.diff', + }, + { + foreground: 'c82829', + token: 'meta.diff.header.from-file', + }, + { + foreground: 'ffffff', + background: '4271ae', + token: 'meta.diff.header.from-file', + }, + { + foreground: 'ffffff', + background: '4271ae', + token: 'meta.diff.header.to-file', + }, + { + foreground: '3e999f', + fontStyle: 'italic', + token: 'meta.diff.range', + }, + ], + colors: { + 'editor.foreground': '#C5C8C6', + 'editor.background': '#1D1F21', + 'editor.selectionBackground': '#373B41', + 'editor.lineHighlightBackground': '#282A2E', + 'editorCursor.foreground': '#AEAFAD', + 'editorWhitespace.foreground': '#4B4E55', + }, +}; diff --git a/src/examples/todomvc.css b/src/examples/todomvc.css new file mode 100644 index 0000000..d2442c2 --- /dev/null +++ b/src/examples/todomvc.css @@ -0,0 +1,377 @@ +html, +body { + margin: 0; + padding: 0; +} + +button { + margin: 0; + padding: 0; + border: 0; + background: none; + font-size: 100%; + vertical-align: baseline; + font-family: inherit; + font-weight: inherit; + color: inherit; + -webkit-appearance: none; + appearance: none; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +body { + font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif; + line-height: 1.4em; + background: #f5f5f5; + color: #111111; + min-width: 230px; + max-width: 550px; + margin: 0 auto; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + font-weight: 300; +} + +:focus { + outline: 0; +} + +.hidden { + display: none; +} + +.todoapp { + background: #fff; + margin: 130px 0 40px 0; + position: relative; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1); +} + +.todoapp input::-webkit-input-placeholder { + font-style: italic; + font-weight: 300; + color: rgba(0, 0, 0, 0.4); +} + +.todoapp input::-moz-placeholder { + font-style: italic; + font-weight: 300; + color: rgba(0, 0, 0, 0.4); +} + +.todoapp input::input-placeholder { + font-style: italic; + font-weight: 300; + color: rgba(0, 0, 0, 0.4); +} + +.todoapp h1 { + position: absolute; + top: -140px; + width: 100%; + font-size: 80px; + font-weight: 200; + text-align: center; + color: #b83f45; + -webkit-text-rendering: optimizeLegibility; + -moz-text-rendering: optimizeLegibility; + text-rendering: optimizeLegibility; +} + +.new-todo, +.edit { + position: relative; + margin: 0; + width: 100%; + font-size: 24px; + font-family: inherit; + font-weight: inherit; + line-height: 1.4em; + color: inherit; + padding: 6px; + border: 1px solid #999; + box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2); + box-sizing: border-box; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.new-todo { + padding: 16px 16px 16px 60px; + border: none; + background: rgba(0, 0, 0, 0.003); + box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03); +} + +.main { + position: relative; + z-index: 2; + border-top: 1px solid #e6e6e6; +} + +.toggle-all { + width: 1px; + height: 1px; + border: none; /* Mobile Safari */ + opacity: 0; + position: absolute; + right: 100%; + bottom: 100%; +} + +.toggle-all + label { + width: 60px; + height: 34px; + font-size: 0; + position: absolute; + top: -52px; + left: -13px; + -webkit-transform: rotate(90deg); + transform: rotate(90deg); +} + +.toggle-all + label:before { + content: '❯'; + font-size: 22px; + color: #e6e6e6; + padding: 10px 27px 10px 27px; +} + +.toggle-all:checked + label:before { + color: #737373; +} + +.todo-list { + margin: 0; + padding: 0; + list-style: none; +} + +.todo-list li { + position: relative; + font-size: 24px; + border-bottom: 1px solid #ededed; +} + +.todo-list li:last-child { + border-bottom: none; +} + +.todo-list li.editing { + border-bottom: none; + padding: 0; +} + +.todo-list li.editing .edit { + display: block; + width: calc(100% - 43px); + padding: 12px 16px; + margin: 0 0 0 43px; +} + +.todo-list li.editing .view { + display: none; +} + +.todo-list li .toggle { + text-align: center; + width: 40px; + /* auto, since non-WebKit browsers doesn't support input styling */ + height: auto; + position: absolute; + top: 0; + bottom: 0; + margin: auto 0; + border: none; /* Mobile Safari */ + -webkit-appearance: none; + appearance: none; +} + +.todo-list li .toggle { + opacity: 0; +} + +.todo-list li .toggle + label { + /* + Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433 + IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/ + */ + background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E'); + background-repeat: no-repeat; + background-position: center left; +} + +.todo-list li .toggle:checked + label { + background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E'); +} + +.todo-list li label { + word-break: break-all; + padding: 15px 15px 15px 60px; + display: block; + line-height: 1.2; + transition: color 0.4s; + font-weight: 400; + color: #4d4d4d; +} + +.todo-list li.completed label { + color: #cdcdcd; + text-decoration: line-through; +} + +.todo-list li .destroy { + display: none; + position: absolute; + top: 0; + right: 10px; + bottom: 0; + width: 40px; + height: 40px; + margin: auto 0; + font-size: 30px; + color: #cc9a9a; + margin-bottom: 11px; + transition: color 0.2s ease-out; +} + +.todo-list li .destroy:hover { + color: #af5b5e; +} + +.todo-list li .destroy:after { + content: '×'; +} + +.todo-list li:hover .destroy { + display: block; +} + +.todo-list li .edit { + display: none; +} + +.todo-list li.editing:last-child { + margin-bottom: -1px; +} + +.footer { + padding: 10px 15px; + height: 20px; + text-align: center; + font-size: 15px; + border-top: 1px solid #e6e6e6; +} + +.footer:before { + content: ''; + position: absolute; + right: 0; + bottom: 0; + left: 0; + height: 50px; + overflow: hidden; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, + 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, + 0 17px 2px -6px rgba(0, 0, 0, 0.2); +} + +.todo-count { + float: left; + text-align: left; +} + +.todo-count strong { + font-weight: 300; +} + +.filters { + margin: 0; + padding: 0; + list-style: none; + position: absolute; + right: 0; + left: 0; +} + +.filters li { + display: inline; +} + +.filters li a { + color: inherit; + margin: 3px; + padding: 3px 7px; + text-decoration: none; + border: 1px solid transparent; + border-radius: 3px; +} + +.filters li a:hover { + border-color: rgba(175, 47, 47, 0.1); +} + +.filters li a.selected { + border-color: rgba(175, 47, 47, 0.2); +} + +.clear-completed, +html .clear-completed:active { + float: right; + position: relative; + line-height: 20px; + text-decoration: none; + cursor: pointer; +} + +.clear-completed:hover { + text-decoration: underline; +} + +.info { + margin: 65px auto 0; + color: #4d4d4d; + font-size: 11px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); + text-align: center; +} + +.info p { + line-height: 1; +} + +.info a { + color: inherit; + text-decoration: none; + font-weight: 400; +} + +.info a:hover { + text-decoration: underline; +} + +/* + Hack to remove background from Mobile Safari. + Can't use it globally since it destroys checkboxes in Firefox +*/ +@media screen and (-webkit-min-device-pixel-ratio: 0) { + .toggle-all, + .todo-list li .toggle { + background: none; + } + + .todo-list li .toggle { + height: 40px; + } +} + +@media (max-width: 430px) { + .footer { + height: 50px; + } + + .filters { + bottom: 10px; + } +} diff --git a/src/examples/todomvc.html b/src/examples/todomvc.html new file mode 100644 index 0000000..568eced --- /dev/null +++ b/src/examples/todomvc.html @@ -0,0 +1,247 @@ + + + +
+
+
+

todos

+ +
+
+ + +
    +
  • +
    + + + +
    + +
  • +
+
+ +
+
+ + diff --git a/src/examples/tree.html b/src/examples/tree.html new file mode 100644 index 0000000..75ecfb9 --- /dev/null +++ b/src/examples/tree.html @@ -0,0 +1,149 @@ + + + + + + + +

(You can double click on an item to turn it into a folder.)

+ + + + + + + diff --git a/src/examples/vModel.html b/src/examples/vModel.html new file mode 100644 index 0000000..49a70eb --- /dev/null +++ b/src/examples/vModel.html @@ -0,0 +1,83 @@ + + + + + + + Document + + + + +
+
{{model.text}}
+ +
+
{{model.radio}}
+ + +
+
{{model.checkbox.toString()}}
+ + + +
+
{{model.singleCheckbox.toString()}}
+ +
+
+ + + diff --git a/src/examples/yarn.lock b/src/examples/yarn.lock new file mode 100644 index 0000000..a3d1256 --- /dev/null +++ b/src/examples/yarn.lock @@ -0,0 +1,23 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +lodash@^4.17.21: + version "4.17.21" + resolved "https://registry.npmmirror.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +marked@^2.1.3: + version "2.1.3" + resolved "https://registry.npmmirror.com/marked/-/marked-2.1.3.tgz#bd017cef6431724fd4b27e0657f5ceb14bff3753" + integrity sha512-/Q+7MGzaETqifOMWYEA7HVMaZb4XbcRfaOzcSsHZEith83KGlvaSG33u0SKu89Mj5h+T8V2hM+8O45Qc5XTgwA== + +monaco-editor@^0.26.1: + version "0.26.1" + resolved "https://registry.npmmirror.com/monaco-editor/-/monaco-editor-0.26.1.tgz#62bb5f658bc95379f8abb64b147632bd1c019d73" + integrity sha512-mm45nUrBDk0DgZKgbD7+bhDOtcAFNGPJJRAdS6Su1kTGl6XEgC7U3xOmDUW/0RrLf+jlvCGaqLvD4p2VjwuwwQ== + +prettier@^2.3.2: + version "2.8.4" + resolved "https://registry.npmmirror.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" + integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== diff --git a/src/index.js b/src/index.js index 8532906..b4ffa21 100644 --- a/src/index.js +++ b/src/index.js @@ -1,27 +1,18 @@ +import { compile } from './compiler/compile' +import { createApp, render, h, Text, Fragment, nextTick } from './runtime' import { reactive, ref, computed, effect } from './reactivity' -import { h, Text, Fragment } from './runtime/vnode' -import { createApp } from './runtime/createApp' -const root = document.createElement('div') +export const MiniVue = (window.MiniVue = { + createApp, + render, + h, + Text, + Fragment, -const Comp = { - setup() { - const counter = ref(0) - const add = () => { - counter.value++ - } - return { - counter, - add - } - }, - render(ctx) { - return [ - h('div', null, ctx.counter.value), - h('button', { onClick: ctx.add }, 'add') - ] - } -} - -createApp(Comp).mount(root) -document.body.appendChild(root) + nextTick, + reactive, + ref, + computed, + effect, + compile +}) diff --git a/src/runtime/index.js b/src/runtime/index.js new file mode 100644 index 0000000..91d0eb1 --- /dev/null +++ b/src/runtime/index.js @@ -0,0 +1,4 @@ +export { h, Text, Fragment } from './vnode' +export { render } from './render' +export { createApp, resolveComponent } from './createApp' +export { nextTick } from './scheduler' diff --git a/webpack.config.js b/webpack.config.js index 728ead7..27361ba 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,4 @@ const path = require('path') -const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { mode: 'development', @@ -11,15 +10,10 @@ module.exports = { path: path.resolve(__dirname, 'dist'), clean: true }, - plugins: [ - // 自动生成html文件,并且引用bundle的文件 - new HtmlWebpackPlugin({ - title: 'mini-vue3' - }) - ], + devServer: { - // 设置内容的根路径,使用该目录中真实存在的静态资源,而不是虚拟资源 - contentBase: './dist', + contentBase: './src/examples', + publicPath: '/dist', watchContentBase: true } }