ligarb 0.6.0 → 0.8.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.
data/lib/ligarb/cli.rb CHANGED
@@ -17,6 +17,10 @@ module Ligarb
17
17
  Builder.new(config_path).build
18
18
  when "init"
19
19
  Initializer.new(args.first).run
20
+ when "setup-github-review"
21
+ require_relative "github_review"
22
+ directory = args.reject { |a| a.start_with?("--") }.first
23
+ GithubReview.run(directory)
20
24
  when "serve"
21
25
  config_paths = args.reject { |a| a.start_with?("--") }
22
26
  config_paths = ["book.yml"] if config_paths.empty?
@@ -67,6 +71,8 @@ module Ligarb
67
71
 
68
72
  Usage:
69
73
  ligarb init [DIRECTORY] Create a new book project
74
+ ligarb setup-github-review [DIRECTORY]
75
+ Set up (or update) GitHub Pages + review workflows
70
76
  ligarb build [CONFIG] Build the HTML book (default CONFIG: book.yml)
71
77
  ligarb serve [CONFIG] Serve the book with live reload and review UI
72
78
  ligarb librarium Serve all */book.yml as a multi-book library
@@ -90,6 +96,8 @@ module Ligarb
90
96
  repository (optional) GitHub repository URL for "Edit on GitHub" links
91
97
  ai_generated (optional) Mark as AI-generated (badge + meta tags, default: false)
92
98
  footer (optional) Custom text at bottom of each chapter
99
+ github_review (optional) Enable the "Report as issue" reader feedback UI ({enabled: true}, needs repository)
100
+ translations (optional) Map of lang => config path for multi-language builds
93
101
 
94
102
  Example:
95
103
  ligarb build
@@ -97,578 +105,10 @@ module Ligarb
97
105
  USAGE
98
106
  end
99
107
 
100
- def spec_text
101
- <<~SPEC
102
- ligarb - Generate a single-page HTML book from Markdown files
103
-
104
- Version: #{VERSION}
105
-
106
- == Overview ==
107
-
108
- ligarb converts multiple Markdown files into a self-contained index.html.
109
- The generated HTML includes:
110
- - A left sidebar with a searchable table of contents (h1-h3)
111
- - Chapter-based content switching in the main area
112
- - Permalink support via URL hash (#chapter-slug)
113
- - Responsive design with print-friendly styles
114
- - Syntax-highlighted code blocks
115
- - Search with content highlighting
116
- - Chapter and section numbering (configurable)
117
- - Previous/Next chapter navigation
118
- - Dark mode toggle (saved to localStorage)
119
- - Custom CSS support
120
- - "Edit on GitHub" links (optional)
121
- - Footnotes (kramdown syntax)
122
-
123
- == Commands ==
124
-
125
- ligarb init [DIRECTORY] Create a new book project with scaffolding.
126
- If DIRECTORY is given, creates and populates that directory.
127
- If omitted, populates the current directory.
128
- Generates book.yml, 01-introduction.md, and images/.
129
- If .md files already exist, registers them as chapters.
130
- Aborts if book.yml already exists.
131
-
132
- ligarb build [CONFIG] Build the HTML book.
133
- CONFIG defaults to 'book.yml' in the current directory.
134
-
135
- ligarb serve [CONFIG...]
136
- Start a local web server with live reload and review UI.
137
- CONFIG defaults to 'book.yml' in the current directory.
138
- Multiple CONFIG paths can be given to serve multiple books.
139
- Options:
140
- --port PORT Server port (default: 3000)
141
- --multi Force multi-book mode (even with 1 CONFIG)
142
- Single book mode (1 CONFIG, without --multi):
143
- - Serves the built HTML book at http://localhost:PORT
144
- Multi-book mode (2+ CONFIGs, or --multi):
145
- - Top page (/) shows a book index with links
146
- - Each book is served at /<directory-name>/
147
- - "Write a new book" button on the index page to generate
148
- a new book via AI (posts a brief, runs Writer in background)
149
- - Example: ligarb serve */book.yml
150
- Features:
151
- - Injects a reload button that pulses when build output changes
152
- - Injects a review UI for commenting on book text
153
- - Review comments are saved to .ligarb/reviews/*.json
154
- (in each book's directory)
155
- - If 'claude' CLI is installed, comments are sent to Claude
156
- for review suggestions, and approved changes are applied
157
- to the source Markdown files and the book is rebuilt
158
- - Review patches can span multiple chapters and the
159
- bibliography file (Claude reads book.yml to find all files)
160
-
161
- ligarb librarium Start a multi-book library server.
162
- Automatically discovers */book.yml in the current directory.
163
- Equivalent to: ligarb serve --multi */book.yml
164
- Options:
165
- --port PORT Server port (default: 3000)
166
-
167
- ligarb help Show this detailed specification.
168
-
169
- ligarb --help Show short usage summary.
170
-
171
- ligarb version Show the version number.
172
-
173
- == Configuration: book.yml ==
174
-
175
- The configuration file is a YAML file with the following fields:
176
-
177
- title: (required) The book title displayed in the header and <title> tag.
178
- author: (optional) Author name displayed in the header. Default: empty.
179
- language: (optional) HTML lang attribute value. Default: "en".
180
- output_dir: (optional) Output directory relative to book.yml. Default: "build".
181
- chapter_numbers: (optional) Show chapter/section numbers (e.g. "1.", "1.1", "1.1.1").
182
- Default: true.
183
- style: (optional) Path to a custom CSS file relative to book.yml.
184
- Loaded after the default styles, so it can override any rule.
185
- repository: (optional) GitHub repository URL (e.g. "https://github.com/user/repo").
186
- When set, each chapter shows a "View on GitHub" link.
187
- The link points to {repository}/blob/HEAD/{path-from-git-root}.
188
- The chapter path is resolved relative to the Git repository root.
189
- ai_generated: (optional) Mark the book as AI-generated content. Default: false.
190
- When true: adds an "AI Generated" badge in the sidebar header,
191
- adds a default disclaimer footer to each chapter, and adds
192
- noindex/noai meta tags to prevent search indexing and AI training.
193
- The footer text can be overridden with the 'footer' field.
194
- footer: (optional) Custom text displayed at the bottom of each chapter.
195
- Overrides the default ai_generated disclaimer if both are set.
196
- Useful for copyright notices, disclaimers, or other per-chapter text.
197
- chapters: (required) Book structure. An array that can contain:
198
- - A cover: a centered title/landing page
199
- - A string: a chapter Markdown file path (relative to book.yml)
200
- - A part: groups chapters under a titled section
201
- - An appendix: groups chapters with alphabetic numbering (A, B, C, ...)
202
-
203
- The chapters array supports four element types:
204
-
205
- 1. Cover (object with 'cover' key):
206
- chapters:
207
- - cover: cover.md # Markdown file: displayed as centered title page
208
- # Not shown in the TOC sidebar.
209
-
210
- 2. Plain chapter (string):
211
- chapters:
212
- - 01-introduction.md
213
-
214
- 3. Part (object with 'part' and 'chapters' keys):
215
- chapters:
216
- - part: part1.md # Markdown file: h1 = part title, body = opening text
217
- chapters:
218
- - 01-introduction.md
219
- - 02-getting-started.md
220
-
221
- 4. Appendix (object with 'appendix' key, value is array of chapter files):
222
- chapters:
223
- - appendix:
224
- - a1-references.md
225
- - a2-glossary.md
226
-
227
- These can be combined freely:
228
-
229
- chapters:
230
- - cover: cover.md
231
- - part: part1.md
232
- chapters:
233
- - 01-introduction.md
234
- - 02-getting-started.md
235
- - part: part2.md
236
- chapters:
237
- - 03-advanced.md
238
- - appendix:
239
- - a1-references.md
240
-
241
- Part numbering is sequential across parts (1, 2, 3, ...).
242
- Appendix numbering uses letters (A, B, C, ...).
243
-
244
- Example book.yml (simple):
245
-
246
- title: "My Software Guide"
247
- author: "Author Name"
248
- language: "ja"
249
- chapters:
250
- - 01-introduction.md
251
- - 02-getting-started.md
252
- - 03-advanced.md
253
-
254
- Example book.yml (with parts and appendix):
255
-
256
- title: "My Software Guide"
257
- author: "Author Name"
258
- language: "ja"
259
- chapters:
260
- - part: part1.md
261
- chapters:
262
- - 01-introduction.md
263
- - 02-getting-started.md
264
- - part: part2.md
265
- chapters:
266
- - 03-advanced.md
267
- - 04-deployment.md
268
- - appendix:
269
- - a1-config-reference.md
270
-
271
- == Directory Structure ==
272
-
273
- A typical book project has this structure:
274
-
275
- my-book/
276
- ├── book.yml # Configuration file
277
- ├── part1.md # Part opening page (optional)
278
- ├── 01-introduction.md # Markdown source files
279
- ├── 02-getting-started.md
280
- ├── 03-advanced.md
281
- └── images/ # Image files (optional)
282
- ├── screenshot.png
283
- └── diagram.svg
284
-
285
- After running 'ligarb build', the output is:
286
-
287
- my-book/
288
- └── build/
289
- ├── index.html # Single-page HTML book
290
- ├── js/ # Auto-downloaded (only if needed)
291
- ├── css/ # Auto-downloaded (only if needed)
292
- └── images/ # Copied image files
293
-
294
- == Markdown Files ==
295
-
296
- Each Markdown file represents one chapter. ligarb uses GitHub Flavored
297
- Markdown (GFM) via kramdown. Supported syntax includes:
298
-
299
- - Headings (# h1, ## h2, ### h3) — used for TOC generation
300
- - Code blocks with language-specific syntax highlighting (``` fenced blocks)
301
- - Tables, task lists, strikethrough, and other GFM extensions
302
- - Inline HTML
303
-
304
- The first heading (h1) in each file becomes the chapter title in the TOC.
305
-
306
- == Fenced Code Blocks ==
307
-
308
- The following fenced code block types are automatically detected and
309
- rendered. Required JS/CSS is auto-downloaded on first build to build/js/
310
- and build/css/.
311
-
312
- ```ruby, ```python, etc. Syntax highlighting (highlight.js, BSD-3-Clause)
313
- ```mermaid Diagrams: flowcharts, sequence, bar/line/pie charts,
314
- gantt, mindmap, etc.
315
- (mermaid, MIT)
316
- ```math LaTeX math equations (KaTeX, MIT)
317
- ```functionplot Function graphs (function-plot + d3, MIT)
318
-
319
- These are rendered visually in the output HTML — use them freely.
320
-
321
- Mermaid example (flowchart):
322
-
323
- ```mermaid
324
- graph TD
325
- A[Start] --> B{Check}
326
- B -->|Yes| C[OK]
327
- B -->|No| D[Retry]
328
- ```
329
-
330
- Mermaid example (sequence diagram):
331
-
332
- ```mermaid
333
- sequenceDiagram
334
- Client->>Server: Request
335
- Server-->>Client: Response
336
- ```
337
-
338
- Mermaid example (bar chart):
339
-
340
- ```mermaid
341
- xychart
342
- title "Monthly Sales"
343
- x-axis ["Jan", "Feb", "Mar", "Apr", "May"]
344
- y-axis "Revenue" 0 --> 500
345
- bar [120, 230, 180, 350, 410]
346
- line [120, 230, 180, 350, 410]
347
- ```
348
-
349
- Mermaid example (line chart, line only):
350
-
351
- ```mermaid
352
- xychart
353
- title "Temperature"
354
- x-axis ["Jan", "Feb", "Mar", "Apr", "May", "Jun"]
355
- y-axis "°C" -5 --> 30
356
- line [2, 4, 10, 16, 22, 26]
357
- ```
358
-
359
- Mermaid example (pie chart):
360
-
361
- ```mermaid
362
- pie title Browser Share
363
- "Chrome" : 65
364
- "Safari" : 19
365
- "Firefox" : 4
366
- "Other" : 12
367
- ```
368
-
369
- Mermaid example (gantt chart):
370
-
371
- ```mermaid
372
- gantt
373
- title Project Plan
374
- dateFormat YYYY-MM-DD
375
- section Design
376
- Requirements :a1, 2025-01-01, 14d
377
- Architecture :a2, after a1, 10d
378
- section Dev
379
- Implementation :b1, after a2, 21d
380
- Testing :b2, after b1, 14d
381
- ```
382
-
383
- Mermaid example (mindmap):
384
-
385
- ```mermaid
386
- mindmap
387
- root((Project))
388
- Frontend
389
- React
390
- CSS
391
- Backend
392
- API
393
- Database
394
- ```
395
-
396
- Math example (KaTeX, LaTeX syntax):
397
-
398
- ```math
399
- E = mc^2
400
- ```
401
-
402
- Inline math uses $...$ syntax within text:
403
-
404
- The equation $E = mc^2$ is well-known.
405
-
406
- Rules for inline math:
407
- - $$ is not matched (use ```math for display math)
408
- - $ followed by a space is not matched (e.g. $10)
409
- - $ preceded by a space is not matched
410
- - Content inside <code> and <pre> is not affected
411
- - The content is rendered with KaTeX (displayMode: false)
412
-
413
- Function plot example:
414
-
415
- ```functionplot
416
- y = sin(x)
417
- y = x^2 - 1
418
- range: [-2pi, 2pi]
419
- yrange: [-3, 3]
420
- ```
421
-
422
- Function plot syntax:
423
- - y = <expr> Standard function (e.g. y = sin(x))
424
- - r = <expr> Polar function (e.g. r = cos(2*theta))
425
- - parametric: <x>, <y> Parametric curve (e.g. parametric: cos(t), sin(t))
426
- - Bare expression Treated as y = <expr>
427
- Options (one per line):
428
- - range / xrange: [min, max] X-axis range (supports pi, e.g. [-2pi, 2pi])
429
- - yrange: [min, max] Y-axis range
430
- - width: <pixels> Plot width (default: 600)
431
- - height: <pixels> Plot height (default: 400)
432
- - title: <text> Plot title
433
- - grid: true Show grid lines
434
-
435
- == Images ==
436
-
437
- Place image files in the 'images/' directory next to book.yml.
438
- Reference them from Markdown with relative paths:
439
-
440
- ![Screenshot](images/screenshot.png)
441
-
442
- ligarb rewrites image paths to 'images/filename' in the output and copies
443
- all files from the images/ directory to the output.
444
-
445
- == Build ==
446
-
447
- Run from the directory containing book.yml:
448
-
449
- ligarb build
108
+ HELP_PATH = File.expand_path("../../../docs/help.md", __FILE__)
450
109
 
451
- Or specify a path to book.yml:
452
-
453
- ligarb build path/to/book.yml
454
-
455
- The generated index.html is a fully self-contained HTML file (CSS and JS
456
- are embedded). Open it directly in a browser — no web server needed.
457
-
458
- == Footnotes ==
459
-
460
- Footnotes use kramdown syntax:
461
-
462
- This is a sentence with a footnote[^1].
463
-
464
- [^1]: This is the footnote content.
465
-
466
- Footnote IDs are scoped per chapter to avoid collisions in the single-page
467
- output.
468
-
469
- == Index ==
470
-
471
- Mark terms for the book index using Markdown link syntax with #index:
472
-
473
- [Ruby](#index) Index the link text as-is
474
- [dynamic typing](#index:動的型付け) Index under a specific term
475
- [Ruby](#index:Ruby,Languages/Ruby) Multiple index entries (comma-separated)
476
- [Ruby](#index:Languages/Ruby) Hierarchical: Languages > Ruby
477
-
478
- The link is rendered as plain text in the output (no link styling).
479
- An "Index" section is automatically appended at the end of the book,
480
- with terms sorted alphabetically and grouped by first character.
481
-
482
- Clicking an index entry navigates to the exact location in the chapter.
483
-
484
- == Bibliography ==
485
-
486
- Cite references in the text using Markdown link syntax with #cite:
487
-
488
- [Ruby](#cite:matz1995) Cite by key; rendered as Ruby[Matsumoto, 1995]
489
-
490
- Define a bibliography data file in book.yml:
491
-
492
- bibliography: references.yml # YAML format
493
- bibliography: references.bib # BibTeX format
494
-
495
- The format is auto-detected by file extension (.bib = BibTeX, otherwise YAML).
496
-
497
- YAML format maps keys to reference data:
498
-
499
- matz1995:
500
- author: "Yukihiro Matsumoto"
501
- title: "The Ruby Programming Language"
502
- year: 1995
503
- url: "https://www.ruby-lang.org"
504
- publisher: "O'Reilly"
505
- doi: "10.1234/example"
506
-
507
- BibTeX format (.bib) is also supported:
508
-
509
- @book{matz1995,
510
- author = {Yukihiro Matsumoto},
511
- title = {The Ruby Programming Language},
512
- year = {1995},
513
- publisher = {O'Reilly},
514
- url = {https://www.ruby-lang.org}
515
- }
516
-
517
- BibTeX notes:
518
- - Entry types (@book, @article, etc.) are preserved for formatting
519
- - Field values can use {braces} or "quotes"
520
- - Nested braces are supported one level deep ({The {Ruby} Language})
521
- - Lines starting with % are comments
522
-
523
- Supported fields (YAML and BibTeX):
524
- author, title, year, url, publisher, journal, booktitle, volume,
525
- number, pages, edition, doi, editor, note.
526
-
527
- The bibliography section formats entries by type:
528
- - book: Author. Title. Edition. Publisher, Year.
529
- - article: Author. "Title". Journal, Volume(Number), Pages, Year.
530
- - inproceedings: Author. "Title". In Booktitle, Pages, Year.
531
- - other/YAML: Author. Title. Publisher/Journal, Volume, Pages, Year.
532
-
533
- If url is present, the title becomes a link. If doi is present, a DOI link
534
- is appended.
535
-
536
- The citation is rendered as a superscript [author, year] link that navigates
537
- to the "Bibliography" section at the end of the book. Hovering the link shows
538
- the full reference. The bibliography section lists all cited entries sorted by
539
- author and year.
540
-
541
- A warning is printed and the citation is rendered as [key?] (highlighted in
542
- red) if a cite key is not found in the bibliography file.
543
- If no bibliography file is configured, cite markers are left as-is.
544
-
545
- == Custom CSS ==
546
-
547
- Add a 'style' field to book.yml to inject custom CSS:
548
-
549
- style: "custom.css"
550
-
551
- The custom CSS is loaded after the default styles. You can override any
552
- CSS custom property (e.g. colors, fonts, sidebar width) or add new rules.
553
-
554
- Example custom.css:
555
-
556
- :root {
557
- --color-accent: #e63946;
558
- --sidebar-width: 320px;
559
- }
560
-
561
- == Dark Mode ==
562
-
563
- The generated HTML includes a dark mode toggle button (moon icon) in the
564
- sidebar header. The user's preference is saved to localStorage and persists
565
- across page reloads.
566
-
567
- Custom CSS can override dark mode colors using the [data-theme="dark"]
568
- selector.
569
-
570
- == Edit on GitHub ==
571
-
572
- Add a 'repository' field to book.yml:
573
-
574
- repository: "https://github.com/user/repo"
575
-
576
- Each chapter will show a "View on GitHub" link pointing to:
577
- {repository}/blob/HEAD/{path-from-git-root}
578
-
579
- == Admonitions ==
580
-
581
- GFM-style blockquote alerts are converted to styled admonition boxes.
582
- Five types are supported: NOTE, TIP, WARNING, CAUTION, IMPORTANT.
583
-
584
- Syntax:
585
-
586
- > [!NOTE]
587
- > This is a note.
588
-
589
- > [!TIP]
590
- > Helpful advice here.
591
-
592
- > [!WARNING]
593
- > Be careful about this.
594
-
595
- > [!CAUTION]
596
- > Dangerous operation.
597
-
598
- > [!IMPORTANT]
599
- > Critical information.
600
-
601
- Each type renders with a distinct color and icon:
602
- - NOTE: blue (info)
603
- - TIP: green (lightbulb)
604
- - WARNING: yellow (warning)
605
- - CAUTION: red (stop)
606
- - IMPORTANT: purple (exclamation)
607
-
608
- == Cross-References ==
609
-
610
- Link to other chapters or headings using standard Markdown relative links.
611
- ligarb resolves .md file references to internal anchors in the single-page
612
- output.
613
-
614
- Syntax:
615
-
616
- [link text](other-chapter.md) Link to a chapter
617
- [link text](other-chapter.md#Heading) Link to a specific heading
618
- [](other-chapter.md) Auto-fill with chapter title
619
- [](other-chapter.md#Heading) Auto-fill with heading text
620
-
621
- The .md path is resolved relative to the current Markdown file's directory.
622
- The heading fragment is matched against heading IDs (case-insensitive,
623
- normalized the same way heading slugs are generated).
624
-
625
- When the link text is empty, ligarb fills it with the target's display text:
626
- - Chapter link: the chapter's display title (e.g. "3. Config Guide")
627
- - Heading link: the heading's display text (e.g. "3.2 Setup")
628
-
629
- If a referenced chapter or heading does not exist, the build fails with an
630
- error message indicating the broken reference and its source file.
631
-
632
- External URLs ending in .md (e.g. https://example.com/README.md) are not
633
- affected — only relative paths are resolved.
634
-
635
- == Previous/Next Navigation ==
636
-
637
- Each chapter displays Previous and Next navigation links at the bottom.
638
- These follow the flat chapter order (including across parts and appendix).
639
- Cover pages do not show navigation.
640
-
641
- == Write Command ==
642
-
643
- ligarb write [BRIEF] Generate a complete book using AI (Claude).
644
- BRIEF defaults to 'brief.yml' in the current directory.
645
- Reads the brief, sends a prompt to Claude, and builds
646
- the generated book. Files are created in the same
647
- directory as brief.yml.
648
-
649
- ligarb write --init [DIR] Create a brief.yml template.
650
- If DIR is given, creates DIR/brief.yml (mkdir as needed).
651
- If omitted, creates brief.yml in the current directory.
652
-
653
- ligarb write --no-build Generate files only, skip the build step.
654
-
655
- brief.yml fields:
656
-
657
- title: (required) The book title.
658
- language: (optional) Language. Default: "ja".
659
- audience: (optional) Target audience (used in the prompt).
660
- notes: (optional) Additional instructions for Claude (free text).
661
- author: (optional) Passed through to book.yml.
662
- output_dir: (optional) Passed through to book.yml.
663
- chapter_numbers: (optional) Passed through to book.yml.
664
- style: (optional) Passed through to book.yml.
665
- repository: (optional) Passed through to book.yml.
666
-
667
- The book is generated in the directory containing brief.yml.
668
- Example: 'ligarb write ruby_book/brief.yml' creates files in ruby_book/.
669
-
670
- Requires the 'claude' CLI to be installed.
671
- SPEC
110
+ def spec_text
111
+ "ligarb #{VERSION}\n\n#{File.read(HELP_PATH)}"
672
112
  end
673
113
 
674
114
  def print_spec