@jschofield/play-ground 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -0
- package/dist/assets/index.js +171 -0
- package/dist/index.html +73 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# @jschofield/play-ground
|
|
2
|
+
|
|
3
|
+
Interactive code editor and live preview web component built with [Lit](https://lit.dev/) and [CodeMirror 6](https://codemirror.net/). A split-pane playground for HTML/CSS/JS — like a lightweight CodePen you can embed anywhere.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @jschofield/play-ground
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### Peer dependencies
|
|
12
|
+
|
|
13
|
+
This component requires the following peer dependencies:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install lit prettier codemirror @codemirror/commands @codemirror/lang-html @codemirror/lang-javascript @codemirror/language @codemirror/state @codemirror/view @replit/codemirror-vim
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| Peer | Version |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `lit` | `^3.0.0` |
|
|
22
|
+
| `prettier` | `^3.0.0` |
|
|
23
|
+
| `codemirror` | `^6.0.1` |
|
|
24
|
+
| `@codemirror/commands` | `^6.3.3` |
|
|
25
|
+
| `@codemirror/lang-html` | `^6.4.8` |
|
|
26
|
+
| `@codemirror/lang-javascript` | `^6.2.1` |
|
|
27
|
+
| `@codemirror/language` | `^6.10.1` |
|
|
28
|
+
| `@codemirror/state` | `^6.4.1` |
|
|
29
|
+
| `@codemirror/view` | `^6.24.1` |
|
|
30
|
+
| `@replit/codemirror-vim` | `^6.3.0` |
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
```html
|
|
35
|
+
<script type="module">
|
|
36
|
+
import '@jschofield/play-ground';
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<play-ground>
|
|
40
|
+
<template>
|
|
41
|
+
<style>
|
|
42
|
+
h1 { color: tomato; }
|
|
43
|
+
</style>
|
|
44
|
+
<h1>Hello!</h1>
|
|
45
|
+
</template>
|
|
46
|
+
</play-ground>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Inline HTML attribute
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<play-ground html="<h1>Quick example</h1>"></play-ground>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Code folding
|
|
56
|
+
|
|
57
|
+
Collapse specific lines on initial load (useful for hiding boilerplate):
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<play-ground fold="1,5">
|
|
61
|
+
<template>
|
|
62
|
+
<!-- line 1 is folded -->
|
|
63
|
+
...
|
|
64
|
+
</template>
|
|
65
|
+
</play-ground>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Without a bundler
|
|
69
|
+
|
|
70
|
+
This component has many CodeMirror peer dependencies, so a bundler is strongly recommended. If you must go without one, you'll need an import map for all peers:
|
|
71
|
+
|
|
72
|
+
```html
|
|
73
|
+
<script type="importmap">
|
|
74
|
+
{
|
|
75
|
+
"imports": {
|
|
76
|
+
"lit": "https://esm.run/lit",
|
|
77
|
+
"lit/": "https://esm.run/lit/",
|
|
78
|
+
"prettier/standalone": "https://esm.run/prettier/standalone",
|
|
79
|
+
"prettier/plugins/": "https://esm.run/prettier/plugins/",
|
|
80
|
+
"codemirror": "https://esm.run/codemirror",
|
|
81
|
+
"@codemirror/commands": "https://esm.run/@codemirror/commands",
|
|
82
|
+
"@codemirror/lang-html": "https://esm.run/@codemirror/lang-html",
|
|
83
|
+
"@codemirror/lang-javascript": "https://esm.run/@codemirror/lang-javascript",
|
|
84
|
+
"@codemirror/language": "https://esm.run/@codemirror/language",
|
|
85
|
+
"@codemirror/state": "https://esm.run/@codemirror/state",
|
|
86
|
+
"@codemirror/view": "https://esm.run/@codemirror/view",
|
|
87
|
+
"@replit/codemirror-vim": "https://esm.run/@replit/codemirror-vim"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
</script>
|
|
91
|
+
<script type="module" src="https://esm.run/@jschofield/play-ground"></script>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Attributes
|
|
95
|
+
|
|
96
|
+
| Attribute | Type | Default | Description |
|
|
97
|
+
|---|---|---|---|
|
|
98
|
+
| `html` | `string` | `""` | Initial HTML content (alternative to `<template>`) |
|
|
99
|
+
| `fold` | `string` | `""` | Comma-separated line numbers to fold on load |
|
|
100
|
+
|
|
101
|
+
## Features
|
|
102
|
+
|
|
103
|
+
- Live preview updates as you type (200ms debounce)
|
|
104
|
+
- Format button (Prettier with HTML/CSS/JS support)
|
|
105
|
+
- Vim mode toggle (persists across page via shared state)
|
|
106
|
+
- Sandboxed iframe preview (`allow-scripts allow-forms allow-same-origin`)
|
|
107
|
+
- Responsive: stacks vertically below 900px
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
MIT
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import{LitElement as e,css as t,html as n}from"lit";import*as r from"prettier/standalone";import i from"prettier/plugins/babel";import a from"prettier/plugins/postcss";import o from"prettier/plugins/estree";import s from"prettier/plugins/html";import{EditorView as c,drawSelection as l,gutters as u,keymap as d,lineNumbers as f}from"@codemirror/view";import{EditorState as p}from"@codemirror/state";import{basicSetup as m}from"codemirror";import{customElement as h,property as g,state as _}from"lit/decorators.js";import{defaultKeymap as v,indentWithTab as y}from"@codemirror/commands";import{html as b}from"@codemirror/lang-html";import{vim as x}from"@replit/codemirror-vim";import{foldCode as S}from"@codemirror/language";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let 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;let n=t(e);fetch(e.href,n)}})();var C=class{static{this.STORAGE_KEY=`repl-playground-state`}static{this.STATE_CHANGE_EVENT=`repl-playground-state-change`}static{this.subscribers=new Set}static getState(){try{let e=localStorage.getItem(this.STORAGE_KEY);if(e)return JSON.parse(e)}catch(e){console.warn(`Failed to parse repl-playground state from localStorage:`,e)}return{vimMode:`disabled`}}static getVimMode(){return this.getState().vimMode===`enabled`}static setVimMode(e){let t={...this.getState(),vimMode:e?`enabled`:`disabled`};try{localStorage.setItem(this.STORAGE_KEY,JSON.stringify(t))}catch(e){console.warn(`Failed to save repl-playground state to localStorage:`,e)}this.notifySubscribers(t),window.dispatchEvent(new CustomEvent(this.STATE_CHANGE_EVENT,{detail:t}))}static subscribe(e){this.subscribers.add(e)}static unsubscribe(e){this.subscribers.delete(e)}static notifySubscribers(e){this.subscribers.forEach(t=>{try{t(e)}catch(e){console.warn(`Error in state change callback:`,e)}})}static initializeStorageListener(){window.addEventListener(`storage`,e=>{if(e.key===this.STORAGE_KEY&&e.newValue)try{let t=JSON.parse(e.newValue);this.notifySubscribers(t)}catch(e){console.warn(`Failed to parse state change from storage event:`,e)}}),window.addEventListener(this.STATE_CHANGE_EVENT,(()=>{}))}},w=(e,t)=>{let n;return((...r)=>{clearTimeout(n),n=setTimeout(()=>e(...r),t)})};function T(e,t,n,r){var i=arguments.length,a=i<3?t:r===null?r=Object.getOwnPropertyDescriptor(t,n):r,o;if(typeof Reflect==`object`&&typeof Reflect.decorate==`function`)a=Reflect.decorate(e,t,n,r);else for(var s=e.length-1;s>=0;s--)(o=e[s])&&(a=(i<3?o(a):i>3?o(t,n,a):o(t,n))||a);return i>3&&a&&Object.defineProperty(t,n,a),a}var E=[i,o,s,a],D=class extends e{constructor(...e){super(...e),this.docContents=``,this.vimMode=!1,this.html=``,this.fold=``,this.handleDocUpdate=()=>{this.docContents=this.editorView.state.doc.toString().trim(),this.updateIframeContent()},this.debouncedHandleDocUpdate=w(this.handleDocUpdate,200),this.onEditorUpdate=e=>{e.docChanged&&this.debouncedHandleDocUpdate()}}get template(){return this.querySelector(`template`)}connectedCallback(){super.connectedCallback(),C.initializeStorageListener(),this.vimMode=C.getVimMode(),this.stateChangeCallback=e=>{let t=e.vimMode===`enabled`;this.vimMode!==t&&(this.vimMode=t,this.buildEditor())},C.subscribe(this.stateChangeCallback)}async initEditorView(){let e=await this.getTemplate();this.docContents=e,this.buildEditor(e),this.fold&&this.foldLines()}buildEditor(e){let t=this.shadowRoot?.querySelector(`#editor`);if(!t)return;let n=[];this.vimMode&&n.push(x()),n.push(l()),n.push(m,d.of([...v,y]),b(),f(),u(),c.updateListener.of(this.onEditorUpdate));let r=p.create({doc:e??this.editorView?.state.doc.toString()??``,extensions:n});this.editorView&&this.editorView.destroy(),this.editorView=new c({state:r,parent:t})}foldLines(){this.fold.split(`,`).map(e=>Number.parseInt(e)).forEach(e=>{let t=this.editorView.state.doc.line(e);this.editorView.dispatch({selection:{anchor:t.from}}),S(this.editorView)})}async getTemplate(){if(this.html)return await this.format(this.html);let e=this.template?.innerHTML.trim();return await this.format(e)}async firstUpdated(){await this.initEditorView(),this.setupIframe()}disconnectedCallback(){super.disconnectedCallback(),this.stateChangeCallback&&C.unsubscribe(this.stateChangeCallback),this.editorView?.destroy()}setupIframe(){this.iframeContainer=this.shadowRoot?.querySelector(`#view-container`),this.iframeContainer&&this.updateIframeContent()}updateIframeContent(){if(!this.iframeContainer)return;let e=(this.docContents||`<!DOCTYPE html><p>Loading...</p>`).replace(`shadowrootmode="open."`,`shadowrootmode="open"`);this.iframe&&this.iframe.remove(),this.iframe=document.createElement(`iframe`),this.iframe.sandbox.add(`allow-scripts`,`allow-forms`,`allow-same-origin`),this.iframe.srcdoc=e,this.iframeContainer.appendChild(this.iframe)}async format(e=``){let t=await r.format(e,{parser:`html`,plugins:E}),n=[`open`,`disabled`,`checked`,`selected`,`readonly`,`required`,`autofocus`,`autoplay`,`controls`,`defer`,`hidden`,`loop`,`multiple`,`muted`,`reversed`,`scoped`,`async`,`default`,`visible`,`active`,`expanded`,`loading`,`invalid`,`complete`,`bool-attr`],i=t;return n.forEach(e=>{let t=RegExp(`\\s${e}=""`,`g`);i=i.replace(t,` ${e}`)}),i}toggleVimMode(){C.setVimMode(!this.vimMode)}async doFormat(){let e=await this.format(this.docContents),{state:t}=this.editorView,n=t.update({changes:{from:0,to:t.doc.length,insert:e}});this.editorView.update([n])}render(){return n`<div part="container" class="query-container">
|
|
2
|
+
<div class="editor-container">
|
|
3
|
+
<div class="editor-wrapper">
|
|
4
|
+
<div id="editor"></div>
|
|
5
|
+
<div class="controls">
|
|
6
|
+
<button
|
|
7
|
+
part="editor-format-button"
|
|
8
|
+
class="format-button"
|
|
9
|
+
type="button"
|
|
10
|
+
@click=${this.doFormat}
|
|
11
|
+
>
|
|
12
|
+
Format
|
|
13
|
+
</button>
|
|
14
|
+
<label class="vim-toggle">
|
|
15
|
+
<input
|
|
16
|
+
type="checkbox"
|
|
17
|
+
class="sr-only"
|
|
18
|
+
.checked=${this.vimMode}
|
|
19
|
+
@change=${this.toggleVimMode}
|
|
20
|
+
/>
|
|
21
|
+
<span class="toggle-track ${this.vimMode?`active`:``}">
|
|
22
|
+
<span class="toggle-thumb"></span>
|
|
23
|
+
</span>
|
|
24
|
+
Vim mode
|
|
25
|
+
</label>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
<div id="view-container"></div>
|
|
29
|
+
</div>
|
|
30
|
+
</div>`}static{this.styles=t`
|
|
31
|
+
:host {
|
|
32
|
+
display: block;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
#editor {
|
|
36
|
+
font-size: 14px;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.query-container {
|
|
40
|
+
container-type: inline-size;
|
|
41
|
+
border: 1px solid #333;
|
|
42
|
+
border-radius: 8px;
|
|
43
|
+
overflow: hidden;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.editor-container {
|
|
47
|
+
position: relative;
|
|
48
|
+
display: flex;
|
|
49
|
+
|
|
50
|
+
& > * {
|
|
51
|
+
width: 50%;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#view-container {
|
|
56
|
+
display: flex;
|
|
57
|
+
border-left: 1px solid #333;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
#view-container iframe {
|
|
61
|
+
width: 100%;
|
|
62
|
+
border: none;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.editor-wrapper {
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.controls {
|
|
71
|
+
display: flex;
|
|
72
|
+
gap: 8px;
|
|
73
|
+
padding: 6px 8px;
|
|
74
|
+
border-top: 1px solid #333;
|
|
75
|
+
background: var(--seasalt, #fafafa);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.controls button {
|
|
79
|
+
padding: 0.25em 1em 0.2em;
|
|
80
|
+
font-size: 0.833rem;
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
border: none;
|
|
83
|
+
border-radius: 8px;
|
|
84
|
+
background: var(--gunmetal, #1b2f36);
|
|
85
|
+
color: var(--seasalt, #fafafa);
|
|
86
|
+
box-shadow: var(--shadow, 0 4px 8px rgba(0, 0, 0, 0.2));
|
|
87
|
+
transition: color 0.2s;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.controls button:hover,
|
|
91
|
+
.controls button:active {
|
|
92
|
+
background: var(--gradient, var(--gunmetal, #1b2f36));
|
|
93
|
+
color: var(--seasalt, #fafafa);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.controls button:focus-visible {
|
|
97
|
+
outline: 2px solid var(--raw-umber, #906b56);
|
|
98
|
+
outline-offset: 1px;
|
|
99
|
+
background: var(--gradient, var(--gunmetal, #1b2f36));
|
|
100
|
+
color: var(--seasalt, #fafafa);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.sr-only {
|
|
104
|
+
position: absolute;
|
|
105
|
+
width: 1px;
|
|
106
|
+
height: 1px;
|
|
107
|
+
padding: 0;
|
|
108
|
+
margin: -1px;
|
|
109
|
+
overflow: hidden;
|
|
110
|
+
clip: rect(0, 0, 0, 0);
|
|
111
|
+
white-space: nowrap;
|
|
112
|
+
border: 0;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.vim-toggle {
|
|
116
|
+
display: flex;
|
|
117
|
+
align-items: center;
|
|
118
|
+
gap: 6px;
|
|
119
|
+
margin-left: auto;
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
font-size: 0.833rem;
|
|
122
|
+
color: var(--gunmetal, #1b2f36);
|
|
123
|
+
user-select: none;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.sr-only:focus-visible + .toggle-track {
|
|
127
|
+
outline: 2px solid var(--raw-umber, #906b56);
|
|
128
|
+
outline-offset: 2px;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.toggle-track {
|
|
132
|
+
display: inline-block;
|
|
133
|
+
position: relative;
|
|
134
|
+
width: 32px;
|
|
135
|
+
height: 18px;
|
|
136
|
+
border-radius: 9px;
|
|
137
|
+
background: #d5d5d5;
|
|
138
|
+
border: 1.5px solid var(--gunmetal, #1b2f36);
|
|
139
|
+
box-sizing: border-box;
|
|
140
|
+
transition: background 0.2s;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.toggle-track.active {
|
|
144
|
+
background: var(--gunmetal, #1b2f36);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.toggle-thumb {
|
|
148
|
+
position: absolute;
|
|
149
|
+
top: 1.5px;
|
|
150
|
+
left: 1.5px;
|
|
151
|
+
width: 12px;
|
|
152
|
+
height: 12px;
|
|
153
|
+
border-radius: 50%;
|
|
154
|
+
background: var(--seasalt, #fafafa);
|
|
155
|
+
transition: transform 0.2s;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.toggle-track.active .toggle-thumb {
|
|
159
|
+
transform: translateX(14px);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
@container (max-width: 900px) {
|
|
163
|
+
.editor-container {
|
|
164
|
+
flex-direction: column;
|
|
165
|
+
|
|
166
|
+
& > * {
|
|
167
|
+
width: initial;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
`}};T([_()],D.prototype,`docContents`,void 0),T([_()],D.prototype,`vimMode`,void 0),T([g()],D.prototype,`html`,void 0),T([g()],D.prototype,`fold`,void 0),D=T([h(`play-ground`)],D);
|
package/dist/index.html
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Vite + Lit + TS</title>
|
|
7
|
+
<script type="module" crossorigin src="/assets/index.js"></script>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<play-ground fold="7">
|
|
11
|
+
<template slot="html">
|
|
12
|
+
<h1>Hello World!</h1>
|
|
13
|
+
<html>
|
|
14
|
+
<img src="https://picsum.photos/id/12/300/200" />
|
|
15
|
+
<script>
|
|
16
|
+
const someJavascript = document.createElement("span");
|
|
17
|
+
</script>
|
|
18
|
+
<style>
|
|
19
|
+
h1 {
|
|
20
|
+
font-weight: bold;
|
|
21
|
+
}
|
|
22
|
+
</style>
|
|
23
|
+
</html>
|
|
24
|
+
</template>
|
|
25
|
+
</play-ground>
|
|
26
|
+
<play-ground fold="3,9">
|
|
27
|
+
<template>
|
|
28
|
+
<link href="./example.css" rel="stylesheet" />
|
|
29
|
+
<div>Div outside the shadow DOM!</div>
|
|
30
|
+
<my-element>
|
|
31
|
+
<template shadowrootmode="open.">
|
|
32
|
+
testing
|
|
33
|
+
<link href="./example.css" rel="stylesheet" />
|
|
34
|
+
</template>
|
|
35
|
+
</my-element>
|
|
36
|
+
<script>
|
|
37
|
+
class MyElement extends HTMLElement {
|
|
38
|
+
connectedCallback() {
|
|
39
|
+
const div = document.createElement("div");
|
|
40
|
+
div.innerHTML = `
|
|
41
|
+
Div inside the shadow DOM!
|
|
42
|
+
`;
|
|
43
|
+
this.shadowRoot.append(div);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
customElements.define("my-element", MyElement);
|
|
47
|
+
</script>
|
|
48
|
+
</template>
|
|
49
|
+
</play-ground>
|
|
50
|
+
|
|
51
|
+
<play-ground
|
|
52
|
+
html='
|
|
53
|
+
<my-element>
|
|
54
|
+
Here is text being passed into the default slot!
|
|
55
|
+
</my-element>
|
|
56
|
+
<script type="module">
|
|
57
|
+
import {
|
|
58
|
+
LitElement, html,
|
|
59
|
+
} from "https://cdn.jsdelivr.net/gh/lit/dist@3/core/lit-core.min.js";
|
|
60
|
+
|
|
61
|
+
class MyElement extends LitElement {
|
|
62
|
+
render() {
|
|
63
|
+
return html`
|
|
64
|
+
<slot></slot>
|
|
65
|
+
`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
customElements.define("my-element", MyElement);
|
|
70
|
+
</script>
|
|
71
|
+
'></play-ground>
|
|
72
|
+
</body>
|
|
73
|
+
</html>
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jschofield/play-ground",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/assets/index.js",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": "./dist/assets/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"description": "Interactive code editor/playground web component built with Lit and CodeMirror",
|
|
13
|
+
"author": "Jim Schofield",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/JimSchofield/jschof.dev",
|
|
18
|
+
"directory": "component/play-ground"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {},
|
|
21
|
+
"peerDependencies": {
|
|
22
|
+
"@codemirror/commands": "^6.3.3",
|
|
23
|
+
"@codemirror/lang-html": "^6.4.8",
|
|
24
|
+
"@codemirror/lang-javascript": "^6.2.1",
|
|
25
|
+
"@codemirror/language": "^6.10.1",
|
|
26
|
+
"@codemirror/state": "^6.4.1",
|
|
27
|
+
"@codemirror/view": "^6.24.1",
|
|
28
|
+
"@replit/codemirror-vim": "^6.3.0",
|
|
29
|
+
"codemirror": "^6.0.1",
|
|
30
|
+
"lit": "^3.0.0",
|
|
31
|
+
"prettier": "^3.0.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"typescript": "^6.0.2",
|
|
35
|
+
"vite": "^8.0.3"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"dev": "vite",
|
|
39
|
+
"build": "tsc && vite build",
|
|
40
|
+
"preview": "vite preview"
|
|
41
|
+
}
|
|
42
|
+
}
|