@docmd/live 0.4.2 → 0.4.4

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.
@@ -30258,7 +30258,7 @@ try {
30258
30258
  <div class="footer-content">
30259
30259
  <div class="user-footer"><%- footerHtml || '' %></div>
30260
30260
  <div class="branding-footer">
30261
- Build with <a href="https://docmd.io" target="_blank" rel="noopener">docmd.</a>
30261
+ Build with <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"></path><path d="M12 5 9.04 7.96a2.17 2.17 0 0 0 0 3.08c.82.82 2.13.85 3 .07l2.07-1.9a2.82 2.82 0 0 1 3.79 0l2.96 2.66"></path><path d="m18 15-2-2"></path><path d="m15 18-2-2"></path></svg> <a href="https://docmd.io" target="_blank" rel="noopener">docmd.</a>
30262
30262
  </div>
30263
30263
  </div>
30264
30264
  </footer>
@@ -30648,7 +30648,7 @@ if (shouldShowToc && !frontmatter?.toc || frontmatter?.toc !== 'false') {
30648
30648
  } catch (e) {
30649
30649
  console.error('Theme init failed', e);
30650
30650
  }
30651
- })();`}});var VX=w((gde,Jv)=>{u();var{createMarkdownProcessor:FX,processContent:UX}=kg(),{renderTemplate:GX}=Qv(),wr=Xv();function HX(e,t={}){let r={siteTitle:"Live Preview",theme:{defaultMode:"light",name:"default",codeHighlight:!0},...t},o=FX(r),i=UX(e,o,r);if(!i)return"<p>Error parsing markdown</p>";let a="./assets",s=[`<link rel="stylesheet" href="${a}/css/docmd-main.css">`];if(r.theme.codeHighlight!==!1){let g=r.theme.defaultMode==="dark"?"dark":"light";s.push(`<link rel="stylesheet" href="${a}/css/docmd-highlight-${g}.css">`)}r.theme.name&&r.theme.name!=="default"&&s.push(`<link rel="stylesheet" href="${a}/css/docmd-theme-${r.theme.name}.css">`),s.push(`<link rel="stylesheet" href="${a}/css/docmd-live-preview.css">`);let l=[`<script src="${a}/js/docmd-main.js"><\/script>`],c="";wr["partials/theme-init.js"]&&(c=`<script>${wr["partials/theme-init.js"]}<\/script>`);let d={content:i.htmlContent,frontmatter:i.frontmatter,headings:i.headings,config:r,siteTitle:r.siteTitle,pageTitle:i.frontmatter.title||"Untitled",description:i.frontmatter.description||"",defaultMode:r.theme.defaultMode,navigationHtml:"",relativePathToRoot:"./",outputPath:"index.html",currentPagePath:"/index",prevPage:null,nextPage:null,pluginHeadScriptsHtml:s.join(`
30651
+ })();`}});var VX=w((gde,Jv)=>{u();var{createMarkdownProcessor:FX,processContent:UX}=kg(),{renderTemplate:GX}=Qv(),wr=Xv();function HX(e,t={}){let r={siteTitle:"Live Preview",theme:{defaultMode:"light",name:"default",codeHighlight:!0},...t},o=FX(r),i=UX(e,o,r);if(!i)return"<p>Error parsing markdown</p>";let a="./assets",s=[`<link rel="stylesheet" href="${a}/css/docmd-main.css">`];if(r.theme.codeHighlight!==!1){let g=r.theme.defaultMode==="dark"?"dark":"light";s.push(`<link rel="stylesheet" href="${a}/css/docmd-highlight-${g}.css">`)}r.theme.name&&r.theme.name!=="default"&&s.push(`<link rel="stylesheet" href="${a}/css/docmd-theme-${r.theme.name}.css">`),s.push(`<link rel="stylesheet" href="${a}/css/docmd-live-preview.css">`);let l=[`<script src="${a}/js/docmd-main.js"><\/script>`],c="";wr["partials/theme-init.js"]&&(c=`<script>${wr["partials/theme-init.js"]}<\/script>`);let d={content:i.htmlContent,frontmatter:i.frontmatter,headings:i.headings,config:r,buildHash:"live",siteTitle:r.siteTitle,pageTitle:i.frontmatter.title||"Untitled",description:i.frontmatter.description||"",defaultMode:r.theme.defaultMode,navigationHtml:"",relativePathToRoot:"./",outputPath:"index.html",currentPagePath:"/index",prevPage:null,nextPage:null,pluginHeadScriptsHtml:s.join(`
30652
30652
  `),pluginBodyScriptsHtml:l.join(`
30653
30653
  `),themeInitScript:c,faviconLinkHtml:"",logo:r.logo,sidebarConfig:{collapsible:!1},theme:r.theme,customCssFiles:[],customJsFiles:[],sponsor:{},footer:"",footerHtml:"",isActivePage:!0,editUrl:null,editLinkText:""},p=i.frontmatter.noStyle?"no-style.ejs":"layout.ejs",h=wr[p];return h?GX(h,d,{includer:g=>{let m=g.endsWith(".ejs")?g:g+".ejs";return wr[m]?{template:wr[m]}:null}}):`Template ${p} not found`}Jv.exports={compile:HX}});return VX();})();
30654
30654
  /*! Bundled license information:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docmd/live",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Browser-based editor engine for docmd",
5
5
  "bin": {
6
6
  "docmd-live": "bin/docmd-live.js"
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "files": [
12
12
  "bin",
13
+ "src",
13
14
  "dist",
14
15
  "index.js",
15
16
  "src/build.js"
@@ -18,9 +19,9 @@
18
19
  "esbuild": "^0.27.3",
19
20
  "buffer": "^6.0.3",
20
21
  "serve": "^14.2.1",
21
- "@docmd/parser": "^0.4.2",
22
- "@docmd/ui": "^0.4.2",
23
- "@docmd/themes": "^0.4.2"
22
+ "@docmd/parser": "^0.4.4",
23
+ "@docmd/ui": "^0.4.4",
24
+ "@docmd/themes": "^0.4.4"
24
25
  },
25
26
  "keywords": [
26
27
  "docmd",
@@ -0,0 +1,102 @@
1
+ const { createMarkdownProcessor, processContent } = require('@docmd/parser/src/markdown-processor');
2
+ const { renderTemplate } = require('@docmd/parser/src/html-renderer');
3
+ const templates = require('virtual:docmd-templates');
4
+
5
+ // Expose the compile function to the window.docmd global
6
+ function compile(markdown, config = {}) {
7
+ const defaults = {
8
+ siteTitle: 'Live Preview',
9
+ theme: { defaultMode: 'light', name: 'default', codeHighlight: true },
10
+ ...config
11
+ };
12
+
13
+ // 1. Process Markdown
14
+ const md = createMarkdownProcessor(defaults);
15
+ const result = processContent(markdown, md, defaults);
16
+
17
+ if (!result) return '<p>Error parsing markdown</p>';
18
+
19
+ // Since we are in the browser, we assume assets are served at ./assets/
20
+ const assetsRoot = './assets';
21
+
22
+ // 1. CSS Injection
23
+ const cssTags = [
24
+ `<link rel="stylesheet" href="${assetsRoot}/css/docmd-main.css">`
25
+ ];
26
+
27
+ if (defaults.theme.codeHighlight !== false) {
28
+ const mode = defaults.theme.defaultMode === 'dark' ? 'dark' : 'light';
29
+ cssTags.push(`<link rel="stylesheet" href="${assetsRoot}/css/docmd-highlight-${mode}.css">`);
30
+ }
31
+
32
+ if (defaults.theme.name && defaults.theme.name !== 'default') {
33
+ cssTags.push(`<link rel="stylesheet" href="${assetsRoot}/css/docmd-theme-${defaults.theme.name}.css">`);
34
+ }
35
+
36
+ cssTags.push(`<link rel="stylesheet" href="${assetsRoot}/css/docmd-live-preview.css">`);
37
+
38
+ // 2. JS Injection
39
+ const jsTags = [
40
+ `<script src="${assetsRoot}/js/docmd-main.js"></script>`
41
+ ];
42
+
43
+ // 3. Theme Init Script
44
+ let themeInitScript = '';
45
+ if (templates['partials/theme-init.js']) {
46
+ themeInitScript = `<script>${templates['partials/theme-init.js']}</script>`;
47
+ }
48
+
49
+ // 4. Prepare Data
50
+ const pageData = {
51
+ content: result.htmlContent,
52
+ frontmatter: result.frontmatter,
53
+ headings: result.headings,
54
+ config: defaults,
55
+ buildHash: 'live',
56
+ siteTitle: defaults.siteTitle,
57
+ pageTitle: result.frontmatter.title || 'Untitled',
58
+ description: result.frontmatter.description || '',
59
+ defaultMode: defaults.theme.defaultMode,
60
+
61
+ // Navigation Stub
62
+ navigationHtml: '',
63
+ relativePathToRoot: './',
64
+ outputPath: 'index.html',
65
+ currentPagePath: '/index',
66
+ prevPage: null,
67
+ nextPage: null,
68
+
69
+ // Inject the constructed assets
70
+ pluginHeadScriptsHtml: cssTags.join('\n'),
71
+ pluginBodyScriptsHtml: jsTags.join('\n'),
72
+ themeInitScript: themeInitScript,
73
+
74
+ // Helpers
75
+ faviconLinkHtml: '',
76
+ logo: defaults.logo,
77
+ sidebarConfig: { collapsible: false },
78
+ theme: defaults.theme,
79
+ customCssFiles: [], customJsFiles: [],
80
+ sponsor: {}, footer: '', footerHtml: '',
81
+ isActivePage: true,
82
+ editUrl: null, editLinkText: ''
83
+ };
84
+
85
+ // 5. Render
86
+ const templateName = result.frontmatter.noStyle ? 'no-style.ejs' : 'layout.ejs';
87
+ const templateStr = templates[templateName];
88
+
89
+ if (!templateStr) return `Template ${templateName} not found`;
90
+
91
+ const options = {
92
+ includer: (originalPath) => {
93
+ let name = originalPath.endsWith('.ejs') ? originalPath : originalPath + '.ejs';
94
+ if (templates[name]) return { template: templates[name] };
95
+ return null;
96
+ }
97
+ };
98
+
99
+ return renderTemplate(templateStr, pageData, options);
100
+ }
101
+
102
+ module.exports = { compile };
@@ -0,0 +1,33 @@
1
+ /*
2
+ * Styles specific to the Live Editor Preview Iframe
3
+ */
4
+
5
+ /* Always hide TOC and Footer Actions in preview to save space */
6
+ .toc-sidebar,
7
+ .page-footer-actions {
8
+ display: none !important;
9
+ }
10
+
11
+ /* Ensure the main content takes full width since TOC is gone */
12
+ .content-layout {
13
+ display: block !important;
14
+ }
15
+
16
+ /* Hide Sidebar specifically on mobile in the preview */
17
+ /* (In Split View on mobile, space is very limited) */
18
+ @media (max-width: 768px) {
19
+ .sidebar {
20
+ display: none !important;
21
+ }
22
+
23
+ .main-content-wrapper {
24
+ margin-left: 0 !important;
25
+ }
26
+ }
27
+
28
+ /* Adjust header to look better without sidebar on mobile */
29
+ @media (max-width: 768px) {
30
+ .sidebar-toggle-button {
31
+ display: none !important;
32
+ }
33
+ }
@@ -0,0 +1,275 @@
1
+ /* Source file from the docmd project — https://github.com/docmd-io/docmd */
2
+
3
+ :root {
4
+ --header-height: 50px;
5
+ --border-color: #e0e0e0;
6
+ --bg-color: #f9fafb;
7
+ --primary-color: #007bff;
8
+ --resizer-width: 8px
9
+ }
10
+
11
+ body {
12
+ margin: 0;
13
+ height: 100vh;
14
+ display: flex;
15
+ flex-direction: column;
16
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
17
+ overflow: hidden
18
+ }
19
+
20
+ .top-bar {
21
+ height: var(--header-height);
22
+ background: #fff;
23
+ border-bottom: 1px solid var(--border-color);
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: space-between;
27
+ padding: 0 1rem;
28
+ flex-shrink: 0
29
+ }
30
+
31
+ .logo {
32
+ font-weight: 700;
33
+ font-size: 1.1rem;
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 12px
37
+ }
38
+
39
+ .logo span {
40
+ background: var(--primary-color);
41
+ color: #fff;
42
+ padding: 2px 6px;
43
+ border-radius: 4px;
44
+ font-size: .75rem;
45
+ text-transform: uppercase
46
+ }
47
+
48
+ .back-link {
49
+ display: flex;
50
+ width: 24px;
51
+ height: 24px;
52
+ background-color: #f0f0f0;
53
+ border-radius: 100%;
54
+ align-items: center;
55
+ justify-content: center;
56
+ color: #666;
57
+ transition: color 0.2s, transform .2s;
58
+ text-decoration: none;
59
+ padding: 4px;
60
+ }
61
+
62
+ .back-link:hover {
63
+ color: var(--primary-color);
64
+ background: #f0f0f0;
65
+ transform: translateX(-2px)
66
+ }
67
+
68
+ .logo .docmd-logo {
69
+ color: inherit;
70
+ text-decoration: none;
71
+ transition: .5s;
72
+ }
73
+
74
+ .logo .docmd-logo:hover {
75
+ color: var(--primary-color);
76
+ }
77
+
78
+ .view-switcher {
79
+ display: flex;
80
+ background: #f0f0f0;
81
+ padding: 3px;
82
+ border-radius: 8px;
83
+ gap: 0;
84
+ }
85
+
86
+ .view-btn {
87
+ border: none;
88
+ background: transparent;
89
+ padding: 6px 12px;
90
+ border-radius: 6px;
91
+ cursor: pointer;
92
+ font-size: 0.85rem;
93
+ color: #666;
94
+ font-weight: 500;
95
+ transition: background 0.15s, color 0.15s;
96
+ }
97
+
98
+ .view-btn:hover {
99
+ color: #333;
100
+ }
101
+
102
+ .view-btn.active {
103
+ background: #fff;
104
+ color: #000;
105
+ box-shadow: 0 1px 3px #0000001a;
106
+ font-weight: 600;
107
+ }
108
+
109
+ .workspace {
110
+ flex: 1;
111
+ display: flex;
112
+ position: relative;
113
+ overflow: hidden
114
+ }
115
+
116
+ .pane {
117
+ height: 100%;
118
+ display: flex;
119
+ flex-direction: column;
120
+ min-width: 300px;
121
+ background: #fff
122
+ }
123
+
124
+ .pane-header {
125
+ padding: 8px 16px;
126
+ font-size: .75rem;
127
+ font-weight: 600;
128
+ text-transform: uppercase;
129
+ color: #888;
130
+ background: var(--bg-color);
131
+ border-bottom: 1px solid var(--border-color);
132
+ flex-shrink: 0
133
+ }
134
+
135
+ .editor-pane {
136
+ width: 50%
137
+ }
138
+
139
+ textarea#input {
140
+ flex: 1;
141
+ border: none;
142
+ resize: none;
143
+ padding: 20px;
144
+ font-family: 'JetBrains Mono', 'Fira Code', Consolas, monospace;
145
+ font-size: 14px;
146
+ line-height: 1.6;
147
+ outline: none;
148
+ background: var(--bg-color)
149
+ }
150
+
151
+ .preview-pane {
152
+ flex: 1;
153
+ background: #fff
154
+ }
155
+
156
+ iframe#preview {
157
+ width: 100%;
158
+ height: 100%;
159
+ border: none;
160
+ display: block
161
+ }
162
+
163
+ .resizer {
164
+ width: var(--resizer-width);
165
+ background: var(--bg-color);
166
+ border-left: 1px solid var(--border-color);
167
+ border-right: 1px solid var(--border-color);
168
+ cursor: col-resize;
169
+ display: flex;
170
+ align-items: center;
171
+ justify-content: center;
172
+ transition: background .2s;
173
+ z-index: 10
174
+ }
175
+
176
+ .resizer:hover,
177
+ .resizer.resizing {
178
+ background: #e0e0e0
179
+ }
180
+
181
+ .resizer::after {
182
+ content: "||";
183
+ color: #aaa;
184
+ font-size: 10px;
185
+ letter-spacing: 1px
186
+ }
187
+
188
+ body.mode-single .resizer {
189
+ display: none
190
+ }
191
+
192
+ body.mode-single .pane {
193
+ width: 100% !important;
194
+ min-width: 0
195
+ }
196
+
197
+ body.mode-single .editor-pane {
198
+ display: none
199
+ }
200
+
201
+ body.mode-single .preview-pane {
202
+ display: none
203
+ }
204
+
205
+ body.mode-single.show-editor .editor-pane {
206
+ display: flex
207
+ }
208
+
209
+ body.mode-single.show-preview .preview-pane {
210
+ display: flex
211
+ }
212
+
213
+ @media (max-width: 768px) {
214
+ .desktop-only {
215
+ display: none !important
216
+ }
217
+
218
+ .resizer {
219
+ display: none !important
220
+ }
221
+
222
+ .pane {
223
+ width: 100% !important
224
+ }
225
+
226
+ .editor-pane {
227
+ display: none
228
+ }
229
+
230
+ .preview-pane {
231
+ display: none
232
+ }
233
+
234
+ body.mobile-tab-editor .editor-pane {
235
+ display: flex
236
+ }
237
+
238
+ body.mobile-tab-preview .preview-pane {
239
+ display: flex
240
+ }
241
+
242
+ .mobile-tabs {
243
+ display: flex !important;
244
+ position: fixed;
245
+ bottom: 0;
246
+ left: 0;
247
+ right: 0;
248
+ height: 50px;
249
+ background: #fff;
250
+ border-top: 1px solid var(--border-color);
251
+ z-index: 100
252
+ }
253
+
254
+ .mobile-tab-btn {
255
+ flex: 1;
256
+ border: none;
257
+ background: transparent;
258
+ font-weight: 600;
259
+ color: #888;
260
+ cursor: pointer
261
+ }
262
+
263
+ .mobile-tab-btn.active {
264
+ color: var(--primary-color);
265
+ border-top: 2px solid var(--primary-color)
266
+ }
267
+
268
+ .workspace {
269
+ padding-bottom: 50px
270
+ }
271
+ }
272
+
273
+ .mobile-tabs {
274
+ display: none
275
+ }
package/src/index.html ADDED
@@ -0,0 +1,189 @@
1
+ <!-- Source file from the docmd project — https://github.com/docmd-io/docmd -->
2
+
3
+ <!DOCTYPE html>
4
+ <html lang="en">
5
+ <head>
6
+ <meta charset="UTF-8">
7
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <title>Docmd Live Editor</title>
9
+ <meta name="description" content="Real-time Markdown preview and editor powered by docmd.">
10
+
11
+ <link rel="stylesheet" href="docmd-live.css">
12
+ <script src="docmd-live.js"></script>
13
+
14
+ <script async src="https://www.googletagmanager.com/gtag/js?id=G-VCMQ0MCSHN"></script>
15
+ <script>
16
+ window.dataLayer = window.dataLayer || [];
17
+ function gtag() { dataLayer.push(arguments); }
18
+ gtag('js', new Date());
19
+ gtag('config', 'G-VCMQ0MCSHN');
20
+ </script>
21
+ </head>
22
+
23
+ <body class="mode-split">
24
+
25
+ <!-- Top Bar -->
26
+ <div class="top-bar">
27
+ <div class="logo">
28
+ <!--<a href="/" class="back-link" id="back-btn" title="Previous Page" aria-label="Back to previous page">
29
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
30
+ stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
31
+ <path d="m12 19-7-7 7-7" />
32
+ <path d="M19 12H5" />
33
+ </svg>
34
+ </a>-->
35
+ <a href="https://docmd.io" class="docmd-logo" title="Back to home" aria-label="Back to homepage"><svg width="24" height="24" id="icon-feather" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.24 12.24a6 6 0 0 0-8.49-8.49L5 10.5V19h8.5z"></path><line x1="16" y1="8" x2="2" y2="22"></line><line x1="17.5" y1="15" x2="9" y2="15"></line></svg></a> docmd <span>Live</span>
36
+ </div>
37
+
38
+ <!-- Unified 3-Way Switcher -->
39
+ <div class="view-switcher desktop-only">
40
+ <button class="view-btn active" onclick="setMode('split')" data-mode="split">Split</button>
41
+ <button class="view-btn" onclick="setMode('editor')" data-mode="editor">Editor</button>
42
+ <button class="view-btn" onclick="setMode('preview')" data-mode="preview">Preview</button>
43
+ </div>
44
+ </div>
45
+
46
+ <!-- Workspace -->
47
+ <div class="workspace" id="workspace">
48
+ <!-- Editor -->
49
+ <div class="pane editor-pane" id="editorPane">
50
+ <div class="pane-header">Markdown</div>
51
+ <textarea id="input" spellcheck="false">
52
+ ---
53
+ title: My Documentation
54
+ description: Start editing to see changes instantly.
55
+ ---
56
+
57
+ # Hello World
58
+
59
+ This is a **live** preview.
60
+
61
+ ::: callout tip
62
+ Try resizing the window or switching to mobile view!
63
+ :::
64
+
65
+ ## Features
66
+ 1. Responsive Design
67
+ 2. Split or Tabbed view
68
+ 3. Instant Rendering
69
+ </textarea>
70
+ </div>
71
+
72
+ <!-- Resizer Handle -->
73
+ <div class="resizer" id="resizer"></div>
74
+
75
+ <!-- Preview -->
76
+ <div class="pane preview-pane" id="previewPane">
77
+ <div class="pane-header">Preview</div>
78
+ <iframe id="preview"></iframe>
79
+ </div>
80
+ </div>
81
+
82
+ <!-- Mobile Bottom Tabs (Keep for small screens) -->
83
+ <div class="mobile-tabs">
84
+ <button class="mobile-tab-btn active" onclick="setMode('editor')" id="mob-edit">Editor</button>
85
+ <button class="mobile-tab-btn" onclick="setMode('preview')" id="mob-prev">Preview</button>
86
+ </div>
87
+
88
+ <script>
89
+ // --- Core Logic ---
90
+ const input = document.getElementById('input');
91
+ const preview = document.getElementById('preview');
92
+ const backBtn = document.getElementById('back-btn');
93
+
94
+ function render() {
95
+ try {
96
+ let html = docmd.compile(input.value, {
97
+ siteTitle: 'My Project',
98
+ search: false,
99
+ theme: { name: 'sky', defaultMode: 'light' },
100
+ sidebar: { collapsible: false }
101
+ });
102
+
103
+ // Injections
104
+ html = html.replace('<head>', '<head><base target="_blank">');
105
+ const customStyle = `
106
+ <style>
107
+ .sidebar-header { display: none !important; }
108
+ .sidebar-nav { margin-top: 1rem; }
109
+ </style>
110
+ `;
111
+ html = html.replace('</body>', `${customStyle}</body>`);
112
+
113
+ const doc = preview.contentWindow.document;
114
+ doc.open();
115
+ doc.write(html);
116
+ doc.close();
117
+ } catch (e) { console.error(e); }
118
+ }
119
+
120
+ let timer;
121
+ input.addEventListener('input', () => {
122
+ clearTimeout(timer);
123
+ timer = setTimeout(render, 300);
124
+ });
125
+ render();
126
+
127
+ // --- Resizer Logic ---
128
+ const resizer = document.getElementById('resizer');
129
+ const editorPane = document.getElementById('editorPane');
130
+ const workspace = document.getElementById('workspace');
131
+ let isResizing = false;
132
+
133
+ resizer.addEventListener('mousedown', (e) => {
134
+ isResizing = true;
135
+ resizer.classList.add('resizing');
136
+ preview.style.pointerEvents = 'none';
137
+ document.body.style.cursor = 'col-resize';
138
+ });
139
+
140
+ document.addEventListener('mousemove', (e) => {
141
+ if (!isResizing) return;
142
+ const containerWidth = workspace.offsetWidth;
143
+ const newEditorWidth = (e.clientX / containerWidth) * 100;
144
+ if (newEditorWidth > 15 && newEditorWidth < 85) {
145
+ editorPane.style.width = newEditorWidth + '%';
146
+ }
147
+ });
148
+
149
+ document.addEventListener('mouseup', () => {
150
+ if (isResizing) {
151
+ isResizing = false;
152
+ resizer.classList.remove('resizing');
153
+ preview.style.pointerEvents = 'auto';
154
+ document.body.style.cursor = 'default';
155
+ }
156
+ });
157
+
158
+ // --- Unified View Logic ---
159
+ function setMode(mode) {
160
+ // 1. Update UI Buttons (Desktop)
161
+ document.querySelectorAll('.view-switcher .view-btn').forEach(btn => {
162
+ btn.classList.toggle('active', btn.dataset.mode === mode);
163
+ });
164
+
165
+ // 2. Update Mobile Buttons
166
+ const mobMode = mode === 'split' ? 'editor' : mode; // Map split to editor on mobile
167
+ document.getElementById('mob-edit').classList.toggle('active', mobMode === 'editor');
168
+ document.getElementById('mob-prev').classList.toggle('active', mobMode === 'preview');
169
+
170
+ // 3. Update Layout Classes
171
+ // Reset
172
+ document.body.classList.remove('mode-split', 'mode-single', 'show-editor', 'show-preview');
173
+
174
+ if (mode === 'split') {
175
+ document.body.classList.add('mode-split');
176
+ } else {
177
+ document.body.classList.add('mode-single');
178
+ document.body.classList.add('show-' + mode);
179
+ }
180
+ }
181
+
182
+ // --- Back Button ---
183
+ /*
184
+ if (window.history.length <= 1) backBtn.style.display = 'none';
185
+ else backBtn.addEventListener('click', (e) => { e.preventDefault(); window.history.back(); });
186
+ */
187
+ </script>
188
+ </body>
189
+ </html>
package/src/shims.js ADDED
@@ -0,0 +1 @@
1
+ import { Buffer } from 'buffer'; globalThis.Buffer = Buffer;