@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.
- package/package.json +1 -1
- package/print.rip +69 -43
package/package.json
CHANGED
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:
|
|
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
|
|
325
|
-
.toolbar select { font-size: 13px; padding: 4px 8px; border-radius: 3px; border: 1px solid
|
|
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
|
-
.
|
|
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:
|
|
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:
|
|
338
|
-
border-top: 1px solid
|
|
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:
|
|
355
|
+
.nav a:hover { color: var(--fg); background: var(--act); }
|
|
344
356
|
|
|
345
|
-
.code-container { overflow-x: auto; border-bottom: 1px solid
|
|
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:
|
|
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
|
-
.
|
|
353
|
-
.file-header {
|
|
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
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
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:
|
|
441
|
+
port: 9111
|
|
416
442
|
fetch: (req) ->
|
|
417
443
|
served = true
|
|
418
444
|
new Response html, headers: { 'Content-Type': 'text/html; charset=utf-8' }
|