Skip to content

Commit

Permalink
Add explorer
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi committed Dec 13, 2020
1 parent 1a1a5bc commit 6a911d4
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
"typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true,
}
},
"vetur.validation.template": false
}
10 changes: 10 additions & 0 deletions explorer/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
parserOptions: {
sourceType: "module",
ecmaVersion: 2020,
},
extends: ["plugin:@ota-meshi/+vue3", "plugin:@ota-meshi/+prettier"],
rules: {
"node/no-unsupported-features/es-syntax": "off",
},
}
1 change: 1 addition & 0 deletions explorer/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package-lock=false
3 changes: 3 additions & 0 deletions explorer/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
presets: ["@vue/cli-plugin-babel/preset"],
}
24 changes: 24 additions & 0 deletions explorer/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "yaml-eslint-parser-ast-explorer",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"yaml-eslint-parser": "0.0.8"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"@vue/compiler-sfc": "^3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
30 changes: 30 additions & 0 deletions explorer/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>yaml-eslint-parser</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.21.2/min/vs/loader.min.js"></script>
<script>
window.require.config({
paths: {
vs: "https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.21.2/min/vs"
},
'vs/nls': {
availableLanguages: {
'*': 'ja'
}
}
})
</script>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
46 changes: 46 additions & 0 deletions explorer/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<template>
<header class="header">
<label class="title">yaml-eslint-parser</label>
<a
href="https://github.com/ota-meshi/yaml-eslint-parser"
class="github-link"
>GitHub</a
>
</header>
<main class="main">
<AstExplorer />
</main>
</template>

<script>
import AstExplorer from "./components/AstExplorer.vue"
export default {
name: "App",
components: {
AstExplorer,
},
}
</script>
<style scoped>
.header {
height: 32px;
display: flex;
border-bottom: 1px #ddd solid;
}
.title {
font-size: 120%;
flex-grow: 1;
display: flex;
align-items: center;
}
.github-link {
width: 4em;
display: flex;
align-items: center;
}
.main {
position: relative;
height: calc(100vh - 32px - 16px);
}
</style>
81 changes: 81 additions & 0 deletions explorer/src/components/AstExplorer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<template>
<div class="ast-explorer-root">
<AstOptions v-model="options" />
<div class="ast-explorer">
<MonacoEditor v-model="yamlValue" language="yaml" />
<MonacoEditor v-model="astJson" language="json" read-only />
</div>
</div>
</template>

<script>
import MonacoEditor from "./MonacoEditor.vue"
import AstOptions from "./AstOptions.vue"
import * as yamlEslintParser from "yaml-eslint-parser"
export default {
name: "AstExplorer",
components: { MonacoEditor, AstOptions },
data() {
return {
options: {
showLocations: false,
},
yamlValue: `---
# Welcome yaml-eslint-parser
message: Here you can see the AST generated by yaml-eslint-parser.
github: https://github.com/ota-meshi/yaml-eslint-parser
eslint: https://github.com/ota-meshi/eslint-plugin-yml
`,
astJson: "",
}
},
watch: {
options: {
handler: "refresh",
deep: true,
},
yamlValue: {
handler: "refresh",
immediate: true,
},
},
methods: {
refresh() {
this.astJson = JSON.stringify(
yamlEslintParser.parseForESLint(this.yamlValue).ast,
replacer.bind(null, this.options),
2,
)
},
},
}
/**
* replacer for AST JSON
*/
function replacer(options, key, val) {
if (key === "parent") {
return undefined
}
if (!options.showLocations) {
if (key === "range" || key === "loc") return undefined
}
return val
}
</script>

<style scoped>
.ast-explorer-root {
min-width: 1px;
min-height: 1px;
display: flex;
flex-direction: column;
height: 100%;
}
.ast-explorer {
min-width: 1px;
display: flex;
height: 100%;
}
</style>
38 changes: 38 additions & 0 deletions explorer/src/components/AstOptions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<label class="ast-options"
><input
type="checkbox"
:checked="modelValue.showLocations"
@change="updateShowLocations($event.target.checked)"
/>Locations</label
>
</template>

<script>
export default {
name: "AstOptions",
props: {
modelValue: {
type: Object,
default() {
return {}
},
},
},
emits: ["update:modelValue"],
methods: {
updateShowLocations(newValue) {
this.$emit("update:modelValue", {
...this.modelValue,
showLocations: newValue,
})
},
},
}
</script>

<style scoped>
.ast-options {
text-align: right;
}
</style>
69 changes: 69 additions & 0 deletions explorer/src/components/MonacoEditor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<template>
<div class="root"></div>
</template>

<script>
const editorLoaded = new Promise((resolve) => {
window.require(["vs/editor/editor.main"], (r) => {
resolve(r)
})
})
export default {
name: "MonacoEditor",
props: {
modelValue: {
type: String,
default: "",
},
language: {
type: String,
default: "json",
},
readOnly: Boolean,
},
emits: ["update:modelValue"],
watch: {
modelValue(newValue) {
const vm = this
if (vm.editor) {
if (newValue !== vm.editor.getValue()) {
vm.editor.setValue(newValue)
}
}
},
},
async mounted() {
const monaco = await editorLoaded
const vm = this
const options = Object.assign(
{
value: vm.modelValue,
readOnly: vm.readOnly,
theme: "vs-dark",
language: vm.language,
automaticLayout: true,
fontSize: 14,
// tabSize: 2,
minimap: {
enabled: false,
},
},
vm.options,
)
vm.editor = monaco.editor.create(vm.$el, options)
vm.editor.onDidChangeModelContent((evt) => {
const value = vm.editor.getValue()
if (vm.modelValue !== value) {
vm.$emit("update:modelValue", value, evt)
}
})
},
}
</script>
<style scoped>
.root {
width: 100%;
height: 100%;
}
</style>
4 changes: 4 additions & 0 deletions explorer/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { createApp } from "vue"
import App from "./App.vue"

createApp(App).mount("#app")

0 comments on commit 6a911d4

Please sign in to comment.