-
Notifications
You must be signed in to change notification settings - Fork 400
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* chore: update * chore: basic work * chore: tweak * fix: dead loop * feat: auto focus and rename to newly added module * chore: tweak style * chore: fmt
- Loading branch information
Showing
13 changed files
with
764 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
<script setup lang="ts"> | ||
import { ref, onMounted, Ref } from 'vue' | ||
import ModuleBlock from './components/ModuleBlock.vue' | ||
import init, { bundle } from '../../wasm' | ||
import { | ||
convertAssetListToModuleList, | ||
normalizeModules, | ||
uniqueModulePath, | ||
} from './utils/index' | ||
import type { ModuleInfo } from './utils/index' | ||
const moduleList: Ref<ModuleInfo[]> = ref([ | ||
{ title: 'index.js', code: `console.log("hello world")` }, | ||
]) | ||
const outputs: Ref<ModuleInfo[]> = ref([]) | ||
const wasmLoadFinished = ref(false) | ||
onMounted(() => { | ||
init().then((_) => { | ||
wasmLoadFinished.value = true | ||
}) | ||
}) | ||
const handleBuild = () => { | ||
const fileList = normalizeModules(moduleList.value) | ||
let res = bundle(fileList) | ||
outputs.value = convertAssetListToModuleList(res) | ||
} | ||
const handleAddModule = () => { | ||
const title = uniqueModulePath(moduleList.value) | ||
moduleList.value.push({ | ||
title, | ||
code: `console.log("hello world")`, | ||
autofocus: true, | ||
}) | ||
} | ||
</script> | ||
|
||
<template> | ||
<div class="container"> | ||
<!-- module declaration block --> | ||
<div class="module-list column"> | ||
<ModuleBlock | ||
v-for="item in moduleList" | ||
:code="item.code" | ||
:title="item.title" | ||
@code="item.code = $event" | ||
@title="item.title = $event.target.innerText" | ||
:auto-focus="item.autofocus" | ||
/> | ||
<button @click="handleAddModule">Add module</button> | ||
</div> | ||
<!-- output block --> | ||
<div class="output column"> | ||
<button @click="handleBuild" :disabled="!wasmLoadFinished">build</button> | ||
<ModuleBlock | ||
v-for="item in outputs" | ||
:code="item.code" | ||
:title="item.title" | ||
@code="item.code = $event" | ||
@title="item.title = $event.target.innerText" | ||
/> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<style scoped> | ||
.container { | ||
display: flex; | ||
} | ||
.column { | ||
flex: 1; | ||
padding: 0 10px; | ||
} | ||
.module-list { | ||
margin-top: 40px; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
<script setup lang="ts"> | ||
import { ShallowRef, defineComponent, ref, shallowRef } from 'vue' | ||
import { Codemirror } from 'vue-codemirror' | ||
import { javascript } from '@codemirror/lang-javascript' | ||
import { oneDark } from '@codemirror/theme-one-dark' | ||
import { EditorState } from '@codemirror/state' | ||
import { EditorView } from '@codemirror/view' | ||
type Payload = { | ||
state: EditorState | ||
view: EditorView | ||
container: HTMLElement | ||
} | ||
defineProps({ | ||
code: String, | ||
}) | ||
const emit = defineEmits(['code']) | ||
const extensions = [javascript(), oneDark] | ||
// Codemirror EditorView instance ref | ||
const view = <ShallowRef<EditorView>>shallowRef() | ||
const handleReady = (payload: Payload) => { | ||
view.value = payload.view | ||
} | ||
// Status is available at all times via Codemirror EditorView | ||
// const getCodemirrorStates = () => { | ||
// const state = view.value.state | ||
// const ranges = state.selection.ranges | ||
// const selected = ranges.reduce((r, range) => r + range.to - range.from, 0) | ||
// const cursor = ranges[0].anchor | ||
// const length = state.doc.length | ||
// const lines = state.doc.lines | ||
// return { | ||
// state, | ||
// ranges, | ||
// selected, | ||
// cursor, | ||
// length, | ||
// lines | ||
// } | ||
// } | ||
const handleCodeChange = (e: string) => { | ||
emit('code', e) | ||
} | ||
const log = console.log | ||
</script> | ||
<template> | ||
<codemirror | ||
:model-value="code" | ||
placeholder="Code goes here..." | ||
:style="{ height: '400px' }" | ||
:autofocus="false" | ||
:indent-with-tab="true" | ||
:tab-size="2" | ||
:extensions="extensions" | ||
@ready="handleReady" | ||
@change="handleCodeChange" | ||
@focus="log('focus', $event)" | ||
@blur="console.log('blur', $event)" | ||
/> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<script setup lang="ts"> | ||
import CodeBlock from './CodeBlock.vue' | ||
import { defineProps, onMounted, ref } from 'vue' | ||
const props = defineProps({ | ||
title: { | ||
type: String, | ||
required: true, | ||
}, | ||
code: { | ||
type: String, | ||
required: true, | ||
}, | ||
autoFocus: { | ||
type: Boolean, | ||
required: false, | ||
}, | ||
}) | ||
const input = ref(null) | ||
onMounted(() => { | ||
if (props.autoFocus && input.value) { | ||
const [basename, _] = props.title.split('.') | ||
const target = input.value as any | ||
var range = document.createRange() | ||
// Select the text nodes within the div (startNode, startOffset, endNode, endOffset) | ||
range.setStart(target.childNodes[0], 0) | ||
range.setEnd(target.childNodes[0], basename.length) | ||
getSelection()?.removeAllRanges() | ||
// Add the new range to the selection | ||
getSelection()?.addRange(range) | ||
target.focus() | ||
} | ||
}) | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<div | ||
class="title" | ||
ref="input" | ||
contenteditable | ||
@input="$emit('title', $event)" | ||
> | ||
{{ title }} | ||
</div> | ||
<CodeBlock :code="code" @code="$emit('code', $event)" /> | ||
</div> | ||
</template> | ||
|
||
<style> | ||
.title { | ||
margin: auto; | ||
} | ||
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { createApp } from 'vue' | ||
import './style.css' | ||
import { basicSetup } from 'codemirror' | ||
import VueCodemirror from 'vue-codemirror' | ||
import App from './App.vue' | ||
|
||
let app = createApp(App) | ||
app.use(VueCodemirror, { | ||
// optional default global options | ||
autofocus: true, | ||
disabled: false, | ||
indentWithTab: true, | ||
tabSize: 2, | ||
placeholder: 'Code goes here...', | ||
extensions: [basicSetup], | ||
// ... | ||
}) | ||
app.mount('#app') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
:root { | ||
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; | ||
line-height: 1.5; | ||
font-weight: 400; | ||
|
||
color-scheme: light dark; | ||
color: rgba(255, 255, 255, 0.87); | ||
background-color: #242424; | ||
|
||
font-synthesis: none; | ||
text-rendering: optimizeLegibility; | ||
-webkit-font-smoothing: antialiased; | ||
-moz-osx-font-smoothing: grayscale; | ||
-webkit-text-size-adjust: 100%; | ||
} | ||
|
||
a { | ||
font-weight: 500; | ||
color: #646cff; | ||
text-decoration: inherit; | ||
} | ||
a:hover { | ||
color: #535bf2; | ||
} | ||
|
||
h1 { | ||
font-size: 3.2em; | ||
line-height: 1.1; | ||
} | ||
|
||
button { | ||
border-radius: 8px; | ||
border: 1px solid transparent; | ||
padding: 0.6em 1.2em; | ||
font-size: 1em; | ||
font-weight: 500; | ||
font-family: inherit; | ||
background-color: #1a1a1a; | ||
cursor: pointer; | ||
transition: border-color 0.25s; | ||
} | ||
button:hover { | ||
border-color: #646cff; | ||
} | ||
button:focus, | ||
button:focus-visible { | ||
outline: 4px auto -webkit-focus-ring-color; | ||
} | ||
|
||
.card { | ||
padding: 2em; | ||
} | ||
|
||
@media (prefers-color-scheme: light) { | ||
:root { | ||
color: #213547; | ||
background-color: #ffffff; | ||
} | ||
a:hover { | ||
color: #747bff; | ||
} | ||
button { | ||
background-color: #f9f9f9; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import * as path from 'path-browserify' | ||
import { AssetItem, FileItem } from '../../../wasm' | ||
|
||
export type ModuleInfo = { | ||
title: string | ||
code: string | ||
autofocus?: boolean | ||
} | ||
|
||
export function normalizeModules(modules: ModuleInfo[]): FileItem[] { | ||
return modules.map(normalizeModule) | ||
} | ||
|
||
export function convertAssetListToModuleList( | ||
assetList: AssetItem[], | ||
): ModuleInfo[] { | ||
return assetList.map((item) => { | ||
return { | ||
title: item.name, | ||
code: item.content, | ||
} | ||
}) | ||
} | ||
|
||
/** | ||
* convert relative path into absolute path in memory fs | ||
* | ||
* */ | ||
function normalizeModule(module: ModuleInfo): FileItem { | ||
let title = module.title | ||
let code = module.code | ||
let isAbsolute = path.isAbsolute(title) | ||
if (!isAbsolute) { | ||
title = path.join('/', title) | ||
} | ||
return new FileItem(title, code) | ||
} | ||
|
||
let moduleId = 1 | ||
|
||
export function uniqueModulePath(modules: ModuleInfo[]): string { | ||
let curName = `module_${moduleId}.js` | ||
while (true) { | ||
let m = modules.find((item) => item.title === curName) | ||
if (!m) { | ||
break | ||
} | ||
curName = `module_${++moduleId}.js` | ||
} | ||
return curName | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
/// <reference types="vite/client" /> |
Oops, something went wrong.