├── packages ├── docs │ ├── .gitignore │ ├── public │ │ ├── favicon.ico │ │ └── logo.svg │ ├── reference │ │ ├── support.md │ │ └── deploy.md │ ├── more │ │ └── feedback.md │ ├── .vitepress │ │ ├── components │ │ │ └── home-hero-after.vue │ │ ├── theme │ │ │ ├── index.ts │ │ │ └── style.scss │ │ └── config.ts │ ├── package.json │ ├── index.md │ └── guide │ │ ├── config.md │ │ ├── importmap.md │ │ └── start.md ├── website │ ├── src │ │ ├── main.ts │ │ ├── vite-env.d.ts │ │ ├── App.vue │ │ └── type.ts │ ├── tsconfig.node.json │ ├── .gitignore │ ├── index.html │ ├── tsconfig.json │ ├── dist │ │ ├── index.html │ │ ├── assets │ │ │ ├── index-eba15397.js │ │ │ ├── azcli-deb61577-f1f7c576.js │ │ │ ├── javascript-3aab9677-e6c2c027.js │ │ │ ├── ini-0cf51c96-18bf1153.js │ │ │ ├── csp-80865a3e-d207cac4.js │ │ │ ├── pla-5b3c3b2c-1b3e1614.js │ │ │ ├── scheme-bd6c73dd-ff6e5671.js │ │ │ ├── flow9-88286753-42a61225.js │ │ │ ├── sb-190efae3-2020a5af.js │ │ │ ├── bat-19ed4cb4-86aea46a.js │ │ │ ├── dockerfile-d28c5166-bbf114b2.js │ │ │ ├── pascaligo-c74f23f5-385edc0e.js │ │ │ ├── lua-250761cb-9adddcd9.js │ │ │ ├── cameligo-145c2c73-8043f913.js │ │ │ ├── graphql-edbbae08-387d549c.js │ │ │ ├── objective-c-4607378b-951ded7b.js │ │ │ ├── lexon-81c06df2-8d4b0444.js │ │ │ ├── xml-1c94689a-3dcda303.js │ │ │ ├── bicep-f7f58c3d-392558ac.js │ │ │ ├── sparql-bcef85eb-e42fb28a.js │ │ │ ├── mips-6984085e-bdd96c5a.js │ │ │ ├── go-e4123ca1-8759e9f7.js │ │ │ ├── sophia-ff9a60c4-12eb7ba8.js │ │ │ ├── m3-cd35fba5-aa2dcf72.js │ │ │ ├── qsharp-d902dfd3-e125d03f.js │ │ │ ├── fsharp-5c8798af-8abe6da0.js │ │ │ ├── pascal-c142b200-7442fd46.js │ │ │ ├── shell-325a523c-3c06def6.js │ │ │ ├── r-1974245b-e0a01d4f.js │ │ │ ├── java-067b9e51-000a6283.js │ │ │ ├── powershell-9e30c619-d3380668.js │ │ │ ├── cypher-6571dbc8-49f5f839.js │ │ │ ├── kotlin-5d8c4070-06ee8898.js │ │ │ └── redis-a4651a9b-d0a12fea.js │ │ └── logo-ff272dde.svg │ ├── vite.config.ts │ ├── package.json │ ├── scripts │ │ └── index.js │ ├── logo.svg │ └── README.md └── core │ ├── src │ ├── templates │ │ ├── index.ts │ │ ├── javascript.ts │ │ ├── typescript.ts │ │ ├── react.ts │ │ ├── vue3.ts │ │ ├── html.ts │ │ └── vue2.ts │ ├── utils │ │ ├── index.ts │ │ ├── debounce.ts │ │ ├── convert.ts │ │ ├── message.ts │ │ ├── str.ts │ │ └── dialog.ts │ ├── assets │ │ ├── default_file.svg │ │ ├── vue.svg │ │ ├── js.svg │ │ ├── ts.svg │ │ ├── html.svg │ │ ├── css.svg │ │ ├── sass.svg │ │ ├── scss.svg │ │ ├── json.svg │ │ ├── jsx.svg │ │ └── tsx.svg │ ├── compiler │ │ ├── plugins │ │ │ └── module-factory.ts │ │ ├── transform │ │ │ └── plugins │ │ │ │ ├── transform-css.ts │ │ │ │ ├── index.ts │ │ │ │ ├── transform-less.ts │ │ │ │ ├── transform-scss.ts │ │ │ │ ├── transform-react.ts │ │ │ │ └── transform-ts.ts │ │ ├── type.ts │ │ ├── file-system │ │ │ └── index.ts │ │ └── index.ts │ ├── index.ts │ ├── vite-env.d.ts │ ├── components │ │ ├── preview │ │ │ └── index.less │ │ ├── monaco-editor │ │ │ └── utils.ts │ │ ├── toolbar │ │ │ ├── icons │ │ │ │ ├── icon.less │ │ │ │ ├── refresh.vue │ │ │ │ ├── share.vue │ │ │ │ ├── docs.vue │ │ │ │ ├── copy.vue │ │ │ │ └── git.vue │ │ │ └── index.vue │ │ ├── index.less │ │ ├── file-bar │ │ │ ├── index.less │ │ │ ├── icons │ │ │ │ ├── add-file.vue │ │ │ │ ├── rename-file.vue │ │ │ │ ├── home-file.vue │ │ │ │ └── delete-file.vue │ │ │ └── file-input.vue │ │ ├── splitter │ │ │ └── index.less │ │ ├── menus │ │ │ ├── utils │ │ │ │ ├── getInfo.ts │ │ │ │ └── system.ts │ │ │ └── type.ts │ │ └── loading │ │ │ └── index.vue │ ├── constant │ │ ├── tooltip.ts │ │ └── index.ts │ ├── style │ │ ├── variable.less │ │ └── global.less │ ├── type.ts │ └── store │ │ └── index.ts │ ├── tsconfig.node.json │ ├── .gitignore │ ├── index.html │ ├── tsconfig.json │ ├── vite.config.ts │ ├── logo.svg │ └── package.json ├── .gitignore ├── .vscode └── extensions.json ├── package.json └── LICENSE /packages/docs/.gitignore: -------------------------------------------------------------------------------- 1 | dist -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | types 3 | dist.zip 4 | 5 | .cache 6 | .temp 7 | stats.html 8 | cache -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] 3 | } 4 | -------------------------------------------------------------------------------- /packages/docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zh-lx/codeplayer/HEAD/packages/docs/public/favicon.ico -------------------------------------------------------------------------------- /packages/docs/reference/support.md: -------------------------------------------------------------------------------- 1 | # 支持语法 2 | 3 | - ✅ html 4 | - ✅ js/ts 5 | - ✅ css/less/scss 6 | - ✅ jsx/tsx 7 | - ✅ vue2/3 8 | - ✅ react 9 | -------------------------------------------------------------------------------- /packages/website/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue'; 2 | import '../../core/dist/style.css'; 3 | 4 | import App from './App.vue'; 5 | 6 | const app = createApp(App); 7 | app.mount('#app'); 8 | -------------------------------------------------------------------------------- /packages/core/src/templates/index.ts: -------------------------------------------------------------------------------- 1 | export * from './html'; 2 | export * from './javascript'; 3 | export * from './react'; 4 | export * from './typescript'; 5 | export * from './vue2'; 6 | export * from './vue3'; 7 | -------------------------------------------------------------------------------- /packages/core/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './debounce'; 2 | export * from './str'; 3 | export * from './module-compiler'; 4 | export * from './convert'; 5 | export * from './message'; 6 | export * from './dialog'; 7 | -------------------------------------------------------------------------------- /packages/core/src/assets/default_file.svg: -------------------------------------------------------------------------------- 1 | 2 | default_file 3 | 4 | -------------------------------------------------------------------------------- /packages/core/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/website/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true 7 | }, 8 | "include": ["vite.config.ts"] 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/src/compiler/plugins/module-factory.ts: -------------------------------------------------------------------------------- 1 | import { Hooks } from '@/compiler/type' 2 | import { compileModulesForPreview } from '@/compiler/module' 3 | 4 | export default function(hooks: Hooks) { 5 | hooks.hook('compile-module', compileModulesForPreview) 6 | } -------------------------------------------------------------------------------- /packages/website/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import { defineComponent } from 'vue'; 5 | const Component: ReturnType; 6 | export default Component; 7 | } 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/core/src/utils/debounce.ts: -------------------------------------------------------------------------------- 1 | export function debounce(fn: Function, n = 100) { 2 | let handle: any; 3 | return (...args: any[]) => { 4 | if (handle) clearTimeout(handle); 5 | handle = setTimeout(() => { 6 | fn(...args); 7 | }, n); 8 | }; 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/src/index.ts: -------------------------------------------------------------------------------- 1 | import CodePlayer from './components/index.vue'; 2 | import '@/style/global.less'; 3 | import '@/style/index.less'; 4 | import 'tippy.js/dist/tippy.css'; 5 | import 'tippy.js/themes/light.css'; 6 | export type { CodePlayerOptions } from './type'; 7 | 8 | export default CodePlayer; 9 | -------------------------------------------------------------------------------- /packages/core/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module '*.vue' { 4 | import { defineComponent } from 'vue'; 5 | const Component: ReturnType; 6 | export default Component; 7 | } 8 | 9 | declare interface Window { 10 | __eruda: any; 11 | } 12 | -------------------------------------------------------------------------------- /packages/website/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist-ssr 12 | *.local 13 | 14 | # Editor directories and files 15 | .vscode/* 16 | !.vscode/extensions.json 17 | .idea 18 | .DS_Store 19 | *.suo 20 | *.ntvs* 21 | *.njsproj 22 | *.sln 23 | *.sw? 24 | -------------------------------------------------------------------------------- /packages/core/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /packages/core/src/components/preview/index.less: -------------------------------------------------------------------------------- 1 | .codeplayer-iframe-container { 2 | position: relative; 3 | height: 100%; 4 | width: 100%; 5 | background-color: @bg-container; 6 | } 7 | .codeplayer-iframe { 8 | border: none; 9 | position: relative; 10 | height: 100%; 11 | width: 100%; 12 | user-select: none; 13 | &:hover { 14 | user-select: initial; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/core/src/components/monaco-editor/utils.ts: -------------------------------------------------------------------------------- 1 | import { Uri, editor } from 'monaco-editor'; 2 | 3 | export function getOrCreateModel( 4 | uri: Uri, 5 | lang: string | undefined, 6 | value: string 7 | ) { 8 | const model = editor.getModel(uri); 9 | if (model) { 10 | model.setValue(value); 11 | return model; 12 | } 13 | return editor.createModel(value, lang, uri); 14 | } 15 | -------------------------------------------------------------------------------- /packages/core/src/utils/convert.ts: -------------------------------------------------------------------------------- 1 | export const convertToNumber = (len: number | string, total: number) => { 2 | if (typeof len === 'number') { 3 | return len; 4 | } 5 | if (len.endsWith('%')) { 6 | return Number(len.slice(0, len.length - 1)) * total * 0.01; 7 | } 8 | if (len.endsWith('px')) { 9 | return Number(len.slice(0, len.length - 2)); 10 | } 11 | return Number(len); 12 | }; 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codeplayer", 3 | "version": "1.0.0", 4 | "description": "一个浏览器代码编辑&可视化运行 web 组件,支持 vue/react 等代码的浏览器编辑及运行", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "private": true, 10 | "keywords": [], 11 | "author": "", 12 | "license": "ISC", 13 | "workspaces": [ 14 | "packages/*" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /packages/docs/more/feedback.md: -------------------------------------------------------------------------------- 1 | # 交流与反馈 2 | 3 | ## 加入用户群 4 | 5 | 任何使用问题欢迎添加作者微信 `zhoulx1688888` 或者 QQ 群 `245077601` 进行咨询与反馈: 6 | 7 |
8 | 9 | 10 |
11 | -------------------------------------------------------------------------------- /packages/core/src/assets/vue.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_vue 3 | 5 | 7 | 9 | -------------------------------------------------------------------------------- /packages/docs/.vitepress/components/home-hero-after.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 18 | -------------------------------------------------------------------------------- /packages/website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CodePlayer 8 | 9 | 10 |
11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/core/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + Vue + TS 8 | 9 | 10 |
11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@codeplayer/website", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "docs:dev": "vitepress dev", 9 | "docs:build": "vitepress build", 10 | "docs:preview": "vitepress preview" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC", 15 | "devDependencies": { 16 | "vitepress": "1.0.0-beta.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/website/src/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 13 | 14 | 20 | -------------------------------------------------------------------------------- /packages/core/src/components/toolbar/icons/icon.less: -------------------------------------------------------------------------------- 1 | .toolbar-icon { 2 | color: var(--codeplayer-text-secondary); 3 | cursor: pointer; 4 | display: flex; 5 | align-items: center; 6 | justify-content: center; 7 | position: relative; 8 | width: 24px; 9 | height: 24px; 10 | border-radius: @border-radius-small; 11 | &:hover { 12 | color: var(--codeplayer-brand-hover); 13 | // background-color: @fill; 14 | } 15 | &:active { 16 | color: var(--codeplayer-brand-active); 17 | // background-color: @fill; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/docs/.vitepress/theme/index.ts: -------------------------------------------------------------------------------- 1 | // https://vitepress.dev/guide/custom-theme 2 | import { h } from 'vue'; 3 | import Theme from 'vitepress/theme'; 4 | // import HomeHeroAfter from '../components/home-hero-after.vue'; 5 | import './style.scss'; 6 | 7 | export default { 8 | ...Theme, 9 | Layout: () => { 10 | return h(Theme.Layout, null, { 11 | // 'home-features-after': () => h(HomeHeroAfter), 12 | // https://vitepress.dev/guide/extending-default-theme#layout-slots 13 | }); 14 | }, 15 | enhanceApp({ app, router, siteData }) { 16 | // ... 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /packages/core/src/compiler/transform/plugins/transform-css.ts: -------------------------------------------------------------------------------- 1 | import { Hooks, ComplierPluginParams } from '@/compiler/type'; 2 | 3 | export async function transformCSS( 4 | params: ComplierPluginParams 5 | ): Promise { 6 | const { fileMap } = params; 7 | const files = Object.keys(fileMap).map((filename) => fileMap[filename]); 8 | 9 | await Promise.all( 10 | files 11 | .filter((file) => file.filename.endsWith('.css')) 12 | .map((file) => { 13 | const { code } = file; 14 | 15 | file.compiled.css = code; 16 | }) 17 | ); 18 | 19 | return; 20 | } 21 | 22 | export default function (hooks: Hooks) { 23 | hooks.hook('transform', transformCSS); 24 | } 25 | -------------------------------------------------------------------------------- /packages/core/src/assets/js.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_js 3 | 6 | -------------------------------------------------------------------------------- /packages/core/src/utils/message.ts: -------------------------------------------------------------------------------- 1 | let messageRef: HTMLDivElement | null = null; 2 | 3 | export const message = ( 4 | text: string, 5 | options?: { duration?: number; type?: 'info' | 'success' | 'danger' } 6 | ) => { 7 | if (messageRef) { 8 | messageRef.remove(); 9 | messageRef = null; 10 | } 11 | messageRef = document.createElement('div'); 12 | messageRef.innerText = text; 13 | messageRef.classList.add('codeplayer-message'); 14 | messageRef.classList.add('codeplayer-message-' + options?.type || 'info'); 15 | document.body.append(messageRef); 16 | setTimeout(() => { 17 | if (messageRef) { 18 | messageRef.remove(); 19 | messageRef = null; 20 | } 21 | }, options?.duration || 3000); 22 | }; 23 | -------------------------------------------------------------------------------- /packages/website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "lib": ["ESNext", "DOM"], 13 | "skipLibCheck": true, 14 | "noEmit": true, 15 | "declaration": true, 16 | "paths": { 17 | "@/*": ["./src/*"] 18 | } 19 | }, 20 | "include": [ 21 | "src/**/*.ts", 22 | "src/*.d.ts", 23 | "src/**/*.tsx", 24 | "src/**/*.vue", 25 | "src/**/*.ce.vue" 26 | ], 27 | "references": [{ "path": "./tsconfig.node.json" }] 28 | } 29 | -------------------------------------------------------------------------------- /packages/core/src/constant/tooltip.ts: -------------------------------------------------------------------------------- 1 | export const TooltipText = { 2 | AddFile: 'Add a new file', 3 | RenameFile: 'Rename', 4 | DeleteFile: 'Delete', 5 | isEntry: 'Entry File', 6 | SetEntry: 'Set to entry', 7 | ToggleFiles: (show: boolean) => `${show ? 'Hide' : 'Show'} FileBar`, 8 | ToggleCode: (show: boolean) => `${show ? 'Hide' : 'Show'} Code Editor`, 9 | Settings: 'Settings', 10 | ToggleWebPreview: (show: boolean) => `${show ? 'Hide' : 'Show'} Web Preview`, 11 | RefreshWebPreview: 'Refresh Web Preview', 12 | SwapLayout: 'Swap the position of CodeEditor and WebPreview', 13 | CopyCode: 'Copy code to clipboard', 14 | Share: 'Share the page', 15 | Docs: 'View documents of codeplayer', 16 | Github: 'View codeplayer on github', 17 | }; 18 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "module": "ESNext", 6 | "moduleResolution": "Node", 7 | "strict": true, 8 | "jsx": "preserve", 9 | "resolveJsonModule": true, 10 | "isolatedModules": true, 11 | "esModuleInterop": true, 12 | "lib": ["ESNext", "DOM"], 13 | "skipLibCheck": true, 14 | "noEmit": true, 15 | "declaration": true, 16 | "declarationDir": "./types", 17 | "paths": { 18 | "@/*": ["./src/*"] 19 | } 20 | }, 21 | "include": [ 22 | "src/**/*.ts", 23 | "src/*.d.ts", 24 | "src/**/*.tsx", 25 | "src/**/*.vue", 26 | "src/**/*.ce.vue" 27 | ], 28 | "references": [{ "path": "./tsconfig.node.json" }] 29 | } 30 | -------------------------------------------------------------------------------- /packages/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | # https://vitepress.dev/reference/default-theme-home-page 3 | layout: home 4 | 5 | hero: 6 | name: 'CodePlayer' 7 | text: '超快的 WebIDE' 8 | tagline: 一款轻量、免登录、极快运行速度的 WebIDE 9 | image: 10 | src: /logo.svg 11 | alt: logo 12 | actions: 13 | - theme: brand 14 | text: 快速开始 15 | link: /guide/start 16 | - theme: alt 17 | text: 加入用户群 18 | link: /more/feedback 19 | 20 | features: 21 | - icon: 🚀 22 | title: 极致的运行速度 23 | details: 能在 3 秒内完成依赖下载、代码编译及运行等全部流程,速度远超 CodeSandbox、Stackblitz 等同类型产品 24 | - icon: 📖 25 | title: 免登录直接使用 26 | details: 无需注册登录,直接在线编写 demo,demo 文件及代码将通过 Hash 和压缩后自动同步至 url 以进行保存及分享 27 | - icon: 🎨 28 | title: 广泛的语法支持 29 | details: 支持 html、javascript、typescript、react、vue、css、less、sass 等多种 web 相关的代码编写和运行 30 | --- 31 | -------------------------------------------------------------------------------- /packages/core/src/utils/str.ts: -------------------------------------------------------------------------------- 1 | import { zlibSync, unzlibSync, strToU8, strFromU8 } from 'fflate'; 2 | 3 | // 将 utf8 转换为压缩字符串 4 | export function utoa(data: string): string { 5 | const buffer = strToU8(data); 6 | const zipped = zlibSync(buffer, { level: 9 }); 7 | const binary = strFromU8(zipped, true); 8 | return btoa(binary); 9 | } 10 | 11 | // 将压缩字符串转换为utf8 12 | export function atou(base64: string): string { 13 | const binary = atob(base64); 14 | 15 | // zlib header (x78), level 9 (xDA) 16 | if (binary.startsWith('\x78\xDA')) { 17 | const buffer = strToU8(binary, true); 18 | const unzipped = unzlibSync(buffer); 19 | return strFromU8(unzipped); 20 | } 21 | 22 | // old unicode hacks for backward compatibility 23 | // https://base64.guru/developers/javascript/examples/unicode-strings 24 | return decodeURIComponent(escape(binary)); 25 | } 26 | -------------------------------------------------------------------------------- /packages/core/src/components/index.less: -------------------------------------------------------------------------------- 1 | @import './splitter/index.less'; 2 | @import './file-bar/index.less'; 3 | @import './preview/index.less'; 4 | .codeplayer-container { 5 | border-radius: 4px; 6 | display: flex; 7 | flex-direction: column; 8 | ::-webkit-scrollbar { 9 | background-color: @bg-layout; 10 | width: 8px; 11 | height: 8px; 12 | // width: 36px; 13 | } 14 | ::-webkit-scrollbar-thumb { 15 | background-color: @border-color; 16 | border-radius: @border-radius-circle; 17 | &:hover { 18 | background-color: @border-color-hover; 19 | } 20 | &:active { 21 | background-color: @border-color-active; 22 | } 23 | } 24 | .main-content { 25 | display: flex; 26 | position: relative; 27 | height: calc(100% - 28px); 28 | width: 100%; 29 | order: 2; 30 | } 31 | .main-content-top { 32 | order: 1; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /packages/core/src/compiler/transform/plugins/index.ts: -------------------------------------------------------------------------------- 1 | import transformTsPlugin from './transform-ts'; 2 | import transformVue3Plugin from './transform-vue3'; 3 | import transformVue2Plugin from './transform-vue2'; 4 | import transformReactPlugin from './transform-react'; 5 | import transformCssPlugin from './transform-css'; 6 | import transformScssPlugin from './transform-scss'; 7 | import transformLessPlugin from './transform-less'; 8 | import compileModulePlugin from '@/compiler/plugins/module-factory'; 9 | import emitHtmlPlugin from '@/compiler/plugins/emit-html'; 10 | 11 | export const builtInPlugins = (vueVersion = 3) => [ 12 | transformTsPlugin, 13 | vueVersion.toString() === '2' ? transformVue2Plugin : transformVue3Plugin, 14 | transformReactPlugin, 15 | transformCssPlugin, 16 | transformScssPlugin, 17 | transformLessPlugin, 18 | compileModulePlugin, 19 | emitHtmlPlugin, 20 | ]; 21 | -------------------------------------------------------------------------------- /packages/website/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | CodePlayer 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/core/src/compiler/transform/plugins/transform-less.ts: -------------------------------------------------------------------------------- 1 | import less from 'less'; 2 | import { Hooks, ComplierPluginParams } from '@/compiler/type'; 3 | 4 | export async function transformLess( 5 | params: ComplierPluginParams 6 | ): Promise { 7 | const { fileMap } = params; 8 | const files = Object.keys(fileMap).map((filename) => fileMap[filename]); 9 | const errors: Error[] = []; 10 | 11 | await Promise.all( 12 | files 13 | .filter((file) => file.filename.endsWith('.less')) 14 | .map(async (file) => { 15 | let { code } = file; 16 | 17 | try { 18 | code = (await less.render(code)).css; 19 | file.compiled.css = code; 20 | } catch (error) { 21 | errors.push(error as Error); 22 | } 23 | }) 24 | ); 25 | 26 | return errors.length ? errors : undefined; 27 | } 28 | 29 | export default function (hooks: Hooks) { 30 | hooks.hook('transform', transformLess); 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/src/compiler/type.ts: -------------------------------------------------------------------------------- 1 | import { Hookable } from 'hookable'; 2 | import * as monaco from 'monaco-editor'; 3 | 4 | export type Hooks = Hookable, string>; 5 | 6 | export type Plugin = (hooks: Hooks) => void; 7 | 8 | export interface ComplierPluginParams { 9 | fileMap: Record; 10 | result: { errors: Error[] }; 11 | entry: string; 12 | iframe: HTMLIFrameElement; 13 | render: boolean; 14 | } 15 | 16 | export interface ComplierPluginResult { 17 | modules: Array; 18 | styles: Array; 19 | links: Array; 20 | html: Array; 21 | } 22 | 23 | export class File { 24 | filename: string; 25 | code: string; 26 | compiled = { 27 | js: '', 28 | css: '', 29 | }; 30 | editorViewState: monaco.editor.ICodeEditorViewState | null; 31 | 32 | constructor(filename: string, code = '') { 33 | this.filename = filename; 34 | this.code = code; 35 | this.editorViewState = null; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/website/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import path from 'path'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | base: 8 | process.env.NODE_ENV == 'production' 9 | ? 'https://cdn.jsdelivr.net/gh/zh-lx/codeplayer/packages/website/dist/' 10 | : './', 11 | plugins: [vue()], 12 | resolve: { 13 | alias: { 14 | '@': path.resolve(__dirname, '../core/src'), 15 | '~@': path.resolve(__dirname, '../core/src'), 16 | path: 'path-browserify', 17 | }, 18 | }, 19 | css: { 20 | preprocessorOptions: { 21 | less: { 22 | additionalData: `@import "../core/src/style/index.less";`, 23 | }, 24 | }, 25 | }, 26 | server: { 27 | host: '0.0.0.0', 28 | fs: { 29 | strict: false, 30 | }, 31 | }, 32 | 33 | build: { 34 | rollupOptions: { 35 | output: { 36 | assetFileNames: () => `[name]-[hash].[ext]`, 37 | }, 38 | }, 39 | }, 40 | }); 41 | -------------------------------------------------------------------------------- /packages/core/src/assets/ts.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_typescript 3 | 6 | -------------------------------------------------------------------------------- /packages/core/src/compiler/transform/plugins/transform-scss.ts: -------------------------------------------------------------------------------- 1 | import { Hooks, ComplierPluginParams } from '@/compiler/type'; 2 | import { compileString } from 'sass'; 3 | 4 | export async function transformSaSS( 5 | params: ComplierPluginParams 6 | ): Promise { 7 | const { fileMap } = params; 8 | const files = Object.keys(fileMap).map((filename) => fileMap[filename]); 9 | const errors: Error[] = []; 10 | 11 | await Promise.all( 12 | files 13 | .filter( 14 | ({ filename }) => 15 | filename.endsWith('.sass') || filename.endsWith('.scss') 16 | ) 17 | .map(async (file) => { 18 | let { code } = file; 19 | 20 | try { 21 | code = (await compileString(code)).css; 22 | file.compiled.css = code; 23 | } catch (error) { 24 | errors.push(error as Error); 25 | } 26 | }) 27 | ); 28 | 29 | return errors.length ? errors : undefined; 30 | } 31 | 32 | export default function (hooks: Hooks) { 33 | hooks.hook('transform', transformSaSS); 34 | } 35 | -------------------------------------------------------------------------------- /packages/website/dist/assets/index-eba15397.js: -------------------------------------------------------------------------------- 1 | import{d as i,c as p,u as a,o as l,E as u,a as f}from"./index-8e8c1687-18fcf4d9.js";(function(){const o=document.createElement("link").relList;if(o&&o.supports&&o.supports("modulepreload"))return;for(const e of document.querySelectorAll('link[rel="modulepreload"]'))n(e);new MutationObserver(e=>{for(const t of e)if(t.type==="childList")for(const c of t.addedNodes)c.tagName==="LINK"&&c.rel==="modulepreload"&&n(c)}).observe(document,{childList:!0,subtree:!0});function r(e){const t={};return e.integrity&&(t.integrity=e.integrity),e.referrerpolicy&&(t.referrerPolicy=e.referrerpolicy),e.crossorigin==="use-credentials"?t.credentials="include":e.crossorigin==="anonymous"?t.credentials="omit":t.credentials="same-origin",t}function n(e){if(e.ep)return;e.ep=!0;const t=r(e);fetch(e.href,t)}})();const d=i({__name:"App",setup(s){const o={appType:"vue3"};return(r,n)=>(l(),p(a(u),{options:o,class:"codeplayer-container"}))}});const _=(s,o)=>{const r=s.__vccOpts||s;for(const[n,e]of o)r[n]=e;return r},m=_(d,[["__scopeId","data-v-230cf52d"]]),y=f(m);y.mount("#app"); 2 | -------------------------------------------------------------------------------- /packages/core/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import dts from 'vite-plugin-dts'; 4 | import path from 'path'; 5 | 6 | // https://vitejs.dev/config/ 7 | export default defineConfig({ 8 | plugins: [ 9 | vue(), 10 | dts({ 11 | outDir: './types', 12 | }), 13 | ], 14 | resolve: { 15 | alias: { 16 | '@': path.resolve(__dirname, './src'), 17 | '~@': path.resolve(__dirname, './src'), 18 | path: 'path-browserify', 19 | }, 20 | }, 21 | css: { 22 | preprocessorOptions: { 23 | less: { 24 | additionalData: `@import "src/style/index.less";`, 25 | }, 26 | }, 27 | }, 28 | define: { 29 | 'process.env.NODE_ENV': '"production"', 30 | }, 31 | base: './', 32 | build: { 33 | emptyOutDir: true, 34 | lib: { 35 | entry: { 36 | index: './src/index.ts', 37 | }, 38 | formats: ['es', 'cjs'], 39 | fileName: '[name]', 40 | }, 41 | rollupOptions: { 42 | external: [/^vue/], 43 | output: {}, 44 | }, 45 | }, 46 | }); 47 | -------------------------------------------------------------------------------- /packages/website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "0.0.1", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vue-tsc && vite build && node ./scripts/index.js", 7 | "preview": "vite preview" 8 | }, 9 | "devDependencies": { 10 | "@babel/standalone": "^7.20.11", 11 | "@babel/types": "^7.20.7", 12 | "@types/hash-sum": "^1.0.0", 13 | "@types/less": "^3.0.3", 14 | "@types/node": "^18.11.18", 15 | "@vitejs/plugin-vue": "^4.0.0", 16 | "@vue/compiler-sfc": "^3.2.45", 17 | "fflate": "^0.7.4", 18 | "hash-sum": "^2.0.0", 19 | "hookable": "^5.5.3", 20 | "less": "^4.2.0", 21 | "monaco-editor-core": "0.41.0", 22 | "monaco-volar": "^0.4.0", 23 | "rollup-plugin-visualizer": "^5.9.0", 24 | "sass": "^1.66.1", 25 | "sucrase": "^3.29.0", 26 | "tslib": "^2.5.0", 27 | "typescript": "^4.9.3", 28 | "vite": "^4.1.0", 29 | "vue": "^3.2.45", 30 | "vue-tsc": "^1.0.24" 31 | }, 32 | "dependencies": { 33 | "codeplayer": "0.0.1-beta.2", 34 | "path-browserify": "^1.0.1", 35 | "tippy.js": "^6.3.7" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/website/dist/assets/azcli-deb61577-f1f7c576.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"#"}},t={defaultToken:"keyword",ignoreCase:!0,tokenPostfix:".azcli",str:/[^#\s]/,tokenizer:{root:[{include:"@comment"},[/\s-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":{token:"key.identifier",next:"@type"}}}],[/^-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":{token:"key.identifier",next:"@type"}}}]],type:[{include:"@comment"},[/-+@str*\s*/,{cases:{"@eos":{token:"key.identifier",next:"@popall"},"@default":"key.identifier"}}],[/@str+\s*/,{cases:{"@eos":{token:"string",next:"@popall"},"@default":"string"}}]],comment:[[/#.*$/,{cases:{"@eos":{token:"comment",next:"@popall"}}}]]}};export{e as conf,t as language}; 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 zhoulixiang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/core/src/compiler/transform/plugins/transform-react.ts: -------------------------------------------------------------------------------- 1 | import { transform } from 'sucrase'; 2 | import { Hooks, ComplierPluginParams } from '@/compiler/type'; 3 | 4 | export async function transformReact( 5 | params: ComplierPluginParams 6 | ): Promise { 7 | const { fileMap } = params; 8 | const files = Object.keys(fileMap).map((filename) => fileMap[filename]); 9 | const errors: Error[] = []; 10 | 11 | await Promise.all( 12 | files 13 | .filter( 14 | ({ filename }) => filename.endsWith('.tsx') || filename.endsWith('.jsx') 15 | ) 16 | .map(async (file) => { 17 | let { code } = file; 18 | 19 | try { 20 | code = await transform(code, { 21 | transforms: ['typescript', 'jsx'], 22 | production: true, 23 | }).code; 24 | file.compiled.js = code; 25 | } catch (error) { 26 | errors.push(error as Error); 27 | } 28 | }) 29 | ); 30 | 31 | return errors.length ? errors : undefined; 32 | } 33 | 34 | export default function (hooks: Hooks) { 35 | hooks.hook('transform', transformReact); 36 | } 37 | -------------------------------------------------------------------------------- /packages/docs/reference/deploy.md: -------------------------------------------------------------------------------- 1 | # 组件式使用 2 | 3 | codeplayer 本身是一个 vue3 组件,因此支持在 vue3 项目中以组件的方式使用,以便于进入进行私有化部署。 4 | 5 | ## 安装 6 | 7 | 选择一个你喜欢的包管理器进行安装: 8 | 9 | ```sh 10 | npm i codeplayer 11 | # or 12 | yarn add codeplayer 13 | # or 14 | pnpm add codeplayer 15 | ``` 16 | 17 | ## 使用 18 | 19 | 如下代码是一个引入 `codeplayer` 并使用的示例: 20 | 21 | ::: code-group 22 | 23 | ```html [App.vue] 24 | 27 | 28 | 35 | 36 | 42 | ``` 43 | 44 | ```ts [main.ts] 45 | import { createApp } from 'vue'; 46 | import 'codeplayer/dist/style.css'; 47 | 48 | import App from './App.vue'; 49 | 50 | const app = createApp(App); 51 | app.mount('#app'); 52 | ``` 53 | 54 | ::: 55 | 56 | ## 配置 57 | 58 | 可以通过 `options` 参数对 `codeplayer` 进行配置,`options` 参数的属性同[指南-配置](/guide/config) 一节。 59 | -------------------------------------------------------------------------------- /packages/core/src/constant/index.ts: -------------------------------------------------------------------------------- 1 | export const COMP_IDENTIFIER = `__sfc__`; 2 | export const modulesKey = `__modules__`; 3 | export const exportKey = `__export__`; 4 | export const dynamicImportKey = `__dynamic_import__`; 5 | export const moduleKey = `__module__`; 6 | export const nextKey = '__next__'; 7 | export const scriptRE = /]*>|>)([^]*?)<\/script>/gi; 8 | export const styleRE = /]*>|>)([^]*?)<\/style>/gi; 9 | export const scriptModuleRE = 10 | /]*type\s*=\s*(?:"module"|'module')[^>]*>([^]*?)<\/script>/gi; 11 | export const MapFile = 'import-map.json'; 12 | export const version = '3.2.45'; 13 | export const defaultentry = 'index.html'; 14 | export const fileTypes = [ 15 | '.html', 16 | '.js', 17 | '.css', 18 | '.vue', 19 | '.ts', 20 | 'jsx', 21 | 'tsx', 22 | 'json', 23 | '.less', 24 | '.scss', 25 | '.sass', 26 | ]; 27 | export const extensions = ['.js', '.ts', '.json', '.jsx', '.tsx', '.vue']; 28 | export const URLCodeKey = '_codeplayer_code'; 29 | export * from './tooltip'; 30 | 31 | export const CodeSizes = [12, 13, 14, 15, 16, 17, 18]; 32 | export const LocalThemeKey = 'codeplayer_local_theme_key'; 33 | -------------------------------------------------------------------------------- /packages/website/scripts/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const directoryPath = path.resolve(__dirname, '../dist'); // 指定要遍历的目录 5 | 6 | function replaceTextInFile(filePath, search, replace) { 7 | let data = fs.readFileSync(filePath, 'utf8'); 8 | while (data.includes(search)) { 9 | data = data.replace(search, replace); 10 | } 11 | // 写入更新后的内容回到文件 12 | fs.writeFileSync(filePath, data, 'utf8'); 13 | } 14 | 15 | function traverseDirectory(dir) { 16 | const files = fs.readdirSync(dir); 17 | files.forEach((file) => { 18 | const filePath = path.join(dir, file); 19 | const stat = fs.statSync(filePath); 20 | if (stat.isDirectory()) { 21 | // 递归遍历子目录 22 | traverseDirectory(filePath); 23 | } else { 24 | // 处理文件中的文本替换 25 | replaceTextInFile( 26 | filePath, 27 | `""+new URL(`, 28 | `URL.createObjectURL(new Blob(['importScripts(` 29 | ); 30 | replaceTextInFile( 31 | filePath, 32 | ',self.location).href', 33 | `);'],{type:"text/javascript"}))` 34 | ); 35 | } 36 | }); 37 | } 38 | 39 | traverseDirectory(directoryPath); 40 | -------------------------------------------------------------------------------- /packages/core/src/assets/html.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_html 3 | 6 | 8 | 11 | 14 | 17 | 20 | -------------------------------------------------------------------------------- /packages/core/src/compiler/transform/plugins/transform-ts.ts: -------------------------------------------------------------------------------- 1 | import { transform } from 'sucrase'; 2 | import { Hooks, ComplierPluginParams } from '@/compiler/type'; 3 | 4 | export async function transformTS( 5 | params: ComplierPluginParams 6 | ): Promise { 7 | const { fileMap } = params; 8 | const files = Object.keys(fileMap).map((filename) => fileMap[filename]); 9 | const errors: Error[] = []; 10 | 11 | await Promise.all( 12 | files 13 | .filter( 14 | ({ filename }) => filename.endsWith('.ts') || filename.endsWith('.js') 15 | ) 16 | .map(async (file) => { 17 | let { filename, code } = file; 18 | 19 | try { 20 | if (filename.endsWith('.ts')) { 21 | code = await transform(code, { 22 | transforms: ['typescript'], 23 | }).code; 24 | } 25 | 26 | file.compiled.js = code; 27 | } catch (error) { 28 | errors.push(error as Error); 29 | } 30 | }) 31 | ); 32 | 33 | return errors.length ? errors : undefined; 34 | } 35 | 36 | export default function (hooks: Hooks) { 37 | hooks.hook('transform', transformTS); 38 | } 39 | -------------------------------------------------------------------------------- /packages/core/src/components/file-bar/index.less: -------------------------------------------------------------------------------- 1 | .codeplayer-files-container { 2 | .files-container { 3 | .file-list { 4 | .file-item { 5 | .file-right { 6 | .file-option-button { 7 | display: none; 8 | } 9 | } 10 | &:hover { 11 | color: var(--codeplayer-brand); 12 | .file-right { 13 | .file-option-button { 14 | display: block; 15 | } 16 | } 17 | } 18 | .home-operate, 19 | .delete-operate { 20 | margin-left: 2px; 21 | } 22 | .current-home-operate { 23 | color: @danger !important; 24 | display: block !important; 25 | } 26 | .hide-file-operate { 27 | display: none; 28 | } 29 | } 30 | } 31 | } 32 | .operate-btn { 33 | display: flex; 34 | align-items: center; 35 | .file-option-button { 36 | cursor: pointer; 37 | &:hover { 38 | color: var(--codeplayer-brand); 39 | } 40 | &:active { 41 | color: var(--codeplayer-brand-active); 42 | } 43 | } 44 | } 45 | .import-map-container { 46 | border-top: 1px solid @border-color; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/website/dist/assets/javascript-3aab9677-e6c2c027.js: -------------------------------------------------------------------------------- 1 | import{conf as t,language as e}from"./typescript-7500bb50-b3387507.js";import"./index-8e8c1687-18fcf4d9.js";/*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var o=t,r={defaultToken:"invalid",tokenPostfix:".js",keywords:["break","case","catch","class","continue","const","constructor","debugger","default","delete","do","else","export","extends","false","finally","for","from","function","get","if","import","in","instanceof","let","new","null","return","set","static","super","switch","symbol","this","throw","true","try","typeof","undefined","var","void","while","with","yield","async","await","of"],typeKeywords:[],operators:e.operators,symbols:e.symbols,escapes:e.escapes,digits:e.digits,octaldigits:e.octaldigits,binarydigits:e.binarydigits,hexdigits:e.hexdigits,regexpctl:e.regexpctl,regexpesc:e.regexpesc,tokenizer:e.tokenizer};export{o as conf,r as language}; 7 | -------------------------------------------------------------------------------- /packages/core/src/templates/javascript.ts: -------------------------------------------------------------------------------- 1 | import { MapFile } from '@/constant'; 2 | 3 | const indexHtml = ` 4 | 5 | 6 | 7 | 8 | 9 | 10 | CodePlayer 11 | 12 | 13 | 14 | 17 | 18 | `.trim(); 19 | 20 | const indexJs = ` 21 | import layui from "layui"; 22 | import "layui/dist/css/layui.css"; 23 | 24 | layer.open({ 25 | type: 1, // page 层类型 26 | area: ['500px', '300px'], 27 | title: 'Hello layer', 28 | shade: 0.6, // 遮罩透明度 29 | shadeClose: true, // 点击遮罩区域,关闭弹层 30 | maxmin: true, // 允许全屏最小化 31 | anim: 0, // 0-6 的动画形式,-1 不开启 32 | content: '
一个普通的页面层,传入了自定义的 HTML
' 33 | }); 34 | `.trim(); 35 | 36 | const importMap = ` 37 | { 38 | "imports": { 39 | "layui": "https://esm.sh/layui@2.8.16", 40 | "layui/": "https://esm.sh/layui@2.8.16/" 41 | } 42 | } 43 | `.trim(); 44 | 45 | export const JsTemplate = { 46 | 'index.html': indexHtml, 47 | 'index.js': indexJs, 48 | [MapFile]: importMap, 49 | }; 50 | -------------------------------------------------------------------------------- /packages/core/src/templates/typescript.ts: -------------------------------------------------------------------------------- 1 | import { MapFile } from '@/constant'; 2 | 3 | const indexHtml = ` 4 | 5 | 6 | 7 | 8 | 9 | 10 | CodePlayer 11 | 12 | 13 | 14 | 17 | 18 | `.trim(); 19 | 20 | const indexTs = ` 21 | import layui from "layui"; 22 | import "layui/dist/css/layui.css"; 23 | 24 | layer.open({ 25 | type: 1, // page 层类型 26 | area: ['500px', '300px'], 27 | title: 'Hello layer', 28 | shade: 0.6, // 遮罩透明度 29 | shadeClose: true, // 点击遮罩区域,关闭弹层 30 | maxmin: true, // 允许全屏最小化 31 | anim: 0, // 0-6 的动画形式,-1 不开启 32 | content: '
一个普通的页面层,传入了自定义的 HTML
' 33 | }); 34 | `.trim(); 35 | 36 | const importMap = ` 37 | { 38 | "imports": { 39 | "layui": "https://esm.sh/layui@2.8.16", 40 | "layui/": "https://esm.sh/layui@2.8.16/" 41 | } 42 | } 43 | `.trim(); 44 | 45 | export const TsTemplate = { 46 | 'index.html': indexHtml, 47 | 'index.ts': indexTs, 48 | [MapFile]: importMap, 49 | }; 50 | -------------------------------------------------------------------------------- /packages/core/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 12 | 14 | 16 | 19 | -------------------------------------------------------------------------------- /packages/website/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 12 | 14 | 16 | 19 | -------------------------------------------------------------------------------- /packages/docs/public/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 12 | 14 | 16 | 19 | -------------------------------------------------------------------------------- /packages/website/dist/logo-ff272dde.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 10 | 12 | 14 | 16 | 19 | -------------------------------------------------------------------------------- /packages/core/src/assets/css.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_css 3 | 6 | 8 | 11 | 14 | 17 | 20 | 23 | -------------------------------------------------------------------------------- /packages/core/src/assets/sass.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_scss 3 | 6 | -------------------------------------------------------------------------------- /packages/core/src/assets/scss.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_scss 3 | 6 | -------------------------------------------------------------------------------- /packages/core/src/components/file-bar/icons/add-file.vue: -------------------------------------------------------------------------------- 1 | 29 | 45 | -------------------------------------------------------------------------------- /packages/website/dist/assets/ini-0cf51c96-18bf1153.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},n={defaultToken:"",tokenPostfix:".ini",escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[[/^\[[^\]]*\]/,"metatag"],[/(^\w+)(\s*)(\=)/,["key","","delimiter"]],{include:"@whitespace"},[/\d+/,"number"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string",'@string."'],[/'/,"string","@string.'"]],whitespace:[[/[ \t\r\n]+/,""],[/^\s*[#;].*$/,"comment"]],string:[[/[^\\"']+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/["']/,{cases:{"$#==$S2":{token:"string",next:"@pop"},"@default":"string"}}]]}};export{e as conf,n as language}; 7 | -------------------------------------------------------------------------------- /packages/core/src/components/file-bar/icons/rename-file.vue: -------------------------------------------------------------------------------- 1 | 29 | 45 | -------------------------------------------------------------------------------- /packages/core/src/components/splitter/index.less: -------------------------------------------------------------------------------- 1 | .codeplayer-splitter { 2 | --codeplayer-border-primary: @border-color; 3 | --codeplayer-border-brand: @brand-light-border; 4 | display: flex; 5 | position: relative; 6 | height: 100%; 7 | width: 100%; 8 | box-sizing: border-box; 9 | user-select: none; 10 | &:hover { 11 | user-select: initial; 12 | } 13 | .splitter-left { 14 | border-right: 1px solid var(--codeplayer-border-color); 15 | position: relative; 16 | } 17 | .splitter-right { 18 | position: relative; 19 | flex: 1; 20 | overflow: hidden; 21 | } 22 | .splitter-mask { 23 | position: absolute; 24 | height: 100%; 25 | width: 100%; 26 | top: 0; 27 | left: 0; 28 | z-index: 3; 29 | } 30 | .splitter-mask-hidden { 31 | display: none; 32 | } 33 | .dragger { 34 | position: absolute; 35 | z-index: 99; 36 | top: 0; 37 | bottom: 0; 38 | right: -3px; 39 | width: 6px; 40 | cursor: col-resize; 41 | &:hover { 42 | background-color: @brand-light-border !important; 43 | } 44 | } 45 | .vertical-dragger { 46 | position: absolute; 47 | z-index: 99; 48 | bottom: -3px; 49 | height: 6px; 50 | left: 0; 51 | right: 0; 52 | width: 100%; 53 | cursor: row-resize; 54 | &:hover { 55 | background-color: @brand-light-border !important; 56 | } 57 | } 58 | } 59 | .codeplayer-splitter-vertical { 60 | flex-direction: column; 61 | } 62 | -------------------------------------------------------------------------------- /packages/core/src/compiler/file-system/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HtmlTemplate, 3 | JsTemplate, 4 | ReactTemplate, 5 | TsTemplate, 6 | Vue3Template, 7 | Vue2Template, 8 | } from '@/templates'; 9 | import { File } from '@/compiler/type'; 10 | 11 | export interface FileSystem { 12 | // 全部文件 13 | files: Record; 14 | // 入口文件 15 | entry: string; 16 | // 当前编辑中的文件 17 | activeFile: string; 18 | // imports map 19 | imports: Record; 20 | } 21 | 22 | export const getTemplate = (appType: string = 'vue3') => { 23 | if (appType === 'vue3' || appType === 'vue') { 24 | return Vue3Template; 25 | } else if (appType === 'vue2') { 26 | return Vue2Template; 27 | } else if (appType === 'react') { 28 | return ReactTemplate; 29 | } else if (appType === 'html') { 30 | return HtmlTemplate; 31 | } else if (appType === 'javascript' || 'js') { 32 | return JsTemplate; 33 | } else { 34 | return TsTemplate; 35 | } 36 | }; 37 | 38 | export const getFileExtraName = (filename: string) => { 39 | const segments = filename?.split('.'); 40 | return segments[segments.length - 1]; 41 | }; 42 | 43 | export const getFileLanguage = (filename: string) => { 44 | const ext = getFileExtraName(filename); 45 | if (ext === 'js' || ext === 'jsx') { 46 | return 'javascript'; 47 | } else if (ext === 'ts' || ext === 'tsx') { 48 | return 'typescript'; 49 | } else if (['css', 'less', 'sass', 'scss'].includes(ext)) { 50 | return 'css'; 51 | } else { 52 | return ext; 53 | } 54 | }; 55 | -------------------------------------------------------------------------------- /packages/core/src/components/toolbar/icons/refresh.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 54 | 57 | -------------------------------------------------------------------------------- /packages/website/README.md: -------------------------------------------------------------------------------- 1 | # Vue 3 + TypeScript + Vite 2 | 3 | This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` 35 | 36 | 56 | 59 | -------------------------------------------------------------------------------- /packages/core/src/assets/json.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_json 3 | 6 | 9 | -------------------------------------------------------------------------------- /packages/core/src/components/menus/utils/getInfo.ts: -------------------------------------------------------------------------------- 1 | export const setCss = (node: HTMLElement, styles: string): void => { 2 | node.style.cssText = node.style.cssText 3 | ? (node.style.cssText += styles) 4 | : styles 5 | } 6 | 7 | export const getWidth: (node: HTMLElement) => number = (node) => 8 | node.getBoundingClientRect().width 9 | 10 | export const getHeight: (node: HTMLElement) => number = (node) => 11 | node.getBoundingClientRect().height 12 | 13 | export const getLeft: (node: HTMLElement) => number = (node) => 14 | node.getBoundingClientRect().left 15 | 16 | export const getRight: (node: HTMLElement) => number = (node) => 17 | node.getBoundingClientRect().right 18 | 19 | export const getTop: (node: HTMLElement) => number = (node) => 20 | node.getBoundingClientRect().top 21 | 22 | export const getBottom: (node: HTMLElement) => number = (node) => 23 | node.getBoundingClientRect().bottom 24 | 25 | export const getX: (node: HTMLElement) => number = (node) => 26 | node.getBoundingClientRect().x 27 | 28 | export const getY: (node: HTMLElement) => number = (node) => 29 | node.getBoundingClientRect().y 30 | 31 | /** 32 | * 获取元素在窗口中的几何属性 33 | * bottom = y + height = top + height 34 | * right = x + width = left + width 35 | * @param { HTMLElement | MouseEvent } node 元素 36 | * @returns { width, height, left, right, top, bottom, x, y } 37 | */ 38 | export const computeRectPosition: (node: HTMLElement | MouseEvent) => { 39 | x: number 40 | y: number 41 | width: number 42 | height: number 43 | left?: number 44 | right?: number 45 | top?: number 46 | bottom?: number 47 | } = (node) => (node as HTMLElement).getBoundingClientRect?.() || node 48 | -------------------------------------------------------------------------------- /packages/website/dist/assets/csp-80865a3e-d207cac4.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var t={brackets:[],autoClosingPairs:[],surroundingPairs:[]},r={keywords:[],typeKeywords:[],tokenPostfix:".csp",operators:[],symbols:/[=> 5 | 6 | 7 | 8 | 9 | 10 | CodePlayer 11 | 12 | 13 |
14 | 15 | 18 | 19 | `.trim(); 20 | 21 | const mainTsx = ` 22 | import React from "react"; 23 | import { createRoot } from "react-dom/client"; 24 | import App from './App.tsx'; 25 | 26 | const root = createRoot(document.getElementById('app')); 27 | root.render() 28 | `.trim(); 29 | 30 | const appTsx = ` 31 | import React from 'react'; 32 | import { Button, Space } from 'antd'; 33 | 34 | const App: React.FC = () => ( 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | ); 43 | 44 | export default App; 45 | `.trim(); 46 | 47 | const importMap = ` 48 | { 49 | "imports": { 50 | "react": "https://esm.sh/react@18.2.0", 51 | "react-dom/": "https://esm.sh/react-dom@18.2.0/", 52 | "antd": "https://esm.sh/antd@5.8.5", 53 | "@antd/": "https://esm.sh/@antd@5.8.5/" 54 | } 55 | } 56 | `.trim(); 57 | 58 | export const ReactTemplate = { 59 | 'index.html': indexHtml, 60 | 'main.tsx': mainTsx, 61 | 'App.tsx': appTsx, 62 | [MapFile]: importMap, 63 | }; 64 | -------------------------------------------------------------------------------- /packages/docs/.vitepress/config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitepress'; 2 | 3 | // https://vitepress.dev/reference/site-config 4 | export default defineConfig({ 5 | title: 'CodePlayer', 6 | description: '浏览器端进行 Web 代码的编写及运行预览', 7 | base: '/docs/', 8 | themeConfig: { 9 | logo: '/logo.svg', 10 | // https://vitepress.dev/reference/default-theme-config 11 | // nav: [{ text: '首页', link: '/' }], 12 | search: { 13 | provider: 'local', 14 | }, 15 | outline: [2, 3], 16 | sidebar: [ 17 | { 18 | text: '指南', 19 | items: [ 20 | { text: '介绍', link: '/guide/introduction' }, 21 | { text: '快速开始', link: '/guide/start' }, 22 | ], 23 | }, 24 | { 25 | text: '参考', 26 | items: [ 27 | { text: '第三方依赖(importmap)', link: '/guide/importmap' }, 28 | { text: '配置', link: '/guide/config' }, 29 | { text: '组件式使用', link: '/reference/deploy' }, 30 | { text: '支持语法', link: '/reference/support' }, 31 | ], 32 | }, 33 | { 34 | text: '更多', 35 | items: [{ text: '交流与反馈', link: '/more/feedback' }], 36 | }, 37 | ], 38 | nav: [ 39 | { text: '在线体验', link: 'https://play.fe-dev.cn', target: '_blank' }, 40 | ], 41 | socialLinks: [ 42 | { icon: 'github', link: 'https://github.com/zh-lx/codeplayer' }, 43 | ], 44 | }, 45 | // locales: { 46 | // root: { 47 | // label: '简体中文', 48 | // lang: 'zh', 49 | // }, 50 | // fr: { 51 | // label: 'English', 52 | // lang: 'en', 53 | // link: 'https://en.inspector.fe-dev.cn', // default /fr/ -- shows on navbar translations menu, can be external 54 | // }, 55 | // }, 56 | }); 57 | -------------------------------------------------------------------------------- /packages/core/src/templates/vue3.ts: -------------------------------------------------------------------------------- 1 | import { MapFile } from '@/constant'; 2 | 3 | const indexHtml = ` 4 | 5 | 6 | 7 | 8 | 9 | 10 | CodePlayer 11 | 12 | 13 |
14 | 15 | 18 | 19 | `.trim(); 20 | 21 | const mainTs = ` 22 | import { createApp } from 'vue' 23 | import ArcoVue from '@arco-design/web-vue'; 24 | import App from './App.vue'; 25 | import '@arco-design/web-vue/dist/arco.css'; 26 | 27 | const app = createApp(App); 28 | app.use(ArcoVue); 29 | app.mount('#app'); 30 | `.trim(); 31 | 32 | const appVue = ` 33 | 44 | 45 | 50 | `.trim(); 51 | 52 | const importMap = ` 53 | { 54 | "imports": { 55 | "vue": "https://esm.sh/vue@latest", 56 | "@arco-design/web-vue": "https://esm.sh/@arco-design/web-vue?deps=vue@latest", 57 | "@arco-design/web-vue/": "https://esm.sh/@arco-design/web-vue/" 58 | } 59 | } 60 | `.trim(); 61 | 62 | export const Vue3Template = { 63 | 'index.html': indexHtml, 64 | 'main.ts': mainTs, 65 | 'App.vue': appVue, 66 | [MapFile]: importMap, 67 | }; 68 | -------------------------------------------------------------------------------- /packages/core/src/components/toolbar/icons/docs.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 62 | 65 | -------------------------------------------------------------------------------- /packages/core/src/components/menus/utils/system.ts: -------------------------------------------------------------------------------- 1 | const userAgent = navigator.userAgent; 2 | 3 | export const isWin = 4 | navigator.platform === 'Win32' || navigator.platform === 'Windows'; 5 | export const isMac = 6 | navigator.platform === 'Mac68K' || 7 | navigator.platform === 'MacPPC' || 8 | navigator.platform === 'Macintosh' || 9 | navigator.platform === 'MacIntel'; 10 | 11 | export const isUnix = navigator.platform === 'X11' && !isWin && !isMac; 12 | export const isLinux = String(navigator.platform).indexOf('Linux') > -1; 13 | 14 | export const isWin2000 = 15 | userAgent.indexOf('Windows NT 5.0') > -1 || 16 | userAgent.indexOf('Windows 2000') > -1; 17 | export const isWinXP = 18 | userAgent.indexOf('Windows NT 5.1') > -1 || 19 | userAgent.indexOf('Windows XP') > -1; 20 | export const isWin2003 = 21 | userAgent.indexOf('Windows NT 5.2') > -1 || 22 | userAgent.indexOf('Windows 2003') > -1; 23 | export const isWinVista = 24 | userAgent.indexOf('Windows NT 6.0') > -1 || 25 | userAgent.indexOf('Windows Vista') > -1; 26 | export const isWin7 = 27 | userAgent.indexOf('Windows NT 6.1') > -1 || 28 | userAgent.indexOf('Windows 7') > -1; 29 | 30 | export const isWin8 = 31 | userAgent.indexOf('Windows NT 8') > -1 || userAgent.indexOf('Windows 8') > -1; 32 | export const isWin10 = 33 | userAgent.indexOf('Windows NT 10') > -1 || 34 | userAgent.indexOf('Windows 10') > -1; 35 | 36 | export const getOperatSystem = () => { 37 | const osList = { 38 | isWin10, 39 | isMac, 40 | isWin7, 41 | isWin8, 42 | isWin2003, 43 | isWin2000, 44 | isWinXP, 45 | isWinVista, 46 | isWin, 47 | isUnix, 48 | isLinux, 49 | }; 50 | for (const key in osList) { 51 | if (osList[key as keyof typeof osList]) { 52 | return key; 53 | } 54 | } 55 | // 如果没有对应的主题样式,默认引入mac的样式 56 | return 'isMac'; 57 | }; 58 | -------------------------------------------------------------------------------- /packages/core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "codeplayer", 3 | "version": "0.3.0", 4 | "main": "./dist/index.js", 5 | "module": "./dist/index.mjs", 6 | "typings": "./types/index.d.ts", 7 | "exports": { 8 | ".": { 9 | "import": { 10 | "types": "./types/index.d.ts", 11 | "default": "./dist/index.mjs" 12 | }, 13 | "require": { 14 | "types": "./types/index.d.ts", 15 | "default": "./dist/index.js" 16 | } 17 | }, 18 | "./dist/style.css": { 19 | "default": "./dist/style.css" 20 | } 21 | }, 22 | "files": [ 23 | "dist", 24 | "types" 25 | ], 26 | "scripts": { 27 | "dev": "vite", 28 | "build": "vue-tsc && vite build", 29 | "preview": "vite preview" 30 | }, 31 | "devDependencies": { 32 | "@babel/standalone": "^7.20.11", 33 | "@babel/types": "^7.20.7", 34 | "@types/hash-sum": "^1.0.0", 35 | "@types/less": "^3.0.3", 36 | "@types/node": "^18.11.18", 37 | "@vitejs/plugin-vue": "^4.0.0", 38 | "@vue/compiler-sfc": "^3.2.45", 39 | "compiler-sfc-browser-vue2": "^0.0.5", 40 | "fflate": "^0.7.4", 41 | "hash-sum": "^2.0.0", 42 | "hookable": "^5.5.3", 43 | "less": "^4.2.0", 44 | "monaco-volar": "^0.4.0", 45 | "rollup-plugin-visualizer": "^5.9.0", 46 | "sass": "^1.66.1", 47 | "sucrase": "^3.29.0", 48 | "tslib": "^2.5.0", 49 | "typescript": "^4.9.3", 50 | "vite": "^4.1.0", 51 | "vite-plugin-dts": "^3.6.1", 52 | "vue": "^3.2.45", 53 | "vue-tsc": "^1.0.24", 54 | "@volar/cdn": "~1.9.2", 55 | "@volar/monaco": "~1.9.2", 56 | "@volar/typescript": "~1.9.2", 57 | "@vue/language-service": "1.8.6", 58 | "monaco-editor": "0.41.0", 59 | "monaco-editor-textmate": "^4.0.0", 60 | "monaco-textmate": "^3.0.1", 61 | "onigasm": "^2.2.5", 62 | "path-browserify": "^1.0.1", 63 | "tippy.js": "^6.3.7" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/core/src/templates/html.ts: -------------------------------------------------------------------------------- 1 | import { MapFile } from '@/constant'; 2 | 3 | const indexHtml = ` 4 | 5 | 6 | 7 | 8 | 9 | 10 | Code player 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 | 32 | 33 | `.trim(); 34 | 35 | const importMap = ` 36 | { 37 | "imports": { 38 | "layui": "https://esm.sh/layui@2.8.16", 39 | "layui/": "https://esm.sh/layui@2.8.16/" 40 | } 41 | } 42 | `.trim(); 43 | 44 | export const HtmlTemplate = { 45 | 'index.html': indexHtml, 46 | [MapFile]: importMap, 47 | }; 48 | -------------------------------------------------------------------------------- /packages/core/src/components/toolbar/index.vue: -------------------------------------------------------------------------------- 1 | 26 | 27 | 41 | 42 | 71 | -------------------------------------------------------------------------------- /packages/website/dist/assets/pla-5b3c3b2c-1b3e1614.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"#"},brackets:[["[","]"],["<",">"],["(",")"]],autoClosingPairs:[{open:"[",close:"]"},{open:"<",close:">"},{open:"(",close:")"}],surroundingPairs:[{open:"[",close:"]"},{open:"<",close:">"},{open:"(",close:")"}]},o={defaultToken:"",tokenPostfix:".pla",brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"<",close:">",token:"delimiter.angle"},{open:"(",close:")",token:"delimiter.parenthesis"}],keywords:[".i",".o",".mv",".ilb",".ob",".label",".type",".phase",".pair",".symbolic",".symbolic-output",".kiss",".p",".e",".end"],comment:/#.*$/,identifier:/[a-zA-Z]+[a-zA-Z0-9_\-]*/,plaContent:/[01\-~\|]+/,tokenizer:{root:[{include:"@whitespace"},[/@comment/,"comment"],[/\.([a-zA-Z_\-]+)/,{cases:{"@eos":{token:"keyword.$1"},"@keywords":{cases:{".type":{token:"keyword.$1",next:"@type"},"@default":{token:"keyword.$1",next:"@keywordArg"}}},"@default":{token:"keyword.$1"}}}],[/@identifier/,"identifier"],[/@plaContent/,"string"]],whitespace:[[/[ \t\r\n]+/,""]],type:[{include:"@whitespace"},[/\w+/,{token:"type",next:"@pop"}]],keywordArg:[[/[ \t\r\n]+/,{cases:{"@eos":{token:"",next:"@pop"},"@default":""}}],[/@comment/,"comment","@pop"],[/[<>()\[\]]/,{cases:{"@eos":{token:"@brackets",next:"@pop"},"@default":"@brackets"}}],[/\-?\d+/,{cases:{"@eos":{token:"number",next:"@pop"},"@default":"number"}}],[/@identifier/,{cases:{"@eos":{token:"identifier",next:"@pop"},"@default":"identifier"}}],[/[;=]/,{cases:{"@eos":{token:"delimiter",next:"@pop"},"@default":"delimiter"}}]]}};export{e as conf,o as language}; 7 | -------------------------------------------------------------------------------- /packages/core/src/components/file-bar/icons/home-file.vue: -------------------------------------------------------------------------------- 1 | 47 | 64 | -------------------------------------------------------------------------------- /packages/docs/guide/config.md: -------------------------------------------------------------------------------- 1 | # 配置 2 | 3 | 你可以在 url 上或者页面 hash 上通过不同的参数,来对 CodePlayer 的功能进行配置,具体的参数及作用如下文所示。 4 | 5 | ## hash 6 | 7 | - 类型: `string` 8 | - 说明: url 上的 hash 部分。文件及代码的序列化字符串,具体请参照[序列化文件对象](/guide/start.html#_2-序列化文件对象) 9 | 10 | ## entry 11 | 12 | - 类型: `string` 13 | - 说明: 入口文件的文件名,必须是一个 html 文件。如果不指定,默认会以 `index.html` 作为入口文件的文件名。 14 | 15 | ## activeFile 16 | 17 | - 类型: `string` 18 | - 说明: 初始化选中并展示代码的文件的文件名。如果不指定,默认为入口文件。 19 | 20 | ## vueVersion 21 | 22 | - 类型: `number` 23 | - 可选值: `2 / 3` 24 | - 说明: 指定 vue 的版本,默认使用 vue3 解析器,如果是使用 vue2,务必指定该项 25 | 26 | ## showFileBar 27 | 28 | - 类型: `boolean` 29 | - 默认值: `true` 30 | - 说明: 是否显示侧文件栏 31 | 32 | ## showCode 33 | 34 | - 类型: `boolean` 35 | - 默认值: `true` 36 | - 说明: 是否显示代码编辑区 37 | 38 | ## showPreview 39 | 40 | - 类型: `boolean` 41 | - 默认值: `true` 42 | - 说明: 是否显示预览区 43 | 44 | ## showFileBar 45 | 46 | - 类型: `boolean` 47 | - 默认值: `true` 48 | - 说明: 是否显示侧文件栏 49 | 50 | ## showEruda 51 | 52 | - 类型: `boolean` 53 | - 默认值: `true` 54 | - 说明: 是否显示 eruda 控制台 55 | 56 | ## openConsole 57 | 58 | - 类型: `boolean` 59 | - 默认值: `false` 60 | - 说明: 初始化是否默认打开 eruda 的控制台 61 | 62 | ## reverse 63 | 64 | - 类型: `boolean` 65 | - 默认值: `false` 66 | - 说明: 是否翻转代码编辑区和预览区 67 | 68 | ## excludeTools 69 | 70 | - 类型: `('refresh' | 'share' | 'docs' | 'git')[]` 71 | - 默认值: `[]` 72 | - 说明: 需要隐藏的工具栏按钮 73 | 74 | ## codeSize 75 | 76 | - 类型: `number` 77 | - 默认值: `14` 78 | - 说明: 初始化的代码编辑区的字号 79 | 80 | ## theme 81 | 82 | - 类型: `'dark' | 'light'` 83 | - 默认值: `light` 84 | - 说明: 主题色 85 | 86 | ## appType 87 | 88 | - 类型: `string` 89 | - 可选值: `vue2 / vue3 / react / js / ts / html` 90 | - 默认值: `vue3` 91 | - 说明: 指定该参数且未指定 `files` 参数时,会使用内置的模板初始化一个对应类型的项目 92 | 93 | ## document 94 | 95 | - 类型: `string` 96 | - 默认值: `https://play.fe-dev.cn/docs` 97 | - 说明: 文档 icon 指向的地址 98 | 99 | ## github 100 | 101 | - 类型: `string` 102 | - 默认值: `https://github.com/zh-lx/codeplayer` 103 | - 说明: Github icon 指向的地址 104 | -------------------------------------------------------------------------------- /packages/website/dist/assets/scheme-bd6c73dd-ff6e5671.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:";",blockComment:["#|","|#"]},brackets:[["(",")"],["{","}"],["[","]"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}]},o={defaultToken:"",ignoreCase:!0,tokenPostfix:".scheme",brackets:[{open:"(",close:")",token:"delimiter.parenthesis"},{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"}],keywords:["case","do","let","loop","if","else","when","cons","car","cdr","cond","lambda","lambda*","syntax-rules","format","set!","quote","eval","append","list","list?","member?","load"],constants:["#t","#f"],operators:["eq?","eqv?","equal?","and","or","not","null?"],tokenizer:{root:[[/#[xXoObB][0-9a-fA-F]+/,"number.hex"],[/[+-]?\d+(?:(?:\.\d*)?(?:[eE][+-]?\d+)?)?/,"number.float"],[/(?:\b(?:(define|define-syntax|define-macro))\b)(\s+)((?:\w|\-|\!|\?)*)/,["keyword","white","variable"]],{include:"@whitespace"},{include:"@strings"},[/[a-zA-Z_#][a-zA-Z0-9_\-\?\!\*]*/,{cases:{"@keywords":"keyword","@constants":"constant","@operators":"operators","@default":"identifier"}}]],comment:[[/[^\|#]+/,"comment"],[/#\|/,"comment","@push"],[/\|#/,"comment","@pop"],[/[\|#]/,"comment"]],whitespace:[[/[ \t\r\n]+/,"white"],[/#\|/,"comment","@comment"],[/;.*$/,"comment"]],strings:[[/"$/,"string","@popall"],[/"(?=.)/,"string","@multiLineString"]],multiLineString:[[/[^\\"]+$/,"string","@popall"],[/[^\\"]+/,"string"],[/\\./,"string.escape"],[/"/,"string","@popall"],[/\\$/,"string"]]}};export{e as conf,o as language}; 7 | -------------------------------------------------------------------------------- /packages/website/dist/assets/flow9-88286753-42a61225.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{blockComment:["/*","*/"],lineComment:"//"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}",notIn:["string"]},{open:"[",close:"]",notIn:["string"]},{open:"(",close:")",notIn:["string"]},{open:'"',close:'"',notIn:["string"]},{open:"'",close:"'",notIn:["string"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}]},o={defaultToken:"",tokenPostfix:".flow",keywords:["import","require","export","forbid","native","if","else","cast","unsafe","switch","default"],types:["io","mutable","bool","int","double","string","flow","void","ref","true","false","with"],operators:["=",">","<","<=",">=","==","!","!=",":=","::=","&&","||","+","-","*","/","@","&","%",":","->","\\","$","??","^"],symbols:/[@$=>](?!@symbols)/,"delimiter"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/((0(x|X)[0-9a-fA-F]*)|(([0-9]+\.?[0-9]*)|(\.[0-9]+))((e|E)(\+|-)?[0-9]+)?)/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]]}};export{e as conf,o as language}; 7 | -------------------------------------------------------------------------------- /packages/website/dist/assets/sb-190efae3-2020a5af.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"'"},brackets:[["(",")"],["[","]"],["If","EndIf"],["While","EndWhile"],["For","EndFor"],["Sub","EndSub"]],autoClosingPairs:[{open:'"',close:'"',notIn:["string","comment"]},{open:"(",close:")",notIn:["string","comment"]},{open:"[",close:"]",notIn:["string","comment"]}]},o={defaultToken:"",tokenPostfix:".sb",ignoreCase:!0,brackets:[{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"keyword.tag-if",open:"If",close:"EndIf"},{token:"keyword.tag-while",open:"While",close:"EndWhile"},{token:"keyword.tag-for",open:"For",close:"EndFor"},{token:"keyword.tag-sub",open:"Sub",close:"EndSub"}],keywords:["Else","ElseIf","EndFor","EndIf","EndSub","EndWhile","For","Goto","If","Step","Sub","Then","To","While"],tagwords:["If","Sub","While","For"],operators:[">","<","<>","<=",">=","And","Or","+","-","*","/","="],identifier:/[a-zA-Z_][\w]*/,symbols:/[=><:+\-*\/%\.,]+/,escapes:/\\(?:[abfnrtv\\"']|x[0-9A-Fa-f]{1,4}|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,tokenizer:{root:[{include:"@whitespace"},[/(@identifier)(?=[.])/,"type"],[/@identifier/,{cases:{"@keywords":{token:"keyword.$0"},"@operators":"operator","@default":"variable.name"}}],[/([.])(@identifier)/,{cases:{$2:["delimiter","type.member"],"@default":""}}],[/\d*\.\d+/,"number.float"],[/\d+/,"number"],[/[()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":"delimiter"}}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,"string","@string"]],whitespace:[[/[ \t\r\n]+/,""],[/(\').*$/,"comment"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"C?/,"string","@pop"]]}};export{e as conf,o as language}; 7 | -------------------------------------------------------------------------------- /packages/website/dist/assets/bat-19ed4cb4-86aea46a.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"REM"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],surroundingPairs:[{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'}],folding:{markers:{start:new RegExp("^\\s*(::\\s*|REM\\s+)#region"),end:new RegExp("^\\s*(::\\s*|REM\\s+)#endregion")}}},s={defaultToken:"",ignoreCase:!0,tokenPostfix:".bat",brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.parenthesis",open:"(",close:")"},{token:"delimiter.square",open:"[",close:"]"}],keywords:/call|defined|echo|errorlevel|exist|for|goto|if|pause|set|shift|start|title|not|pushd|popd/,symbols:/[=> = T extends ElementType ? keyof T : never; 33 | 34 | type ElementKeysType = GetKeysType; 35 | 36 | export type ConfigType = { 37 | el: string | HTMLElement; 38 | mode?: 'context-menu' | 'nav-menu' | 'click'; // 模式, 默认为context-menu 39 | theme?: string; // 主题样式, 默认为auto 40 | minWidth?: string | number; // 最小宽度 41 | maxWidth?: string | number; // 最大宽度 42 | include?: string[] | RegExp; // 包含的元素 43 | exclude?: string[] | RegExp; // 排除的元素 44 | defaultProps?: { 45 | // 默认参数配置项 46 | [key in ElementKeysType]?: string; 47 | }; 48 | beforeInit?: Function; // 初始化前 49 | afterInit?: Function; // 初始化后 50 | beforeShow?: Function; // 显示菜单前 51 | afterShow?: Function; // 显示菜单后 52 | beforeHide?: Function; // 隐藏菜单前 53 | afterHide?: Function; // 隐藏菜单后 54 | color?: 'dark' | 'light'; 55 | }; 56 | 57 | export type OptionsType = 58 | | ItemType[] 59 | | ((e: Event, config: ConfigType) => ItemType[] | Promise); 60 | 61 | export interface MenuElement extends HTMLElement { 62 | direction?: LayoutMenuDirection; 63 | } 64 | 65 | // type RequireKeys = 'el' 66 | export const ConnectOffset = 5; 67 | 68 | export const ATTR_LIST = ['class', 'style']; 69 | 70 | export const SPLIT_SYMBOL = { 71 | class: ' ', 72 | style: ';', 73 | }; 74 | 75 | export const enum LayoutMenuDirection { 76 | Left = -1, 77 | Right = 1, 78 | } 79 | -------------------------------------------------------------------------------- /packages/core/src/utils/dialog.ts: -------------------------------------------------------------------------------- 1 | let dialogRef: HTMLDivElement | null = null; 2 | 3 | export const dialog = (options: { 4 | title?: string; 5 | content?: string; 6 | confirmText?: string; 7 | cancelText?: string; 8 | cancel?: () => void; 9 | confirm?: () => void; 10 | }) => { 11 | if (dialogRef) { 12 | dialogRef.remove(); 13 | dialogRef = null; 14 | } 15 | dialogRef = document.createElement('div'); 16 | dialogRef.innerHTML = ` 17 |
18 |
19 |

${options.title}

20 |
21 | 22 |
23 |

${options.content}

24 |
25 | 28 | 31 |
32 |
33 |
`; 34 | document.body.append(dialogRef); 35 | const closeIcon = document.querySelector( 36 | '#__codeplayer-dialog-close__' 37 | ) as HTMLDivElement; 38 | const cancelIcon = document.querySelector( 39 | '#__codeplayer-dialog-button-cancel__' 40 | ) as HTMLDivElement; 41 | const confirmIcon = document.querySelector( 42 | '#__codeplayer-dialog-button-confirm__' 43 | ) as HTMLDivElement; 44 | closeIcon.onclick = cancelIcon.onclick = () => { 45 | dialogRef?.remove(); 46 | dialogRef = null; 47 | options.cancel && options.cancel(); 48 | }; 49 | confirmIcon.onclick = () => { 50 | dialogRef?.remove(); 51 | dialogRef = null; 52 | options.confirm && options.confirm(); 53 | }; 54 | }; 55 | -------------------------------------------------------------------------------- /packages/core/src/assets/jsx.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_reactjs 3 | 4 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /packages/core/src/assets/tsx.svg: -------------------------------------------------------------------------------- 1 | 2 | file_type_reactts 3 | 4 | 7 | 10 | 13 | -------------------------------------------------------------------------------- /packages/core/src/components/file-bar/icons/delete-file.vue: -------------------------------------------------------------------------------- 1 | 52 | 73 | -------------------------------------------------------------------------------- /packages/core/src/components/file-bar/file-input.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 51 | 82 | -------------------------------------------------------------------------------- /packages/core/src/compiler/index.ts: -------------------------------------------------------------------------------- 1 | import { createHooks, Hookable } from 'hookable'; 2 | import { builtInPlugins } from './transform/plugins'; 3 | import { File } from './type'; 4 | import { Plugin, ComplierPluginParams, ComplierPluginResult } from './type'; 5 | 6 | export * from './file-system'; 7 | export * from './module'; 8 | export * from './type'; 9 | 10 | interface CompilerOptions { 11 | plugins?: Array; 12 | vueVersion?: 2 | 3; 13 | } 14 | 15 | export class Compiler { 16 | hooks: Hookable, string>; 17 | vueVersion: 2 | 3; 18 | 19 | constructor(options?: CompilerOptions) { 20 | this.hooks = createHooks(); 21 | this.vueVersion = options?.vueVersion || 3; 22 | this.init(options?.plugins || []); 23 | } 24 | 25 | async init(_plugins: Array) { 26 | [...builtInPlugins(this.vueVersion), ..._plugins].forEach((plugin) => { 27 | plugin(this.hooks); 28 | }); 29 | await this.hooks.callHook('after-init'); 30 | } 31 | 32 | async run(params: ComplierPluginParams) { 33 | // before-transform 34 | await this.hooks.callHook('before-transform', params); 35 | // transform 36 | await this.hooks.callHook('transform', params); 37 | // before-compile 38 | await this.hooks.callHook('before-compile', params); 39 | // compile-module 40 | const compiledResult = (await this.hooks.callHook( 41 | 'compile-module', 42 | params 43 | )) as ComplierPluginResult; 44 | // before-emit 45 | await this.hooks.callHook('before-emit', params, compiledResult); 46 | // emit 47 | await this.hooks.callHook('emit', params, compiledResult); 48 | // after-emit 49 | await this.hooks.callHook('after-emit', params, compiledResult); 50 | } 51 | 52 | // 文件转换 53 | async transform(files: File[], result: { errors: Error[] }) { 54 | const transformTasks = files.map( 55 | (file) => 56 | new Promise(async (resolve) => { 57 | const errors = await this.hooks.callHook('transform', file); 58 | if (errors) { 59 | result.errors.push(...errors); 60 | } 61 | resolve(true); 62 | }) 63 | ); 64 | await Promise.all(transformTasks); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /packages/website/dist/assets/pascaligo-c74f23f5-385edc0e.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"//",blockComment:["(*","*)"]},brackets:[["{","}"],["[","]"],["(",")"],["<",">"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"}]},o={defaultToken:"",tokenPostfix:".pascaligo",ignoreCase:!0,brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],keywords:["begin","block","case","const","else","end","fail","for","from","function","if","is","nil","of","remove","return","skip","then","type","var","while","with","option","None","transaction"],typeKeywords:["bool","int","list","map","nat","record","string","unit","address","map","mtz","xtz"],operators:["=",">","<","<=",">=","<>",":",":=","and","mod","or","+","-","*","/","@","&","^","%"],symbols:/[=><:@\^&|+\-*\/\^%]+/,tokenizer:{root:[[/[a-zA-Z_][\w]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/\$[0-9a-fA-F]{1,16}/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'/,"string","@string"],[/'[^\\']'/,"string"],[/'/,"string.invalid"],[/\#\d+/,"string"]],comment:[[/[^\(\*]+/,"comment"],[/\*\)/,"comment","@pop"],[/\(\*/,"comment"]],string:[[/[^\\']+/,"string"],[/\\./,"string.escape.invalid"],[/'/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,"white"],[/\(\*/,"comment","@comment"],[/\/\/.*$/,"comment"]]}};export{e as conf,o as language}; 7 | -------------------------------------------------------------------------------- /packages/core/src/components/toolbar/icons/copy.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 56 | 57 | 82 | -------------------------------------------------------------------------------- /packages/website/dist/assets/lua-250761cb-9adddcd9.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"--",blockComment:["--[[","]]"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},o={defaultToken:"",tokenPostfix:".lua",keywords:["and","break","do","else","elseif","end","false","for","function","goto","if","in","local","nil","not","or","repeat","return","then","true","until","while"],brackets:[{token:"delimiter.bracket",open:"{",close:"}"},{token:"delimiter.array",open:"[",close:"]"},{token:"delimiter.parenthesis",open:"(",close:")"}],operators:["+","-","*","/","%","^","#","==","~=","<=",">=","<",">","=",";",":",",",".","..","..."],symbols:/[=>"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'},{open:"(*",close:"*)"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'},{open:"(*",close:"*)"}]},o={defaultToken:"",tokenPostfix:".cameligo",ignoreCase:!0,brackets:[{open:"{",close:"}",token:"delimiter.curly"},{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"},{open:"<",close:">",token:"delimiter.angle"}],keywords:["abs","assert","block","Bytes","case","Crypto","Current","else","failwith","false","for","fun","if","in","let","let%entry","let%init","List","list","Map","map","match","match%nat","mod","not","operation","Operation","of","record","Set","set","sender","skip","source","String","then","to","true","type","with"],typeKeywords:["int","unit","string","tz","nat","bool"],operators:["=",">","<","<=",">=","<>",":",":=","and","mod","or","+","-","*","/","@","&","^","%","->","<-","&&","||"],symbols:/[=><:@\^&|+\-*\/\^%]+/,tokenizer:{root:[[/[a-zA-Z_][\w]*/,{cases:{"@keywords":{token:"keyword.$0"},"@default":"identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/[<>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/\$[0-9a-fA-F]{1,16}/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/'/,"string","@string"],[/'[^\\']'/,"string"],[/'/,"string.invalid"],[/\#\d+/,"string"]],comment:[[/[^\(\*]+/,"comment"],[/\*\)/,"comment","@pop"],[/\(\*/,"comment"]],string:[[/[^\\']+/,"string"],[/\\./,"string.escape.invalid"],[/'/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,"white"],[/\(\*/,"comment","@comment"],[/\/\/.*$/,"comment"]]}};export{e as conf,o as language}; 7 | -------------------------------------------------------------------------------- /packages/core/src/style/variable.less: -------------------------------------------------------------------------------- 1 | @import './base.less'; 2 | 3 | .codeplayer-theme-light { 4 | --codeplayer-filebar-bgc: @neutral-white; 5 | --codeplayer-toolbar-bgc: @neutral-white; 6 | --codeplayer-main-color: @neutral-10; 7 | --codeplayer-tertiary-color: @neutral-5; 8 | --codeplayer-text-secondary: @text-color-secondary; 9 | --codeplayer-active-file-bgc: rgba(0, 0, 0, 0.08); 10 | --codeplayer-active-file-color: @brand-6; 11 | --codeplayer-brand: @brand-6; // 主色 12 | --codeplayer-brand-active: @brand-7; // active 13 | --codeplayer-brand-hover: @brand-5; // hover 14 | --codeplayer-copy-icon-color: @neutral-1; 15 | --codeplayer-border-color: @border-color; 16 | --codeplayer-float-bgc: @neutral-2; 17 | --codeplayer-menu-color: @text-color; 18 | --codeplayer-menu-shadow: 0px 0px 10px rgba(0, 0, 0, 0.16), 19 | 0px 0px 15px rgba(0, 0, 0, 0.12), 0px 0px 25px rgba(0, 0, 0, 0.08); 20 | --codeplayer-copy-shadow: 0px 0px 2px rgba(0, 0, 0, 0.16), 21 | -2px 2px 8px rgba(0, 0, 0, 0.12), -4px 4px 12px rgba(0, 0, 0, 0.08); 22 | .tippy-box { 23 | box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.16), 24 | 0px 0px 15px rgba(0, 0, 0, 0.12), 0px 0px 25px rgba(0, 0, 0, 0.08); 25 | } 26 | } 27 | 28 | .codeplayer-theme-dark { 29 | --codeplayer-filebar-bgc: rgb(37, 37, 38); 30 | --codeplayer-toolbar-bgc: rgb(22, 22, 22); 31 | --codeplayer-main-color: @neutral-3; 32 | --codeplayer-text-secondary: @neutral-4; 33 | --codeplayer-tertiary-color: @neutral-6; 34 | --codeplayer-active-file-bgc: rgba(0, 0, 0, 0.5); 35 | --codeplayer-active-file-color: @brand-6; 36 | --codeplayer-brand: @dark-brand-6; // 主色 37 | --codeplayer-brand-active: @dark-brand-7; // active 38 | --codeplayer-brand-hover: @dark-brand-5; // hover 39 | --codeplayer-copy-icon-color: #282828; 40 | --codeplayer-border-color: @dark-neutral-6; 41 | --codeplayer-float-bgc: #282828; 42 | --codeplayer-menu-color: @neutral-4; 43 | --codeplayer-menu-shadow: 0px 0px 10px rgba(0, 0, 0, 0.56), 44 | 0px 0px 15px rgba(0, 0, 0, 0.48), 0px 0px 25px rgba(0, 0, 0, 0.32); 45 | --codeplayer-copy-shadow: -10px 10px 10px rgba(0, 0, 0, 0.56), 46 | -15px 15px 15px rgba(0, 0, 0, 0.48), -25px 25px 25px rgba(0, 0, 0, 0.32); 47 | .tippy-box { 48 | background-color: #282828; 49 | box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.56), 50 | 0px 0px 15px rgba(0, 0, 0, 0.48), 0px 0px 25px rgba(0, 0, 0, 0.32); 51 | } 52 | } 53 | 54 | .monaco-editor { 55 | width: 100% !important; 56 | } 57 | -------------------------------------------------------------------------------- /packages/website/dist/assets/graphql-edbbae08-387d549c.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"#"},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"""',close:'"""',notIn:["string","comment"]},{open:'"',close:'"',notIn:["string","comment"]}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"""',close:'"""'},{open:'"',close:'"'}],folding:{offSide:!0}},n={defaultToken:"invalid",tokenPostfix:".gql",keywords:["null","true","false","query","mutation","subscription","extend","schema","directive","scalar","type","interface","union","enum","input","implements","fragment","on"],typeKeywords:["Int","Float","String","Boolean","ID"],directiveLocations:["SCHEMA","SCALAR","OBJECT","FIELD_DEFINITION","ARGUMENT_DEFINITION","INTERFACE","UNION","ENUM","ENUM_VALUE","INPUT_OBJECT","INPUT_FIELD_DEFINITION","QUERY","MUTATION","SUBSCRIPTION","FIELD","FRAGMENT_DEFINITION","FRAGMENT_SPREAD","INLINE_FRAGMENT","VARIABLE_DEFINITION"],operators:["=","!","?",":","&","|"],symbols:/[=!?:&|]+/,escapes:/\\(?:["\\\/bfnrt]|u[0-9A-Fa-f]{4})/,tokenizer:{root:[[/[a-z_][\w$]*/,{cases:{"@keywords":"keyword","@default":"key.identifier"}}],[/[$][\w$]*/,{cases:{"@keywords":"keyword","@default":"argument.identifier"}}],[/[A-Z][\w\$]*/,{cases:{"@typeKeywords":"keyword","@default":"type.identifier"}}],{include:"@whitespace"},[/[{}()\[\]]/,"@brackets"],[/@symbols/,{cases:{"@operators":"operator","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,{token:"annotation",log:"annotation token: $0"}],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F]+/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"],[/"""/,{token:"string",next:"@mlstring",nextEmbedded:"markdown"}],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"/,{token:"string.quote",bracket:"@open",next:"@string"}]],mlstring:[[/[^"]+/,"string"],['"""',{token:"string",next:"@pop",nextEmbedded:"@pop"}]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,{token:"string.quote",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[/#.*$/,"comment"]]}};export{e as conf,n as language}; 7 | -------------------------------------------------------------------------------- /packages/core/src/components/toolbar/icons/git.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 54 | 57 | -------------------------------------------------------------------------------- /packages/docs/guide/importmap.md: -------------------------------------------------------------------------------- 1 | # 第三方依赖(importmap) 2 | 3 | 在 CodePlayer 中,第三方依赖库是在一个名为 `import-map.json` 的文件中声明和引入的,这借助了浏览器的 [importmap](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/script/type/importmap) 特性。 4 | 5 | :::tip 注意 6 | CodePlayer 会自动创建一个 `` 标签,并将 `import-map.json` 中的内容插入到这个标签中。你只需要在 `import-map.json` 中声明依赖,无需关注 `` 标签的创建。 7 | ::: 8 | 9 | ## import-map.json 10 | 11 | 浏览器标准的 `import-map.json` 包括 `imports` 和 `scopes` 两个字段,在 CodePlayer 中,所有的第三方库都在 `imports` 中声明,无需使用 `scopes`。格式如下: 12 | 13 | ```json 14 | { 15 | "imports": { 16 | "包名": "包对应的 esm 格式文件地址" 17 | } 18 | } 19 | ``` 20 | 21 | ### esm 文件地址 22 | 23 | 由于 `import` 是使用了现代浏览器的 esm 规范,所以第三方库映射的文件必须为 esm 规范的文件。 24 | 25 | 所有通过 npm 公共源发布的第三方库,都可以在 [esm.sh](https://esm.sh) 上找到对应的 esm 规范的文件: `https://esm.sh/@` 即为第三方库对应版本的地址。 26 | 27 | 例如 `react 18.2.0` 版本的对应 esm 规范文件地址为:`https://esm.sh/react@18.2.0` 28 | 29 | 对应的 `import-map.json` 应为: 30 | 31 | ```json 32 | { 33 | "imports": { 34 | "react": "https://esm.sh/react@18.2.0" 35 | } 36 | } 37 | ``` 38 | 39 | 当你使用 `react` 库时,浏览器就会根据 `import-map.json` 自动进行映射: 40 | 41 | ```js 42 | import { useState } from 'react'; 43 | 44 | // 等同于转换为 45 | 46 | import { useState } from 'https://esm.sh/react@18.2.0'; 47 | ``` 48 | 49 | ### 映射模块前缀 50 | 51 | 假设现在你要使用以下代码: 52 | 53 | ```js 54 | import { createRoot } from 'react-dom/client'; 55 | 56 | const domNode = document.getElementById('root'); 57 | const root = createRoot(domNode); 58 | ``` 59 | 60 | 上述代码和 `react` 的不同之处是,从 `react-dom` 的 `client` 路径下引入了 api,而非直接从包本身引入了 api。 61 | 62 | 我们还可能从 `react-dom` 的其他路径下引入其他 api,`importmap` 的映射模块前缀特性可以让我们便捷地支持这种情况: 63 | 64 | ```json 65 | { 66 | "imports": { 67 | "react-dom/": "https://esm.sh/react-dom@18.2.0/" 68 | } 69 | } 70 | ``` 71 | 72 | 只需要在包名及映射的 esm 路径后面都加一个 `/`,就可以进行路径的映射。 73 | 74 | ### 万能法则 75 | 76 | 如果你不太明白如何正确地在 `import-map.json` 中声明所有的第三方依赖,可以参考这个法则:无论使用了哪个第三方库,都在 `import-map.json` 的 `imports` 字段中添加以下两行: 77 | 78 | ```json 79 | { 80 | "imports": { 81 | // others... 82 | // 直接引入库 83 | "": "https://esm.sh/@", 84 | // 直接引入库中的文件 85 | "/": "https://esm.sh/@/" 86 | } 87 | } 88 | ``` 89 | 90 | 例如,使用了 `element-plus` 的 `2.3.12` 版本,则添加以下代码: 91 | 92 | ```json 93 | { 94 | "imports": { 95 | // others... 96 | "element-plus": "https://esm.sh/element-plus@2.3.12", 97 | "element-plus/": "https://esm.sh/element-plus@2.3.12/" 98 | } 99 | } 100 | ``` 101 | -------------------------------------------------------------------------------- /packages/website/dist/assets/objective-c-4607378b-951ded7b.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},n={defaultToken:"",tokenPostfix:".objective-c",keywords:["#import","#include","#define","#else","#endif","#if","#ifdef","#ifndef","#ident","#undef","@class","@defs","@dynamic","@encode","@end","@implementation","@interface","@package","@private","@protected","@property","@protocol","@public","@selector","@synthesize","__declspec","assign","auto","BOOL","break","bycopy","byref","case","char","Class","const","copy","continue","default","do","double","else","enum","extern","FALSE","false","float","for","goto","if","in","int","id","inout","IMP","long","nil","nonatomic","NULL","oneway","out","private","public","protected","readwrite","readonly","register","return","SEL","self","short","signed","sizeof","static","struct","super","switch","typedef","TRUE","true","union","unsigned","volatile","void","while"],decpart:/\d(_?\d)*/,decimal:/0|@decpart/,tokenizer:{root:[{include:"@comments"},{include:"@whitespace"},{include:"@numbers"},{include:"@strings"},[/[,:;]/,"delimiter"],[/[{}\[\]()<>]/,"@brackets"],[/[a-zA-Z@#]\w*/,{cases:{"@keywords":"keyword","@default":"identifier"}}],[/[<>=\\+\\-\\*\\/\\^\\|\\~,]|and\\b|or\\b|not\\b]/,"operator"]],whitespace:[[/\s+/,"white"]],comments:[["\\/\\*","comment","@comment"],["\\/\\/+.*","comment"]],comment:[["\\*\\/","comment","@pop"],[".","comment"]],numbers:[[/0[xX][0-9a-fA-F]*(_?[0-9a-fA-F])*/,"number.hex"],[/@decimal((\.@decpart)?([eE][\-+]?@decpart)?)[fF]*/,{cases:{"(\\d)*":"number",$0:"number.float"}}]],strings:[[/'$/,"string.escape","@popall"],[/'/,"string.escape","@stringBody"],[/"$/,"string.escape","@popall"],[/"/,"string.escape","@dblStringBody"]],stringBody:[[/[^\\']+$/,"string","@popall"],[/[^\\']+/,"string"],[/\\./,"string"],[/'/,"string.escape","@popall"],[/\\$/,"string"]],dblStringBody:[[/[^\\"]+$/,"string","@popall"],[/[^\\"]+/,"string"],[/\\./,"string"],[/"/,"string.escape","@popall"],[/\\$/,"string"]]}};export{e as conf,n as language}; 7 | -------------------------------------------------------------------------------- /packages/website/dist/assets/lexon-81c06df2-8d4b0444.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={comments:{lineComment:"COMMENT"},brackets:[["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:":",close:"."}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:"`",close:"`"},{open:'"',close:'"'},{open:"'",close:"'"},{open:":",close:"."}],folding:{markers:{start:new RegExp("^\\s*(::\\s*|COMMENT\\s+)#region"),end:new RegExp("^\\s*(::\\s*|COMMENT\\s+)#endregion")}}},t={tokenPostfix:".lexon",ignoreCase:!0,keywords:["lexon","lex","clause","terms","contracts","may","pay","pays","appoints","into","to"],typeKeywords:["amount","person","key","time","date","asset","text"],operators:["less","greater","equal","le","gt","or","and","add","added","subtract","subtracted","multiply","multiplied","times","divide","divided","is","be","certified"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,"delimiter"],[/\d*\.\d*\.\d*/,"number.semver"],[/\d*\.\d+([eE][\-+]?\d+)?/,"number.float"],[/0[xX][0-9a-fA-F]+/,"number.hex"],[/\d+/,"number"],[/[;,.]/,"delimiter"]],quoted_identifier:[[/[^\\"]+/,"identifier"],[/"/,{token:"identifier.quote",bracket:"@close",next:"@pop"}]],space_identifier_until_period:[[":","delimiter"],[" ",{token:"white",next:"@identifier_rest"}]],identifier_until_period:[{include:"@whitespace"},[":",{token:"delimiter",next:"@identifier_rest"}],[/[^\\.]+/,"identifier"],[/\./,{token:"delimiter",bracket:"@close",next:"@pop"}]],identifier_rest:[[/[^\\.]+/,"identifier"],[/\./,{token:"delimiter",bracket:"@close",next:"@pop"}]],semver:[{include:"@whitespace"},[":","delimiter"],[/\d*\.\d*\.\d*/,{token:"number.semver",bracket:"@close",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,"white"]]}};export{e as conf,t as language}; 7 | -------------------------------------------------------------------------------- /packages/website/dist/assets/xml-1c94689a-3dcda303.js: -------------------------------------------------------------------------------- 1 | import{Q as m}from"./index-8e8c1687-18fcf4d9.js";/*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var l=Object.defineProperty,c=Object.getOwnPropertyDescriptor,d=Object.getOwnPropertyNames,s=Object.prototype.hasOwnProperty,r=(t,e,o,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of d(e))!s.call(t,n)&&n!==o&&l(t,n,{get:()=>e[n],enumerable:!(i=c(e,n))||i.enumerable});return t},u=(t,e,o)=>(r(t,e,"default"),o&&r(o,e,"default")),a={};u(a,m);var f={comments:{blockComment:[""]},brackets:[["<",">"]],autoClosingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],surroundingPairs:[{open:"<",close:">"},{open:"'",close:"'"},{open:'"',close:'"'}],onEnterRules:[{beforeText:new RegExp("<([_:\\w][_:\\w-.\\d]*)([^/>]*(?!/)>)[^<]*$","i"),afterText:/^<\/([_:\w][_:\w-.\d]*)\s*>$/i,action:{indentAction:a.languages.IndentAction.IndentOutdent}},{beforeText:new RegExp("<(\\w[\\w\\d]*)([^/>]*(?!/)>)[^<]*$","i"),action:{indentAction:a.languages.IndentAction.Indent}}]},g={defaultToken:"",tokenPostfix:".xml",ignoreCase:!0,qualifiedName:/(?:[\w\.\-]+:)?[\w\.\-]+/,tokenizer:{root:[[/[^<&]+/,""],{include:"@whitespace"},[/(<)(@qualifiedName)/,[{token:"delimiter"},{token:"tag",next:"@tag"}]],[/(<\/)(@qualifiedName)(\s*)(>)/,[{token:"delimiter"},{token:"tag"},"",{token:"delimiter"}]],[/(<\?)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/(<\!)(@qualifiedName)/,[{token:"delimiter"},{token:"metatag",next:"@tag"}]],[/<\!\[CDATA\[/,{token:"delimiter.cdata",next:"@cdata"}],[/&\w+;/,"string.escape"]],cdata:[[/[^\]]+/,""],[/\]\]>/,{token:"delimiter.cdata",next:"@pop"}],[/\]/,""]],tag:[[/[ \t\r\n]+/,""],[/(@qualifiedName)(\s*=\s*)("[^"]*"|'[^']*')/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">?\/]*|'[^'>?\/]*)(?=[\?\/]\>)/,["attribute.name","","attribute.value"]],[/(@qualifiedName)(\s*=\s*)("[^">]*|'[^'>]*)/,["attribute.name","","attribute.value"]],[/@qualifiedName/,"attribute.name"],[/\?>/,{token:"delimiter",next:"@pop"}],[/(\/)(>)/,[{token:"tag"},{token:"delimiter",next:"@pop"}]],[/>/,{token:"delimiter",next:"@pop"}]],whitespace:[[/[ \t\r\n]+/,""],[//,{token:"comment",next:"@pop"}],[/","<--"],escapes:/\\(?:[tbnrf\\"'`]|u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8})/,digits:/\d+/,octaldigits:/[0-7]+/,hexdigits:/[0-9a-fA-F]+/,tokenizer:{root:[[/[{}[\]()]/,"@brackets"],{include:"common"}],common:[{include:"@whitespace"},{include:"@numbers"},{include:"@strings"},[/:[a-zA-Z_][\w]*/,"type.identifier"],[/[a-zA-Z_][\w]*(?=\()/,{cases:{"@builtinFunctions":"predefined.function"}}],[/[a-zA-Z_$][\w$]*/,{cases:{"@keywords":"keyword","@builtinLiterals":"predefined.literal","@default":"identifier"}}],[/`/,"identifier.escape","@identifierBacktick"],[/[;,.:|]/,"delimiter"],[/[<>=%+\-*/^]+/,{cases:{"@operators":"delimiter","@default":""}}]],numbers:[[/-?(@digits)[eE](-?(@digits))?/,"number.float"],[/-?(@digits)?\.(@digits)([eE]-?(@digits))?/,"number.float"],[/-?0x(@hexdigits)/,"number.hex"],[/-?0(@octaldigits)/,"number.octal"],[/-?(@digits)/,"number"]],strings:[[/"([^"\\]|\\.)*$/,"string.invalid"],[/'([^'\\]|\\.)*$/,"string.invalid"],[/"/,"string","@stringDouble"],[/'/,"string","@stringSingle"]],whitespace:[[/[ \t\r\n]+/,"white"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/\/\/.*/,"comment"],[/[^/*]+/,"comment"],[/\*\//,"comment","@pop"],[/[/*]/,"comment"]],stringDouble:[[/[^\\"]+/,"string"],[/@escapes/,"string"],[/\\./,"string.invalid"],[/"/,"string","@pop"]],stringSingle:[[/[^\\']+/,"string"],[/@escapes/,"string"],[/\\./,"string.invalid"],[/'/,"string","@pop"]],identifierBacktick:[[/[^\\`]+/,"identifier.escape"],[/@escapes/,"identifier.escape"],[/\\./,"identifier.escape.invalid"],[/`/,"identifier.escape","@pop"]]}};export{e as conf,i as language}; 7 | -------------------------------------------------------------------------------- /packages/website/dist/assets/kotlin-5d8c4070-06ee8898.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var e={wordPattern:/(-?\d*\.\d\w*)|([^\`\~\!\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,comments:{lineComment:"//",blockComment:["/*","*/"]},brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"},{open:"<",close:">"}],folding:{markers:{start:new RegExp("^\\s*//\\s*(?:(?:#?region\\b)|(?:))")}}},t={defaultToken:"",tokenPostfix:".kt",keywords:["as","as?","break","class","continue","do","else","false","for","fun","if","in","!in","interface","is","!is","null","object","package","return","super","this","throw","true","try","typealias","val","var","when","while","by","catch","constructor","delegate","dynamic","field","file","finally","get","import","init","param","property","receiver","set","setparam","where","actual","abstract","annotation","companion","const","crossinline","data","enum","expect","external","final","infix","inline","inner","internal","lateinit","noinline","open","operator","out","override","private","protected","public","reified","sealed","suspend","tailrec","vararg","field","it"],operators:["+","-","*","/","%","=","+=","-=","*=","/=","%=","++","--","&&","||","!","==","!=","===","!==",">","<","<=",">=","[","]","!!","?.","?:","::","..",":","?","->","@",";","$","_"],symbols:/[=>](?!@symbols)/,"@brackets"],[/@symbols/,{cases:{"@operators":"delimiter","@default":""}}],[/@\s*[a-zA-Z_\$][\w\$]*/,"annotation"],[/(@digits)[eE]([\-+]?(@digits))?[fFdD]?/,"number.float"],[/(@digits)\.(@digits)([eE][\-+]?(@digits))?[fFdD]?/,"number.float"],[/0[xX](@hexdigits)[Ll]?/,"number.hex"],[/0(@octaldigits)[Ll]?/,"number.octal"],[/0[bB](@binarydigits)[Ll]?/,"number.binary"],[/(@digits)[fFdD]/,"number.float"],[/(@digits)[lL]?/,"number"],[/[;,.]/,"delimiter"],[/"([^"\\]|\\.)*$/,"string.invalid"],[/"""/,"string","@multistring"],[/"/,"string","@string"],[/'[^\\']'/,"string"],[/(')(@escapes)(')/,["string","string.escape","string"]],[/'/,"string.invalid"]],whitespace:[[/[ \t\r\n]+/,""],[/\/\*\*(?!\/)/,"comment.doc","@javadoc"],[/\/\*/,"comment","@comment"],[/\/\/.*$/,"comment"]],comment:[[/[^\/*]+/,"comment"],[/\/\*/,"comment","@comment"],[/\*\//,"comment","@pop"],[/[\/*]/,"comment"]],javadoc:[[/[^\/*]+/,"comment.doc"],[/\/\*/,"comment.doc","@push"],[/\/\*/,"comment.doc.invalid"],[/\*\//,"comment.doc","@pop"],[/[\/*]/,"comment.doc"]],string:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"/,"string","@pop"]],multistring:[[/[^\\"]+/,"string"],[/@escapes/,"string.escape"],[/\\./,"string.escape.invalid"],[/"""/,"string","@pop"],[/./,"string"]]}};export{e as conf,t as language}; 7 | -------------------------------------------------------------------------------- /packages/core/src/store/index.ts: -------------------------------------------------------------------------------- 1 | import { reactive, watch } from 'vue'; 2 | import type { File } from '@/compiler'; 3 | import type { Control } from '@/type'; 4 | import { utoa } from '@//utils'; 5 | import { LocalThemeKey } from '@/constant'; 6 | 7 | export type Theme = 'light' | 'dark'; 8 | export interface Store { 9 | entry: string; 10 | activeFile: string; 11 | files: Record; 12 | showFileBar: boolean; 13 | showCode: boolean; 14 | showPreview: boolean; 15 | showEruda: boolean; 16 | openConsole: boolean; 17 | reverse: boolean; 18 | excludeTools: Control[]; 19 | editor: any | null; // code Mirror 编辑器 20 | rerenderID: number; // 用于 preview 刷新的标识,当点击刷新按钮该值 +1 触发刷新 21 | codeSize: number; 22 | vueVersion: 2 | 3; 23 | typescriptVersion: string; 24 | theme: Theme; 25 | reloadLanguageTools: () => void; 26 | document: string; 27 | github: string; 28 | } 29 | 30 | const params = new URLSearchParams(location.search); 31 | 32 | export const store = reactive({ 33 | // 文件系统相关 34 | entry: decodeURIComponent(params.get('params') || 'index.html'), 35 | files: {}, 36 | activeFile: decodeURIComponent(params.get('activeFile') || ''), 37 | showFileBar: params.get('showFileBar') !== 'false', 38 | showCode: params.get('showCode') !== 'false', 39 | showPreview: params.get('showPreview') !== 'false', 40 | showEruda: params.get('showEruda') !== 'false', 41 | openConsole: params.get('openConsole') === 'true', 42 | reverse: params.get('reverse') === 'true', 43 | excludeTools: 44 | JSON.parse(decodeURIComponent(params.get('excludeTools') || '[]')) || [], 45 | editor: null, 46 | rerenderID: 0, 47 | codeSize: Number(params.get('codeSize') || 14), 48 | vueVersion: Number(params.get('vueVersion') || 3) as 2 | 3, 49 | typescriptVersion: '4.9.3', 50 | theme: 51 | (params.get('theme') as Theme) || 52 | (localStorage.getItem(LocalThemeKey) as Theme) || 53 | 'light', 54 | reloadLanguageTools: () => {}, 55 | document: decodeURIComponent( 56 | params.get('document') || 'https://play.fe-dev.cn/docs' 57 | ), 58 | github: decodeURIComponent( 59 | params.get('github') || 'https://github.com/zh-lx/codeplayer' 60 | ), 61 | }); 62 | 63 | watch( 64 | () => store.files, 65 | (val) => { 66 | if (!val) { 67 | return; 68 | } 69 | const fileMap: Record = {}; 70 | for (let key in store.files) { 71 | fileMap[key] = store.files[key].code; 72 | } 73 | location.hash = utoa(JSON.stringify(fileMap)); 74 | }, 75 | { deep: true } 76 | ); 77 | 78 | watch( 79 | () => store.theme, 80 | (val) => { 81 | document.body.className = `codeplayer-theme-${val}`; 82 | }, 83 | { immediate: true } 84 | ); 85 | 86 | function syncStoreToUrl(keys: string[]) { 87 | for (let key of keys) { 88 | watch( 89 | () => store[key as keyof typeof store], 90 | (val) => { 91 | if (val !== undefined) { 92 | const url = new URL(location.href); 93 | if (typeof val === 'object') { 94 | url.searchParams.set(key, encodeURIComponent(JSON.stringify(val))); 95 | } else { 96 | url.searchParams.set(key, val); 97 | } 98 | history.pushState({}, '', url); 99 | } 100 | }, 101 | { deep: true } 102 | ); 103 | } 104 | } 105 | 106 | syncStoreToUrl([ 107 | 'entry', 108 | 'activeFile', 109 | 'showFileBar', 110 | 'showCode', 111 | 'showPreview', 112 | 'showEruda', 113 | 'openConsole', 114 | 'reverse', 115 | 'excludeTools', 116 | 'codeSize', 117 | 'theme', 118 | ]); 119 | -------------------------------------------------------------------------------- /packages/website/dist/assets/redis-a4651a9b-d0a12fea.js: -------------------------------------------------------------------------------- 1 | /*!----------------------------------------------------------------------------- 2 | * Copyright (c) Microsoft Corporation. All rights reserved. 3 | * Version: 0.41.0(38e1e3d097f84e336c311d071a9ffb5191d4ffd1) 4 | * Released under the MIT license 5 | * https://github.com/microsoft/monaco-editor/blob/main/LICENSE.txt 6 | *-----------------------------------------------------------------------------*/var E={brackets:[["{","}"],["[","]"],["(",")"]],autoClosingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}],surroundingPairs:[{open:"{",close:"}"},{open:"[",close:"]"},{open:"(",close:")"},{open:'"',close:'"'},{open:"'",close:"'"}]},S={defaultToken:"",tokenPostfix:".redis",ignoreCase:!0,brackets:[{open:"[",close:"]",token:"delimiter.square"},{open:"(",close:")",token:"delimiter.parenthesis"}],keywords:["APPEND","AUTH","BGREWRITEAOF","BGSAVE","BITCOUNT","BITFIELD","BITOP","BITPOS","BLPOP","BRPOP","BRPOPLPUSH","CLIENT","KILL","LIST","GETNAME","PAUSE","REPLY","SETNAME","CLUSTER","ADDSLOTS","COUNT-FAILURE-REPORTS","COUNTKEYSINSLOT","DELSLOTS","FAILOVER","FORGET","GETKEYSINSLOT","INFO","KEYSLOT","MEET","NODES","REPLICATE","RESET","SAVECONFIG","SET-CONFIG-EPOCH","SETSLOT","SLAVES","SLOTS","COMMAND","COUNT","GETKEYS","CONFIG","GET","REWRITE","SET","RESETSTAT","DBSIZE","DEBUG","OBJECT","SEGFAULT","DECR","DECRBY","DEL","DISCARD","DUMP","ECHO","EVAL","EVALSHA","EXEC","EXISTS","EXPIRE","EXPIREAT","FLUSHALL","FLUSHDB","GEOADD","GEOHASH","GEOPOS","GEODIST","GEORADIUS","GEORADIUSBYMEMBER","GETBIT","GETRANGE","GETSET","HDEL","HEXISTS","HGET","HGETALL","HINCRBY","HINCRBYFLOAT","HKEYS","HLEN","HMGET","HMSET","HSET","HSETNX","HSTRLEN","HVALS","INCR","INCRBY","INCRBYFLOAT","KEYS","LASTSAVE","LINDEX","LINSERT","LLEN","LPOP","LPUSH","LPUSHX","LRANGE","LREM","LSET","LTRIM","MGET","MIGRATE","MONITOR","MOVE","MSET","MSETNX","MULTI","PERSIST","PEXPIRE","PEXPIREAT","PFADD","PFCOUNT","PFMERGE","PING","PSETEX","PSUBSCRIBE","PUBSUB","PTTL","PUBLISH","PUNSUBSCRIBE","QUIT","RANDOMKEY","READONLY","READWRITE","RENAME","RENAMENX","RESTORE","ROLE","RPOP","RPOPLPUSH","RPUSH","RPUSHX","SADD","SAVE","SCARD","SCRIPT","FLUSH","LOAD","SDIFF","SDIFFSTORE","SELECT","SETBIT","SETEX","SETNX","SETRANGE","SHUTDOWN","SINTER","SINTERSTORE","SISMEMBER","SLAVEOF","SLOWLOG","SMEMBERS","SMOVE","SORT","SPOP","SRANDMEMBER","SREM","STRLEN","SUBSCRIBE","SUNION","SUNIONSTORE","SWAPDB","SYNC","TIME","TOUCH","TTL","TYPE","UNSUBSCRIBE","UNLINK","UNWATCH","WAIT","WATCH","ZADD","ZCARD","ZCOUNT","ZINCRBY","ZINTERSTORE","ZLEXCOUNT","ZRANGE","ZRANGEBYLEX","ZREVRANGEBYLEX","ZRANGEBYSCORE","ZRANK","ZREM","ZREMRANGEBYLEX","ZREMRANGEBYRANK","ZREMRANGEBYSCORE","ZREVRANGE","ZREVRANGEBYSCORE","ZREVRANK","ZSCORE","ZUNIONSTORE","SCAN","SSCAN","HSCAN","ZSCAN"],operators:[],builtinFunctions:[],builtinVariables:[],pseudoColumns:[],tokenizer:{root:[{include:"@whitespace"},{include:"@pseudoColumns"},{include:"@numbers"},{include:"@strings"},{include:"@scopes"},[/[;,.]/,"delimiter"],[/[()]/,"@brackets"],[/[\w@#$]+/,{cases:{"@keywords":"keyword","@operators":"operator","@builtinVariables":"predefined","@builtinFunctions":"predefined","@default":"identifier"}}],[/[<>=!%&+\-*/|~^]/,"operator"]],whitespace:[[/\s+/,"white"]],pseudoColumns:[[/[$][A-Za-z_][\w@#$]*/,{cases:{"@pseudoColumns":"predefined","@default":"identifier"}}]],numbers:[[/0[xX][0-9a-fA-F]*/,"number"],[/[$][+-]*\d*(\.\d*)?/,"number"],[/((\d+(\.\d*)?)|(\.\d+))([eE][\-+]?\d+)?/,"number"]],strings:[[/'/,{token:"string",next:"@string"}],[/"/,{token:"string.double",next:"@stringDouble"}]],string:[[/[^']+/,"string"],[/''/,"string"],[/'/,{token:"string",next:"@pop"}]],stringDouble:[[/[^"]+/,"string.double"],[/""/,"string.double"],[/"/,{token:"string.double",next:"@pop"}]],scopes:[]}};export{E as conf,S as language}; 7 | --------------------------------------------------------------------------------