@lexibase/rdx-ui 2.0.0 → 3.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/THIRD_PARTY_NOTICES.md +7 -2
- package/package.json +8 -5
- package/src/components/button.tsx +2 -0
- package/src/components/code-block.tsx +274 -46
- package/src/components/copy-code-button.tsx +1 -79
- package/src/components/dialog.tsx +123 -36
- package/src/components/docs-search-dialog.tsx +6 -1
- package/src/components/mdx-code-block-view.tsx +77 -0
- package/src/components/mdx-code-block.tsx +108 -0
- package/src/components/mdx-components.tsx +47 -13
- package/src/components/mdx-image.tsx +73 -0
- package/src/components/tabs.tsx +7 -2
- package/src/hooks/use-highlighted-code.ts +75 -0
- package/src/lib/highlighter.tsx +124 -0
- package/src/lib/i18n.ts +12 -0
- package/src/styles/globals.css +1 -0
- package/src/styles/shadcn.css +650 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import {
|
|
3
|
+
createHighlighterCore,
|
|
4
|
+
type GrammarState,
|
|
5
|
+
type HighlighterCore,
|
|
6
|
+
} from 'shiki/core'
|
|
7
|
+
import { createJavaScriptRegexEngine } from 'shiki/engine/javascript'
|
|
8
|
+
|
|
9
|
+
// Add the languages you need. Each one loads the first time it is used.
|
|
10
|
+
const languages = {
|
|
11
|
+
bash: () => import('shiki/langs/shellscript.mjs'),
|
|
12
|
+
css: () => import('shiki/langs/css.mjs'),
|
|
13
|
+
diff: () => import('shiki/langs/diff.mjs'),
|
|
14
|
+
html: () => import('shiki/langs/html.mjs'),
|
|
15
|
+
javascript: () => import('shiki/langs/javascript.mjs'),
|
|
16
|
+
json: () => import('shiki/langs/json.mjs'),
|
|
17
|
+
jsx: () => import('shiki/langs/jsx.mjs'),
|
|
18
|
+
markdown: () => import('shiki/langs/markdown.mjs'),
|
|
19
|
+
python: () => import('shiki/langs/python.mjs'),
|
|
20
|
+
sql: () => import('shiki/langs/sql.mjs'),
|
|
21
|
+
tsx: () => import('shiki/langs/tsx.mjs'),
|
|
22
|
+
typescript: () => import('shiki/langs/typescript.mjs'),
|
|
23
|
+
yaml: () => import('shiki/langs/yaml.mjs'),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const aliases: Record<string, keyof typeof languages> = {
|
|
27
|
+
js: 'javascript',
|
|
28
|
+
md: 'markdown',
|
|
29
|
+
py: 'python',
|
|
30
|
+
sh: 'bash',
|
|
31
|
+
shell: 'bash',
|
|
32
|
+
shellscript: 'bash',
|
|
33
|
+
ts: 'typescript',
|
|
34
|
+
yml: 'yaml',
|
|
35
|
+
zsh: 'bash',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
let highlighter: Promise<HighlighterCore> | undefined
|
|
39
|
+
|
|
40
|
+
function getHighlighter() {
|
|
41
|
+
highlighter ??= createHighlighterCore({
|
|
42
|
+
themes: [
|
|
43
|
+
import('shiki/themes/github-light.mjs'),
|
|
44
|
+
import('shiki/themes/github-dark.mjs'),
|
|
45
|
+
],
|
|
46
|
+
langs: [],
|
|
47
|
+
engine: createJavaScriptRegexEngine({ forgiving: true }),
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
return highlighter
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getLanguage(language: string) {
|
|
54
|
+
const name = language.toLowerCase()
|
|
55
|
+
|
|
56
|
+
if (name === 'ansi') {
|
|
57
|
+
return name
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (name in languages) {
|
|
61
|
+
return name as keyof typeof languages
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return aliases[name] ?? null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Loads a language and returns a highlighter for it, or null for a language
|
|
68
|
+
// that is not listed.
|
|
69
|
+
export async function loadHighlighter(language: string) {
|
|
70
|
+
const lang = getLanguage(language)
|
|
71
|
+
|
|
72
|
+
if (!lang) {
|
|
73
|
+
return null
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const shiki = await getHighlighter()
|
|
77
|
+
|
|
78
|
+
if (lang !== 'ansi' && !shiki.getLoadedLanguages().includes(lang)) {
|
|
79
|
+
await shiki.loadLanguage(languages[lang])
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
// Returns one React node per line, and the grammar state after the last
|
|
84
|
+
// line. Pass that state back to continue where the code left off.
|
|
85
|
+
highlight(code: string, state?: GrammarState) {
|
|
86
|
+
const tokenize = (text: string) =>
|
|
87
|
+
shiki.codeToTokens(text, {
|
|
88
|
+
lang,
|
|
89
|
+
themes: { light: 'github-light', dark: 'github-dark' },
|
|
90
|
+
defaultColor: false,
|
|
91
|
+
grammarState: state,
|
|
92
|
+
}).tokens
|
|
93
|
+
|
|
94
|
+
// ANSI has no grammar state, so each line is tokenized on its own and
|
|
95
|
+
// gets the same colors whether it arrives in one piece or streams.
|
|
96
|
+
const tokens =
|
|
97
|
+
lang === 'ansi'
|
|
98
|
+
? code.split('\n').flatMap((line) => tokenize(line))
|
|
99
|
+
: tokenize(code)
|
|
100
|
+
|
|
101
|
+
return {
|
|
102
|
+
lines: tokens.map((line) =>
|
|
103
|
+
line.map((token, index) => (
|
|
104
|
+
<span
|
|
105
|
+
key={index}
|
|
106
|
+
style={token.htmlStyle as React.CSSProperties}
|
|
107
|
+
className="text-(--shiki-light) dark:text-(--shiki-dark)"
|
|
108
|
+
>
|
|
109
|
+
{token.content}
|
|
110
|
+
</span>
|
|
111
|
+
))
|
|
112
|
+
),
|
|
113
|
+
state: shiki.getLastGrammarState(tokens),
|
|
114
|
+
}
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Returns one React node per line, or null for a language that is not listed.
|
|
120
|
+
export async function highlightCode(code: string, language: string) {
|
|
121
|
+
const highlighter = await loadHighlighter(language)
|
|
122
|
+
|
|
123
|
+
return highlighter ? highlighter.highlight(code).lines : null
|
|
124
|
+
}
|
package/src/lib/i18n.ts
CHANGED
|
@@ -26,7 +26,12 @@ const en = {
|
|
|
26
26
|
open: 'Open',
|
|
27
27
|
close: 'Close',
|
|
28
28
|
closeSearch: 'Close search',
|
|
29
|
+
enlargeImage: 'Enlarge image: {alt}',
|
|
30
|
+
closeImage: 'Close image',
|
|
31
|
+
imagePreviewDescription:
|
|
32
|
+
'Press Escape or use the close button to return to the document.',
|
|
29
33
|
copyCode: 'Copy code',
|
|
34
|
+
wrapCode: 'Wrap lines',
|
|
30
35
|
codeCopied: 'Code copied to clipboard.',
|
|
31
36
|
copyCodeError: 'Could not copy. Select the code and copy it manually.',
|
|
32
37
|
copyRetry: 'Could not copy. Try again or copy manually.',
|
|
@@ -35,6 +40,7 @@ const en = {
|
|
|
35
40
|
tabCopied: 'Tab content copied to clipboard.',
|
|
36
41
|
copyTabError: 'Could not copy. Select the tab content and copy it manually.',
|
|
37
42
|
code: 'Code',
|
|
43
|
+
folderTree: 'Folder',
|
|
38
44
|
table: 'Table',
|
|
39
45
|
current: 'Current',
|
|
40
46
|
version: 'Version {version}',
|
|
@@ -89,7 +95,12 @@ const ptBR = {
|
|
|
89
95
|
open: 'Abrir',
|
|
90
96
|
close: 'Fechar',
|
|
91
97
|
closeSearch: 'Fechar busca',
|
|
98
|
+
enlargeImage: 'Ampliar imagem: {alt}',
|
|
99
|
+
closeImage: 'Fechar imagem',
|
|
100
|
+
imagePreviewDescription:
|
|
101
|
+
'Pressione Escape ou use o botão de fechar para voltar ao documento.',
|
|
92
102
|
copyCode: 'Copiar código',
|
|
103
|
+
wrapCode: 'Quebrar linhas',
|
|
93
104
|
codeCopied: 'Código copiado para a área de transferência.',
|
|
94
105
|
copyCodeError:
|
|
95
106
|
'Não foi possível copiar. Selecione o código e copie manualmente.',
|
|
@@ -100,6 +111,7 @@ const ptBR = {
|
|
|
100
111
|
copyTabError:
|
|
101
112
|
'Não foi possível copiar. Selecione o conteúdo da aba e copie manualmente.',
|
|
102
113
|
code: 'Código',
|
|
114
|
+
folderTree: 'Pastas',
|
|
103
115
|
table: 'Tabela',
|
|
104
116
|
current: 'Atual',
|
|
105
117
|
version: 'Versão {version}',
|