Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions demo/App.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<main style="text-align: center;">
<main style="text-align: center">
<h1>Vue Live renders vue code in the browser</h1>
<p class="description">
<em>vue-live</em> is a VueJs component. It renders the code passed in prop
Expand Down Expand Up @@ -35,9 +35,7 @@
<h2>Pure JavaScript code</h2>
<p>Or if you prefer to, use the <b>new Vue()</b> format</p>
<VueLive :code="codeJs" :layout="CustomLayout" />
<h2>
Extra dependencies
</h2>
<h2>Extra dependencies</h2>
<p>
Use the <b>requires</b> prop to make libraries and packages available in
the browser
Expand All @@ -60,7 +58,7 @@
/>

<h2>Default Layout</h2>
<div style="width: 950px; max-width: 95vw; margin: 20px auto;">
<div style="width: 950px; max-width: 95vw; margin: 20px auto">
<VueLive :code="`<input type='button' value='I am Groot' />`" />
</div>
<h2>Custom Layout</h2>
Expand All @@ -84,11 +82,19 @@
<h2>Separate components for Editor and Preview</h2>
<div class="separate">
<div class="preview-separate">
<VueLivePreview :code="separateCode" />
<VueLivePreview
:code="separateCode"
@error="(e) => (error = e)"
@success="error = undefined"
/>
</div>
<hr style="width: 950px;" />
<hr style="width: 950px" />
<p>Edit the code here</p>
<VueLiveEditor :code="separateCode" @change="updateCode" />
<VueLiveEditor
:code="separateCode"
@change="updateCode"
:error="error"
/>
<div class="button-bar"><button>Save</button></div>
</div>
</div>
Expand Down Expand Up @@ -128,6 +134,7 @@ export default {
realjsx,
separateCode: codeSfc,
openExamples: false,
error: undefined,
};
},
methods: {
Expand Down
26 changes: 13 additions & 13 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"hash-sum": "^2.0.0",
"prismjs": "^1.21.0",
"recast": "^0.19.1",
"vue-inbrowser-compiler": "^4.32.1",
"vue-inbrowser-compiler": "^4.33.4",
"vue-prism-editor": "^1.2.2",
"vue-template-compiler": "^2.6.12"
},
Expand Down
70 changes: 26 additions & 44 deletions src/Editor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,55 +9,14 @@

<script>
import { PrismEditor } from "vue-prism-editor";
import debounce from "debounce";

import {
highlight as prismHighlight,
languages,
} from "prismjs/components/prism-core";
import "prismjs/components/prism-clike";
import "prismjs/components/prism-markup";
import "prismjs/components/prism-javascript";
import "prismjs/components/prism-jsx";
import "vue-prism-editor/dist/prismeditor.min.css";

import debounce from "debounce";
import getScript from "./utils/getScript";
import highlight from "./utils/highlight";

const UPDATE_DELAY = 300;

const highlight = (lang, jsxInExamples) => {
if (lang === "vsg") {
return (code) => {
if (!code) {
return "";
}
const scriptCode = getScript(code, jsxInExamples);
const scriptCodeHighlighted = prismHighlight(
scriptCode,
languages[jsxInExamples ? "jsx" : "js"],
lang
);
if (code.length === scriptCode.length) {
return scriptCodeHighlighted;
}
const templateCode = code.slice(scriptCode.length);
const templateHighlighted = prismHighlight(templateCode, languages["html"], lang)
return (
scriptCodeHighlighted +
templateHighlighted
);
};
} else {
return (code) => {
const langScheme = languages[lang];
if(!langScheme){
return code
}
return prismHighlight(code, langScheme, lang);
}
}
};

export default {
name: "VueLiveEditor",
components: { PrismEditor },
Expand All @@ -66,6 +25,10 @@ export default {
type: String,
required: true,
},
error: {
type: [Error, Object],
default: undefined,
},
delay: {
type: Number,
default: UPDATE_DELAY,
Expand All @@ -83,6 +46,10 @@ export default {
type: Boolean,
default: false,
},
squiggles: {
type: Boolean,
default: true,
},
},
data() {
return {
Expand All @@ -97,7 +64,10 @@ export default {
},
methods: {
highlighter(code) {
return highlight(this.prismLang, this.jsx)(code);
return highlight(this.prismLang, this.jsx)(
code,
this.squiggles && this.error && this.error.loc
);
},
},
watch: {
Expand All @@ -113,3 +83,15 @@ export default {
},
};
</script>

<style>
.VueLive-squiggles-wrapper {
position: absolute;
width: 100%;
height: 100%;
}

.VueLive-squiggles {
border-bottom: 2px dotted red;
}
</style>
5 changes: 3 additions & 2 deletions src/Preview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ export default {
// if so, change scheme used by editor
// NOTE: vsg is a superset of JavaScript allowing
// the template to succeed litterally code, very useful for examples
// vsg stands for vue-styleguidist
// NOTE2: vsg stands for vue-styleguidist
this.$emit("detect-language", isCodeVueSfc(code) ? "vue" : "vsg");

// compile and execute the script
Expand Down Expand Up @@ -192,9 +192,10 @@ export default {
} else {
this.handleError({
message:
"[Vue Live] no template or render function specified, you might have an issue in your example",
"[Vue Live] no template or render function specified. Example cannot be rendered.",
});
}
this.$emit("success");
},
},
};
Expand Down
21 changes: 18 additions & 3 deletions src/VueLive.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
:delay="delay"
:prism-lang="prismLang"
:editor-props="editorProps"
:error="error"
:jsx="jsx"
:squiggles="squiggles"
@change="updatePreview"
/>
</template>
Expand All @@ -30,7 +32,8 @@
:key="codeKey"
:code="model"
@detect-language="switchLanguage"
@error="(e) => $emit('error', e)"
@error="handleError"
@success="error = undefined"
:components="components"
:requires="requires"
:jsx="jsx"
Expand All @@ -55,7 +58,7 @@ const LANG_TO_PRISM = {
const UPDATE_DELAY = 300;

export default {
name: "VueLivePreview",
name: "VueLive",
components: { Preview, Editor },
props: {
/**
Expand Down Expand Up @@ -139,6 +142,14 @@ export default {
type: Boolean,
default: true,
},
/**
* Show the red markings
* where the compiler found errors
*/
squiggles: {
type: Boolean,
default: true,
},
},
data() {
return {
Expand All @@ -152,6 +163,7 @@ export default {
* editor repainted every keystroke
*/
stableCode: this.code,
error: undefined,
};
},
computed: {
Expand All @@ -169,7 +181,6 @@ export default {
updatePreview(code) {
this.stableCode = code;
this.model = code;

this.$emit("change", code);
},
switchLanguage(newLang) {
Expand All @@ -180,6 +191,10 @@ export default {
this.stableCode = this.model;
}
},
handleError(e) {
this.error = e;
this.$emit("error", e);
},
},
};
</script>
23 changes: 22 additions & 1 deletion src/utils/__tests__/checkTemplate.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ test("parse invalid template with an error if the value is not in data", () => {
);
});

test("parse template interpolatio and detect undefined variables", () => {
test("parse template interpolation and detect lonely undefined variables", () => {
expect(() =>
checkTemplate({
template: "<div><compo>{{ hello }}</compo></div>",
Expand All @@ -119,6 +119,27 @@ test("parse template interpolatio and detect undefined variables", () => {
);
});

test("parse template interpolation and detect impacted undefined variables", () => {
expect(() =>
checkTemplate({
template: "<div><compo>{{ hello + 'bonjour' }}</compo></div>",
})
).toThrowErrorMatchingInlineSnapshot(
`"Variable \\"hello\\" is not defined."`
);
});

test("parse template interpolation and detect impacted right variables", () => {
expect(() =>
checkTemplate({
template:
"<div><compo>{{ 'bonjour' + hello + 'sayonara' }}</compo></div>",
})
).toThrowErrorMatchingInlineSnapshot(
`"Variable \\"hello\\" is not defined."`
);
});

test("parse invalid : template by throwing an error", () => {
expect(() =>
checkTemplate({
Expand Down
Loading