@levino/shipyard-base 0.8.0 → 0.8.1-rc-20260509110053
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": "@levino/shipyard-base",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1-rc-20260509110053",
|
|
4
4
|
"description": "Core layouts, components, and configuration for shipyard - a composable page builder for Astro",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"@tailwindcss/typography": "^0.5.10",
|
|
42
|
-
"astro": "^6.
|
|
42
|
+
"astro": "^6.1.6",
|
|
43
43
|
"daisyui": "^5",
|
|
44
44
|
"tailwindcss": "^4"
|
|
45
45
|
},
|
|
@@ -60,12 +60,13 @@
|
|
|
60
60
|
"remark-html": "^16.0.1",
|
|
61
61
|
"tailwindcss": "^4",
|
|
62
62
|
"typescript": "^5.2.2",
|
|
63
|
-
"vite": "^7",
|
|
63
|
+
"vite": "^7.3.2",
|
|
64
64
|
"vitest": "^4.1.0"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"clsx": "^2.1.0",
|
|
68
68
|
"mdast-util-directive": "^3.0.0",
|
|
69
|
+
"micromark-extension-directive": "^3.0.0",
|
|
69
70
|
"ramda": "^0.31",
|
|
70
71
|
"remark-directive": "^3.0.0",
|
|
71
72
|
"tailwind-merge": "^2.2.0",
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url'
|
|
2
2
|
import type { AstroIntegration } from 'astro'
|
|
3
|
-
import remarkDirective from 'remark-directive'
|
|
4
3
|
import { remarkAdmonitions } from './remark/remarkAdmonitions'
|
|
4
|
+
import { remarkBlockDirective } from './remark/remarkBlockDirective'
|
|
5
5
|
import { remarkNpm2Yarn } from './remark/remarkNpm2Yarn'
|
|
6
6
|
import type { Config } from './schemas/config'
|
|
7
7
|
import { checkLinks, reportBrokenLinks } from './tools/linkChecker'
|
|
@@ -47,7 +47,11 @@ export default (config: Config): AstroIntegration => {
|
|
|
47
47
|
|
|
48
48
|
updateConfig({
|
|
49
49
|
markdown: {
|
|
50
|
-
remarkPlugins: [
|
|
50
|
+
remarkPlugins: [
|
|
51
|
+
remarkBlockDirective,
|
|
52
|
+
remarkAdmonitions,
|
|
53
|
+
remarkNpm2Yarn,
|
|
54
|
+
],
|
|
51
55
|
},
|
|
52
56
|
vite: {
|
|
53
57
|
plugins: [
|
package/src/remark/index.ts
CHANGED
|
@@ -9,4 +9,5 @@
|
|
|
9
9
|
// Re-export remark-directive for convenience
|
|
10
10
|
export { default as remarkDirective } from 'remark-directive'
|
|
11
11
|
export { type AdmonitionType, remarkAdmonitions } from './remarkAdmonitions'
|
|
12
|
+
export { remarkBlockDirective } from './remarkBlockDirective'
|
|
12
13
|
export { remarkNpm2Yarn } from './remarkNpm2Yarn'
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { remark } from 'remark'
|
|
2
|
+
import remarkHtml from 'remark-html'
|
|
3
|
+
import { describe, expect, it } from 'vitest'
|
|
4
|
+
import { remarkAdmonitions } from './remarkAdmonitions'
|
|
5
|
+
import { remarkBlockDirective } from './remarkBlockDirective'
|
|
6
|
+
|
|
7
|
+
const process = async (markdown: string): Promise<string> => {
|
|
8
|
+
const result = await remark()
|
|
9
|
+
.use(remarkBlockDirective)
|
|
10
|
+
.use(remarkAdmonitions)
|
|
11
|
+
.use(remarkHtml, { sanitize: false })
|
|
12
|
+
.process(markdown)
|
|
13
|
+
return String(result)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
describe('remarkBlockDirective', () => {
|
|
17
|
+
describe('German gender colon', () => {
|
|
18
|
+
it('does not split paragraphs containing :innen', async () => {
|
|
19
|
+
const input =
|
|
20
|
+
'herzlicher Dank an die Organisator:innen vom **ADFC** und an alle Ordner:innen'
|
|
21
|
+
const result = await process(input)
|
|
22
|
+
expect(result).toContain('Organisator:innen')
|
|
23
|
+
expect(result).toContain('Ordner:innen')
|
|
24
|
+
expect(result).not.toContain('<div></div>')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('preserves :innen inside a paragraph as plain text', async () => {
|
|
28
|
+
const input = 'Liebe Anwohner:innen, willkommen.'
|
|
29
|
+
const result = await process(input)
|
|
30
|
+
expect(result).toContain('Liebe Anwohner:innen, willkommen.')
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
it('handles multiple gender colon variants in one paragraph', async () => {
|
|
34
|
+
const input = 'Mitarbeiter:innen, Lehrer:innen und Schüler:innen.'
|
|
35
|
+
const result = await process(input)
|
|
36
|
+
expect(result).toContain(
|
|
37
|
+
'Mitarbeiter:innen, Lehrer:innen und Schüler:innen.',
|
|
38
|
+
)
|
|
39
|
+
expect(result).not.toContain('<div></div>')
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
describe('container directives', () => {
|
|
44
|
+
it('still parses :::note admonitions', async () => {
|
|
45
|
+
const input = ':::note\nThis is a note\n:::'
|
|
46
|
+
const result = await process(input)
|
|
47
|
+
expect(result).toContain('admonition')
|
|
48
|
+
expect(result).toContain('admonition-note')
|
|
49
|
+
expect(result).toContain('This is a note')
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('still parses :::warning with custom title', async () => {
|
|
53
|
+
const input = ':::warning[Be Careful]\nWatch out\n:::'
|
|
54
|
+
const result = await process(input)
|
|
55
|
+
expect(result).toContain('admonition-warning')
|
|
56
|
+
expect(result).toContain('Be Careful')
|
|
57
|
+
})
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
describe('inline text directives', () => {
|
|
61
|
+
it('does not consume :name as a directive', async () => {
|
|
62
|
+
const input = 'Use :foo as a marker.'
|
|
63
|
+
const result = await process(input)
|
|
64
|
+
// Without text-directive support `:foo` stays as plain text.
|
|
65
|
+
expect(result).toContain(':foo')
|
|
66
|
+
expect(result).not.toContain('<div></div>')
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Root } from 'mdast'
|
|
2
|
+
import { directiveFromMarkdown } from 'mdast-util-directive'
|
|
3
|
+
import { directive } from 'micromark-extension-directive'
|
|
4
|
+
import type { Plugin, Processor } from 'unified'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Like `remark-directive`, but only enables block-level directives — container
|
|
8
|
+
* (`:::name`) and leaf (`::name`) — and disables inline text directives
|
|
9
|
+
* (`:name`).
|
|
10
|
+
*
|
|
11
|
+
* Why: the inline text directive syntax conflicts with the German gender
|
|
12
|
+
* colon (e.g. `Organisator:innen`, `Ordner:innen`), which would otherwise be
|
|
13
|
+
* tokenised as a directive and rendered as an empty `<div>`, tearing the
|
|
14
|
+
* surrounding paragraph apart.
|
|
15
|
+
*
|
|
16
|
+
* Block directives stay available so admonitions (`:::note`, `:::warning`)
|
|
17
|
+
* keep working.
|
|
18
|
+
*/
|
|
19
|
+
export const remarkBlockDirective: Plugin<[], Root> = function () {
|
|
20
|
+
const self = this as unknown as Processor<Root>
|
|
21
|
+
const data = self.data()
|
|
22
|
+
|
|
23
|
+
if (!data.micromarkExtensions) {
|
|
24
|
+
data.micromarkExtensions = []
|
|
25
|
+
}
|
|
26
|
+
if (!data.fromMarkdownExtensions) {
|
|
27
|
+
data.fromMarkdownExtensions = []
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const { flow } = directive()
|
|
31
|
+
data.micromarkExtensions.push({ flow })
|
|
32
|
+
data.fromMarkdownExtensions.push(directiveFromMarkdown())
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default remarkBlockDirective
|