fix(vue): tweak semicolon for single expression in event bindings (#5519)

master
Ika 2018-11-29 09:28:35 +08:00 committed by GitHub
parent 0af81c7695
commit 0534735c2f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 974 additions and 58 deletions

View File

@ -33,6 +33,10 @@ module.exports = [
return eval("require")("../language-js/parser-babylon").parsers
.__vue_expression;
},
get __vue_event_binding() {
return eval("require")("../language-js/parser-babylon").parsers
.__vue_event_binding;
},
// JS - Flow
get flow() {
return eval("require")("../language-js/parser-flow").parsers.flow;

View File

@ -41,7 +41,11 @@ const {
const preprocess = require("./preprocess");
const assert = require("assert");
const { insertPragma } = require("./pragma");
const { printVueFor, printVueSlotScope } = require("./syntax-vue");
const {
printVueFor,
printVueSlotScope,
isVueEventBindingExpression
} = require("./syntax-vue");
const { printImgSrcset } = require("./syntax-attribute");
function concat(parts) {
@ -942,17 +946,13 @@ function printEmbeddedAttributeValue(node, originalTextToDoc, options) {
const jsExpressionBindingPatterns = ["^v-"];
if (isKeyMatched(vueEventBindingPatterns)) {
// copied from https://github.com/vuejs/vue/blob/v2.5.17/src/compiler/codegen/events.js#L3-L4
const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/;
const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/;
const value = getValue()
// https://github.com/vuejs/vue/blob/v2.5.17/src/compiler/helpers.js#L104
.trim();
const value = getValue();
return printMaybeHug(
simplePathRE.test(value) || fnExpRE.test(value)
isVueEventBindingExpression(value)
? textToDoc(value, { parser: "__js_expression" })
: stripTrailingHardline(textToDoc(value, { parser: "babylon" }))
: stripTrailingHardline(
textToDoc(value, { parser: "__vue_event_binding" })
)
);
}

View File

@ -66,7 +66,21 @@ function printVueSlotScope(value, textToDoc) {
});
}
function isVueEventBindingExpression(eventBindingValue) {
// https://github.com/vuejs/vue/blob/v2.5.17/src/compiler/codegen/events.js#L3-L4
// arrow function or anonymous function
const fnExpRE = /^([\w$_]+|\([^)]*?\))\s*=>|^function\s*\(/;
// simple member expression chain (a, a.b, a['b'], a["b"], a[0], a[b])
const simplePathRE = /^[A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*|\['[^']*?']|\["[^"]*?"]|\[\d+]|\[[A-Za-z_$][\w$]*])*$/;
// https://github.com/vuejs/vue/blob/v2.5.17/src/compiler/helpers.js#L104
const value = eventBindingValue.trim();
return fnExpRE.test(value) || simplePathRE.test(value);
}
module.exports = {
isVueEventBindingExpression,
printVueFor,
printVueSlotScope
};

View File

@ -45,6 +45,25 @@ function printHtmlBinding(path, options, print) {
}
}
// based on https://github.com/prettier/prettier/blob/master/src/language-html/syntax-vue.js isVueEventBindingExpression()
function isVueEventBindingExpression(node) {
switch (node.type) {
case "MemberExpression":
switch (node.property.type) {
case "Identifier":
case "NumericLiteral":
case "StringLiteral":
return isVueEventBindingExpression(node.object);
}
return false;
case "Identifier":
return true;
default:
return false;
}
}
module.exports = {
isVueEventBindingExpression,
printHtmlBinding
};

View File

@ -41,44 +41,49 @@ function babylonOptions(extraOptions, extraPlugins) {
);
}
function parse(text, parsers, opts) {
// Inline the require to avoid loading all the JS if we don't use it
const babylon = require("@babel/parser");
function createParse(parseMethod) {
return (text, parsers, opts) => {
// Inline the require to avoid loading all the JS if we don't use it
const babylon = require("@babel/parser");
const combinations = [
babylonOptions({ strictMode: true }, ["decorators-legacy"]),
babylonOptions({ strictMode: false }, ["decorators-legacy"]),
babylonOptions({ strictMode: true }, [
["decorators", { decoratorsBeforeExport: false }]
]),
babylonOptions({ strictMode: false }, [
["decorators", { decoratorsBeforeExport: false }]
])
];
const combinations = [
babylonOptions({ strictMode: true }, ["decorators-legacy"]),
babylonOptions({ strictMode: false }, ["decorators-legacy"]),
babylonOptions({ strictMode: true }, [
["decorators", { decoratorsBeforeExport: false }]
]),
babylonOptions({ strictMode: false }, [
["decorators", { decoratorsBeforeExport: false }]
])
];
const parseMethod =
!opts || opts.parser === "babylon" ? "parse" : "parseExpression";
let ast;
try {
ast = tryCombinations(babylon[parseMethod].bind(null, text), combinations);
} catch (error) {
throw createError(
// babel error prints (l:c) with cols that are zero indexed
// so we need our custom error
error.message.replace(/ \(.*\)/, ""),
{
start: {
line: error.loc.line,
column: error.loc.column + 1
let ast;
try {
ast = tryCombinations(
babylon[parseMethod].bind(null, text),
combinations
);
} catch (error) {
throw createError(
// babel error prints (l:c) with cols that are zero indexed
// so we need our custom error
error.message.replace(/ \(.*\)/, ""),
{
start: {
line: error.loc.line,
column: error.loc.column + 1
}
}
}
);
}
delete ast.tokens;
return postprocess(ast, Object.assign({}, opts, { originalText: text }));
);
}
delete ast.tokens;
return postprocess(ast, Object.assign({}, opts, { originalText: text }));
};
}
const parse = createParse("parse");
const parseExpression = createParse("parseExpression");
function tryCombinations(fn, combinations) {
let error;
for (let i = 0; i < combinations.length; i++) {
@ -94,7 +99,7 @@ function tryCombinations(fn, combinations) {
}
function parseJson(text, parsers, opts) {
const ast = parse(text, parsers, Object.assign({}, opts, { parser: "json" }));
const ast = parseExpression(text, parsers, opts);
ast.comments.forEach(assertJsonNode);
assertJsonNode(ast);
@ -164,17 +169,20 @@ const babylon = Object.assign(
{ parse, astFormat: "estree", hasPragma },
locFns
);
const babylonExpression = Object.assign({}, babylon, {
parse: parseExpression
});
// Export as a plugin so we can reuse the same bundle for UMD loading
module.exports = {
parsers: {
babylon,
json: Object.assign({}, babylon, {
json: Object.assign({}, babylonExpression, {
hasPragma() {
return true;
}
}),
json5: babylon,
json5: babylonExpression,
"json-stringify": Object.assign(
{
parse: parseJson,
@ -183,8 +191,10 @@ module.exports = {
locFns
),
/** @internal */
__js_expression: babylon,
__js_expression: babylonExpression,
/** for vue filter */
__vue_expression: babylon
__vue_expression: babylonExpression,
/** for vue event binding to handle semicolon */
__vue_event_binding: babylon
}
};

View File

@ -34,7 +34,10 @@ const clean = require("./clean");
const insertPragma = require("./pragma").insertPragma;
const handleComments = require("./comments");
const pathNeedsParens = require("./needs-parens");
const { printHtmlBinding } = require("./html-binding");
const {
printHtmlBinding,
isVueEventBindingExpression
} = require("./html-binding");
const preprocess = require("./preprocess");
const {
hasNode,
@ -494,6 +497,21 @@ function printPathNoParens(path, options, print, args) {
if (n.directive) {
return concat([nodeStr(n.expression, options, true), semi]);
}
if (options.parser === "__vue_event_binding") {
const parent = path.getParentNode();
if (
parent.type === "Program" &&
parent.body.length === 1 &&
parent.body[0] === n
) {
return concat([
path.call(print, "expression"),
isVueEventBindingExpression(n.expression) ? ";" : ""
]);
}
}
// Do not append semicolon after the only JSX element in a program
return concat([
path.call(print, "expression"),

View File

@ -37,6 +37,8 @@ printWidth: 80
console.log(test);
}
"
@click="doSomething()"
@click="doSomething;"
></div>
</template>
@ -59,9 +61,9 @@ printWidth: 80
return x;
})"
@click="/* hello */"
@click="/* 1 */ $emit(/* 2 */ 'click' /* 3 */) /* 4 */; /* 5 */"
@click="$emit('click');"
@click="$emit('click');"
@click="/* 1 */ $emit(/* 2 */ 'click' /* 3 */) /* 4 */ /* 5 */"
@click="$emit('click')"
@click="$emit('click')"
@click="
$emit('click');
if (something) {
@ -96,6 +98,8 @@ printWidth: 80
console.log(test);
}
"
@click="doSomething()"
@click="doSomething;"
></div>
</template>
@ -140,6 +144,8 @@ trailingComma: "es5"
console.log(test);
}
"
@click="doSomething()"
@click="doSomething;"
></div>
</template>
@ -162,9 +168,9 @@ trailingComma: "es5"
return x;
})"
@click="/* hello */"
@click="/* 1 */ $emit(/* 2 */ 'click' /* 3 */) /* 4 */; /* 5 */"
@click="$emit('click');"
@click="$emit('click');"
@click="/* 1 */ $emit(/* 2 */ 'click' /* 3 */) /* 4 */ /* 5 */"
@click="$emit('click')"
@click="$emit('click')"
@click="
$emit('click');
if (something) {
@ -199,6 +205,115 @@ trailingComma: "es5"
console.log(test);
}
"
@click="doSomething()"
@click="doSomething;"
></div>
</template>
================================================================================
`;
exports[`attributes.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<template>
<div
v-for=" item in items "
v-for=" item of items "
v-for="( item , index) in items"
v-for="value in object"
v-for="(value, key) in object"
v-for="(value, key) of object"
v-for="(value , key, index) in object"
v-for=" n in evenNumbers"
v-for=" n in even ( numbers) "
v-for=" n in 10"
v-for=" { a } in [0].map(()=>({a:1})) "
v-for=" ({ a }, [c ]) in [0].map(()=>1) "
v-for=" n in items.map(x => { return x }) "
@click=" /* hello */ "
@click=" /* 1 */ $emit( /* 2 */ 'click' /* 3 */ ) /* 4 */ ; /* 5 */ "
@click=" $emit( 'click' ) "
@click=" $emit( 'click' ) ;"
@click=" $emit( 'click' ) ;if(something){for(let i=j;i<100;i++){}}else{}"
slot-scope="{destructuring:{a:{b}}}"
:class="{ longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true }"
:class="(() => { return 'hello' })()"
:key="index /* hello */ "
:key="index // hello "
@click="() => {console.log(test)}"
@click="
() => {
console.log(test);
}
"
@click="doSomething()"
@click="doSomething;"
></div>
</template>
=====================================output=====================================
<template>
<div
v-for="item in items"
v-for="item of items"
v-for="(item, index) in items"
v-for="value in object"
v-for="(value, key) in object"
v-for="(value, key) of object"
v-for="(value, key, index) in object"
v-for="n in evenNumbers"
v-for="n in even(numbers)"
v-for="n in 10"
v-for="{ a } in [0].map(() => ({ a: 1 }))"
v-for="({ a }, [c]) in [0].map(() => 1)"
v-for="n in items.map(x => {
return x
})"
@click="/* hello */"
@click="/* 1 */ $emit(/* 2 */ 'click' /* 3 */) /* 4 */ /* 5 */"
@click="$emit('click')"
@click="$emit('click')"
@click="
$emit('click')
if (something) {
for (let i = j; i < 100; i++) {}
} else {
}
"
slot-scope="{
destructuring: {
a: { b }
}
}"
:class="{
longlonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglonglong: true
}"
:class="
(() => {
return 'hello'
})()
"
:key="index /* hello */"
:key="
index // hello
"
@click="
() => {
console.log(test)
}
"
@click="
() => {
console.log(test)
}
"
@click="doSomething()"
@click="doSomething;"
></div>
</template>
@ -355,7 +470,7 @@ export default {
:data-issue-id="issue.id"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event);"
@mouseup="showIssue($event)"
>
<issue-card-inner
:list="list"
@ -521,7 +636,173 @@ export default {
:data-issue-id="issue.id"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event);"
@mouseup="showIssue($event)"
>
<issue-card-inner
:list="list"
:issue="issue"
:issue-link-base="issueLinkBase"
:root-path="rootPath"
:update-filters="true"
/>
</li>
</template>
================================================================================
`;
exports[`board_card.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<script>
import './issue_card_inner';
import eventHub from '../eventhub';
const Store = gl.issueBoards.BoardsStore;
export default {
name: 'BoardsIssueCard',
components: {
'issue-card-inner': gl.issueBoards.IssueCardInner,
},
props: {
list: Object,
issue: Object,
issueLinkBase: String,
disabled: Boolean,
index: Number,
rootPath: String,
},
data() {
return {
showDetail: false,
detailIssue: Store.detail,
};
},
computed: {
issueDetailVisible() {
return (
this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id
);
},
},
methods: {
mouseDown() {
this.showDetail = true;
},
mouseMove() {
this.showDetail = false;
},
showIssue(e) {
if (e.target.classList.contains('js-no-trigger')) return;
if (this.showDetail) {
this.showDetail = false;
if (Store.detail.issue && Store.detail.issue.id === this.issue.id) {
eventHub.$emit('clearDetailIssue');
} else {
eventHub.$emit('newDetailIssue', this.issue);
Store.detail.list = this.list;
}
}
},
},
};
</script>
<template>
<li class="card"
:class="{ 'user-can-drag': !disabled && issue.id, 'is-disabled': disabled || !issue.id, 'is-active': issueDetailVisible }"
:index="index"
:data-issue-id="issue.id"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event)">
<issue-card-inner
:list="list"
:issue="issue"
:issue-link-base="issueLinkBase"
:root-path="rootPath"
:update-filters="true" />
</li>
</template>
=====================================output=====================================
<script>
import "./issue_card_inner"
import eventHub from "../eventhub"
const Store = gl.issueBoards.BoardsStore
export default {
name: "BoardsIssueCard",
components: {
"issue-card-inner": gl.issueBoards.IssueCardInner
},
props: {
list: Object,
issue: Object,
issueLinkBase: String,
disabled: Boolean,
index: Number,
rootPath: String
},
data() {
return {
showDetail: false,
detailIssue: Store.detail
}
},
computed: {
issueDetailVisible() {
return (
this.detailIssue.issue && this.detailIssue.issue.id === this.issue.id
)
}
},
methods: {
mouseDown() {
this.showDetail = true
},
mouseMove() {
this.showDetail = false
},
showIssue(e) {
if (e.target.classList.contains("js-no-trigger")) return
if (this.showDetail) {
this.showDetail = false
if (Store.detail.issue && Store.detail.issue.id === this.issue.id) {
eventHub.$emit("clearDetailIssue")
} else {
eventHub.$emit("newDetailIssue", this.issue)
Store.detail.list = this.list
}
}
}
}
}
</script>
<template>
<li
class="card"
:class="{
'user-can-drag': !disabled && issue.id,
'is-disabled': disabled || !issue.id,
'is-active': issueDetailVisible
}"
:index="index"
:data-issue-id="issue.id"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="showIssue($event)"
>
<issue-card-inner
:list="list"
@ -595,6 +876,36 @@ trailingComma: "es5"
================================================================================
`;
exports[`custom-block.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<i18n>
en:
one: One
two: Two
</i18n>
<html><head></head><body></body></html>
=====================================output=====================================
<i18n>
en:
one: One
two: Two
</i18n>
<html>
<head></head>
<body></body>
</html>
================================================================================
`;
exports[`filter.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -710,6 +1021,64 @@ trailingComma: "es5"
================================================================================
`;
exports[`filter.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<!-- vue filters are only allowed in v-bind and interpolation -->
<template>
<div class="allowed">{{value | thisIsARealSuperLongFilterPipe("arg1", arg2) | anotherPipeLongJustForFun | pipeTheThird}}</div>
<div class="allowed" v-bind:something='value | thisIsARealSuperLongFilterPipe("arg1", arg2) | anotherPipeLongJustForFun | pipeTheThird'></div>
<div class="allowed" :class='value | thisIsARealSuperLongFilterPipe("arg1", arg2) | anotherPipeLongJustForFun | pipeTheThird'></div>
<div class="not-allowed" v-if='value | thisIsARealSuperLongFilterPipe("arg1", arg2) | anotherPipeLongJustForFun | pipeTheThird'></div>
</template>
=====================================output=====================================
<!-- vue filters are only allowed in v-bind and interpolation -->
<template>
<div class="allowed">
{{
value
| thisIsARealSuperLongFilterPipe("arg1", arg2)
| anotherPipeLongJustForFun
| pipeTheThird
}}
</div>
<div
class="allowed"
v-bind:something="
value
| thisIsARealSuperLongFilterPipe('arg1', arg2)
| anotherPipeLongJustForFun
| pipeTheThird
"
></div>
<div
class="allowed"
:class="
value
| thisIsARealSuperLongFilterPipe('arg1', arg2)
| anotherPipeLongJustForFun
| pipeTheThird
"
></div>
<div
class="not-allowed"
v-if="
value |
thisIsARealSuperLongFilterPipe('arg1', arg2) |
anotherPipeLongJustForFun |
pipeTheThird
"
></div>
</template>
================================================================================
`;
exports[`interpolations.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -971,6 +1340,137 @@ x => {
================================================================================
`;
exports[`interpolations.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<template>
<div>Fuga magnam facilis. Voluptatem quaerat porro.{{
x => {
const hello = 'world'
return hello;
}
}} Magni consectetur in et molestias neque esse voluptatibus voluptas. {{
some_variable
}} Eum quia nihil nulla esse. Dolorem asperiores vero est error {{
preserve
invalid
interpolation
}} reprehenderit voluptates minus {{console.log( short_interpolation )}} nemo.</div>
<script type="text/jsx">
export default {
render (h) {
return (
<ul
class={{
'a': b,
'c': d,
"e": f
}}
>
{ this.xyz }
</ul>
)
};
</script>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890{{ something }}1234567890
</div>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890 {{ something }}1234567890
</div>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890{{ something }} 1234567890
</div>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890 {{ something }} 1234567890
</div>
</template>
=====================================output=====================================
<template>
<div>
Fuga magnam facilis. Voluptatem quaerat porro.{{
x => {
const hello = "world"
return hello
}
}}
Magni consectetur in et molestias neque esse voluptatibus voluptas.
{{ some_variable }} Eum quia nihil nulla esse. Dolorem asperiores vero est
error
{{
preserve
invalid
interpolation
}}
reprehenderit voluptates minus {{ console.log(short_interpolation) }} nemo.
</div>
<script type="text/jsx">
export default {
render (h) {
return (
<ul
class={{
'a': b,
'c': d,
"e": f
}}
>
{ this.xyz }
</ul>
)
};
</script>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890{{
something
}}1234567890
</div>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890
{{ something }}1234567890
</div>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890{{
something
}}
1234567890
</div>
<div>
1234567890123456789012345678901234567890123456789012345678901234567890
{{ something }} 1234567890
</div>
</template>
================================================================================
`;
exports[`pre-child.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -1182,6 +1682,112 @@ trailingComma: "es5"
================================================================================
`;
exports[`pre-child.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<template>
<!-- copied from https://github.com/gitlabhq/gitlabhq/blob/master/app/assets/javascripts/ide/components/jobs/detail.vue -->
<pre
ref="buildTrace"
class="build-trace mb-0 h-100"
@scroll="scrollBuildLog"
>
<code
v-show="!detailJob.isLoading"
class="bash"
v-html="jobOutput"
>
</code>
<div
v-show="detailJob.isLoading"
class="build-loader-animation"
>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</pre>
</template>
<!-- copied from https://github.com/gitlabhq/gitlabhq/blob/master/app/assets/javascripts/vue_shared/components/code_block.vue -->
<template>
<pre class="code-block rounded">
<code class="d-block">{{ code }}</code>
</pre>
</template>
<template>
<pre class='woot'>
{{ stuff }}
</pre>
</template>
<template>
<pre class='woot'>
123{{ wqeqwwqwqweqweqwewwq || wqeqwwqwqweqweqwewwq || wqeqwwqwqweqweqwewwq || wqeqwwqwqweqweqwewwq }}123
123{{ wqeqwwqwqweqweqwewwq || wqeqwwqwqweqweqwewwq || wqeqwwqwqweqweqwewwq || wqeqwwqwqweqweqwewwq }}123
</pre>
</template>
=====================================output=====================================
<template>
<!-- copied from https://github.com/gitlabhq/gitlabhq/blob/master/app/assets/javascripts/ide/components/jobs/detail.vue -->
<pre ref="buildTrace" class="build-trace mb-0 h-100" @scroll="scrollBuildLog">
<code
v-show="!detailJob.isLoading"
class="bash"
v-html="jobOutput"
>
</code>
<div
v-show="detailJob.isLoading"
class="build-loader-animation"
>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</pre>
</template>
<!-- copied from https://github.com/gitlabhq/gitlabhq/blob/master/app/assets/javascripts/vue_shared/components/code_block.vue -->
<template>
<pre class="code-block rounded">
<code class="d-block">{{ code }}</code>
</pre>
</template>
<template>
<pre class="woot">
{{ stuff }}
</pre>
</template>
<template>
<pre class="woot">
123{{
wqeqwwqwqweqweqwewwq ||
wqeqwwqwqweqweqwewwq ||
wqeqwwqwqweqweqwewwq ||
wqeqwwqwqweqweqwewwq
}}123
123{{
wqeqwwqwqweqweqwewwq ||
wqeqwwqwqweqweqwewwq ||
wqeqwwqwqweqweqwewwq ||
wqeqwwqwqweqweqwewwq
}}123
</pre
>
</template>
================================================================================
`;
exports[`script_src.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -1215,6 +1821,23 @@ trailingComma: "es5"
================================================================================
`;
exports[`script_src.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<script src="https://www.gstatic.com/firebasejs/4.10.1/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.10.1/firebase-firestore.js"></script>
=====================================output=====================================
<script src="https://www.gstatic.com/firebasejs/4.10.1/firebase.js"></script>
<script src="https://www.gstatic.com/firebasejs/4.10.1/firebase-firestore.js"></script>
================================================================================
`;
exports[`self_closing.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -1304,6 +1927,51 @@ foo();
================================================================================
`;
exports[`self_closing.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<template>
<div />
</template>
<script>
foo( )
</script>
<template>
<div class="container">
<HomeH />
<HomeA />
<HomeX />
<HomeY />
</div>
</template>
=====================================output=====================================
<template>
<div />
</template>
<script>
foo()
</script>
<template>
<div class="container">
<HomeH />
<HomeA />
<HomeX />
<HomeY />
</div>
</template>
================================================================================
`;
exports[`self_closing_style.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -1349,6 +2017,29 @@ trailingComma: "es5"
================================================================================
`;
exports[`self_closing_style.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<template>
<span :class="$style.root"><slot /></span>
</template>
<style src="./style.css" module />
=====================================output=====================================
<template>
<span :class="$style.root"><slot /></span>
</template>
<style src="./style.css" module />
================================================================================
`;
exports[`tag-name.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -1386,6 +2077,25 @@ trailingComma: "es5"
================================================================================
`;
exports[`tag-name.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<template>
<Table></Table>
</template>
=====================================output=====================================
<template>
<Table></Table>
</template>
================================================================================
`;
exports[`template.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -1517,6 +2227,72 @@ trailingComma: "es5"
================================================================================
`;
exports[`template.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<!--copied from https://github.com/gitlabhq/gitlabhq/blob/master/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue-->
<template>
<div class="file-container">
<div class="file-content image_file">
<img
ref="contentImg"
:class="{ 'is-zoomable': isZoomable, 'is-zoomed': isZoomed }"
:src="path"
:alt="path"
@load="onImgLoad"
@click="onImgClick"/>
<p
v-if="renderInfo"
class="file-info prepend-top-10">
<template v-if="fileSize>0">
{{ fileSizeReadable }}
</template>
<template v-if="fileSize>0 && width && height">
|
</template>
<template v-if="width && height">
W: {{ width }} | H: {{ height }}
</template>
</p>
</div>
</div>
</template>
=====================================output=====================================
<!--copied from https://github.com/gitlabhq/gitlabhq/blob/master/app/assets/javascripts/vue_shared/components/content_viewer/viewers/image_viewer.vue-->
<template>
<div class="file-container">
<div class="file-content image_file">
<img
ref="contentImg"
:class="{ 'is-zoomable': isZoomable, 'is-zoomed': isZoomed }"
:src="path"
:alt="path"
@load="onImgLoad"
@click="onImgClick"
/>
<p v-if="renderInfo" class="file-info prepend-top-10">
<template v-if="fileSize > 0">
{{ fileSizeReadable }}
</template>
<template v-if="fileSize > 0 && width && height">
|
</template>
<template v-if="width && height">
W: {{ width }} | H: {{ height }}
</template>
</p>
</div>
</div>
</template>
================================================================================
`;
exports[`template-lang.vue 1`] = `
====================================options=====================================
parsers: ["vue"]
@ -1572,6 +2348,45 @@ trailingComma: "es5"
lang='pug'>
.test
#foo
.bla
</template>
=====================================output=====================================
<template lang="pug">
.test
#foo
.bla
</template>
<template lang="pug">
.test
#foo
.bla
</template>
================================================================================
`;
exports[`template-lang.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<template lang="pug">
.test
#foo
.bla
</template>
<template
lang='pug'>
.test
#foo
@ -1650,3 +2465,32 @@ trailingComma: "es5"
================================================================================
`;
exports[`test.vue 3`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
semi: false
| printWidth
=====================================input======================================
<script>
</script>
<template>
<br />
<footer>
foo
<br/>
</footer>
</template>
=====================================output=====================================
<script></script>
<template>
<br />
<footer>foo <br /></footer>
</template>
================================================================================
`;

View File

@ -29,5 +29,7 @@
console.log(test);
}
"
@click="doSomething()"
@click="doSomething;"
></div>
</template>

View File

@ -1,2 +1,3 @@
run_spec(__dirname, ["vue"]);
run_spec(__dirname, ["vue"], { trailingComma: "es5" });
run_spec(__dirname, ["vue"], { semi: false });

View File

@ -92,7 +92,7 @@ printWidth: 80
<div v-bind:id="'&quot;' + id"></div>
<div v-bind:id="rawId | formatId"></div>
<div v-bind:id="ok ? 'YES' : 'NO'"></div>
<button @click="foo(arg, 'string');"></button>
<button @click="foo(arg, 'string')"></button>
</template>
================================================================================

View File

@ -37,6 +37,10 @@ var parsers = {
importScriptOnce("lib/parser-babylon.js");
return prettierPlugins.babylon.parsers.__vue_expression;
},
get __vue_event_binding() {
importScriptOnce("lib/parser-babylon.js");
return prettierPlugins.babylon.parsers.__vue_event_binding;
},
// JS - Flow
get flow() {
importScriptOnce("lib/parser-flow.js");