@rip-lang/print 0.1.9 → 1.0.1
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/README.md +1 -1
- package/bin/rip-print +2 -1
- package/hljs-rip.js +1 -1
- package/package.json +2 -2
- package/print.rip +64 -43
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ rip-print -x lock,map src/
|
|
|
51
51
|
## How It Works
|
|
52
52
|
|
|
53
53
|
1. Walks the specified paths, discovers source files
|
|
54
|
-
2. Highlights each file using
|
|
54
|
+
2. Highlights each file using highlight.js with the detected language
|
|
55
55
|
3. Builds a single HTML page with table of contents
|
|
56
56
|
4. Starts a Bun server on a random port
|
|
57
57
|
5. Opens the browser
|
package/bin/rip-print
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
3
|
import { execFileSync } from 'child_process';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
4
5
|
import { dirname, join } from 'path';
|
|
5
6
|
|
|
6
|
-
const printRip = join(dirname(
|
|
7
|
+
const printRip = join(dirname(fileURLToPath(import.meta.url)), '..', 'print.rip');
|
|
7
8
|
|
|
8
9
|
try {
|
|
9
10
|
execFileSync('rip', [printRip, ...process.argv.slice(2)], { stdio: 'inherit' });
|
package/hljs-rip.js
CHANGED
|
@@ -118,7 +118,7 @@ export default function(hljs) {
|
|
|
118
118
|
|
|
119
119
|
const OPERATORS = {
|
|
120
120
|
className: 'operator',
|
|
121
|
-
begin:
|
|
121
|
+
begin: /\|>|::=|::|:=|~=|~>|<=>|=!|!\?|=~|\?\?|\?\.|\.\.\.|\.\.|=>|->|\*\*|\/\/|%%|===|!==|==|!=|<=|>=|&&|\|\||[+\-*\/%&|^~<>=!?]/,
|
|
122
122
|
relevance: 0,
|
|
123
123
|
};
|
|
124
124
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rip-lang/print",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Syntax-highlighted source code printer — Shiki-powered, serves once, auto-opens browser",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "print.rip",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"author": "Steve Shreeve <steve.shreeve@gmail.com>",
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"rip-lang": "^3.
|
|
32
|
+
"rip-lang": "^3.8.9",
|
|
33
33
|
"highlight.js": "^11.11.1"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
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,14 +17,14 @@ 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
26
|
if args.includes('-v') or args.includes('--version')
|
|
27
|
-
console.log "rip-print 0.
|
|
27
|
+
console.log "rip-print 1.0.0"
|
|
28
28
|
process.exit(0)
|
|
29
29
|
|
|
30
30
|
if args.includes('-h') or args.includes('--help')
|
|
@@ -76,9 +76,9 @@ defaultExclude = new Set [
|
|
|
76
76
|
for ext in excludeExts
|
|
77
77
|
defaultExclude.add ext
|
|
78
78
|
|
|
79
|
-
#
|
|
79
|
+
# ==============================================================================
|
|
80
80
|
# File discovery
|
|
81
|
-
#
|
|
81
|
+
# ==============================================================================
|
|
82
82
|
|
|
83
83
|
skipDirs = new Set ['.git', 'node_modules', '.rip-cache', '.zig-cache', 'zig-out', 'dist', 'misc']
|
|
84
84
|
|
|
@@ -121,9 +121,9 @@ if allFiles.length is 0
|
|
|
121
121
|
|
|
122
122
|
console.log "#{allFiles.length} file#{if allFiles.length > 1 then 's' else ''}"
|
|
123
123
|
|
|
124
|
-
#
|
|
124
|
+
# ==============================================================================
|
|
125
125
|
# Language detection
|
|
126
|
-
#
|
|
126
|
+
# ==============================================================================
|
|
127
127
|
|
|
128
128
|
extToLang =
|
|
129
129
|
rip: 'rip'
|
|
@@ -181,9 +181,9 @@ def getLang(file)
|
|
|
181
181
|
return lang if lang and hljs.getLanguage(lang)
|
|
182
182
|
return 'plaintext'
|
|
183
183
|
|
|
184
|
-
#
|
|
184
|
+
# ==============================================================================
|
|
185
185
|
# Highlight and build HTML
|
|
186
|
-
#
|
|
186
|
+
# ==============================================================================
|
|
187
187
|
|
|
188
188
|
def stripTopComments(code)
|
|
189
189
|
lines = code.split('\n')
|
|
@@ -232,9 +232,9 @@ for file in allFiles
|
|
|
232
232
|
html = "<pre><code class=\"hljs\">#{highlighted}</code></pre>"
|
|
233
233
|
sections.push { file, lineCount, lang, timestamp, html }
|
|
234
234
|
|
|
235
|
-
#
|
|
235
|
+
# ==============================================================================
|
|
236
236
|
# HTML template
|
|
237
|
-
#
|
|
237
|
+
# ==============================================================================
|
|
238
238
|
|
|
239
239
|
bgColor = if dark then '#0d1117' else '#ffffff'
|
|
240
240
|
textColor = if dark then '#e6edf3' else '#1f2328'
|
|
@@ -323,48 +323,59 @@ html = """
|
|
|
323
323
|
<link rel="icon" href="data:,">
|
|
324
324
|
<style id="hljs-theme">#{defaultCss}</style>
|
|
325
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'}; }
|
|
326
327
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
327
|
-
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); }
|
|
328
329
|
|
|
329
|
-
.toolbar { padding: 8px 16px; border-bottom: 1px solid
|
|
330
|
-
.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); }
|
|
331
332
|
.toolbar label { color: #888; margin-left: 16px; }
|
|
332
|
-
.
|
|
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); }
|
|
333
340
|
.toc h2 { font-size: 18px; margin-bottom: 10px; }
|
|
334
341
|
.toc ol { padding-left: 24px; columns: 2; column-gap: 40px; }
|
|
335
342
|
.toc li { font-size: 13px; line-height: 1.8; }
|
|
336
|
-
.toc a { color:
|
|
343
|
+
.toc a { color: var(--fg); text-decoration: none; }
|
|
337
344
|
.toc a:hover { text-decoration: underline; }
|
|
338
345
|
.meta { color: #888; font-size: 12px; }
|
|
339
346
|
|
|
340
347
|
.file-section { margin-bottom: 0; margin-top: -1px; }
|
|
341
348
|
.file-header {
|
|
342
|
-
background:
|
|
343
|
-
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);
|
|
344
351
|
display: flex; justify-content: space-between; align-items: center;
|
|
345
352
|
}
|
|
346
353
|
.nav { font-weight: normal; font-size: 12px; }
|
|
347
354
|
.nav a { color: #888; text-decoration: none; padding: 6px 10px; border-radius: 3px; }
|
|
348
|
-
.nav a:hover { color:
|
|
355
|
+
.nav a:hover { color: var(--fg); background: var(--act); }
|
|
349
356
|
|
|
350
|
-
.code-container { overflow-x: auto; border-bottom: 1px solid
|
|
357
|
+
.code-container { overflow-x: auto; border-bottom: 1px solid var(--brd); }
|
|
351
358
|
.code-container pre { margin: 0; border-radius: 0; }
|
|
352
|
-
.code-container code { font-size: 13px; line-height: 1.5; padding: 0 !important; display: block; }
|
|
353
|
-
.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); }
|
|
354
361
|
.line-num.first { padding-top: 4px; }
|
|
355
362
|
|
|
356
363
|
@media print {
|
|
357
|
-
.
|
|
358
|
-
.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; }
|
|
359
366
|
.toolbar { display: none; }
|
|
360
367
|
.nav { display: none; }
|
|
361
368
|
body { background: white !important; color: black !important; }
|
|
362
|
-
code { font-size: 11px !important; }
|
|
363
369
|
}
|
|
364
370
|
</style>
|
|
365
371
|
</head>
|
|
366
372
|
<body>
|
|
367
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>
|
|
368
379
|
<label>Theme: <select id="theme-picker">
|
|
369
380
|
<optgroup label="Light">#{themeOptions.split('\n').filter((o) -> o.includes('data-dark="false"')).join('')}</optgroup>
|
|
370
381
|
<optgroup label="Dark">#{themeOptions.split('\n').filter((o) -> o.includes('data-dark="true"')).join('')}</optgroup>
|
|
@@ -384,20 +395,13 @@ html = """
|
|
|
384
395
|
if (!t) return;
|
|
385
396
|
document.getElementById('hljs-theme').textContent = t.c;
|
|
386
397
|
var d = t.d;
|
|
387
|
-
var
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
document.querySelectorAll('.toolbar').forEach(function(e) { e.style.borderColor = brd; });
|
|
395
|
-
document.querySelectorAll('.toolbar select').forEach(function(e) { e.style.background = bg; e.style.color = fg; e.style.borderColor = brd; });
|
|
396
|
-
document.querySelectorAll('.toc').forEach(function(e) { e.style.borderColor = brd; });
|
|
397
|
-
document.querySelectorAll('.file-header').forEach(function(e) { e.style.background = hdr; e.style.borderColor = brd; e.style.color = fg; });
|
|
398
|
-
document.querySelectorAll('.line-num').forEach(function(e) { e.style.background = gut; e.style.borderColor = brd; });
|
|
399
|
-
document.querySelectorAll('.code-container').forEach(function(e) { e.style.borderColor = brd; });
|
|
400
|
-
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');
|
|
401
405
|
});
|
|
402
406
|
// Restore saved theme
|
|
403
407
|
var saved = localStorage.getItem('rip-print-theme');
|
|
@@ -405,14 +409,31 @@ html = """
|
|
|
405
409
|
document.getElementById('theme-picker').value = saved;
|
|
406
410
|
document.getElementById('theme-picker').dispatchEvent(new Event('change'));
|
|
407
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
|
+
}
|
|
408
429
|
</script>
|
|
409
430
|
</body>
|
|
410
431
|
</html>
|
|
411
432
|
"""
|
|
412
433
|
|
|
413
|
-
#
|
|
434
|
+
# ==============================================================================
|
|
414
435
|
# Serve once and open browser
|
|
415
|
-
#
|
|
436
|
+
# ==============================================================================
|
|
416
437
|
|
|
417
438
|
served = false
|
|
418
439
|
|