use-playground.ts 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import stackblitzSdk from '@stackblitz/sdk';
  2. import type { Project as StackBlitzProject } from '@stackblitz/sdk';
  3. import pkg from '../../../../package.json' assert { type: 'json' };
  4. import { isClient, MaybeRefOrGetter } from '@vueuse/core'
  5. import { computed, toValue } from 'vue';
  6. const pkgDependencyList = {
  7. ...pkg.dependencies,
  8. ...pkg.peerDependencies
  9. }
  10. interface Playground {
  11. title: MaybeRefOrGetter<string>;
  12. rawSource: MaybeRefOrGetter<string>;
  13. path: MaybeRefOrGetter<string>;
  14. }
  15. export function usePlayground({ title, rawSource, path }: Playground) {
  16. const dependencies = computed(() => toValue(rawSource).split(/\n/).reduce<Record<PropertyKey, string>>(
  17. (acc, line) => {
  18. const matches = line.match(/import .+? from '(.+)';\r?$/);
  19. if (matches?.[1]) {
  20. const paths = matches[1].split('/');
  21. const dep = paths[0].startsWith('@') ? `${paths[0]}/${paths[1]}` : paths[0];
  22. acc[dep] ??= pkgDependencyList[dep] ?? 'latest';
  23. }
  24. return acc;
  25. },
  26. {
  27. 'ant-design-vue': pkgDependencyList['ant-design-vue'],
  28. 'ant-design-x-vue': pkg.version
  29. },
  30. ));
  31. const html = `<!doctype html>
  32. <html lang="en">
  33. <head>
  34. <meta charset="UTF-8" />
  35. <link rel="icon" type="image/svg+xml" href="/vite.svg" />
  36. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  37. <title>Vite + Vue + TS</title>
  38. </head>
  39. <body>
  40. <div id="app"></div>
  41. <script type="module" src="/src/main.ts"></script>
  42. </body>
  43. </html>
  44. `
  45. const mainTsContent = `import { createApp } from 'vue'
  46. import './style.css'
  47. import Demo from './Demo.vue'
  48. createApp(Demo).mount('#app')
  49. `
  50. const styleCssContent = ``
  51. const demoVueContent = computed(() => `${decodeURIComponent(toValue(rawSource))}`)
  52. const tsconfig = {
  53. compilerOptions: {
  54. target: 'esnext',
  55. module: 'esnext',
  56. esModuleInterop: true,
  57. moduleResolution: 'bundler',
  58. jsx: "preserve",
  59. jsxImportSource: "vue",
  60. },
  61. };
  62. const packageJson = computed(() => ({
  63. "name": `${toValue(path).replaceAll('/', '-')}`,
  64. "private": true,
  65. "version": "0.0.0",
  66. "type": "module",
  67. "scripts": {
  68. "dev": "vite",
  69. "build": "vue-tsc -b && vite build",
  70. "preview": "vite preview"
  71. },
  72. "dependencies": {
  73. ...dependencies.value
  74. },
  75. "devDependencies": {
  76. "@vitejs/plugin-vue-jsx": pkg.devDependencies['@vitejs/plugin-vue-jsx'],
  77. "@vitejs/plugin-vue": pkg.devDependencies['@vitejs/plugin-vue'],
  78. "typescript": pkg.devDependencies.typescript,
  79. "vite": pkg.devDependencies.vite,
  80. "vue-tsc": pkg.devDependencies['vue-tsc'],
  81. 'unplugin-vue-macros': pkg.devDependencies['unplugin-vue-macros']
  82. }
  83. }))
  84. const viteTsContent = `import { defineConfig } from 'vite'
  85. import VueMacros from 'unplugin-vue-macros/vite'
  86. import vue from '@vitejs/plugin-vue';
  87. import vueJsx from '@vitejs/plugin-vue-jsx';
  88. // https://vite.dev/config/
  89. export default defineConfig({
  90. plugins: [
  91. VueMacros({
  92. plugins: {
  93. vue: vue(),
  94. vueJsx: vueJsx(),
  95. }
  96. }),
  97. ],
  98. })
  99. `
  100. const vueEnvTsContent = `declare module '*.vue' {
  101. import { DefineComponent, MaybeRefOrGetter, toValue } from 'vue';
  102. // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
  103. const component: DefineComponent<{}, {}, any>;
  104. export default component;
  105. }
  106. `
  107. const stackblitzPrefillConfig: StackBlitzProject = {
  108. title: `${toValue(title)} - antd-design-x-vue@${pkg.version}`,
  109. template: 'node',
  110. description: '',
  111. files: {
  112. [`src/style.css`]: styleCssContent,
  113. [`src/main.ts`]: mainTsContent,
  114. [`src/Demo.vue`]: demoVueContent.value,
  115. 'index.html': html,
  116. 'tsconfig.json': JSON.stringify(tsconfig, null, 2),
  117. 'package.json': JSON.stringify(packageJson.value, null, 2),
  118. 'vite.config.ts': viteTsContent,
  119. 'vue.env.d.ts': vueEnvTsContent
  120. },
  121. };
  122. const onStackblitzPlayBtnClick = () => {
  123. if (!isClient) {
  124. return
  125. }
  126. stackblitzSdk.openProject(stackblitzPrefillConfig, {
  127. openFile: [`src/Demo.vue`],
  128. });
  129. }
  130. return {
  131. onStackblitzPlayBtnClick
  132. }
  133. }