@rip-lang/print 0.1.2 → 0.1.4
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/hljs-rip.js +159 -0
- package/package.json +2 -1
- package/print.rip +13 -10
package/hljs-rip.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
// highlight.js language definition for Rip
|
|
2
|
+
// Derived from the Monarch grammar in docs/index.html
|
|
3
|
+
|
|
4
|
+
export default function(hljs) {
|
|
5
|
+
const KEYWORDS = [
|
|
6
|
+
'if', 'else', 'unless', 'then', 'switch', 'when', 'for', 'while', 'until',
|
|
7
|
+
'loop', 'do', 'return', 'break', 'continue', 'throw', 'try', 'catch', 'finally',
|
|
8
|
+
'yield', 'await', 'import', 'export', 'from', 'default', 'delete', 'typeof',
|
|
9
|
+
'instanceof', 'new', 'super', 'debugger', 'use', 'own', 'extends', 'in', 'of',
|
|
10
|
+
'by', 'as', 'class', 'def', 'enum', 'interface', 'component', 'render',
|
|
11
|
+
'and', 'or', 'not', 'is', 'isnt',
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
const LITERALS = [
|
|
15
|
+
'true', 'false', 'yes', 'no', 'on', 'off',
|
|
16
|
+
'null', 'undefined', 'NaN', 'Infinity',
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const BUILT_INS = [
|
|
20
|
+
'console', 'process', 'require', 'module', 'exports',
|
|
21
|
+
'setTimeout', 'setInterval', 'clearTimeout', 'clearInterval',
|
|
22
|
+
'Promise', 'Array', 'Object', 'String', 'Number', 'Boolean',
|
|
23
|
+
'Math', 'Date', 'RegExp', 'Error', 'JSON', 'Map', 'Set',
|
|
24
|
+
'Symbol', 'Buffer', 'Bun',
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const INTERPOLATION = {
|
|
28
|
+
className: 'subst',
|
|
29
|
+
begin: /#\{/, end: /\}/,
|
|
30
|
+
keywords: { keyword: KEYWORDS, literal: LITERALS },
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const STRING_DOUBLE = {
|
|
34
|
+
className: 'string',
|
|
35
|
+
begin: '"', end: '"',
|
|
36
|
+
contains: [hljs.BACKSLASH_ESCAPE, INTERPOLATION],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const STRING_SINGLE = {
|
|
40
|
+
className: 'string',
|
|
41
|
+
begin: "'", end: "'",
|
|
42
|
+
contains: [hljs.BACKSLASH_ESCAPE],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const HEREDOC_DOUBLE = {
|
|
46
|
+
className: 'string',
|
|
47
|
+
begin: '"""', end: '"""',
|
|
48
|
+
contains: [hljs.BACKSLASH_ESCAPE, INTERPOLATION],
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const HEREDOC_SINGLE = {
|
|
52
|
+
className: 'string',
|
|
53
|
+
begin: "'''", end: "'''",
|
|
54
|
+
contains: [hljs.BACKSLASH_ESCAPE],
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const HEREGEX = {
|
|
58
|
+
className: 'regexp',
|
|
59
|
+
begin: '///', end: '///[gimsuy]*',
|
|
60
|
+
contains: [INTERPOLATION, hljs.HASH_COMMENT_MODE],
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const REGEX = {
|
|
64
|
+
className: 'regexp',
|
|
65
|
+
begin: /\/(?![/*])(?:[^\/\\]|\\.)*\/[gimsuy]*/,
|
|
66
|
+
relevance: 0,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const BLOCK_COMMENT = {
|
|
70
|
+
className: 'comment',
|
|
71
|
+
begin: '###', end: '###',
|
|
72
|
+
contains: [hljs.PHRASAL_WORDS_MODE],
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const LINE_COMMENT = hljs.COMMENT('#', '$');
|
|
76
|
+
|
|
77
|
+
const NUMBER = {
|
|
78
|
+
className: 'number',
|
|
79
|
+
variants: [
|
|
80
|
+
{ begin: /0x[0-9a-fA-F](?:_?[0-9a-fA-F])*n?/ },
|
|
81
|
+
{ begin: /0o[0-7](?:_?[0-7])*n?/ },
|
|
82
|
+
{ begin: /0b[01](?:_?[01])*n?/ },
|
|
83
|
+
{ begin: /\d[\d_]*(?:\.[\d][\d_]*)?(?:[eE][+-]?\d+)?n?/ },
|
|
84
|
+
],
|
|
85
|
+
relevance: 0,
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const INSTANCE_VAR = {
|
|
89
|
+
className: 'variable',
|
|
90
|
+
begin: /@[a-zA-Z_$][\w$]*/,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const CLASS_NAME = {
|
|
94
|
+
className: 'title.class',
|
|
95
|
+
begin: /[A-Z][\w]*/,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const FUNCTION_DEF = {
|
|
99
|
+
className: 'function',
|
|
100
|
+
begin: /\bdef\s+/,
|
|
101
|
+
end: /[(\s]/,
|
|
102
|
+
excludeEnd: true,
|
|
103
|
+
keywords: { keyword: 'def' },
|
|
104
|
+
contains: [
|
|
105
|
+
{ className: 'title.function', begin: /[a-zA-Z_$][\w$]*[!?]?/ },
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
const CLASS_DEF = {
|
|
110
|
+
className: 'class',
|
|
111
|
+
beginKeywords: 'class',
|
|
112
|
+
end: /$/,
|
|
113
|
+
contains: [
|
|
114
|
+
{ className: 'title.class', begin: /[A-Z][\w]*/ },
|
|
115
|
+
{ beginKeywords: 'extends', contains: [CLASS_NAME] },
|
|
116
|
+
],
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const OPERATORS = {
|
|
120
|
+
className: 'operator',
|
|
121
|
+
begin: /::=|::|:=|~=|~>|<=>|=!|!\?|=~|\?\?|\?\.|\.\.\.|\.\.|=>|->|\*\*|\/\/|%%|===|!==|==|!=|<=|>=|&&|\|\||[+\-*\/%&|^~<>=!?]/,
|
|
122
|
+
relevance: 0,
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const TYPE_KEYWORDS = {
|
|
126
|
+
className: 'type',
|
|
127
|
+
begin: /\b(?:number|string|boolean|void|any|never|unknown|object|symbol|bigint)\b/,
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return {
|
|
131
|
+
name: 'Rip',
|
|
132
|
+
aliases: ['rip'],
|
|
133
|
+
keywords: {
|
|
134
|
+
keyword: KEYWORDS,
|
|
135
|
+
literal: LITERALS,
|
|
136
|
+
built_in: BUILT_INS,
|
|
137
|
+
},
|
|
138
|
+
contains: [
|
|
139
|
+
BLOCK_COMMENT,
|
|
140
|
+
LINE_COMMENT,
|
|
141
|
+
HEREDOC_DOUBLE,
|
|
142
|
+
HEREDOC_SINGLE,
|
|
143
|
+
STRING_DOUBLE,
|
|
144
|
+
STRING_SINGLE,
|
|
145
|
+
HEREGEX,
|
|
146
|
+
REGEX,
|
|
147
|
+
FUNCTION_DEF,
|
|
148
|
+
CLASS_DEF,
|
|
149
|
+
NUMBER,
|
|
150
|
+
INSTANCE_VAR,
|
|
151
|
+
TYPE_KEYWORDS,
|
|
152
|
+
OPERATORS,
|
|
153
|
+
{ // inline JS
|
|
154
|
+
className: 'string',
|
|
155
|
+
begin: /`[^`]*`/,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
};
|
|
159
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rip-lang/print",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Syntax-highlighted source code printer — Shiki-powered, serves once, auto-opens browser",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "print.rip",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"print.rip",
|
|
37
|
+
"hljs-rip.js",
|
|
37
38
|
"bin/rip-print",
|
|
38
39
|
"README.md"
|
|
39
40
|
]
|
package/print.rip
CHANGED
|
@@ -9,10 +9,14 @@
|
|
|
9
9
|
# ============================================================================
|
|
10
10
|
|
|
11
11
|
import hljs from 'highlight.js'
|
|
12
|
+
import ripLanguage from './hljs-rip.js'
|
|
12
13
|
import { existsSync, readdirSync, readFileSync, statSync } from 'fs'
|
|
13
14
|
import { basename, extname, join, relative } from 'path'
|
|
14
15
|
import { execSync } from 'child_process'
|
|
15
16
|
|
|
17
|
+
# Register Rip language with highlight.js
|
|
18
|
+
hljs.registerLanguage 'rip', ripLanguage
|
|
19
|
+
|
|
16
20
|
# ============================================================================
|
|
17
21
|
# CLI argument parsing
|
|
18
22
|
# ============================================================================
|
|
@@ -117,7 +121,7 @@ console.log "#{allFiles.length} file#{if allFiles.length > 1 then 's' else ''}"
|
|
|
117
121
|
# ============================================================================
|
|
118
122
|
|
|
119
123
|
extToLang =
|
|
120
|
-
rip: '
|
|
124
|
+
rip: 'rip'
|
|
121
125
|
coffee: 'coffeescript'
|
|
122
126
|
js: 'javascript'
|
|
123
127
|
mjs: 'javascript'
|
|
@@ -196,11 +200,10 @@ def highlightCode(code, lang)
|
|
|
196
200
|
# fall through
|
|
197
201
|
highlighted ?= escapeHtml code
|
|
198
202
|
|
|
199
|
-
# Add line numbers
|
|
203
|
+
# Add line numbers (fixed 4-digit width for consistent gutter)
|
|
200
204
|
lines = highlighted.split('\n')
|
|
201
|
-
width = String(lines.length).length
|
|
202
205
|
numbered = lines.map (line, i) ->
|
|
203
|
-
num = String(i + 1).padStart(
|
|
206
|
+
num = String(i + 1).padStart(4)
|
|
204
207
|
"<span class=\"line-num\">#{num}</span> #{line}"
|
|
205
208
|
numbered.join('\n')
|
|
206
209
|
|
|
@@ -296,20 +299,20 @@ html = """
|
|
|
296
299
|
.toc a:hover { text-decoration: underline; }
|
|
297
300
|
.meta { color: #888; font-size: 12px; }
|
|
298
301
|
|
|
299
|
-
.file-section { margin-bottom: 0; }
|
|
302
|
+
.file-section { margin-bottom: 0; margin-top: -1px; }
|
|
300
303
|
.file-header {
|
|
301
|
-
background: #{headerBg}; padding:
|
|
304
|
+
background: #{headerBg}; padding: 10px 16px 10px 5.85em; font-size: 13px; font-weight: 600;
|
|
302
305
|
border-top: 1px solid #{borderColor}; border-bottom: 1px solid #{borderColor};
|
|
303
306
|
display: flex; justify-content: space-between; align-items: center;
|
|
304
307
|
}
|
|
305
308
|
.nav { font-weight: normal; font-size: 12px; }
|
|
306
|
-
.nav a { color: #888; text-decoration: none;
|
|
307
|
-
.nav a:hover { color: #{textColor}; }
|
|
309
|
+
.nav a { color: #888; text-decoration: none; padding: 6px 10px; border-radius: 3px; }
|
|
310
|
+
.nav a:hover { color: #{textColor}; background: #{if dark then '#30363d' else '#e0e0e0'}; }
|
|
308
311
|
|
|
309
|
-
.code-container { overflow-x: auto; }
|
|
312
|
+
.code-container { overflow-x: auto; border-bottom: 1px solid #{borderColor}; }
|
|
310
313
|
.code-container pre { margin: 0; border-radius: 0; }
|
|
311
314
|
.code-container code { font-size: 13px; line-height: 1.5; padding: 0 !important; display: block; }
|
|
312
|
-
.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-
|
|
315
|
+
.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}; }
|
|
313
316
|
|
|
314
317
|
@media print {
|
|
315
318
|
.toc { page-break-after: always; }
|