sdocs-dev 1.0.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/bin/sdocs-dev.js +443 -0
- package/package.json +40 -0
- package/public/css/layout.css +237 -0
- package/public/css/mobile.css +189 -0
- package/public/css/panel.css +348 -0
- package/public/css/rendered.css +278 -0
- package/public/css/tokens.css +112 -0
- package/public/css/write.css +128 -0
- package/public/default.md +129 -0
- package/public/index.html +533 -0
- package/public/sdocs-app.js +595 -0
- package/public/sdocs-controls.js +221 -0
- package/public/sdocs-export.js +193 -0
- package/public/sdocs-state.js +43 -0
- package/public/sdocs-styles.js +285 -0
- package/public/sdocs-theme.js +168 -0
- package/public/sdocs-write.js +737 -0
- package/public/sdocs-yaml.js +78 -0
- package/server.js +65 -0
package/bin/sdocs-dev.js
ADDED
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* sdoc CLI
|
|
4
|
+
* Usage:
|
|
5
|
+
* sdoc report.md # open file in browser
|
|
6
|
+
* sdoc share report.md # print shareable URL to stdout
|
|
7
|
+
* sdoc new # blank document in write mode
|
|
8
|
+
* cat file.md | sdoc # pipe markdown to browser
|
|
9
|
+
* sdoc # open studio with empty editor
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
const zlib = require('zlib');
|
|
15
|
+
const { execSync } = require('child_process');
|
|
16
|
+
const SDocYaml = require('../public/sdocs-yaml.js');
|
|
17
|
+
|
|
18
|
+
const DEFAULT_URL = 'https://sdocs.dev';
|
|
19
|
+
|
|
20
|
+
// ── Help ───────────────────────────────────────────────────
|
|
21
|
+
const HELP = `
|
|
22
|
+
SDocs CLI
|
|
23
|
+
=========
|
|
24
|
+
Open, share, and style markdown files from the terminal.
|
|
25
|
+
|
|
26
|
+
USAGE
|
|
27
|
+
sdoc <file> Open file in browser (read mode)
|
|
28
|
+
sdoc <file> --write Open in write mode
|
|
29
|
+
sdoc <file> --style Open with style panel
|
|
30
|
+
sdoc <file> --raw Open raw markdown source
|
|
31
|
+
sdoc new New blank document (write mode)
|
|
32
|
+
sdoc share <file> Print shareable URL to stdout
|
|
33
|
+
sdoc share <file> --section "X" URL with section anchor
|
|
34
|
+
sdoc schema Print the full styles schema
|
|
35
|
+
sdoc defaults Show ~/.sdocs/styles.yaml
|
|
36
|
+
sdoc defaults --reset Remove default styles
|
|
37
|
+
sdoc help Show this help
|
|
38
|
+
cat file.md | sdoc Pipe markdown from stdin
|
|
39
|
+
cat file.md | sdoc share Pipe to shareable URL
|
|
40
|
+
|
|
41
|
+
MODE FLAGS
|
|
42
|
+
--read Clean reading view (default when file given)
|
|
43
|
+
--write Opens the contentEditable writer
|
|
44
|
+
--style Styled preview with style panel visible
|
|
45
|
+
--raw Shows raw markdown source
|
|
46
|
+
|
|
47
|
+
OPTIONS
|
|
48
|
+
--section <heading> Scroll to heading section on load
|
|
49
|
+
--url <base> Custom base URL (default: https://sdocs.dev)
|
|
50
|
+
--mode <m> Alias for --read / --write / --style / --raw
|
|
51
|
+
|
|
52
|
+
ENVIRONMENT
|
|
53
|
+
SDOCS_URL Fallback base URL if --url is not passed.
|
|
54
|
+
|
|
55
|
+
STYLED MARKDOWN FORMAT
|
|
56
|
+
SDocs extends standard .md files with an optional YAML
|
|
57
|
+
front matter block (the same standard used by Jekyll, Hugo, Obsidian).
|
|
58
|
+
The \`styles\` key controls every visual aspect of the rendered document.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
title: "My Document"
|
|
62
|
+
styles:
|
|
63
|
+
fontFamily: Inter
|
|
64
|
+
baseFontSize: 16
|
|
65
|
+
color: "#1c1917"
|
|
66
|
+
h1: { fontSize: 2.2, color: "#1a3a5c", fontWeight: 700 }
|
|
67
|
+
p: { lineHeight: 1.85, marginBottom: 1.1 }
|
|
68
|
+
---
|
|
69
|
+
# My Document
|
|
70
|
+
Content here...
|
|
71
|
+
|
|
72
|
+
Run \`sdoc schema\` for the complete list of style properties.
|
|
73
|
+
`;
|
|
74
|
+
|
|
75
|
+
const SCHEMA = `
|
|
76
|
+
SDocs — Styles Schema
|
|
77
|
+
=====================
|
|
78
|
+
All style values live under the \`styles:\` key in YAML front matter.
|
|
79
|
+
Every property is optional — omit anything you want left at its default.
|
|
80
|
+
|
|
81
|
+
GENERAL
|
|
82
|
+
fontFamily string Any of the supported fonts (see FONTS below)
|
|
83
|
+
Default: "Inter"
|
|
84
|
+
baseFontSize number Base font size in px. All rem/em values scale from this.
|
|
85
|
+
Default: 16
|
|
86
|
+
color string Master body text color (hex). Cascades to headings,
|
|
87
|
+
paragraphs, and lists unless those are overridden.
|
|
88
|
+
Default: "#1c1917"
|
|
89
|
+
lineHeight number Global line-height multiplier.
|
|
90
|
+
Default: 1.75
|
|
91
|
+
|
|
92
|
+
HEADINGS (general heading controls)
|
|
93
|
+
headers:
|
|
94
|
+
scale number Relative size multiplier applied across all heading levels.
|
|
95
|
+
Default: 1.0
|
|
96
|
+
marginBottom number Space below headings (em). Default: 0.4
|
|
97
|
+
color string Heading color — cascades to h1/h2/h3/h4 unless overridden.
|
|
98
|
+
Default: inherits \`color\`
|
|
99
|
+
|
|
100
|
+
PER-HEADING (each independently overrides the heading defaults above)
|
|
101
|
+
h1: { fontSize: number, color: string, fontWeight: number }
|
|
102
|
+
h2: { fontSize: number, color: string, fontWeight: number }
|
|
103
|
+
h3: { fontSize: number, color: string, fontWeight: number }
|
|
104
|
+
h4: { fontSize: number, color: string, fontWeight: number }
|
|
105
|
+
|
|
106
|
+
fontSize is in rem (relative to baseFontSize).
|
|
107
|
+
Sensible defaults: h1 2.2, h2 1.55, h3 1.2, h4 1.0
|
|
108
|
+
fontWeight: 400 (regular) · 600 (semibold) · 700 (bold)
|
|
109
|
+
|
|
110
|
+
PARAGRAPH
|
|
111
|
+
p:
|
|
112
|
+
lineHeight number Line height for body paragraphs. Default: 1.75
|
|
113
|
+
marginBottom number Space between paragraphs (em). Default: 1.1
|
|
114
|
+
color string Paragraph text color. Default: inherits \`color\`
|
|
115
|
+
|
|
116
|
+
LISTS
|
|
117
|
+
list:
|
|
118
|
+
color string Color for list items and bullet/number markers.
|
|
119
|
+
Default: inherits paragraph color
|
|
120
|
+
|
|
121
|
+
LINKS
|
|
122
|
+
link:
|
|
123
|
+
color string Link color. Default: "#2563eb"
|
|
124
|
+
decoration string "underline" | "none". Default: "underline"
|
|
125
|
+
|
|
126
|
+
CODE
|
|
127
|
+
code:
|
|
128
|
+
fontFamily string Monospace font. Default: "ui-monospace, monospace"
|
|
129
|
+
background string Inline/block code background color. Default: "#F1EDE8"
|
|
130
|
+
padding number Inline code padding (em). Default: 0.2
|
|
131
|
+
|
|
132
|
+
BLOCKQUOTE
|
|
133
|
+
blockquote:
|
|
134
|
+
borderColor string Left border accent color. Default: "#2563eb"
|
|
135
|
+
borderWidth number Left border thickness (px). Default: 3
|
|
136
|
+
color string Quote text color. Default: "#6b6560"
|
|
137
|
+
|
|
138
|
+
COLOR CASCADE
|
|
139
|
+
Colors cascade from general → specific:
|
|
140
|
+
color → headers.color → h1.color, h2.color, h3.color, h4.color
|
|
141
|
+
color → p.color → list.color
|
|
142
|
+
Set a child color only when you want it to differ from its parent.
|
|
143
|
+
|
|
144
|
+
FONTS (24 supported, loaded lazily from Google Fonts)
|
|
145
|
+
Inter · Roboto · Open Sans · Lato · Montserrat · Source Sans 3
|
|
146
|
+
Oswald · Raleway · Poppins · Merriweather · Ubuntu · Nunito
|
|
147
|
+
Playfair Display · Roboto Slab · PT Sans · Lora · Mulish · Noto Sans
|
|
148
|
+
Rubik · Dosis · Josefin Sans · PT Serif · Libre Franklin · Crimson Text
|
|
149
|
+
|
|
150
|
+
EXAMPLE — editorial article with colored heading tiers
|
|
151
|
+
---
|
|
152
|
+
styles:
|
|
153
|
+
fontFamily: Lora
|
|
154
|
+
baseFontSize: 17
|
|
155
|
+
color: "#1a1a2e"
|
|
156
|
+
headers:
|
|
157
|
+
color: "#2c3e50"
|
|
158
|
+
h1: { fontSize: 2.3, color: "#c0392b", fontWeight: 700 }
|
|
159
|
+
h2: { fontSize: 1.55, color: "#8e44ad", fontWeight: 600 }
|
|
160
|
+
h3: { fontSize: 1.2, color: "#16a085", fontWeight: 600 }
|
|
161
|
+
p: { lineHeight: 1.9, marginBottom: 1.2 }
|
|
162
|
+
link: { color: "#e67e22", decoration: "underline" }
|
|
163
|
+
blockquote: { borderColor: "#c0392b", borderWidth: 4, color: "#7f8c8d" }
|
|
164
|
+
---
|
|
165
|
+
`;
|
|
166
|
+
|
|
167
|
+
// ── Compression (deflate-raw + base64url) ─────────────────
|
|
168
|
+
|
|
169
|
+
function compressToBase64Url(text) {
|
|
170
|
+
const deflated = zlib.deflateRawSync(Buffer.from(text, 'utf-8'));
|
|
171
|
+
return deflated.toString('base64')
|
|
172
|
+
.replace(/\+/g, '-')
|
|
173
|
+
.replace(/\//g, '_')
|
|
174
|
+
.replace(/=+$/, '');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function decompressFromBase64Url(b64url) {
|
|
178
|
+
let b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
|
|
179
|
+
const pad = (4 - b64.length % 4) % 4;
|
|
180
|
+
b64 += '='.repeat(pad);
|
|
181
|
+
return zlib.inflateRawSync(Buffer.from(b64, 'base64')).toString('utf-8');
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// ── Slugify ───────────────────────────────────────────────
|
|
185
|
+
|
|
186
|
+
function slugify(text) {
|
|
187
|
+
return text.toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-]/g, '').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// ── Parse args ────────────────────────────────────────────
|
|
191
|
+
|
|
192
|
+
const SUBCOMMANDS = new Set(['new', 'share', 'schema', 'defaults', 'help']);
|
|
193
|
+
|
|
194
|
+
function parseArgs(argv) {
|
|
195
|
+
const args = argv || process.argv.slice(2);
|
|
196
|
+
let file = null;
|
|
197
|
+
let mode = null;
|
|
198
|
+
let url = null;
|
|
199
|
+
let subcommand = null;
|
|
200
|
+
let section = null;
|
|
201
|
+
let resetFlag = false;
|
|
202
|
+
|
|
203
|
+
for (let i = 0; i < args.length; i++) {
|
|
204
|
+
const arg = args[i];
|
|
205
|
+
|
|
206
|
+
// Legacy / shortcut flags that map to subcommands
|
|
207
|
+
if (arg === '--help' || arg === '-h') { subcommand = 'help'; continue; }
|
|
208
|
+
if (arg === '--schema') { subcommand = 'schema'; continue; }
|
|
209
|
+
|
|
210
|
+
// Mode shorthand flags
|
|
211
|
+
if (arg === '--write') { mode = 'write'; continue; }
|
|
212
|
+
if (arg === '--style') { mode = 'style'; continue; }
|
|
213
|
+
if (arg === '--raw') { mode = 'raw'; continue; }
|
|
214
|
+
if (arg === '--read') { mode = 'read'; continue; }
|
|
215
|
+
|
|
216
|
+
// Long-form --mode
|
|
217
|
+
if (arg === '--mode' || arg === '-m') {
|
|
218
|
+
mode = args[++i];
|
|
219
|
+
if (!['read', 'write', 'style', 'raw'].includes(mode)) {
|
|
220
|
+
console.error(`sdoc: unknown mode "${mode}" — use read, write, style, or raw`);
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// --url flag
|
|
227
|
+
if (arg === '--url') { url = args[++i]; continue; }
|
|
228
|
+
|
|
229
|
+
// --section flag
|
|
230
|
+
if (arg === '--section' || arg === '-s') { section = args[++i]; continue; }
|
|
231
|
+
|
|
232
|
+
// --reset flag (for defaults subcommand)
|
|
233
|
+
if (arg === '--reset') { resetFlag = true; continue; }
|
|
234
|
+
|
|
235
|
+
// Positional: check for subcommand first, then file
|
|
236
|
+
if (!subcommand && SUBCOMMANDS.has(arg)) {
|
|
237
|
+
subcommand = arg;
|
|
238
|
+
continue;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (!file) { file = arg; continue; }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
return { file, mode, url, subcommand, section, resetFlag };
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// ── Build URL ─────────────────────────────────────────────
|
|
248
|
+
|
|
249
|
+
function buildUrl(content, opts) {
|
|
250
|
+
const baseUrl = opts.url || process.env.SDOCS_URL || DEFAULT_URL;
|
|
251
|
+
const params = new URLSearchParams();
|
|
252
|
+
|
|
253
|
+
if (content) {
|
|
254
|
+
params.set('md', compressToBase64Url(content));
|
|
255
|
+
} else if (opts.defaultStyles) {
|
|
256
|
+
const stylesJson = JSON.stringify(opts.defaultStyles);
|
|
257
|
+
params.set('styles', encodeURIComponent(Buffer.from(stylesJson, 'utf-8').toString('base64')));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const mode = opts.mode || (content ? 'read' : 'style');
|
|
261
|
+
if (mode && mode !== 'read') params.set('mode', mode);
|
|
262
|
+
|
|
263
|
+
if (opts.section) {
|
|
264
|
+
params.set('sec', slugify(opts.section));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const qs = params.toString();
|
|
268
|
+
return qs ? `${baseUrl}/#${qs}` : baseUrl;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// ── YAML parsing (shared module) ──
|
|
272
|
+
const { parseSimpleYaml, parseFrontMatter, serializeFrontMatter } = SDocYaml;
|
|
273
|
+
|
|
274
|
+
// ── ~/.sdocs/styles.yaml default styles ────────────────────
|
|
275
|
+
|
|
276
|
+
function getDefaultsPath() {
|
|
277
|
+
return path.join(require('os').homedir(), '.sdocs', 'styles.yaml');
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function loadDefaultStyles() {
|
|
281
|
+
const configPath = getDefaultsPath();
|
|
282
|
+
if (!fs.existsSync(configPath)) return null;
|
|
283
|
+
try {
|
|
284
|
+
const yaml = fs.readFileSync(configPath, 'utf-8');
|
|
285
|
+
return parseSimpleYaml(yaml);
|
|
286
|
+
} catch {
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function showDefaults() {
|
|
292
|
+
const configPath = getDefaultsPath();
|
|
293
|
+
if (!fs.existsSync(configPath)) {
|
|
294
|
+
console.log('No default styles set (~/.sdocs/styles.yaml not found).');
|
|
295
|
+
console.log('\nTo set defaults, style a document in SDocs and use');
|
|
296
|
+
console.log('the "Save as Default" panel to generate the command.');
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
console.log(fs.readFileSync(configPath, 'utf-8'));
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function resetDefaults() {
|
|
303
|
+
const configPath = getDefaultsPath();
|
|
304
|
+
if (!fs.existsSync(configPath)) {
|
|
305
|
+
console.log('No default styles to remove.');
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
fs.unlinkSync(configPath);
|
|
309
|
+
console.log('Removed ' + configPath);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Deep merge: defaults under file styles (file wins on conflict)
|
|
313
|
+
function mergeStyles(defaults, fileStyles) {
|
|
314
|
+
if (!defaults) return fileStyles || {};
|
|
315
|
+
if (!fileStyles) return { ...defaults };
|
|
316
|
+
const merged = { ...defaults };
|
|
317
|
+
for (const [k, v] of Object.entries(fileStyles)) {
|
|
318
|
+
if (typeof v === 'object' && v !== null && typeof merged[k] === 'object' && merged[k] !== null) {
|
|
319
|
+
merged[k] = { ...merged[k], ...v };
|
|
320
|
+
} else {
|
|
321
|
+
merged[k] = v;
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
return merged;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Apply default styles to content, returning modified content
|
|
328
|
+
function applyDefaultStyles(content) {
|
|
329
|
+
const defaults = loadDefaultStyles();
|
|
330
|
+
if (!defaults) return content;
|
|
331
|
+
|
|
332
|
+
const { meta, body } = parseFrontMatter(content);
|
|
333
|
+
const mergedStyles = mergeStyles(defaults, meta.styles);
|
|
334
|
+
const newMeta = { ...meta, styles: mergedStyles };
|
|
335
|
+
return serializeFrontMatter(newMeta) + '\n' + body;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ── Read content ───────────────────────────────────────────
|
|
339
|
+
|
|
340
|
+
async function readContent(file) {
|
|
341
|
+
if (file) {
|
|
342
|
+
const resolved = path.resolve(file);
|
|
343
|
+
if (!fs.existsSync(resolved)) {
|
|
344
|
+
console.error(`sdoc: file not found: ${file}`);
|
|
345
|
+
process.exit(1);
|
|
346
|
+
}
|
|
347
|
+
return fs.readFileSync(resolved, 'utf-8');
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Check if stdin has data (piped input)
|
|
351
|
+
if (!process.stdin.isTTY) {
|
|
352
|
+
return new Promise((resolve, reject) => {
|
|
353
|
+
let data = '';
|
|
354
|
+
process.stdin.setEncoding('utf-8');
|
|
355
|
+
process.stdin.on('data', chunk => data += chunk);
|
|
356
|
+
process.stdin.on('end', () => resolve(data));
|
|
357
|
+
process.stdin.on('error', reject);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
return null; // no content — just open studio
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// ── Open browser ───────────────────────────────────────────
|
|
365
|
+
|
|
366
|
+
function openBrowser(url) {
|
|
367
|
+
const platform = process.platform;
|
|
368
|
+
try {
|
|
369
|
+
if (platform === 'darwin') execSync(`open "${url}"`);
|
|
370
|
+
else if (platform === 'win32') execSync(`start "" "${url}"`);
|
|
371
|
+
else execSync(`xdg-open "${url}"`);
|
|
372
|
+
} catch {
|
|
373
|
+
console.log(`Open in browser: ${url}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// ── Main ───────────────────────────────────────────────────
|
|
378
|
+
|
|
379
|
+
if (require.main === module) {
|
|
380
|
+
(async () => {
|
|
381
|
+
const opts = parseArgs();
|
|
382
|
+
|
|
383
|
+
// Subcommand dispatch
|
|
384
|
+
if (opts.subcommand === 'help') { console.log(HELP); process.exit(0); }
|
|
385
|
+
if (opts.subcommand === 'schema') { console.log(SCHEMA); process.exit(0); }
|
|
386
|
+
if (opts.subcommand === 'defaults') {
|
|
387
|
+
if (opts.resetFlag) resetDefaults();
|
|
388
|
+
else showDefaults();
|
|
389
|
+
process.exit(0);
|
|
390
|
+
}
|
|
391
|
+
if (opts.subcommand === 'new') {
|
|
392
|
+
const baseUrl = opts.url || process.env.SDOCS_URL || DEFAULT_URL;
|
|
393
|
+
const url = baseUrl + '/new';
|
|
394
|
+
openBrowser(url);
|
|
395
|
+
console.log(`SDocs → ${url}`);
|
|
396
|
+
process.exit(0);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// File / stdin handling
|
|
400
|
+
let content = await readContent(opts.file);
|
|
401
|
+
|
|
402
|
+
// Apply ~/.sdocs/styles.yaml defaults
|
|
403
|
+
const defaults = loadDefaultStyles();
|
|
404
|
+
if (content && defaults) {
|
|
405
|
+
content = applyDefaultStyles(content);
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
const url = buildUrl(content, {
|
|
409
|
+
url: opts.url,
|
|
410
|
+
mode: opts.mode,
|
|
411
|
+
defaultStyles: !content ? defaults : null,
|
|
412
|
+
section: opts.section,
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
// Share: print URL to stdout, don't open browser
|
|
416
|
+
if (opts.subcommand === 'share') {
|
|
417
|
+
process.stdout.write(url + '\n');
|
|
418
|
+
process.exit(0);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// Default: open browser
|
|
422
|
+
openBrowser(url);
|
|
423
|
+
console.log(`SDocs → ${url.length > 80 ? url.slice(0, 77) + '...' : url}`);
|
|
424
|
+
})().catch(e => {
|
|
425
|
+
console.error('sdoc:', e.message);
|
|
426
|
+
process.exit(1);
|
|
427
|
+
});
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// ── Exports (for tests) ───────────────────────────────────
|
|
431
|
+
|
|
432
|
+
module.exports = {
|
|
433
|
+
mergeStyles,
|
|
434
|
+
applyDefaultStyles,
|
|
435
|
+
parseFrontMatter,
|
|
436
|
+
serializeFrontMatter,
|
|
437
|
+
parseSimpleYaml,
|
|
438
|
+
parseArgs,
|
|
439
|
+
buildUrl,
|
|
440
|
+
slugify,
|
|
441
|
+
compressToBase64Url,
|
|
442
|
+
decompressFromBase64Url,
|
|
443
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "sdocs-dev",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Open, share, and style markdown files from the terminal",
|
|
5
|
+
"main": "server.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"sdoc": "./bin/sdocs-dev.js",
|
|
8
|
+
"sdocs-dev": "./bin/sdocs-dev.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"bin/",
|
|
12
|
+
"public/",
|
|
13
|
+
"server.js"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"start": "node server.js",
|
|
17
|
+
"test": "node test/run.js"
|
|
18
|
+
},
|
|
19
|
+
"keywords": [
|
|
20
|
+
"markdown",
|
|
21
|
+
"editor",
|
|
22
|
+
"styling",
|
|
23
|
+
"pdf",
|
|
24
|
+
"docx",
|
|
25
|
+
"cli"
|
|
26
|
+
],
|
|
27
|
+
"author": "Josh Summers",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/JoshInLisbon/SDocs.git"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://sdocs.dev",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"marked": "^11.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@playwright/test": "^1.58.2"
|
|
39
|
+
}
|
|
40
|
+
}
|