@rip-lang/print 0.1.8 → 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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/print.rip +69 -43
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rip-lang/print",
3
- "version": "0.1.8",
3
+ "version": "1.0.0",
4
4
  "description": "Syntax-highlighted source code printer — Shiki-powered, serves once, auto-opens browser",
5
5
  "type": "module",
6
6
  "main": "print.rip",
package/print.rip CHANGED
@@ -1,4 +1,4 @@
1
- # ============================================================================
1
+ # ==============================================================================
2
2
  # rip-print — Syntax-highlighted source code printer
3
3
  #
4
4
  # Author: Steve Shreeve (steve.shreeve@gmail.com)
@@ -6,7 +6,7 @@
6
6
  #
7
7
  # Highlights source code using Shiki (VS Code's syntax engine) and serves
8
8
  # the result in the browser for viewing and printing. Serves once and exits.
9
- # ============================================================================
9
+ # ==============================================================================
10
10
 
11
11
  import hljs from 'highlight.js'
12
12
  import ripLanguage from './hljs-rip.js'
@@ -17,12 +17,16 @@ import { execSync } from 'child_process'
17
17
  # Register Rip language with highlight.js
18
18
  hljs.registerLanguage 'rip', ripLanguage
19
19
 
20
- # ============================================================================
20
+ # ==============================================================================
21
21
  # CLI argument parsing
22
- # ============================================================================
22
+ # ==============================================================================
23
23
 
24
24
  args = process.argv.slice(2)
25
25
 
26
+ if args.includes('-v') or args.includes('--version')
27
+ console.log "rip-print 1.0.0"
28
+ process.exit(0)
29
+
26
30
  if args.includes('-h') or args.includes('--help')
27
31
  console.log """
28
32
  usage: rip-print [options] <paths ...>
@@ -31,6 +35,7 @@ if args.includes('-h') or args.includes('--help')
31
35
  -b, --bypass Strip leading comment blocks from files
32
36
  -d, --dark Use dark theme (default: light)
33
37
  -h, --help Show this help message
38
+ -v, --version Show version and quit
34
39
  -x <exts> Comma list of extensions to exclude
35
40
 
36
41
  Examples:
@@ -71,9 +76,9 @@ defaultExclude = new Set [
71
76
  for ext in excludeExts
72
77
  defaultExclude.add ext
73
78
 
74
- # ============================================================================
79
+ # ==============================================================================
75
80
  # File discovery
76
- # ============================================================================
81
+ # ==============================================================================
77
82
 
78
83
  skipDirs = new Set ['.git', 'node_modules', '.rip-cache', '.zig-cache', 'zig-out', 'dist', 'misc']
79
84
 
@@ -116,9 +121,9 @@ if allFiles.length is 0
116
121
 
117
122
  console.log "#{allFiles.length} file#{if allFiles.length > 1 then 's' else ''}"
118
123
 
119
- # ============================================================================
124
+ # ==============================================================================
120
125
  # Language detection
121
- # ============================================================================
126
+ # ==============================================================================
122
127
 
123
128
  extToLang =
124
129
  rip: 'rip'
@@ -176,9 +181,9 @@ def getLang(file)
176
181
  return lang if lang and hljs.getLanguage(lang)
177
182
  return 'plaintext'
178
183
 
179
- # ============================================================================
184
+ # ==============================================================================
180
185
  # Highlight and build HTML
181
- # ============================================================================
186
+ # ==============================================================================
182
187
 
183
188
  def stripTopComments(code)
184
189
  lines = code.split('\n')
@@ -227,9 +232,9 @@ for file in allFiles
227
232
  html = "<pre><code class=\"hljs\">#{highlighted}</code></pre>"
228
233
  sections.push { file, lineCount, lang, timestamp, html }
229
234
 
230
- # ============================================================================
235
+ # ==============================================================================
231
236
  # HTML template
232
- # ============================================================================
237
+ # ==============================================================================
233
238
 
234
239
  bgColor = if dark then '#0d1117' else '#ffffff'
235
240
  textColor = if dark then '#e6edf3' else '#1f2328'
@@ -318,48 +323,59 @@ html = """
318
323
  <link rel="icon" href="data:,">
319
324
  <style id="hljs-theme">#{defaultCss}</style>
320
325
  <style>
326
+ :root { --bg: #{bgColor}; --fg: #{textColor}; --hdr: #{headerBg}; --brd: #{borderColor}; --gut: #{if dark then '#161b22' else '#f4f4f4'}; --act: #{if dark then '#30363d' else '#e0e0e0'}; }
321
327
  * { margin: 0; padding: 0; box-sizing: border-box; }
322
- body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: #{bgColor}; color: #{textColor}; }
328
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--fg); }
323
329
 
324
- .toolbar { padding: 8px 16px; border-bottom: 1px solid #{borderColor}; text-align: right; font-size: 13px; }
325
- .toolbar select { font-size: 13px; padding: 4px 8px; border-radius: 3px; border: 1px solid #{borderColor}; background: #{bgColor}; color: #{textColor}; }
330
+ .toolbar { padding: 8px 16px; border-bottom: 1px solid var(--brd); text-align: right; font-size: 13px; }
331
+ .toolbar select { font-size: 13px; padding: 4px 8px; border-radius: 3px; border: 1px solid var(--brd); background: var(--bg); color: var(--fg); }
326
332
  .toolbar label { color: #888; margin-left: 16px; }
327
- .toc { padding: 20px 30px; border-bottom: 1px solid #{borderColor}; }
333
+ .size-group { display: inline-flex; vertical-align: middle; margin-left: 4px; }
334
+ .size-btn { font-size: 13px; width: 32px; height: 28px; border: 1px solid var(--brd); background: var(--bg); color: #888; cursor: pointer; margin: 0; padding: 0; }
335
+ .size-btn:first-child { border-radius: 3px 0 0 3px; }
336
+ .size-btn:last-child { border-radius: 0 3px 3px 0; }
337
+ .size-btn + .size-btn { margin-left: -1px; }
338
+ .size-btn.active { background: var(--act); color: var(--fg); font-weight: 600; }
339
+ .toc { padding: 20px 30px; border-bottom: 1px solid var(--brd); }
328
340
  .toc h2 { font-size: 18px; margin-bottom: 10px; }
329
341
  .toc ol { padding-left: 24px; columns: 2; column-gap: 40px; }
330
342
  .toc li { font-size: 13px; line-height: 1.8; }
331
- .toc a { color: #{textColor}; text-decoration: none; }
343
+ .toc a { color: var(--fg); text-decoration: none; }
332
344
  .toc a:hover { text-decoration: underline; }
333
345
  .meta { color: #888; font-size: 12px; }
334
346
 
335
347
  .file-section { margin-bottom: 0; margin-top: -1px; }
336
348
  .file-header {
337
- background: #{headerBg}; padding: 10px 16px 10px 5.85em; font-size: 13px; font-weight: 600;
338
- border-top: 1px solid #{borderColor}; border-bottom: 1px solid #{borderColor};
349
+ background: var(--hdr); padding: 10px 16px 10px 5.85em; font-size: 13px; font-weight: 600;
350
+ border-top: 1px solid var(--brd); border-bottom: 1px solid var(--brd);
339
351
  display: flex; justify-content: space-between; align-items: center;
340
352
  }
341
353
  .nav { font-weight: normal; font-size: 12px; }
342
354
  .nav a { color: #888; text-decoration: none; padding: 6px 10px; border-radius: 3px; }
343
- .nav a:hover { color: #{textColor}; background: #{if dark then '#30363d' else '#e0e0e0'}; }
355
+ .nav a:hover { color: var(--fg); background: var(--act); }
344
356
 
345
- .code-container { overflow-x: auto; border-bottom: 1px solid #{borderColor}; }
357
+ .code-container { overflow-x: auto; border-bottom: 1px solid var(--brd); }
346
358
  .code-container pre { margin: 0; border-radius: 0; }
347
- .code-container code { font-size: 13px; line-height: 1.5; padding: 0 !important; display: block; }
348
- .line-num { color: #aaa; background: #{if dark then '#161b22' else '#f4f4f4'}; user-select: none; display: inline-block; min-width: 2em; text-align: right; padding: 0 0.7em; margin-right: 0.7em; border-right: 1px solid #{borderColor}; }
359
+ .code-container code { font-size: var(--code-size, 13px); line-height: 1.5; padding: 0 !important; display: block; }
360
+ .line-num { color: #aaa; background: var(--gut); user-select: none; display: inline-block; min-width: 2em; text-align: right; padding: 0 0.7em; margin-right: 0.7em; border-right: 1px solid var(--brd); }
349
361
  .line-num.first { padding-top: 4px; }
350
362
 
351
363
  @media print {
352
- .toc { page-break-after: always; }
353
- .file-header { background: #f0f0f0 !important; color: #000 !important; }
364
+ .file-header { background: #333 !important; color: #fff !important; box-shadow: inset 0 0 0 1000px #333; -webkit-print-color-adjust: exact; print-color-adjust: exact; }
365
+ .file-header .meta { color: #ccc !important; }
354
366
  .toolbar { display: none; }
355
367
  .nav { display: none; }
356
368
  body { background: white !important; color: black !important; }
357
- code { font-size: 11px !important; }
358
369
  }
359
370
  </style>
360
371
  </head>
361
372
  <body>
362
373
  <div class="toolbar">
374
+ <label>Size: <span class="size-group">
375
+ <button class="size-btn" data-size="11">S</button>
376
+ <button class="size-btn active" data-size="13">M</button>
377
+ <button class="size-btn" data-size="15">L</button>
378
+ </span></label>
363
379
  <label>Theme: <select id="theme-picker">
364
380
  <optgroup label="Light">#{themeOptions.split('\n').filter((o) -> o.includes('data-dark="false"')).join('')}</optgroup>
365
381
  <optgroup label="Dark">#{themeOptions.split('\n').filter((o) -> o.includes('data-dark="true"')).join('')}</optgroup>
@@ -379,20 +395,13 @@ html = """
379
395
  if (!t) return;
380
396
  document.getElementById('hljs-theme').textContent = t.c;
381
397
  var d = t.d;
382
- var bg = d ? '#0d1117' : '#ffffff';
383
- var fg = d ? '#e6edf3' : '#1f2328';
384
- var hdr = d ? '#161b22' : '#f6f8fa';
385
- var brd = d ? '#30363d' : '#d0d7de';
386
- var gut = d ? '#161b22' : '#f4f4f4';
387
- document.body.style.background = bg;
388
- document.body.style.color = fg;
389
- document.querySelectorAll('.toolbar').forEach(function(e) { e.style.borderColor = brd; });
390
- document.querySelectorAll('.toolbar select').forEach(function(e) { e.style.background = bg; e.style.color = fg; e.style.borderColor = brd; });
391
- document.querySelectorAll('.toc').forEach(function(e) { e.style.borderColor = brd; });
392
- document.querySelectorAll('.file-header').forEach(function(e) { e.style.background = hdr; e.style.borderColor = brd; e.style.color = fg; });
393
- document.querySelectorAll('.line-num').forEach(function(e) { e.style.background = gut; e.style.borderColor = brd; });
394
- document.querySelectorAll('.code-container').forEach(function(e) { e.style.borderColor = brd; });
395
- document.querySelectorAll('.toc a').forEach(function(e) { e.style.color = fg; });
398
+ var r = document.documentElement.style;
399
+ r.setProperty('--bg', d ? '#0d1117' : '#ffffff');
400
+ r.setProperty('--fg', d ? '#e6edf3' : '#1f2328');
401
+ r.setProperty('--hdr', d ? '#161b22' : '#f6f8fa');
402
+ r.setProperty('--brd', d ? '#30363d' : '#d0d7de');
403
+ r.setProperty('--gut', d ? '#161b22' : '#f4f4f4');
404
+ r.setProperty('--act', d ? '#30363d' : '#e0e0e0');
396
405
  });
397
406
  // Restore saved theme
398
407
  var saved = localStorage.getItem('rip-print-theme');
@@ -400,19 +409,36 @@ html = """
400
409
  document.getElementById('theme-picker').value = saved;
401
410
  document.getElementById('theme-picker').dispatchEvent(new Event('change'));
402
411
  }
412
+
413
+ // Font size buttons
414
+ document.querySelectorAll('.size-btn').forEach(function(btn) {
415
+ btn.addEventListener('click', function() {
416
+ var size = btn.getAttribute('data-size') + 'px';
417
+ document.documentElement.style.setProperty('--code-size', size);
418
+ document.querySelectorAll('.size-btn').forEach(function(b) { b.classList.remove('active'); });
419
+ btn.classList.add('active');
420
+ localStorage.setItem('rip-print-size', btn.getAttribute('data-size'));
421
+ });
422
+ });
423
+ // Restore saved size
424
+ var savedSize = localStorage.getItem('rip-print-size');
425
+ if (savedSize) {
426
+ var sizeBtn = document.querySelector('.size-btn[data-size="' + savedSize + '"]');
427
+ if (sizeBtn) sizeBtn.click();
428
+ }
403
429
  </script>
404
430
  </body>
405
431
  </html>
406
432
  """
407
433
 
408
- # ============================================================================
434
+ # ==============================================================================
409
435
  # Serve once and open browser
410
- # ============================================================================
436
+ # ==============================================================================
411
437
 
412
438
  served = false
413
439
 
414
440
  server = Bun.serve
415
- port: 0
441
+ port: 9111
416
442
  fetch: (req) ->
417
443
  served = true
418
444
  new Response html, headers: { 'Content-Type': 'text/html; charset=utf-8' }