@estiva-app/ui 0.64.0 → 0.65.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@estiva-app/ui",
3
- "version": "0.64.0",
3
+ "version": "0.65.0",
4
4
  "description": "Estiva's design tokens (the contract) and a small set of primitives (a convenience) for every Estiva app.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/registry.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "kind": "package",
5
5
  "repo": "estiva-ui",
6
6
  "package": "@estiva-app/ui",
7
- "packageVersion": "0.64.0",
7
+ "packageVersion": "0.65.0",
8
8
  "exports": 140,
9
9
  "typeExports": 145,
10
10
  "files": null
@@ -5415,7 +5415,7 @@
5415
5415
  "looks": [
5416
5416
  "[&_:is(ul,ol)]:pl-5 [&_li>p]:m-0 [&_li]:break-words [&_li]:marker:text-text-secondary [&_ol]:list-decimal [&_ul]:list-disc",
5417
5417
  "[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-text-muted [&_blockquote]:pl-2.5",
5418
- "[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:text-text-code [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary",
5418
+ "[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:border [&_:not(pre)>code]:border-border-default [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary",
5419
5419
  "[&_pre>code]:text-[1em] [&_pre]:whitespace-pre-wrap [&_pre]:break-words [&_pre]:rounded-md [&_pre]:bg-bg-code [&_pre]:px-3 [&_pre]:py-2.5 [&_pre]:font-mono [&_pre]:text-[0.85em] [&_pre]:leading-relaxed [&_pre]:text-text-primary",
5420
5420
  "[&_:is(.hljs-keyword,.hljs-doctag,.hljs-type,.hljs-template-tag,.hljs-template-variable)]:text-syntax-keyword [&_.hljs-title]:text-syntax-function [&_:is(.hljs-number,.hljs-literal,.hljs-attr,.hljs-attribute,.hljs-meta,.hljs-variable,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id)]:text-syntax-constant [&_:is(.hljs-string,.hljs-regexp)]:text-syntax-string [&_:is(.hljs-built_in,.hljs-symbol)]:text-syntax-variable [&_.hljs-comment]:text-syntax-comment [&_:is(.hljs-name,.hljs-quote,.hljs-selector-tag,.hljs-selector-pseudo)]:text-syntax-tag",
5421
5421
  "[&_:is(th,td)>p]:m-0 [&_:is(th,td)]:border [&_:is(th,td)]:border-border-default [&_:is(th,td)]:px-2 [&_:is(th,td)]:py-1 [&_:is(th,td)]:text-left [&_:is(th,td)]:align-top [&_table]:w-full [&_table]:border-collapse [&_th]:bg-bg-code [&_th]:font-medium [&_th]:text-text-primary",
@@ -19,7 +19,7 @@ are the ones RichText reads it in, so writing looks the same as reading.
19
19
 
20
20
  - Drawing text that is already written → **RichText**, which colours its code
21
21
  blocks itself.
22
- - Code in a sentence → the code mark. It is amber and takes no other colours.
22
+ - Code in a sentence → the code mark. It takes no colours.
23
23
 
24
24
  ## How
25
25
 
@@ -38,8 +38,9 @@ useEditor({
38
38
  class list; without it the words are named but drawn in one colour.
39
39
  - The block keeps the name `codeBlock` and its `language`, so text written
40
40
  before it was added reads the same.
41
- - It colours highlight.js's 37 everyday languages. A block in any other
42
- language, or in none, stays one colour.
41
+ - It colours highlight.js's 37 everyday languages, only by the language the
42
+ block names (```` ```ts ```` then Enter). A block in any other language, or
43
+ in none, stays one colour: it never guesses, so it looks the same once read.
43
44
  - The app installs `@tiptap/extension-code-block-lowlight`, as it installs the
44
45
  other Tiptap parts.
45
46
 
@@ -0,0 +1,36 @@
1
+ // @vitest-environment jsdom
2
+ /**
3
+ * CodeBlockColours colours a block only by the language it names, as RichText
4
+ * does when the text is read (Katerina, 9 October: never guess).
5
+ */
6
+ import { afterEach, describe, expect, it } from 'vitest'
7
+ import { Editor } from '@tiptap/core'
8
+ import StarterKit from '@tiptap/starter-kit'
9
+ import { CodeBlockColours } from './CodeBlockColours'
10
+
11
+ let editor: Editor | undefined
12
+ afterEach(() => editor?.destroy())
13
+
14
+ const coloured = (content: string) => {
15
+ editor = new Editor({ element: document.createElement('div'), extensions: [StarterKit.configure({ codeBlock: false }), CodeBlockColours], content })
16
+ return editor.view.dom.querySelectorAll('pre [class*="hljs-"]').length
17
+ }
18
+
19
+ describe('CodeBlockColours', () => {
20
+ it('colours a block that names its language', () => {
21
+ expect(coloured('<pre><code class="language-ts">const done = items.length</code></pre>')).toBeGreaterThan(0)
22
+ })
23
+
24
+ it('leaves a block that names no language in one colour, as RichText reads it', () => {
25
+ expect(coloured('<pre><code>const done = items.length</code></pre>')).toBe(0)
26
+ })
27
+
28
+ it('leaves a block in a language it does not know in one colour', () => {
29
+ expect(coloured('<pre><code class="language-nothing">const done = items.length</code></pre>')).toBe(0)
30
+ })
31
+
32
+ it('keeps the block a code block, with its language', () => {
33
+ coloured('<pre><code class="language-ts">const done = 1</code></pre>')
34
+ expect(editor!.getJSON().content?.[0]).toMatchObject({ type: 'codeBlock', attrs: { language: 'ts' } })
35
+ })
36
+ })
@@ -2,6 +2,20 @@
2
2
  import { CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight'
3
3
  import { lowlight } from './codeColours'
4
4
 
5
+ /*
6
+ The editor library guesses a language for a block that names none, or names
7
+ one it does not know, and colours it by the guess. RichText never guesses, so
8
+ that block was coloured while written and plain once read. A block is
9
+ coloured only by the language it names, while written and when read
10
+ (Katerina, 9 October: never guess).
11
+ */
12
+ const namedOnly = {
13
+ highlight: (language: string, value: string) => lowlight().highlight(language, value),
14
+ highlightAuto: (value: string) => ({ type: 'root' as const, children: [{ type: 'text' as const, value }], data: { language: undefined, relevance: 0 } }),
15
+ listLanguages: () => lowlight().listLanguages(),
16
+ registered: (language: string) => lowlight().registered(language),
17
+ }
18
+
5
19
  /**
6
20
  * A code block in the editor, with the colours RichText reads it in (Katerina,
7
21
  * 9 October): the same highlight.js languages, the same classes, and the
@@ -11,4 +25,4 @@ import { lowlight } from './codeColours'
11
25
  * then add `CodeBlockColours`. The block keeps its name, `codeBlock`, and its
12
26
  * `language` attribute, so nothing already written changes.
13
27
  */
14
- export const CodeBlockColours = CodeBlockLowlight.configure({ lowlight })
28
+ export const CodeBlockColours = CodeBlockLowlight.configure({ lowlight: namedOnly })
package/src/RichText.tsx CHANGED
@@ -95,9 +95,9 @@ const RICH_TEXT_CLASSES = {
95
95
  /* The line in the muted text grey, not the border grey: a border grey was 1.3 : 1 in Leaf (Katerina, 9 October). */
96
96
  // eslint-disable-next-line token-spacing/no-restricted-classes -- @estiva-escape: the quote line is Peek's, 3px, between the ramp's 2 and 4
97
97
  quote: '[&_blockquote>p]:m-0 [&_blockquote]:border-l-[3px] [&_blockquote]:border-text-muted [&_blockquote]:pl-2.5',
98
- /* Code in a sentence is amber, its own colour (Katerina, 9 October: option I). */
98
+ /* Code in a sentence: the code fill and a thin border, in the heading colour (Katerina, 9 October: option B; the amber of 0.64.0 was too much). */
99
99
  // eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.85 of the text around it, so it scales with a heading and with `small`; a named size is fixed
100
- code: '[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:text-text-code [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary',
100
+ code: '[&_:not(pre)>code]:rounded-sm [&_:not(pre)>code]:bg-bg-code [&_:not(pre)>code]:px-1 [&_:not(pre)>code]:py-0.5 [&_:not(pre)>code]:border [&_:not(pre)>code]:border-border-default [&_code]:font-mono [&_code]:text-[0.85em] [&_code]:text-text-primary',
101
101
  /* 12px either side, 10px above and below, looser lines than the text (Katerina, 9 October; 8px all round before). */
102
102
  // eslint-disable-next-line token-values/no-restricted-classes -- @estiva-escape: code is 0.85 of the text around it; the code inside the block is the block's own size, not 0.85 of it again
103
103
  codeBlock: '[&_pre>code]:text-[1em] [&_pre]:whitespace-pre-wrap [&_pre]:break-words [&_pre]:rounded-md [&_pre]:bg-bg-code [&_pre]:px-3 [&_pre]:py-2.5 [&_pre]:font-mono [&_pre]:text-[0.85em] [&_pre]:leading-relaxed [&_pre]:text-text-primary',
@@ -11,8 +11,16 @@ import { common, createLowlight } from 'lowlight'
11
11
  *
12
12
  * `common` is highlight.js's 37 everyday languages. A language outside them, or
13
13
  * none, leaves the code in one colour.
14
+ *
15
+ * Made the first time code is coloured, not when the package loads: a call at
16
+ * the top of the file is kept by every app's bundler, so an app that never draws
17
+ * code carried highlight.js too (measured: an app importing only `Link` was
18
+ * 55 KB gzipped).
14
19
  */
15
- export const lowlight = createLowlight(common)
20
+ let instance: ReturnType<typeof createLowlight> | undefined
21
+ export function lowlight() {
22
+ return (instance ??= createLowlight(common))
23
+ }
16
24
 
17
25
  interface HastNode {
18
26
  type: string
@@ -28,6 +36,6 @@ function draw(node: HastNode, key: number): ReactNode {
28
36
 
29
37
  /** The code, its words wrapped in highlight.js's classes; the text as it is when the language is unknown. */
30
38
  export function codeColours(text: string, language?: string): ReactNode {
31
- if (!language || !lowlight.registered(language)) return text
32
- return (lowlight.highlight(language, text).children as HastNode[]).map(draw)
39
+ if (!language || !lowlight().registered(language)) return text
40
+ return (lowlight().highlight(language, text).children as HastNode[]).map(draw)
33
41
  }
@@ -155,7 +155,6 @@ export default {
155
155
  'bg-tooltip-key': 'var(--bg-tooltip-key)',
156
156
  'bg-field': 'var(--bg-field)',
157
157
  'bg-code': 'var(--bg-code)',
158
- 'text-code': 'var(--text-code)',
159
158
  'syntax-keyword': 'var(--syntax-keyword)',
160
159
  'syntax-function': 'var(--syntax-function)',
161
160
  'syntax-constant': 'var(--syntax-constant)',
package/tokens.css CHANGED
@@ -101,8 +101,6 @@
101
101
  /* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
102
102
  Here, the hover fill: bg-active, #D4D4D8, was the darkest thing on a white card (Katerina, 28 September). */
103
103
  --bg-code: #E9E9EB;
104
- /* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Darker than the warning amber, which is 3.8 : 1 on the code fill; this is 4.8. */
105
- --text-code: #855f00;
106
104
  /* Colours inside a code block, by language (Katerina, 9 October). GitHub's light set; the keyword one shade darker (#cf222e is 4.4 : 1 on our fill, this 4.9). */
107
105
  --syntax-keyword: #c21f2b;
108
106
  --syntax-function: #6639ba;
@@ -194,8 +192,6 @@
194
192
  /* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
195
193
  Here, bg-active, as Peek draws code (Katerina, 28 September). */
196
194
  --bg-code: #2D2D31;
197
- /* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Amber 400, as on GitHub's dark ground. */
198
- --text-code: #fbbf24;
199
195
  /* Colours inside a code block, by language (Katerina, 9 October). GitHub's dark set. */
200
196
  --syntax-keyword: #ff7b72;
201
197
  --syntax-function: #d2a8ff;
@@ -291,8 +287,6 @@
291
287
  /* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
292
288
  Here, bg-active, as Peek draws code (Katerina, 28 September). */
293
289
  --bg-code: rgba(255, 255, 255, 0.08);
294
- /* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Signal's warning amber. */
295
- --text-code: #ffb020;
296
290
  /* Colours inside a code block, by language (Katerina, 9 October). GitHub's dark set. */
297
291
  --syntax-keyword: #ff7b72;
298
292
  --syntax-function: #d2a8ff;
@@ -402,8 +396,6 @@
402
396
  /* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
403
397
  Here, bg-active, as Peek draws code (Katerina, 28 September). */
404
398
  --bg-code: rgba(255, 255, 255, 0.08);
405
- /* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Ship's warning amber. */
406
- --text-code: #e0b04a;
407
399
  /* Colours inside a code block, by language (Katerina, 9 October). GitHub's dark set. */
408
400
  --syntax-keyword: #ff7b72;
409
401
  --syntax-function: #d2a8ff;
@@ -505,8 +497,6 @@
505
497
  /* Code, in a sentence and as a block, and a table's header row (RichText, UIG-30).
506
498
  Here, the inset fill: lighter than bg-active on a white card (Katerina, 28 September). */
507
499
  --bg-code: #e9e9ea;
508
- /* Inline code's text: amber, on --bg-code (Katerina, 9 October: option I). Darker than Leaf's warning amber (#967000, 3.8 : 1 on the code fill); this is 4.8. */
509
- --text-code: #855f00;
510
500
  /* Colours inside a code block, by language (Katerina, 9 October). GitHub's light set; the keyword one shade darker (#cf222e is 4.4 : 1 on our fill, this 4.9). */
511
501
  --syntax-keyword: #c21f2b;
512
502
  --syntax-function: #6639ba;