vuepress-plugin-demo-block
Version:
demo block for vuepress both support vue and react
389 lines (352 loc) • 20.8 kB
JavaScript
function styleInject(css, ref) {
if (ref === void 0) ref = {};
var insertAt = ref.insertAt;
if (!css || typeof document === 'undefined') {
return;
}
var head = document.head || document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
if (insertAt === 'top') {
if (head.firstChild) {
head.insertBefore(style, head.firstChild);
} else {
head.appendChild(style);
}
} else {
head.appendChild(style);
}
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
}
var css = "@media (max-width: 1000px) {\n .vuepress-plugin-demo-block__h_code {\n display: none;\n }\n .vuepress-plugin-demo-block__app {\n margin-left: auto !important;\n margin-right: auto !important;\n }\n}\n.vuepress-plugin-demo-block__wrapper {\n margin-top: 10px;\n border: 1px solid #ebebeb;\n border-radius: 4px;\n transition: all 0.2s;\n}\n.vuepress-plugin-demo-block__wrapper.vuepress-plugin-demo-block__horizontal .vuepress-plugin-demo-block__display {\n height: 400px;\n display: flex;\n}\n.vuepress-plugin-demo-block__wrapper.vuepress-plugin-demo-block__horizontal .vuepress-plugin-demo-block__display .vuepress-plugin-demo-block__app {\n width: 300px;\n border: 1px solid #ebebeb;\n box-shadow: 1px 1px 3px #ebebeb;\n margin-right: 5px;\n overflow: auto;\n}\n.vuepress-plugin-demo-block__wrapper.vuepress-plugin-demo-block__horizontal .vuepress-plugin-demo-block__display .vuepress-plugin-demo-block__h_code {\n flex: 1;\n overflow: auto;\n height: 100%;\n}\n.vuepress-plugin-demo-block__wrapper.vuepress-plugin-demo-block__horizontal .vuepress-plugin-demo-block__display .vuepress-plugin-demo-block__h_code > pre {\n overflow: visible;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__display {\n max-height: 400px;\n overflow: auto;\n}\n.vuepress-plugin-demo-block__wrapper div {\n box-sizing: border-box;\n}\n.vuepress-plugin-demo-block__wrapper:hover {\n box-shadow: 0 0 11px rgba(33, 33, 33, 0.2);\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__code {\n overflow: hidden;\n height: 0;\n padding: 0 !important;\n background-color: #282c34;\n border-radius: 0 !important;\n transition: height 0.5s;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__code pre {\n margin: 0 !important;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__display {\n padding: 20px;\n border-bottom: 1px solid #ebebeb;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer {\n position: relative;\n text-align: center;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer.vuepress-plugin-demo-block__show-link .vuepress-plugin-demo-block__jsfiddle,\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer.vuepress-plugin-demo-block__show-link .vuepress-plugin-demo-block__codepen {\n opacity: 1;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer.vuepress-plugin-demo-block__show-link .vuepress-plugin-demo-block__expand::before {\n border-top: none;\n border-right: 6px solid transparent;\n border-bottom: 6px solid #ccc;\n border-left: 6px solid transparent;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover .vuepress-plugin-demo-block__jsfiddle,\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover .vuepress-plugin-demo-block__codepen,\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover .vuepress-plugin-demo-block__expand span,\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover .vuepress-plugin-demo-block__expand {\n opacity: 1;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover .vuepress-plugin-demo-block__expand::before {\n border-top-color: #3eaf7c !important;\n border-bottom-color: #3eaf7c !important;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer:hover svg {\n fill: #3eaf7c !important;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__expand-text {\n transition: all 0.5s;\n opacity: 0;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer form:nth-last-child(2) {\n right: 50px;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer form:last-child {\n right: 10px;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__button {\n border-color: transparent;\n background-color: transparent;\n font-size: 14px;\n color: #3eaf7c;\n cursor: pointer;\n outline: none;\n margin: 0;\n width: 46px;\n position: relative;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__button:hover::before {\n content: attr(data-tip);\n white-space: nowrap;\n position: absolute;\n top: -30px;\n left: 50%;\n color: #eee;\n line-height: 1;\n z-index: 1000;\n border-radius: 4px;\n padding: 6px;\n -webkit-transform: translateX(-50%);\n transform: translateX(-50%);\n background-color: rgba(0, 0, 0, 0.8);\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__button:hover::after {\n content: '' !important;\n display: block;\n position: absolute;\n left: 50%;\n top: -5px;\n -webkit-transform: translateX(-50%);\n transform: translateX(-50%);\n border: 5px solid transparent;\n border-top-color: rgba(0, 0, 0, 0.8);\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__button svg {\n width: 34px;\n height: 20px;\n fill: #ccc;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__jsfiddle,\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__codepen {\n position: absolute;\n top: 10px;\n transition: all 0.5s;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__expand {\n position: relative;\n width: 100px;\n height: 40px;\n margin: 0;\n color: #3eaf7c;\n font-size: 14px;\n background-color: transparent;\n border-color: transparent;\n outline: none;\n transition: all 0.5s;\n cursor: pointer;\n}\n.vuepress-plugin-demo-block__wrapper .vuepress-plugin-demo-block__footer .vuepress-plugin-demo-block__expand::before {\n content: \"\";\n position: absolute;\n top: 50%;\n left: 50%;\n width: 0;\n height: 0;\n border-top: 6px solid #ccc;\n border-right: 6px solid transparent;\n border-left: 6px solid transparent;\n -webkit-transform: translate(-50%, -50%);\n transform: translate(-50%, -50%);\n}\n";
styleInject(css);
var CLASS_WRAPPER = 'vuepress-plugin-demo-block__wrapper';
var CLASS_DISPLAY = 'vuepress-plugin-demo-block__display';
var CLASS_CODE = 'vuepress-plugin-demo-block__code';
var CLASS_FOOTER = 'vuepress-plugin-demo-block__footer';
var CLASS_HORIZONTAL = 'vuepress-plugin-demo-block__horizontal';
var CLASS_H_CODE = 'vuepress-plugin-demo-block__h_code';
var CLASS_APP = 'vuepress-plugin-demo-block__app';
var CLASS_SHOW_LINK = 'vuepress-plugin-demo-block__show-link';
var CLASS_EXPAND = 'vuepress-plugin-demo-block__expand';
var CLASS_CODEPEN = 'vuepress-plugin-demo-block__codepen';
var CLASS_JSFIDDLE = 'vuepress-plugin-demo-block__jsfiddle';
var CLASS_BUTTON = 'vuepress-plugin-demo-block__button';
var DEFAULT_SETTINGS = {
jsLib: [],
cssLib: [],
jsfiddle: true,
codepen: true,
codepenLayout: 'left',
codepenJsProcessor: 'babel',
codepenEditors: '101',
horizontal: false,
vue: 'https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js',
react: 'https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js',
reactDOM: 'https://cdn.jsdelivr.net/npm/react-dom/umd/react-dom.production.min.js'
};
var SETTINGS_KEY = '$VUEPRESS_DEMO_BLOCK';
var _once = {};
var getHtmlTpl = function getHtmlTpl(html) {
return "<div id=\"app\">\n".concat(html, "\n</div>");
};
var getVueJsTpl = function getVueJsTpl(js) {
var jsContent = js.replace(/export\s+default\s*?\{\n*/, '').replace(/\n*\}\s*$/, '').trim();
return "new Vue({\n el: '#app',\n ".concat(jsContent, "\n})");
};
var toArray = function toArray(value) {
return Array.prototype.slice.call(value);
};
var getSettings = function getSettings(key) {
return window[SETTINGS_KEY] && window[SETTINGS_KEY][key] !== undefined ? window[SETTINGS_KEY][key] : DEFAULT_SETTINGS[key];
};
var h = function h(tag, attrs, children) {
var node = document.createElement(tag);
attrs && Object.keys(attrs).forEach(function (key) {
if (!key.indexOf('data')) {
var k = key.replace('data', '');
node.dataset[k] = attrs[key];
} else {
node[key] = attrs[key];
}
});
children && children.forEach(function (_ref) {
var tag = _ref.tag,
attrs = _ref.attrs,
children = _ref.children;
node.appendChild(h(tag, attrs, children));
});
return node;
};
var $ = function $(parent, node, returnArray) {
var result = toArray(parent.querySelectorAll(".".concat(node)));
return result.length === 1 && !returnArray ? result[0] : result;
};
var getVueScript = function getVueScript(js, html) {
var scripts = js.split(/export\s+default/);
var scriptStrOrg = "(function() {".concat(scripts[0], " ; return ").concat(scripts[1], "})()");
var scriptStr = window.Babel ? window.Babel.transform(scriptStrOrg, {
presets: ['es2015']
}).code : scriptStrOrg;
var scriptObj = [eval][0](scriptStr);
scriptObj.template = html;
return scriptObj;
};
var getVanillaScript = function getVanillaScript(js) {
return window.Babel ? window.Babel.transform(js, {
presets: ['es2015']
}).code : js;
};
var getVueDetail = function getVueDetail(code, config) {
var cssBlock = code.match(/<style>([\s\S]+)<\/style>/);
var htmlBlock = code.match(/<template>([\s\S]+)<\/template>/);
var jsBlock = code.match(/<script>([\s\S]+)<\/script>/);
var result = {
css: cssBlock && cssBlock[1].replace(/^\n|\n$/g, ''),
html: htmlBlock && htmlBlock[1].replace(/^\n|\n$/g, ''),
js: jsBlock && jsBlock[1].replace(/^\n|\n$/g, ''),
jsLib: config.jsLib || [],
cssLib: config.cssLib || []
};
result.htmlTpl = getHtmlTpl(result.html);
result.jsTpl = getVueJsTpl(result.js);
result.script = getVueScript(result.js, result.html);
var vueResource = getSettings('vue');
result.jsLib.unshift(vueResource);
return result;
};
var getVanillaDetail = function getVanillaDetail(code, config) {
var cssBlock = code.match(/<style>([\s\S]+)<\/style>/);
var htmlBlock = code.match(/<html>([\s\S]+)<\/html>/);
var jsBlock = code.match(/<script>([\s\S]+)<\/script>/);
var result = {
css: cssBlock && cssBlock[1].replace(/^\n|\n$/g, ''),
html: htmlBlock && htmlBlock[1].replace(/^\n|\n$/g, ''),
js: jsBlock && jsBlock[1].replace(/^\n|\n$/g, ''),
jsLib: config.jsLib || [],
cssLib: config.cssLib || []
};
result.htmlTpl = result.html;
result.jsTpl = result.js;
result.script = getVanillaScript(result.js);
return result;
};
var getReactTpl = function getReactTpl(code) {
code = code.replace('export default ', '').replace(/App\.__style__(\s*)=(\s*)`([\s\S]*)?`/, '');
code += 'ReactDOM.render(React.createElement(App), document.getElementById("app"))';
return code;
};
var getReactDetail = function getReactDetail(code, config) {
var transform = window.Babel.transform;
var ins = transform(code, {
presets: ['es2015', 'react']
}).code;
var script = "(function(exports){var module={};module.exports=exports;".concat(ins, ";return module.exports.__esModule?module.exports.default:module.exports;})({})");
var scriptObj = new Function("return ".concat(script))();
var result = {
js: scriptObj,
css: scriptObj.__style__ || '',
jsLib: config.jsLib || [],
cssLib: config.cssLib || [],
jsTpl: getReactTpl(code),
htmlTpl: getHtmlTpl('')
};
var reactResource = getSettings('react');
var reactDOMResource = getSettings('reactDOM');
result.jsLib.unshift(reactResource, reactDOMResource);
return result;
};
var injectCss = function injectCss(css) {
if (_once[css]) return;
var style = h('style', {
innerHTML: css
});
document.body.appendChild(style);
_once[css] = true;
};
var codepenIcon = "xml version=\"1.0\" standalone=\"no\"?></style></defs><path d=\"M123.428571 668l344.571429 229.714286v-205.142857L277.142857 565.142857z m-35.428571-82.285714l110.285714-73.714286-110.285714-73.714286v147.428572z m468 312l344.571429-229.714286-153.714286-102.857143-190.857143 127.428572v205.142857z m-44-281.714286l155.428571-104-155.428571-104-155.428571 104zM277.142857 458.857143l190.857143-127.428572V126.285714L123.428571 356z m548.571429 53.142857l110.285714 73.714286V438.285714z m-78.857143-53.142857l153.714286-102.857143-344.571429-229.714286v205.142857z m277.142857-102.857143v312q0 23.428571-19.428571 36.571429l-468 312q-12 7.428571-24.571429 7.428571t-24.571429-7.428571L19.428571 704.571429q-19.428571-13.142857-19.428571-36.571429V356q0-23.428571 19.428571-36.571429L487.428571 7.428571q12-7.428571 24.571429-7.428571t24.571429 7.428571l468 312q19.428571 13.142857 19.428571 36.571429z\" p-id=\"1738\"></path></svg>";
function getCodepenBtn(_ref) {
var css = _ref.css,
htmlTpl = _ref.htmlTpl,
jsTpl = _ref.jsTpl,
jsLib = _ref.jsLib,
cssLib = _ref.cssLib;
var value = JSON.stringify({
css: css,
html: htmlTpl,
js: jsTpl,
js_external: jsLib.concat(getSettings('jsLib')).join(';'),
css_external: cssLib.concat(getSettings('cssLib')).join(';'),
layout: getSettings('codepenLayout'),
js_pre_processor: getSettings('codepenJsProcessor'),
editors: getSettings('codepenEditors')
});
var form = h('form', {
className: CLASS_CODEPEN,
target: '_blank',
action: 'https://codepen.io/pen/define',
method: 'post'
}, [{
tag: 'input',
attrs: {
type: 'hidden',
name: 'data',
value: value
}
}, {
tag: 'button',
attrs: {
type: 'submit',
innerHTML: codepenIcon,
className: CLASS_BUTTON,
datatip: 'Codepen'
}
}]);
return form;
}
var jsfiddleIcon = "<?xml version=\"1.0\" standalone=\"no\"?>