@sakura-ui/sakura-ui 0.5.3 β 0.5.5
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 +4 -4
- package/packages/core/package.json +1 -1
- package/packages/core/src/components/Link.tsx +17 -0
- package/packages/core/tests/Link.test.tsx +41 -0
- package/packages/forms/.turbo/turbo-build.log +2 -2
- package/packages/helper/.turbo/turbo-build.log +2 -2
- package/packages/markdown/.turbo/turbo-build.log +5 -5
- package/packages/markdown/README.md +17 -1
- package/packages/markdown/dist/index.cjs.js +22 -22
- package/packages/markdown/dist/index.es.js +369 -335
- package/packages/markdown/dist/types/components/Markdown.d.ts.map +1 -1
- package/packages/markdown/dist/types/decorate.d.ts +2 -5
- package/packages/markdown/dist/types/decorate.d.ts.map +1 -1
- package/packages/markdown/dist/types/marked/attributes.d.ts +4 -7
- package/packages/markdown/dist/types/marked/attributes.d.ts.map +1 -1
- package/packages/markdown/dist/types/marked/directives/image.d.ts +3 -0
- package/packages/markdown/dist/types/marked/directives/image.d.ts.map +1 -0
- package/packages/markdown/dist/types/marked/directives/index.d.ts.map +1 -1
- package/packages/markdown/dist/types/marked/html.d.ts.map +1 -1
- package/packages/markdown/dist/types/marked/registry.d.ts.map +1 -1
- package/packages/markdown/dist/types/marked/renderer.d.ts +4 -6
- package/packages/markdown/dist/types/marked/renderer.d.ts.map +1 -1
- package/packages/markdown/dist/types/marked/tokenizer.d.ts.map +1 -1
- package/packages/markdown/dist/types/sanitize.d.ts.map +1 -1
- package/packages/markdown/package.json +1 -1
- package/packages/markdown/src/components/Markdown.tsx +12 -6
- package/packages/markdown/src/decorate.ts +23 -16
- package/packages/markdown/src/marked/attributes.ts +4 -7
- package/packages/markdown/src/marked/directives/card.ts +2 -2
- package/packages/markdown/src/marked/directives/image.ts +29 -0
- package/packages/markdown/src/marked/directives/index.ts +2 -0
- package/packages/markdown/src/marked/html.ts +17 -4
- package/packages/markdown/src/marked/registry.ts +3 -5
- package/packages/markdown/src/marked/renderer.ts +7 -9
- package/packages/markdown/src/marked/tokenizer.ts +5 -7
- package/packages/markdown/src/sanitize.ts +9 -2
- package/packages/markdown/tests/__snapshots__/Markdown.test.tsx.snap +61 -61
- package/packages/markdown/tests/image.test.ts +64 -0
- package/packages/markdown/tests/sanitize.test.ts +17 -0
- package/packages/tailwind-theme-plugin/.turbo/turbo-build.log +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sakura-ui/sakura-ui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
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/forms": "0.4.3",
|
|
25
|
+
"@sakura-ui/core": "0.5.3"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"react": "^19.2.1",
|
|
@@ -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
|
-
$ vite build
|
|
4
3
|
$ tsc && tsc-alias
|
|
4
|
+
$ vite build
|
|
5
5
|
[36mvite v7.3.6 [32mbuilding client environment for production...[36m[39m
|
|
6
6
|
transforming...
|
|
7
7
|
[32mβ[39m 25 modules transformed.
|
|
@@ -9,4 +9,4 @@ rendering chunks...
|
|
|
9
9
|
computing gzip size...
|
|
10
10
|
[2mdist/[22m[36mindex.es.js [39m[1m[2m24.22 kB[22m[1m[22m[2m β gzip: 6.09 kB[22m
|
|
11
11
|
[2mdist/[22m[36mindex.cjs.js [39m[1m[2m16.80 kB[22m[1m[22m[2m β gzip: 5.23 kB[22m
|
|
12
|
-
[32mβ built in
|
|
12
|
+
[32mβ built in 378ms[39m
|
|
@@ -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
|
[36mvite v7.3.6 [32mbuilding client environment for production...[36m[39m
|
|
6
6
|
transforming...
|
|
7
7
|
[32mβ[39m 6 modules transformed.
|
|
@@ -9,4 +9,4 @@ rendering chunks...
|
|
|
9
9
|
computing gzip size...
|
|
10
10
|
[2mdist/[22m[36mindex.es.js [39m[1m[2m2.76 kB[22m[1m[22m[2m β gzip: 0.96 kB[22m
|
|
11
11
|
[2mdist/[22m[36mindex.cjs.js [39m[1m[2m2.58 kB[22m[1m[22m[2m β gzip: 0.95 kB[22m
|
|
12
|
-
[32mβ built in
|
|
12
|
+
[32mβ built in 194ms[39m
|
|
@@ -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
|
[36mvite v7.3.6 [32mbuilding client environment for production...[36m[39m
|
|
6
6
|
transforming...
|
|
7
|
-
[32mβ[39m
|
|
7
|
+
[32mβ[39m 32 modules transformed.
|
|
8
8
|
rendering chunks...
|
|
9
9
|
computing gzip size...
|
|
10
|
-
[2mdist/[22m[36mindex.es.js [39m[1m[
|
|
11
|
-
[2mdist/[22m[36mindex.cjs.js [39m[1m[2m98.
|
|
12
|
-
[32mβ built in
|
|
10
|
+
[2mdist/[22m[36mindex.es.js [39m[1m[2m130.23 kB[22m[1m[22m[2m β gzip: 39.67 kB[22m
|
|
11
|
+
[2mdist/[22m[36mindex.cjs.js [39m[1m[2m98.98 kB[22m[1m[22m[2m β gzip: 35.01 kB[22m
|
|
12
|
+
[32mβ built in 485ms[39m
|
|
@@ -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
|
+
`` 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-
|
|
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
|
|