├── .gitignore
├── .eslintignore
├── README.md
├── .eslintrc.js
├── scripts
└── getYYYYMMDD.js
├── src
├── playground.scss
├── playground.ts
└── index.html
├── package.json
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | web_modules
3 | dist
4 | .cache
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | *.*
2 | !*.js
3 | !*.ts
4 | node_modules
5 | dist
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # code-playground
2 |
3 | One of them, with good code completion is
4 |
5 | -
6 |
7 | Otherwise, just use [CodeMirror](https://codemirror.net/).
8 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | browser: true,
4 | es6: true
5 | },
6 | extends: [
7 | 'standard'
8 | ],
9 | globals: {
10 | Atomics: 'readonly',
11 | SharedArrayBuffer: 'readonly'
12 | },
13 | parser: '@typescript-eslint/parser',
14 | parserOptions: {
15 | ecmaVersion: 2018,
16 | sourceType: 'module'
17 | },
18 | plugins: [
19 | '@typescript-eslint'
20 | ],
21 | rules: {
22 | 'no-unused-vars': 0
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/scripts/getYYYYMMDD.js:
--------------------------------------------------------------------------------
1 | function getYYYYMMDD (d0) {
2 | let d = d0
3 | if (!(d0 instanceof Date)) {
4 | d = new Date(d0)
5 | }
6 | d.setTime(d.getTime() - d.getTimezoneOffset() * 60 * 1000)
7 |
8 | return `${
9 | padStart(d.getFullYear(), 4, '0')
10 | }-${
11 | padStart(d.getMonth() + 1, 2, '0')
12 | }-${
13 | padStart(d.getDate(), 2, '0')
14 | }`
15 | }
16 |
17 | /**
18 | *
19 | * @param {*} s
20 | * @param {number} length
21 | * @param {*} [c]
22 | */
23 | function padStart (s, length, c = '') {
24 | const s0 = s.toString()
25 | if (s0.length > length) {
26 | return s0
27 | } else {
28 | return Array(length - s0.length).fill(c).join('') + s0
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/playground.scss:
--------------------------------------------------------------------------------
1 | html, body, #App {
2 | box-sizing: border-box;
3 | }
4 |
5 | #App {
6 | width: 100vw;
7 | height: 100vh;
8 | }
9 |
10 | #Output {
11 | padding: 1em;
12 | width: 100%;
13 | height: 100%;
14 | }
15 |
16 | .flex-grow-1 {
17 | flex-grow: 1;
18 | flex-basis: 0;
19 | }
20 |
21 | [class^=flex-] {
22 | display: flex;
23 | // align-items: center;
24 | // justify-content: center;
25 | }
26 |
27 | .flex-vertical {
28 | flex-direction: column;
29 | }
30 |
31 | .flex-horizontal {
32 | flex-direction: row;
33 | }
34 |
35 | .h-100 {
36 | height: 100%;
37 | }
38 |
39 | @media screen and (max-width: 800px) {
40 | .flex-vertical-mobile {
41 | flex-direction: column;
42 | }
43 | }
44 |
45 | .CodeMirror-line {
46 | word-break: break-all !important;
47 | }
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "code-playground",
3 | "private": true,
4 | "description": "One of them, with good code completion is",
5 | "scripts": {
6 | "preinstall": "if !(test -x is-npm); then is-npm; fi",
7 | "start": "parcel src/index.html",
8 | "build": "parcel build src/index.html",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/patarapolw/code-playground.git"
14 | },
15 | "keywords": [
16 | "playground"
17 | ],
18 | "author": {
19 | "email": "patarapolw@gmail.com",
20 | "name": "Pacharapol Withayasakpunt",
21 | "url": "https://polvcode.dev"
22 | },
23 | "license": "ISC",
24 | "bugs": {
25 | "url": "https://github.com/patarapolw/code-playground/issues"
26 | },
27 | "homepage": "https://github.com/patarapolw/code-playground#readme",
28 | "dependencies": {
29 | "@types/codemirror": "0.0.88",
30 | "codemirror": "^5.52.0",
31 | "safe-eval": "^0.4.1",
32 | "typescript": "^3.8.3"
33 | },
34 | "devDependencies": {
35 | "@typescript-eslint/eslint-plugin": "^2.24.0",
36 | "@typescript-eslint/parser": "^2.24.0",
37 | "eslint": "^6.8.0",
38 | "eslint-config-standard": "^14.1.0",
39 | "eslint-plugin-import": "^2.20.1",
40 | "eslint-plugin-node": "^11.0.0",
41 | "eslint-plugin-promise": "^4.2.1",
42 | "eslint-plugin-standard": "^4.0.1",
43 | "sass": "^1.26.3"
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/playground.ts:
--------------------------------------------------------------------------------
1 | import CodeMirror from 'codemirror'
2 | import typescript from 'typescript'
3 | import tsconfig from '../tsconfig.json'
4 |
5 | import 'codemirror/lib/codemirror.css'
6 | import 'codemirror/mode/markdown/markdown.js'
7 | import 'codemirror/mode/yaml/yaml.js'
8 | import 'codemirror/mode/python/python.js'
9 | import 'codemirror/mode/yaml-frontmatter/yaml-frontmatter.js'
10 | import 'codemirror/mode/pug/pug.js'
11 | import 'codemirror/mode/css/css.js'
12 | import 'codemirror/mode/javascript/javascript.js'
13 | import 'codemirror/mode/clike/clike.js'
14 | import 'codemirror/mode/php/php.js'
15 | import 'codemirror/mode/xml/xml.js'
16 | import 'codemirror/mode/htmlmixed/htmlmixed.js'
17 | import 'codemirror/addon/edit/closebrackets.js'
18 | import 'codemirror/addon/comment/comment.js'
19 | import 'codemirror/addon/fold/foldcode.js'
20 | import 'codemirror/addon/fold/foldgutter.js'
21 | import 'codemirror/addon/fold/brace-fold.js'
22 | import 'codemirror/addon/fold/indent-fold.js'
23 | import 'codemirror/addon/fold/comment-fold.js'
24 | import 'codemirror/addon/fold/markdown-fold.js'
25 | import 'codemirror/addon/fold/foldgutter.css'
26 | import 'codemirror/theme/monokai.css'
27 |
28 | const cm = CodeMirror.fromTextArea(document.getElementById('cm') as HTMLTextAreaElement, {
29 | theme: 'monokai',
30 | lineNumbers: true,
31 | autoCloseBrackets: true,
32 | gutters: ['CodeMirror-linenumbers', 'CodeMirror-foldgutter'],
33 | lineWrapping: true,
34 | tabSize: 2,
35 | extraKeys: {
36 | 'Cmd-/': 'toggleComment',
37 | 'Ctrl-/': 'toggleComment',
38 | Tab: (cm: CodeMirror.Editor) => {
39 | const spaces = Array(cm.getOption('indentUnit')! + 1).join(' ')
40 | cm.getDoc().replaceSelection(spaces)
41 | }
42 | },
43 | foldGutter: true,
44 | mode: 'text/javascript'
45 | })
46 |
47 | cm.setSize('100%', '100%')
48 |
49 | // @ts-ignore
50 | window.outputEl = document.getElementById('Output')
51 |
52 | document.querySelectorAll('#lang-select').forEach((el) => {
53 | if (el instanceof HTMLSelectElement) {
54 | el.onchange = () => {
55 | cm.setOption('mode', el.value)
56 | }
57 | }
58 | })
59 |
60 | document.querySelectorAll('#lang-select-button').forEach((el) => {
61 | if (el instanceof HTMLButtonElement) {
62 | el.onclick = () => {
63 | let v = cm.getValue()
64 | const mode = cm.getOption('mode').split('/')[1]
65 | if (mode === 'typescript') {
66 | v = typescript.transpileModule(v, tsconfig as any).outputText
67 | }
68 |
69 | // eslint-disable-next-line no-eval
70 | eval(v)
71 | }
72 | }
73 | })
74 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Code Playground
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
25 |
26 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | To access the output, refer to document.getElementById('Output')
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Basic Options */
4 | // "incremental": true, /* Enable incremental compilation */
5 | "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
6 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
7 | // "lib": [], /* Specify library files to be included in the compilation. */
8 | // "allowJs": true, /* Allow javascript files to be compiled. */
9 | // "checkJs": true, /* Report errors in .js files. */
10 | // "jsx": "react", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
11 | // "jsxFactory": "h",
12 | // "declaration": true, /* Generates corresponding '.d.ts' file. */
13 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
14 | // "sourceMap": true, /* Generates corresponding '.map' file. */
15 | // "outFile": "./", /* Concatenate and emit output to single file. */
16 | // "outDir": "./", /* Redirect output structure to the directory. */
17 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
18 | // "composite": true, /* Enable project compilation */
19 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
20 | // "removeComments": true, /* Do not emit comments to output. */
21 | // "noEmit": true, /* Do not emit outputs. */
22 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
23 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
24 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
25 |
26 | /* Strict Type-Checking Options */
27 | "strict": true, /* Enable all strict type-checking options. */
28 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
29 | "strictNullChecks": true, /* Enable strict null checks. */
30 | "strictFunctionTypes": true, /* Enable strict checking of function types. */
31 | "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
32 | "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
33 | "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
34 | "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
35 |
36 | /* Additional Checks */
37 | // "noUnusedLocals": true, /* Report errors on unused locals. */
38 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
39 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
40 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
41 |
42 | /* Module Resolution Options */
43 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
44 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
45 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
46 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
47 | // "typeRoots": [], /* List of folders to include type definitions from. */
48 | // "types": [], /* Type declaration files to be included in compilation. */
49 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
50 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
51 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
52 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
53 |
54 | /* Source Map Options */
55 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
56 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
57 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
58 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
59 |
60 | /* Experimental Options */
61 | "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
62 | "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
63 |
64 | /* Advanced Options */
65 | "forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
66 |
67 | "resolveJsonModule": true
68 | }
69 | }
70 |
--------------------------------------------------------------------------------