Skip to content

Commit c1faacc

Browse files
authored
Merge pull request #11 from vue-styleguidist/fet-devtoolsupdate
feat: devtools update
2 parents 90a1ae1 + a6204c4 commit c1faacc

File tree

6 files changed

+111
-152
lines changed

6 files changed

+111
-152
lines changed

demo/assets/Button.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<template>
22
<div class="hello">
3+
<h1>Colored Text</h1>
34
<button>{{ msg }}</button>
45
</div>
56
</template>
@@ -14,8 +15,9 @@ export default {
1415
};
1516
</script>
1617

17-
<style scoped>
18+
<style>
1819
.hello {
1920
text-align: center;
21+
color: #900;
2022
}
2123
</style>

demo/assets/input.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
new Vue({
22
template: `
33
<div>
4-
<input v-model="value" type="checkbox" :name="cname">
4+
<input v-model="value" type="checkbox">
55
<h1 v-if="value">I am checked</h1>
66
</div>`,
77
data() {
88
return {
9-
cname: "myCheck",
109
value: false
1110
};
1211
}

src/Preview.vue

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
11
<template>
22
<div>
33
<div style="color:red" v-if="error">{{this.error}}</div>
4-
<div :id="scope"/>
4+
<VuePreview :id="scope"/>
55
</div>
66
</template>
77

88
<script>
9-
import Vue from "vue";
109
import { transform } from "buble";
1110
import compileCode, { isCodeVueSfc } from "./utils/compileCode";
1211
import getVars from "./utils/getVars";
1312
import getVueConfigObject from "./utils/getVueConfigObject";
14-
import styleScoper from "./utils/styleScoper";
13+
import addScopedStyle from "./utils/addScopedStyle";
1514
1615
export default {
1716
name: "VueLivePreviewComponent",
17+
components: {},
1818
props: {
1919
code: {
2020
type: String,
2121
required: true
2222
},
23-
scoped: {
24-
type: Boolean,
25-
default: true
26-
},
2723
components: {
2824
type: Object,
2925
default: () => {}
@@ -35,7 +31,7 @@ export default {
3531
error: false
3632
};
3733
},
38-
mounted() {
34+
beforeMount() {
3935
this.renderComponent(this.code.trim());
4036
},
4137
methods: {
@@ -50,11 +46,11 @@ export default {
5046
this.error = e.message;
5147
},
5248
renderComponent(code) {
53-
let data = {},
54-
script,
55-
style,
56-
template;
49+
let data = {};
5750
let listVars = [];
51+
let script;
52+
let style;
53+
let template;
5854
try {
5955
const renderedComponent = compileCode(code);
6056
style = renderedComponent.style;
@@ -89,22 +85,14 @@ export default {
8985
}
9086
9187
data.components = this.components;
92-
93-
// eslint-disable-next-line no-new
94-
const vueInstance = new Vue({
95-
el: `#${this.scope}`,
96-
render: createElement => createElement(data)
97-
});
98-
99-
// Add the scoped style if there is any
10088
if (style) {
101-
vueInstance.$el.setAttribute(`data-${this.scope}`, true);
102-
const styleContainer = document.createElement("div");
103-
styleContainer.innerHTML = style;
104-
styleContainer.firstChild.id = `data-${this.scope}`;
105-
vueInstance.$el.appendChild(styleContainer.firstChild);
89+
// To add the scope id attribute to each item in the html
90+
// this way when we add the scoped style sheet it will be aplied
91+
data._scopeId = `data-${this.scope}`;
92+
addScopedStyle(style, this.scope);
10693
}
107-
styleScoper();
94+
95+
this.$options.components.VuePreview = data;
10896
}
10997
}
11098
};

src/utils/addScopedStyle.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { scoper } from "./styleScoper";
2+
3+
export default function addScopedStyle(css, suffix) {
4+
const head = document.head || document.getElementsByTagName("head")[0];
5+
const newstyle = document.createElement("style");
6+
newstyle.dataset.cssscoper = "true";
7+
const csses = scoper(css, `[data-${suffix}]`);
8+
if (newstyle.styleSheet) {
9+
newstyle.styleSheet.cssText = csses;
10+
} else {
11+
newstyle.appendChild(document.createTextNode(csses));
12+
}
13+
head.appendChild(newstyle);
14+
}

src/utils/normalizeSfcComponent.js

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,55 @@
1-
import { parseComponent } from 'vue-template-compiler'
2-
import walkes from 'walkes'
3-
import transformOneImport from './transformOneImport'
4-
import getAst from './getAst'
1+
import { parseComponent } from "vue-template-compiler";
2+
import walkes from "walkes";
3+
import transformOneImport from "./transformOneImport";
4+
import getAst from "./getAst";
55

66
const buildStyles = function(styles) {
7-
let _styles = ''
7+
let _styles = "";
88
if (styles) {
99
styles.forEach(it => {
1010
if (it.content) {
11-
_styles += it.content
11+
_styles += it.content;
1212
}
13-
})
13+
});
1414
}
15-
if (_styles !== '') {
16-
return `<style scoped>${_styles.trim()}</style>`
15+
if (_styles !== "") {
16+
return _styles.trim();
1717
}
18-
return undefined
19-
}
18+
return undefined;
19+
};
2020

2121
function getSingleFileComponentParts(code) {
22-
const parts = parseComponent(code)
22+
const parts = parseComponent(code);
2323
if (parts.script)
2424
parts.script.content = parts.script.content.replace(
2525
/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm,
26-
'$1'
27-
)
28-
return parts
26+
"$1"
27+
);
28+
return parts;
2929
}
3030

3131
function injectTemplateAndParseExport(parts) {
32-
const templateString = parts.template.content.replace(/`/g, '\\`')
32+
const templateString = parts.template.content.replace(/`/g, "\\`");
3333

34-
if (!parts.script) return `{\ntemplate: \`${templateString}\` }`
34+
if (!parts.script) return `{\ntemplate: \`${templateString}\` }`;
3535

36-
let code = parts.script.content
37-
let preprocessing = ''
38-
let startIndex = -1
39-
let endIndex = -1
40-
let offset = 0
36+
let code = parts.script.content;
37+
let preprocessing = "";
38+
let startIndex = -1;
39+
let endIndex = -1;
40+
let offset = 0;
4141
walkes(getAst(code), {
4242
// export const MyComponent = {}
4343
ExportNamedDeclaration(node) {
44-
preprocessing = code.slice(0, node.start + offset)
45-
startIndex = node.declaration.declarations[0].init.start + offset
46-
endIndex = node.declaration.declarations[0].init.end + offset
44+
preprocessing = code.slice(0, node.start + offset);
45+
startIndex = node.declaration.declarations[0].init.start + offset;
46+
endIndex = node.declaration.declarations[0].init.end + offset;
4747
},
4848
// export default {}
4949
ExportDefaultDeclaration(node) {
50-
preprocessing = code.slice(0, node.start + offset)
51-
startIndex = node.declaration.start + offset
52-
endIndex = node.declaration.end + offset
50+
preprocessing = code.slice(0, node.start + offset);
51+
startIndex = node.declaration.start + offset;
52+
endIndex = node.declaration.end + offset;
5353
},
5454
// module.exports = {}
5555
AssignmentExpression(node) {
@@ -59,26 +59,26 @@ function injectTemplateAndParseExport(parts) {
5959
/module/.test(node.left.object.name) &&
6060
/exports/.test(node.left.property.name))
6161
) {
62-
preprocessing = code.slice(0, node.start + offset)
63-
startIndex = node.right.start + offset
64-
endIndex = node.right.end + offset
62+
preprocessing = code.slice(0, node.start + offset);
63+
startIndex = node.right.start + offset;
64+
endIndex = node.right.end + offset;
6565
}
6666
},
6767
ImportDeclaration(node) {
68-
const ret = transformOneImport(node, code, offset)
69-
offset = ret.offset
70-
code = ret.code
68+
const ret = transformOneImport(node, code, offset);
69+
offset = ret.offset;
70+
code = ret.code;
7171
}
72-
})
72+
});
7373
if (startIndex === -1) {
74-
throw new Error('Failed to parse single file component: ' + code)
74+
throw new Error("Failed to parse single file component: " + code);
7575
}
76-
let right = code.slice(startIndex + 1, endIndex - 1)
76+
let right = code.slice(startIndex + 1, endIndex - 1);
7777
return {
7878
preprocessing,
7979
component: `{\n template: \`${templateString}\`,\n ${right}}`,
8080
postprocessing: code.slice(endIndex)
81-
}
81+
};
8282
}
8383

8484
/**
@@ -87,14 +87,14 @@ function injectTemplateAndParseExport(parts) {
8787
* transformed into requires
8888
*/
8989
export default function normalizeSfcComponent(code) {
90-
const parts = getSingleFileComponentParts(code)
91-
const extractedComponent = injectTemplateAndParseExport(parts)
90+
const parts = getSingleFileComponentParts(code);
91+
const extractedComponent = injectTemplateAndParseExport(parts);
9292
return {
9393
component: [
9494
extractedComponent.preprocessing,
9595
`new Vue(${extractedComponent.component});`,
9696
extractedComponent.postprocessing
97-
].join('\n'),
97+
].join("\n"),
9898
style: buildStyles(parts.styles)
99-
}
99+
};
100100
}

src/utils/styleScoper.js

Lines changed: 37 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,43 @@
11
/* eslint-disable no-control-regex */
22

33
// used to make CSS selectors remain scoped properly
4-
function init() {
5-
const style = document.createElement('style')
6-
style.appendChild(document.createTextNode(''))
7-
document.head.appendChild(style)
8-
style.sheet.insertRule('body { visibility: hidden; }', 0)
9-
}
104

115
export function scoper(css, suffix) {
12-
const re = /([^\r\n,{}]+)(,(?=[^}]*{)|s*{)/g
13-
14-
// `after` is going to contain eithe a comma or an opening curly bracket
15-
css = css.replace(re, function(full, selector, after) {
16-
// if non-rule delimiter
17-
if (selector.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) {
18-
return selector + after
19-
}
20-
21-
// deal with :scope pseudo selectors
22-
if (selector.match(/:scope/)) {
23-
selector = selector.replace(/([^\s]*):scope/, function(full, cutSelector) {
24-
if (cutSelector === '') {
25-
return '> *'
26-
}
27-
return '> ' + cutSelector
28-
})
29-
}
30-
31-
// deal with other pseudo selectors
32-
let pseudo = ''
33-
if (selector.match(/:/)) {
34-
const parts = selector.split(/:/)
35-
selector = parts[0]
36-
pseudo = ':' + parts[1]
37-
}
38-
39-
selector = selector.trim() + ' '
40-
selector = selector.replace(/ /g, suffix + pseudo + ' ')
41-
42-
return selector + after
43-
})
44-
45-
return css
46-
}
47-
48-
function process() {
49-
const styles = document.body.querySelectorAll('style[scoped]')
50-
51-
if (styles.length === 0) {
52-
document.getElementsByTagName('body')[0].style.visibility = 'visible'
53-
return
54-
}
55-
56-
const head = document.head || document.getElementsByTagName('head')[0]
57-
const newstyle = document.createElement('style')
58-
newstyle.dataset.cssscoper = 'true'
59-
let csses = ''
60-
61-
let idx
62-
for (idx = 0; idx < styles.length; idx++) {
63-
const style = styles[idx]
64-
const moduleId = style.id
65-
const css = style.innerHTML
66-
67-
if (css && style.parentElement.nodeName !== 'BODY') {
68-
const suffix = '[' + moduleId + ']'
69-
style.parentNode.removeChild(style)
70-
71-
csses = csses + scoper(css, suffix)
72-
}
73-
}
74-
75-
if (newstyle.styleSheet) {
76-
newstyle.styleSheet.cssText = csses
77-
} else {
78-
newstyle.appendChild(document.createTextNode(csses))
79-
}
80-
head.appendChild(newstyle)
81-
82-
document.getElementsByTagName('body')[0].style.visibility = 'visible'
6+
const re = /([^\r\n,{}]+)(,(?=[^}]*{)|s*{)/g;
7+
8+
// `after` is going to contain eithe a comma or an opening curly bracket
9+
css = css.replace(re, function(full, selector, after) {
10+
// if non-rule delimiter
11+
if (selector.match(/^\s*(@media|@keyframes|to|from|@font-face)/)) {
12+
return selector + after;
13+
}
14+
15+
// deal with :scope pseudo selectors
16+
if (selector.match(/:scope/)) {
17+
selector = selector.replace(/([^\s]*):scope/, function(
18+
full,
19+
cutSelector
20+
) {
21+
if (cutSelector === "") {
22+
return "> *";
23+
}
24+
return "> " + cutSelector;
25+
});
26+
}
27+
28+
// deal with other pseudo selectors
29+
let pseudo = "";
30+
if (selector.match(/:/)) {
31+
const parts = selector.split(/:/);
32+
selector = parts[0];
33+
pseudo = ":" + parts[1];
34+
}
35+
36+
selector = selector.trim() + " ";
37+
selector = selector.replace(/ /g, suffix + pseudo + " ");
38+
39+
return selector + after;
40+
});
41+
42+
return css;
8343
}
84-
85-
init()
86-
87-
export default process

0 commit comments

Comments
 (0)