@sakura-ui/sakura-ui 0.5.4 β†’ 0.5.6

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.
Files changed (30) hide show
  1. package/package.json +4 -4
  2. package/packages/core/package.json +1 -1
  3. package/packages/core/src/components/Link.tsx +17 -0
  4. package/packages/core/tests/Link.test.tsx +41 -0
  5. package/packages/forms/.turbo/turbo-build.log +2 -2
  6. package/packages/helper/.turbo/turbo-build.log +1 -1
  7. package/packages/markdown/.turbo/turbo-build.log +5 -5
  8. package/packages/markdown/README.md +17 -1
  9. package/packages/markdown/dist/index.cjs.js +110 -43
  10. package/packages/markdown/dist/index.es.js +862 -744
  11. package/packages/markdown/dist/types/decorate.d.ts.map +1 -1
  12. package/packages/markdown/dist/types/marked/directives/image.d.ts +3 -0
  13. package/packages/markdown/dist/types/marked/directives/image.d.ts.map +1 -0
  14. package/packages/markdown/dist/types/marked/directives/index.d.ts.map +1 -1
  15. package/packages/markdown/dist/types/marked/html.d.ts.map +1 -1
  16. package/packages/markdown/dist/types/marked/registry.d.ts.map +1 -1
  17. package/packages/markdown/dist/types/sanitize.d.ts.map +1 -1
  18. package/packages/markdown/package.json +1 -1
  19. package/packages/markdown/src/decorate.ts +25 -9
  20. package/packages/markdown/src/marked/directives/image.ts +29 -0
  21. package/packages/markdown/src/marked/directives/index.ts +2 -0
  22. package/packages/markdown/src/marked/html.ts +14 -1
  23. package/packages/markdown/src/marked/registry.ts +1 -0
  24. package/packages/markdown/src/marked/renderer.ts +3 -3
  25. package/packages/markdown/src/sanitize.ts +9 -2
  26. package/packages/markdown/tests/Markdown.test.tsx +17 -0
  27. package/packages/markdown/tests/__snapshots__/Markdown.test.tsx.snap +36 -31
  28. package/packages/markdown/tests/image.test.ts +64 -0
  29. package/packages/markdown/tests/sanitize.test.ts +17 -0
  30. package/packages/tailwind-theme-plugin/.turbo/turbo-build.log +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sakura-ui/sakura-ui",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "keywords": [],
5
5
  "author": "glassonion1",
6
6
  "homepage": "https://github.com/glassonion1/sakura-ui",
@@ -19,10 +19,10 @@
19
19
  "pnpm": ">=9.15.1"
20
20
  },
21
21
  "dependencies": {
22
- "@sakura-ui/core": "0.5.2",
23
- "@sakura-ui/forms": "0.4.3",
24
22
  "@sakura-ui/helper": "0.0.10",
25
- "@sakura-ui/tailwind-theme-plugin": "0.4.2"
23
+ "@sakura-ui/tailwind-theme-plugin": "0.4.2",
24
+ "@sakura-ui/core": "0.5.3",
25
+ "@sakura-ui/forms": "0.4.3"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "react": "^19.2.1",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sakura-ui/core",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "",
5
5
  "keywords": [
6
6
  "react",
@@ -20,6 +20,22 @@ export namespace Link {
20
20
  }
21
21
  }
22
22
 
23
+ /**
24
+ * A link that opens elsewhere must not hand the opener to the page it opens.
25
+ * Merged with what the caller asked for rather than replacing it, so a
26
+ * `rel="nofollow"` does not take `noopener` away with it.
27
+ */
28
+ const externalRel = (rel: unknown): string =>
29
+ Array.from(
30
+ new Set([
31
+ 'noopener',
32
+ 'noreferrer',
33
+ ...String(rel ?? '')
34
+ .split(/\s+/)
35
+ .filter(Boolean)
36
+ ])
37
+ ).join(' ')
38
+
23
39
  export const Link = <T extends React.ElementType = 'a'>(
24
40
  props: Link.Props<T> & Omit<React.ComponentProps<T>, keyof Link.Props<T>>
25
41
  ) => {
@@ -32,6 +48,7 @@ export const Link = <T extends React.ElementType = 'a'>(
32
48
  className={cx(style, className)}
33
49
  target="_blank"
34
50
  {...restProps}
51
+ rel={externalRel(restProps.rel)}
35
52
  >
36
53
  <span>{children}</span>
37
54
  <Icon opticalSize={16} altText="Opens in new tab" className="ml-0.5">
@@ -39,6 +39,47 @@ describe('Link', () => {
39
39
  expect(text).toBeInTheDocument()
40
40
  })
41
41
 
42
+ it('should not hand the opener to the page it opens', async () => {
43
+ render(<Link href="https://example.com">Button</Link>)
44
+
45
+ expect(screen.getByRole('link')).toHaveAttribute(
46
+ 'rel',
47
+ 'noopener noreferrer'
48
+ )
49
+ })
50
+
51
+ it('should keep the rel the caller asked for as well', async () => {
52
+ render(
53
+ <Link href="https://example.com" rel="nofollow">
54
+ Button
55
+ </Link>
56
+ )
57
+
58
+ const rel = screen.getByRole('link').getAttribute('rel')?.split(' ')
59
+ expect(rel).toContain('noopener')
60
+ expect(rel).toContain('noreferrer')
61
+ expect(rel).toContain('nofollow')
62
+ })
63
+
64
+ it('should not repeat a rel the caller already asked for', async () => {
65
+ render(
66
+ <Link href="https://example.com" rel="noopener">
67
+ Button
68
+ </Link>
69
+ )
70
+
71
+ expect(screen.getByRole('link')).toHaveAttribute(
72
+ 'rel',
73
+ 'noopener noreferrer'
74
+ )
75
+ })
76
+
77
+ it('should leave a link that stays on the page without a rel', async () => {
78
+ render(<Link href="/">Button</Link>)
79
+
80
+ expect(screen.getByRole('link')).not.toHaveAttribute('rel')
81
+ })
82
+
42
83
  it('should labeled text from Button', async () => {
43
84
  render(<Link href="/">here</Link>)
44
85
 
@@ -1,7 +1,7 @@
1
1
  $ rimraf dist
2
2
  $ run-p build:*
3
- $ tsc && tsc-alias
4
3
  $ vite build
4
+ $ tsc && tsc-alias
5
5
  vite v7.3.6 building client environment for production...
6
6
  transforming...
7
7
  βœ“ 25 modules transformed.
@@ -9,4 +9,4 @@ rendering chunks...
9
9
  computing gzip size...
10
10
  dist/index.es.js 24.22 kB β”‚ gzip: 6.09 kB
11
11
  dist/index.cjs.js 16.80 kB β”‚ gzip: 5.23 kB
12
- βœ“ built in 474ms
12
+ βœ“ built in 493ms
@@ -9,4 +9,4 @@ rendering chunks...
9
9
  computing gzip size...
10
10
  dist/index.es.js 2.76 kB β”‚ gzip: 0.96 kB
11
11
  dist/index.cjs.js 2.58 kB β”‚ gzip: 0.95 kB
12
- βœ“ built in 340ms
12
+ βœ“ built in 215ms
@@ -1,12 +1,12 @@
1
1
  $ rimraf dist
2
2
  $ run-p build:*
3
- $ vite build
4
3
  $ tsc && tsc-alias
4
+ $ vite build
5
5
  vite v7.3.6 building client environment for production...
6
6
  transforming...
7
- βœ“ 31 modules transformed.
7
+ βœ“ 33 modules transformed.
8
8
  rendering chunks...
9
9
  computing gzip size...
10
- dist/index.es.js 129.50 kB β”‚ gzip: 39.49 kB
11
- dist/index.cjs.js 98.47 kB β”‚ gzip: 34.86 kB
12
- βœ“ built in 657ms
10
+ dist/index.es.js 132.42 kB β”‚ gzip: 40.29 kB
11
+ dist/index.cjs.js 100.96 kB β”‚ gzip: 35.57 kB
12
+ βœ“ built in 666ms
@@ -116,6 +116,22 @@ instead.
116
116
  ```
117
117
  <img width="288" alt="γ‚Ήγ‚―γƒͺγƒΌγƒ³γ‚·γƒ§γƒƒγƒˆ 2024-07-26 23 44 39" src="https://github.com/user-attachments/assets/997ccf27-4d83-4fb5-b173-ae94cd7d76cb">
118
118
 
119
+ ### Image
120
+
121
+ `![alt](src)` has nowhere to put a size, so `::img` takes one. `width` and
122
+ `height` are pixels; either on its own leaves the other to follow the
123
+ proportions of the image.
124
+
125
+ ```
126
+ ::img{src=/photo.jpg alt="A field at dawn" width=520}
127
+ ```
128
+
129
+ A width also caps the image at the width of its column, so a number larger than
130
+ the screen shrinks rather than overflowing.
131
+
132
+ Write `alt` for anything a reader would miss without it. An image that only
133
+ decorates takes `alt=""`, which tells a screen reader to skip it.
134
+
119
135
  ### YouTube
120
136
 
121
137
  The address of the video, as it is copied from the browser. The watch page, the
@@ -347,7 +363,7 @@ using them is what keeps a new directive behaving like the others:
347
363
 
348
364
  | | |
349
365
  |---|---|
350
- | `root(…)` | Attributes for the element the directive **is**. Adds the id from `{#name}`, and `data-sakura`, which tells `decorate.ts` the element is dressed already and to leave its classes alone. Headings are the exception: one rendered by a directive still has an id generated for it and still reaches the table of contents, which is how a card title gets there. |
366
+ | `root(…)` | Attributes for the element the directive **is**. Adds the id from `{#name}`, and `data-styled`, which tells `decorate.ts` the element is dressed already and to leave its classes alone. Headings are the exception: one rendered by a directive still has an id generated for it and still reaches the table of contents, which is how a card title gets there. |
351
367
  | `own(…)` | The same without the id, for elements **inside** it. A link card's title is a heading around an anchor; only the heading is the directive. |
352
368
  | `body()` | The children, already rendered β€” inline for a `TEXT` or `LEAF`, block for a `CONTAINER`. |
353
369