markwell 0.0.1 → 0.1.3

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Markwell Contributors
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.
package/README.md ADDED
@@ -0,0 +1,425 @@
1
+ # Markwell
2
+
3
+ Convert documents to and from Markdown. The source from which polished documents flow.
4
+
5
+ Markwell gives Claude Code and AI agents the ability to **transform** documents — Word files, spreadsheets, presentations, and transcripts — using Markdown as the universal hub format. Install it once, and your agent gains a complete document toolkit.
6
+
7
+ ## Why Markwell?
8
+
9
+ AI agents work in plain text. Documents live in binary formats like `.docx`, `.xlsx`, and `.pptx`. Markwell bridges this gap:
10
+
11
+ - **Ingest** any supported document into Markdown so an agent can read and reason about it
12
+ - **Export** Markdown back into polished, styled documents ready for sharing
13
+ - **Theme** exports with professional styling — no manual formatting needed
14
+
15
+ ```
16
+ .docx ─┐ ┌─ .docx
17
+ .xlsx ─┤ ├─ .xlsx
18
+ .pptx ─┤ ┌──────────┐ ├─ .pptx / .html / .pdf
19
+ .vtt ─┤──▶│ Markdown │──▶ ├─ .vtt / .srt
20
+ .srt ─┤ └──────────┘ └─ (themed output)
21
+ .html ─┤ Hub Format
22
+ .rtf ─┤
23
+ .json ─┘
24
+ ```
25
+
26
+ ## Install
27
+
28
+ ```bash
29
+ npm install -g markwell
30
+ ```
31
+
32
+ Requires Node.js 20 or later. All dependencies are included — no additional system software needed.
33
+
34
+ ### Claude Code Integration
35
+
36
+ Install the Markwell skill so Claude Code knows how to use it:
37
+
38
+ ```bash
39
+ markwell install-skills # project-level (.claude/commands/)
40
+ markwell install-skills --global # global (~/.claude/commands/)
41
+ ```
42
+
43
+ This copies a skill file that teaches Claude Code the available commands, formats, and options.
44
+
45
+ ## Quick Start
46
+
47
+ ### Reading Documents (Ingest)
48
+
49
+ Convert any supported file to Markdown:
50
+
51
+ ```bash
52
+ markwell convert report.docx # → report.md
53
+ markwell convert financials.xlsx # → financials/ (one CSV per sheet)
54
+ markwell convert deck.pptx # → deck.md
55
+ markwell convert meeting.vtt # → meeting.md
56
+ markwell convert page.html # → page.md
57
+ markwell convert data.json # → data.md
58
+ ```
59
+
60
+ ### Creating Documents (Export)
61
+
62
+ Convert Markdown into styled output using format aliases:
63
+
64
+ ```bash
65
+ markwell convert draft.md --to docx # → draft.docx
66
+ markwell convert draft.md --to word # → draft.docx (alias)
67
+ markwell convert data.csv --to xlsx # → data.xlsx
68
+ markwell convert data.csv --to excel # → data.xlsx (alias)
69
+ markwell convert slides.md --to pptx # → slides.pptx
70
+ markwell convert slides.md --to powerpoint # → slides.pptx (alias)
71
+ markwell convert slides.md --to html # → slides.html
72
+ markwell convert slides.md --to pdf # → slides.pdf
73
+ markwell convert transcript.md --to vtt # → transcript.vtt
74
+ markwell convert transcript.md --to srt # → transcript.srt
75
+ markwell convert draft.md --to docx,pdf # → draft.docx + draft.pdf
76
+ ```
77
+
78
+ ### Batch Processing
79
+
80
+ Use glob patterns to convert multiple files at once:
81
+
82
+ ```bash
83
+ markwell convert "docs/*.docx" # all Word files
84
+ markwell convert "**/*.html" -o output/ # recursive, custom output dir
85
+ markwell convert "reports/*.md" --to docx --force # overwrite without prompting
86
+ ```
87
+
88
+ ## Supported Formats
89
+
90
+ ### Ingest (read)
91
+
92
+ | Category | Extensions |
93
+ | ------------ | --------------------------------- |
94
+ | Document | `.docx`, `.doc` |
95
+ | Spreadsheet | `.xlsx`, `.xls`, `.xlsm` |
96
+ | Presentation | `.pptx`, `.ppt` |
97
+ | Transcript | `.vtt`, `.srt` |
98
+ | Web | `.html`, `.htm` |
99
+ | Rich Text | `.rtf` |
100
+ | Data | `.json`, `.jsonl`, `.jsonc` |
101
+ | Drawing | `.excalidraw` |
102
+ | Slides (MD) | `.md` (Marp format) |
103
+
104
+ ### Export (create)
105
+
106
+ | Category | Extensions | Aliases |
107
+ | ------------ | ---------------------------- | ------------------------------------------- |
108
+ | Document | `.docx`, `.html`, `.pdf`* | `word`, `doc`, `docx` |
109
+ | Spreadsheet | `.xlsx` | `excel`, `xlsx`, `xls`, `sheets` |
110
+ | Presentation | `.html`, `.pptx`, `.pdf` | `powerpoint`, `slides`, `pptx`, `ppt` |
111
+ | Transcript | `.vtt`, `.srt` | `vtt`, `srt`, `transcription` |
112
+
113
+ ## CLI Reference
114
+
115
+ ### `markwell convert <file-or-glob>`
116
+
117
+ The primary command. Converts files to or from Markdown.
118
+
119
+ ```
120
+ Options:
121
+ --to <format> Export format(s): docx, pptx, pdf, xlsx, vtt, srt, etc.
122
+ -o, --output <path> Output file or directory
123
+ --theme <name|path> Theme name or path to .markwell.yaml
124
+ --force Overwrite existing files without prompting
125
+ --dry-run Show what would happen without writing
126
+ --verbose Show detailed processing info
127
+ ```
128
+
129
+ When `--to` is omitted, Markwell ingests the file into Markdown. When `--to` is provided, it exports Markdown to the specified format. You can use format aliases like `powerpoint`, `word`, or `excel`, and comma-separated values for multi-format output (e.g., `--to docx,pdf`).
130
+
131
+ The `--dry-run` flag is useful for previewing what an agent would do before committing to file writes.
132
+
133
+ ### `markwell converters list`
134
+
135
+ Show all registered ingest and export converters with their supported extensions and formats.
136
+
137
+ ### `markwell converters info <name>`
138
+
139
+ Show details about a specific converter (e.g., `markwell converters info docx`).
140
+
141
+ ### `markwell themes list`
142
+
143
+ List all available themes — both built-in and any `.markwell.yaml` found in the directory tree.
144
+
145
+ ### `markwell themes preview <name>`
146
+
147
+ Display a fully resolved theme with all settings — colors, typography, spacing, and format-specific options.
148
+
149
+ ### `markwell themes init`
150
+
151
+ Create a starter `.markwell.yaml` in the current directory. Use `--force` to overwrite an existing file.
152
+
153
+ ### `markwell install-skills [--global]`
154
+
155
+ Copy the Claude Code skill file to `.claude/commands/markwell.md`. With `--global`, installs to `~/.claude/commands/` instead.
156
+
157
+ ## Themes
158
+
159
+ Themes control the visual styling of exported documents. Four built-in themes are included:
160
+
161
+ | Theme | Description |
162
+ | ---------------- | ----------------------------------------------------------- |
163
+ | `default` | Clean, minimal styling — Calibri 11pt, standard margins |
164
+ | `professional` | Corporate/consulting — darker palette, wider margins |
165
+ | `modern` | Contemporary — bolder accent colors, Segoe UI font |
166
+ | `minimal` | Stripped down — content-focused, fewer decorative elements |
167
+
168
+ ### Using Themes
169
+
170
+ ```bash
171
+ # Apply a built-in theme
172
+ markwell convert report.md --to docx --theme professional
173
+
174
+ # Apply a custom theme file
175
+ markwell convert report.md --to docx --theme ./brand.markwell.yaml
176
+ ```
177
+
178
+ ### Automatic Theme Discovery
179
+
180
+ If you place a `.markwell.yaml` file in your project, Markwell finds it automatically by walking up the directory tree from the input file. No `--theme` flag needed.
181
+
182
+ ```bash
183
+ # Create a project theme
184
+ markwell themes init
185
+
186
+ # Edit .markwell.yaml to customize, then convert — theme applies automatically
187
+ markwell convert report.md --to docx
188
+ ```
189
+
190
+ ### Custom Themes
191
+
192
+ A `.markwell.yaml` file extends a base theme and overrides specific settings:
193
+
194
+ ```yaml
195
+ extends: professional
196
+
197
+ colors:
198
+ primary: "1A4F8B"
199
+ accent: "E8491D"
200
+
201
+ typography:
202
+ fontFamily: Georgia
203
+
204
+ document:
205
+ header: "{title}"
206
+ footer: "Page {page} of {pages}"
207
+ margins:
208
+ left: 1800
209
+ right: 1800
210
+
211
+ spreadsheet:
212
+ headerBackground: "$primary"
213
+ headerBold: true
214
+
215
+ presentation:
216
+ footer: "Confidential"
217
+ paginate: true
218
+ ```
219
+
220
+ Color variables like `$primary` and `$accent` reference values from the `colors` section and are substituted automatically.
221
+
222
+ ### Theme Sections
223
+
224
+ | Section | Controls |
225
+ | ---------------- | ---------------------------------------------------------------------------------------------- |
226
+ | `colors` | Primary, accent, text, background, muted (hex values) |
227
+ | `typography` | Font family, body size, heading sizes, code font |
228
+ | `spacing` | Paragraph spacing, heading spacing (before/after) |
229
+ | `document` | Margins, headers, footers (with `{title}`, `{page}`, `{pages}`, `{date}` placeholders) |
230
+ | `spreadsheet` | Header row background, text color, bold |
231
+ | `presentation` | Theme name, pagination, background color, header/footer, custom CSS |
232
+ | `transcript` | Speaker label inclusion |
233
+
234
+ ### Theme Inheritance
235
+
236
+ Themes can chain: your theme extends `professional`, which extends `default`. Each layer deep-merges — objects merge recursively, primitives replace. Circular inheritance is detected and rejected.
237
+
238
+ ---
239
+
240
+ ## Developer Guide
241
+
242
+ ### Getting Started
243
+
244
+ ```bash
245
+ git clone <repo-url>
246
+ cd markwell
247
+ npm install
248
+ npm run build # compile TypeScript + copy themes/skills to dist
249
+ npm test # run all 184 tests
250
+ npm run lint # ESLint
251
+ npm run typecheck # TypeScript strict mode check
252
+ ```
253
+
254
+ The build step runs `tsdown` to bundle the CLI entry point, then copies `src/themes/` and `src/skills/` to `dist/` (these are runtime assets that must be accessible from the compiled output).
255
+
256
+ ### Project Structure
257
+
258
+ ```
259
+ src/
260
+ ├── cli/
261
+ │ ├── index.ts # CLI entry point (commander setup)
262
+ │ ├── setup-registry.ts # Converter registration
263
+ │ └── commands/
264
+ │ ├── convert.ts # convert command (ingest + export logic)
265
+ │ ├── converters.ts # converters list/info commands
266
+ │ ├── themes.ts # themes list/preview/init commands
267
+ │ └── install-skills.ts # install-skills command
268
+ ├── core/
269
+ │ ├── types.ts # Shared interfaces
270
+ │ ├── registry.ts # ConverterRegistry class
271
+ │ ├── theme-schema.ts # Theme types and defaults
272
+ │ └── theme-loader.ts # Theme resolution, inheritance, variable substitution
273
+ ├── ingest/ # One file per ingest converter
274
+ ├── export/ # One file per export converter
275
+ │ └── utils/
276
+ │ └── markdown-parser.ts # Shared unified/remark AST parser
277
+ ├── themes/ # Built-in theme YAML files
278
+ └── skills/ # Claude Code skill template
279
+ tests/
280
+ ├── fixtures/ # Sample files for testing
281
+ └── integration/ # CLI e2e, round-trip, registry, startup tests
282
+ ```
283
+
284
+ ### How Converters Work
285
+
286
+ Markwell uses a **registry pattern** with two-stage resolution for ingest and category-based resolution for export.
287
+
288
+ #### Ingest Converters
289
+
290
+ An ingest converter transforms a source file into Markdown:
291
+
292
+ ```typescript
293
+ interface IngestConverter {
294
+ name: string; // e.g., "docx"
295
+ extensions: string[]; // e.g., [".docx", ".doc"]
296
+ canProcess(input: CanProcessInput): Promise<boolean>;
297
+ ingest(input: IngestInput): Promise<IngestOutput>;
298
+ }
299
+ ```
300
+
301
+ **Resolution** works in two stages:
302
+
303
+ 1. **Extension filter** — narrow to converters whose `extensions` array matches the input file
304
+ 2. **Content inspection** — call `canProcess()` on each match (in registration order) with the first 1KB of file content
305
+
306
+ This allows smart detection — for example, `.json` files are checked for Excalidraw schema before falling back to the generic JSON converter.
307
+
308
+ **Output** is either a single Markdown string (`markdown`) or multiple files (`files` — used by xlsx for one CSV per sheet), plus optional binary `assets` and `metadata`.
309
+
310
+ #### Export Converters
311
+
312
+ An export converter transforms Markdown (or CSV) into a styled output format:
313
+
314
+ ```typescript
315
+ interface ExportConverter {
316
+ name: string; // e.g., "document"
317
+ category: ExportCategory; // "document" | "spreadsheet" | "presentation" | "transcript"
318
+ formats: ExportFormat[]; // Supported output formats
319
+ export(input: ExportInput): Promise<ExportOutput>;
320
+ }
321
+ ```
322
+
323
+ **Resolution** matches by category, then validates the requested format against the converter's `formats` array.
324
+
325
+ The `ExportInput` includes the resolved theme, so converters apply styling without needing to know about theme loading.
326
+
327
+ #### Adding a New Converter
328
+
329
+ 1. Create `src/ingest/myformat.ts` (or `src/export/myformat.ts`)
330
+ 2. Implement the `IngestConverter` or `ExportConverter` interface
331
+ 3. Register it in `src/cli/setup-registry.ts` — order matters for ingest (specific before generic)
332
+ 4. Add tests alongside (e.g., `src/ingest/myformat.test.ts`)
333
+ 5. Add test fixtures to `tests/fixtures/`
334
+
335
+ #### Lazy Loading
336
+
337
+ Heavy dependencies (mammoth, exceljs, docx, marp-core) are loaded via dynamic `import()` inside converter functions. This keeps CLI startup fast — the 62KB bundle loads instantly, and heavy libraries are only pulled in when a specific converter is used.
338
+
339
+ ### The Style API
340
+
341
+ Export converters receive a fully resolved `ResolvedTheme` object. Here's how each export uses it:
342
+
343
+ #### Document Export (DOCX)
344
+
345
+ The document exporter walks the Markdown AST (via unified/remark-parse/remark-gfm) and maps nodes to `docx` package elements:
346
+
347
+ ```typescript
348
+ // Theme values used:
349
+ theme.typography.fontFamily // → font for all text runs
350
+ theme.typography.bodySize // → body text size (half-points)
351
+ theme.typography.headingSizes // → { 1: 48, 2: 40, ... } per heading level
352
+ theme.typography.codeFont // → font for code blocks/inline code
353
+ theme.colors.primary // → heading text color
354
+ theme.colors.text // → body text color
355
+ theme.colors.accent // → table header background, link color
356
+ theme.spacing.paragraphAfter // → paragraph spacing (twips)
357
+ theme.spacing.headingBefore // → space before headings
358
+ theme.spacing.headingAfter // → space after headings
359
+ theme.document.margins // → { top, bottom, left, right } in twips
360
+ theme.document.header // → header text (supports {title}, {page}, {pages}, {date})
361
+ theme.document.footer // → footer text
362
+ ```
363
+
364
+ #### Spreadsheet Export (XLSX)
365
+
366
+ Parses CSV/TSV input and creates ExcelJS workbooks:
367
+
368
+ ```typescript
369
+ theme.spreadsheet.headerBackground // → header row fill color (supports $variable)
370
+ theme.spreadsheet.headerTextColor // → header row font color
371
+ theme.spreadsheet.headerBold // → bold header row
372
+ ```
373
+
374
+ #### Presentation Export (HTML/PPTX/PDF)
375
+
376
+ Injects theme settings as Marp frontmatter directives and custom CSS:
377
+
378
+ ```typescript
379
+ theme.presentation.theme // → Marp theme name
380
+ theme.presentation.paginate // → slide numbering
381
+ theme.presentation.backgroundColor // → slide background
382
+ theme.presentation.header // → slide header
383
+ theme.presentation.footer // → slide footer
384
+ theme.presentation.style // → custom CSS injected into output
385
+ theme.colors.primary // → heading color via CSS
386
+ theme.typography.fontFamily // → font-family via CSS
387
+ ```
388
+
389
+ #### Transcript Export (VTT/SRT)
390
+
391
+ Parses the shared transcript Markdown format and reconstructs subtitle files:
392
+
393
+ ```typescript
394
+ theme.transcript.speakerLabels // → include speaker labels in VTT output
395
+ ```
396
+
397
+ ### Testing
398
+
399
+ Tests live alongside source files (`*.test.ts`) and in `tests/integration/`:
400
+
401
+ ```bash
402
+ npm test # run all tests
403
+ npm run test:watch # watch mode
404
+ npx vitest run src/ingest/ # run only ingest tests
405
+ npx vitest run tests/integration/ # run only integration tests
406
+ ```
407
+
408
+ **Note:** First-run tests for converters that lazy-load heavy dependencies may need extended timeouts (15-30s) due to cold-start module loading in dev containers.
409
+
410
+ ## Contributing
411
+
412
+ 1. Fork the repository
413
+ 2. Create a feature branch
414
+ 3. Make your changes with tests
415
+ 4. Ensure `npm run lint`, `npm run typecheck`, and `npm test` all pass
416
+ 5. Submit a pull request
417
+
418
+ ### CI/CD
419
+
420
+ - **CI** runs on every push to `main` and on PRs: lint, typecheck, test (with coverage), and build across Node.js 18 and 20
421
+ - **Release** triggers on `v*` tags and publishes to npm with provenance
422
+
423
+ ## License
424
+
425
+ MIT
@@ -0,0 +1 @@
1
+ export {};