sugar-high 1.1.0 → 1.2.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 +16 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.js +29 -7
- package/lib/presets/index.d.ts +2 -0
- package/lib/presets/index.js +1 -0
- package/lib/presets/lang/diff.js +11 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,6 +33,8 @@ import { rust } from 'sugar-high/presets'
|
|
|
33
33
|
const html = highlight(source, { ...rust })
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
+
Available presets: `c`, `css`, `diff`, `go`, `java`, `python`, and `rust`.
|
|
37
|
+
|
|
36
38
|
For more language presets and syntax color themes, see **[sugar-high.vercel.app](https://sugar-high.vercel.app/)**.
|
|
37
39
|
|
|
38
40
|
## Styling
|
|
@@ -78,11 +80,24 @@ pre code {
|
|
|
78
80
|
Target a line with `.sh__line:nth-child(<n>)` (1-based):
|
|
79
81
|
|
|
80
82
|
```css
|
|
83
|
+
.sh__line {
|
|
84
|
+
display: block;
|
|
85
|
+
padding: 0 12px;
|
|
86
|
+
margin: 0 -12px;
|
|
87
|
+
min-height: 1rem;
|
|
88
|
+
}
|
|
89
|
+
|
|
81
90
|
.sh__line:nth-child(5) {
|
|
82
|
-
background: #
|
|
91
|
+
background: #fff8c5;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.sh__line--highlighted {
|
|
95
|
+
background: #fff8c5;
|
|
83
96
|
}
|
|
84
97
|
```
|
|
85
98
|
|
|
99
|
+
Use `.sh__line--highlighted` when you add highlight classes yourself (for example with `lineClassName`).
|
|
100
|
+
|
|
86
101
|
## Remark
|
|
87
102
|
|
|
88
103
|
Use the [remark plugin](https://sugar-high.vercel.app/remark) to highlight fenced code blocks when processing Markdown with [remark](https://remark.js.org/). Details: [`packages/remark-sugar-high`](https://github.com/huozhi/sugar-high/tree/main/packages/remark-sugar-high).
|
package/lib/index.d.ts
CHANGED
|
@@ -11,11 +11,12 @@ type HighlightOptions = {
|
|
|
11
11
|
* or null/undefined or a number below 1 for default JS single-quoted string rules.
|
|
12
12
|
*/
|
|
13
13
|
onQuote?: (curr: string, i: number, code: string) => number | null | undefined
|
|
14
|
+
lineClassName?: (line: string, index: number) => string | null | undefined
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export function highlight(code: string, options?: HighlightOptions): string
|
|
17
18
|
export function tokenize(code: string, options?: HighlightOptions): Array<[number, string]>
|
|
18
|
-
export function generate(tokens: Array<[number, string]>): Array<any>
|
|
19
|
+
export function generate(tokens: Array<[number, string]>, options?: Pick<HighlightOptions, 'lineClassName'>): Array<any>
|
|
19
20
|
export const SugarHigh: {
|
|
20
21
|
TokenTypes: {
|
|
21
22
|
[key: number]: string
|
package/lib/index.js
CHANGED
|
@@ -309,6 +309,7 @@ function isRegexStart(str) {
|
|
|
309
309
|
* onCommentStart?: (curr: string, next: string) => number | boolean
|
|
310
310
|
* onCommentEnd?: (prev: string, curr: string) => number | boolean
|
|
311
311
|
* onQuote?: (curr: string, i: number, code: string) => number | null | undefined
|
|
312
|
+
* lineClassName?: (line: string, index: number) => string | null | undefined
|
|
312
313
|
* } | undefined} options
|
|
313
314
|
* Optional `onQuote(curr, i, code)` at `code[i] === "'"`: return length to consume from `i` (>= 1),
|
|
314
315
|
* or null/undefined/below 1 for default JS single-quoted strings. No substring allocation.
|
|
@@ -714,9 +715,16 @@ function tokenize(code, options) {
|
|
|
714
715
|
|
|
715
716
|
let foundClose = false
|
|
716
717
|
|
|
718
|
+
// `/` is literal inside regex character classes, e.g. `[/]`.
|
|
719
|
+
let inCharClass = false
|
|
720
|
+
|
|
717
721
|
// traverse to find closing regex slash
|
|
718
722
|
for (; !isEol(); i++) {
|
|
719
|
-
|
|
723
|
+
const ch = code[i]
|
|
724
|
+
const escaped = code[i - 1] === '\\'
|
|
725
|
+
if (!escaped && ch === '[') inCharClass = true
|
|
726
|
+
if (!escaped && ch === ']') inCharClass = false
|
|
727
|
+
if (ch === '/' && !inCharClass && !escaped) {
|
|
720
728
|
foundClose = true
|
|
721
729
|
// end of regex, append regex flags
|
|
722
730
|
while (start !== i && /^[a-z]$/.test(code[i + 1]) && !isEol()) {
|
|
@@ -813,29 +821,42 @@ function tokenize(code, options) {
|
|
|
813
821
|
|
|
814
822
|
/**
|
|
815
823
|
* @param {Array<[number, string]>} tokens
|
|
824
|
+
* @param {{
|
|
825
|
+
* lineClassName?: (line: string, index: number) => string | null | undefined
|
|
826
|
+
* } | undefined} options
|
|
816
827
|
* @return {Array<{type: string, tagName: string, children: any[], properties: Record<string, string>}>}
|
|
817
828
|
*/
|
|
818
|
-
function generate(tokens) {
|
|
829
|
+
function generate(tokens, options) {
|
|
819
830
|
const lines = []
|
|
831
|
+
const lineClassName = options && typeof options.lineClassName === 'function'
|
|
832
|
+
? options.lineClassName
|
|
833
|
+
: null
|
|
834
|
+
let lineIndex = 0
|
|
820
835
|
/**
|
|
821
836
|
* @param {any} children
|
|
837
|
+
* @param {string} text
|
|
822
838
|
* @return {{type: string, tagName: string, children: any[], properties: Record<string, string>}}
|
|
823
839
|
*/
|
|
824
|
-
const createLine = (children) =>
|
|
825
|
-
|
|
840
|
+
const createLine = (children, text) => {
|
|
841
|
+
const extraClassName = lineClassName ? lineClassName(text, lineIndex) : ''
|
|
842
|
+
lineIndex++
|
|
843
|
+
|
|
844
|
+
return ({
|
|
826
845
|
type: 'element',
|
|
827
846
|
tagName: 'span',
|
|
828
847
|
children,
|
|
829
848
|
properties: {
|
|
830
|
-
className: 'sh__line',
|
|
849
|
+
className: extraClassName ? `sh__line ${extraClassName}` : 'sh__line',
|
|
831
850
|
},
|
|
832
851
|
})
|
|
852
|
+
}
|
|
833
853
|
|
|
834
854
|
/**
|
|
835
855
|
* @param {Array<[number, string]>} tokens
|
|
836
856
|
* @returns {void}
|
|
837
857
|
*/
|
|
838
858
|
function flushLine(tokens) {
|
|
859
|
+
const lineText = tokens.map(([, value]) => value).join('')
|
|
839
860
|
/** @type {Array<any>} */
|
|
840
861
|
const lineTokens = (
|
|
841
862
|
tokens
|
|
@@ -855,7 +876,7 @@ function generate(tokens) {
|
|
|
855
876
|
}
|
|
856
877
|
})
|
|
857
878
|
)
|
|
858
|
-
lines.push(createLine(lineTokens))
|
|
879
|
+
lines.push(createLine(lineTokens, lineText))
|
|
859
880
|
}
|
|
860
881
|
/** @type {Array<[number, string]>} */
|
|
861
882
|
const lineTokens = []
|
|
@@ -945,13 +966,14 @@ function toHtml(lines) {
|
|
|
945
966
|
* onCommentStart?: (curr: string, next: string) => number | boolean
|
|
946
967
|
* onCommentEnd?: (curr: string, prev: string) => number | boolean
|
|
947
968
|
* onQuote?: (curr: string, i: number, code: string) => number | null | undefined
|
|
969
|
+
* lineClassName?: (line: string, index: number) => string | null | undefined
|
|
948
970
|
* } | undefined} options
|
|
949
971
|
* `onQuote` same as `tokenize`.
|
|
950
972
|
* @returns {string}
|
|
951
973
|
*/
|
|
952
974
|
function highlight(code, options) {
|
|
953
975
|
const tokens = tokenize(code, options)
|
|
954
|
-
const lines = generate(tokens)
|
|
976
|
+
const lines = generate(tokens, options)
|
|
955
977
|
const output = toHtml(lines)
|
|
956
978
|
return output
|
|
957
979
|
}
|
package/lib/presets/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ type LanguageConfig = {
|
|
|
4
4
|
onCommentStart?(curr: string, next: string): 0 | 1 | 2
|
|
5
5
|
onCommentEnd?(prev: string, curr: string): 0 | 1 | 2
|
|
6
6
|
onQuote?(curr: string, i: number, code: string): number | null | undefined
|
|
7
|
+
lineClassName?(line: string, index: number): string | null | undefined
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
export const css: LanguageConfig
|
|
@@ -12,3 +13,4 @@ export const python: LanguageConfig
|
|
|
12
13
|
export const c: LanguageConfig
|
|
13
14
|
export const go: LanguageConfig
|
|
14
15
|
export const java: LanguageConfig
|
|
16
|
+
export const diff: LanguageConfig
|
package/lib/presets/index.js
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
export const keywords = new Set([])
|
|
4
|
+
|
|
5
|
+
export const lineClassName = (line) => {
|
|
6
|
+
if (line.startsWith('+') && !line.startsWith('+++')) return 'sh__line--diff-add'
|
|
7
|
+
if (line.startsWith('-') && !line.startsWith('---')) return 'sh__line--diff-remove'
|
|
8
|
+
if (line.startsWith('@@')) return 'sh__line--diff-hunk'
|
|
9
|
+
if (/^(diff --git|index |--- |\+\+\+ )/.test(line)) return 'sh__line--diff-meta'
|
|
10
|
+
return undefined
|
|
11
|
+
}
|