mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-12-02 03:58:05 +08:00
doc: support CodeSandbox (#4861)
This commit is contained in:
parent
c3400115dd
commit
45c0583426
@ -127,6 +127,7 @@
|
|||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
"cheerio": "^1.0.0-rc.2",
|
"cheerio": "^1.0.0-rc.2",
|
||||||
"codecov": "^3.0.0",
|
"codecov": "^3.0.0",
|
||||||
|
"codesandbox": "^2.2.3",
|
||||||
"colorful": "^2.1.0",
|
"colorful": "^2.1.0",
|
||||||
"commander": "^7.2.0",
|
"commander": "^7.2.0",
|
||||||
"compare-versions": "^3.3.0",
|
"compare-versions": "^3.3.0",
|
||||||
|
@ -19,6 +19,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="code-box-description" v-html="docHtml"></div>
|
<div class="code-box-description" v-html="docHtml"></div>
|
||||||
<div class="code-box-actions">
|
<div class="code-box-actions">
|
||||||
|
<a-tooltip :title="$t('app.demo.codesandbox')">
|
||||||
|
<CodeSandboxOutlined
|
||||||
|
class="code-box-code-copy code-box-code-action"
|
||||||
|
@click="handleCodeSandbox"
|
||||||
|
/>
|
||||||
|
</a-tooltip>
|
||||||
<a-tooltip :title="$t(`app.demo.type.${type === 'JS' ? 'js' : 'ts'}`)">
|
<a-tooltip :title="$t(`app.demo.type.${type === 'JS' ? 'js' : 'ts'}`)">
|
||||||
<span
|
<span
|
||||||
class="code-expand-icon code-box-code-action"
|
class="code-expand-icon code-box-code-action"
|
||||||
@ -72,7 +78,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
<section :class="highlightClass">
|
<section :class="highlightClass">
|
||||||
<div class="highlight">
|
<div class="highlight" ref="codeRef">
|
||||||
<slot v-if="type === 'TS'" name="htmlCode" />
|
<slot v-if="type === 'TS'" name="htmlCode" />
|
||||||
<slot v-else name="jsVersionHtml" />
|
<slot v-else name="jsVersionHtml" />
|
||||||
</div>
|
</div>
|
||||||
@ -84,13 +90,17 @@
|
|||||||
import type { GlobalConfig } from '../App.vue';
|
import type { GlobalConfig } from '../App.vue';
|
||||||
import { GLOBAL_CONFIG } from '../SymbolKey';
|
import { GLOBAL_CONFIG } from '../SymbolKey';
|
||||||
import { computed, defineComponent, inject, onMounted, ref } from 'vue';
|
import { computed, defineComponent, inject, onMounted, ref } from 'vue';
|
||||||
import { CheckOutlined, SnippetsOutlined } from '@ant-design/icons-vue';
|
import { CheckOutlined, SnippetsOutlined, CodeSandboxOutlined } from '@ant-design/icons-vue';
|
||||||
|
import { getCodeSandboxParams } from '../utils/generateOnlineDemo';
|
||||||
|
import packageInfo from '../../../package.json';
|
||||||
|
|
||||||
// import { Modal } from 'ant-design-vue';
|
// import { Modal } from 'ant-design-vue';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'DemoBox',
|
name: 'DemoBox',
|
||||||
components: {
|
components: {
|
||||||
CheckOutlined,
|
CheckOutlined,
|
||||||
SnippetsOutlined,
|
SnippetsOutlined,
|
||||||
|
CodeSandboxOutlined,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
jsfiddle: Object,
|
jsfiddle: Object,
|
||||||
@ -100,6 +110,7 @@ export default defineComponent({
|
|||||||
const type = ref('TS');
|
const type = ref('TS');
|
||||||
const copyTooltipVisible = ref(false);
|
const copyTooltipVisible = ref(false);
|
||||||
const copied = ref(false);
|
const copied = ref(false);
|
||||||
|
const codeRef = ref<HTMLDivElement>();
|
||||||
const sectionId = computed(() => {
|
const sectionId = computed(() => {
|
||||||
const relativePath = props.jsfiddle?.relativePath || '';
|
const relativePath = props.jsfiddle?.relativePath || '';
|
||||||
return `${relativePath.split('/').join('-').replace('.vue', '')}`;
|
return `${relativePath.split('/').join('-').replace('.vue', '')}`;
|
||||||
@ -170,6 +181,21 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
type.value = type.value === 'TS' ? 'JS' : 'TS';
|
type.value = type.value === 'TS' ? 'JS' : 'TS';
|
||||||
};
|
};
|
||||||
|
const handleCodeSandbox = () => {
|
||||||
|
const code = codeRef.value!.innerText;
|
||||||
|
const params = getCodeSandboxParams(code, {
|
||||||
|
title: `${title.value} - ant-design-vue@${packageInfo.version}`,
|
||||||
|
});
|
||||||
|
const div = document.createElement('div');
|
||||||
|
div.style.display = 'none';
|
||||||
|
div.innerHTML = `<form action="https://codesandbox.io/api/v1/sandboxes/define" method="POST" target="_blank">
|
||||||
|
<input type="hidden" name="parameters" value="${params}" />
|
||||||
|
<input type="submit" value="Open in sandbox" />
|
||||||
|
</form>`;
|
||||||
|
document.body.appendChild(div);
|
||||||
|
(div.firstElementChild as HTMLFormElement).submit();
|
||||||
|
document.body.removeChild(div);
|
||||||
|
};
|
||||||
const highlightClass = computed(() => {
|
const highlightClass = computed(() => {
|
||||||
return {
|
return {
|
||||||
'highlight-wrapper': true,
|
'highlight-wrapper': true,
|
||||||
@ -207,6 +233,8 @@ export default defineComponent({
|
|||||||
highlightClass,
|
highlightClass,
|
||||||
sourceCode: decodeURIComponent(escape(window.atob(props.jsfiddle?.sourceCode))),
|
sourceCode: decodeURIComponent(escape(window.atob(props.jsfiddle?.sourceCode))),
|
||||||
jsSourceCode: decodeURIComponent(escape(window.atob(props.jsfiddle?.jsSourceCode))),
|
jsSourceCode: decodeURIComponent(escape(window.atob(props.jsfiddle?.jsSourceCode))),
|
||||||
|
codeRef,
|
||||||
|
handleCodeSandbox,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
94
site/src/utils/generateOnlineDemo.ts
Normal file
94
site/src/utils/generateOnlineDemo.ts
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
import { getParameters } from 'codesandbox/lib/api/define';
|
||||||
|
|
||||||
|
const indexHtml = `<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title>Ant Design Vue Demo</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const appVue = `<template>
|
||||||
|
<Demo />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { defineComponent } from "vue";
|
||||||
|
import Demo from "./demo.vue";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
Demo,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>`;
|
||||||
|
|
||||||
|
const mainJs = `import { createApp } from "vue";
|
||||||
|
import App from "./App.vue";
|
||||||
|
import Antd from 'ant-design-vue';
|
||||||
|
import 'ant-design-vue/dist/antd.css';
|
||||||
|
|
||||||
|
const app = createApp(App).use(Antd);
|
||||||
|
app.mount("#app");
|
||||||
|
`;
|
||||||
|
|
||||||
|
function getDeps(code: string) {
|
||||||
|
return (code.match(/from '([^']+)';\n/g) || [])
|
||||||
|
.map(v => v.slice(6, v.length - 3))
|
||||||
|
.reduce((prevV, dep) => {
|
||||||
|
prevV[dep] = 'latest';
|
||||||
|
return prevV;
|
||||||
|
}, {});
|
||||||
|
}
|
||||||
|
|
||||||
|
type Meta = {
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// codeSandbox
|
||||||
|
export function getCodeSandboxParams(code: string, meta: Meta): string {
|
||||||
|
return getParameters({
|
||||||
|
files: {
|
||||||
|
'package.json': {
|
||||||
|
content: JSON.stringify({
|
||||||
|
title: meta.title,
|
||||||
|
dependencies: {
|
||||||
|
...getDeps(code),
|
||||||
|
vue: 'next',
|
||||||
|
'ant-design-vue': 'next',
|
||||||
|
},
|
||||||
|
devDependencies: {
|
||||||
|
'@vue/cli-plugin-babel': '~4.5.0',
|
||||||
|
typescript: '^4.0.5',
|
||||||
|
},
|
||||||
|
browserslist: ['> 0.2%', 'not dead'],
|
||||||
|
}),
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'index.html': {
|
||||||
|
content: indexHtml,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'src/demo.vue': {
|
||||||
|
content: code,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'src/App.vue': {
|
||||||
|
content: appVue,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
'src/main.js': {
|
||||||
|
content: mainJs,
|
||||||
|
isBinary: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user