@levino/shipyard-base 0.8.5 → 0.9.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/README.md +4 -4
- package/package.json +10 -9
- package/src/index.ts +31 -6
- package/src/markdownProcessor.test.ts +92 -0
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ npm install @levino/shipyard-base
|
|
|
10
10
|
|
|
11
11
|
## Peer Dependencies
|
|
12
12
|
|
|
13
|
-
- `astro` ^
|
|
14
|
-
- `tailwindcss` ^
|
|
15
|
-
- `daisyui` ^
|
|
16
|
-
- `@tailwindcss/typography` ^0.5.
|
|
13
|
+
- `astro` ^7.2.4
|
|
14
|
+
- `tailwindcss` ^4
|
|
15
|
+
- `daisyui` ^5
|
|
16
|
+
- `@tailwindcss/typography` ^0.5.20
|
|
17
17
|
|
|
18
18
|
## Basic Usage
|
|
19
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@levino/shipyard-base",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Core layouts, components, and configuration for shipyard - a composable page builder for Astro",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -38,8 +38,8 @@
|
|
|
38
38
|
"./styles/components.css": "./src/styles/components.css"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@tailwindcss/typography": "^0.5.
|
|
42
|
-
"astro": "^
|
|
41
|
+
"@tailwindcss/typography": "^0.5.20",
|
|
42
|
+
"astro": "^7.2.4",
|
|
43
43
|
"daisyui": "^5",
|
|
44
44
|
"tailwindcss": "^4"
|
|
45
45
|
},
|
|
@@ -53,21 +53,22 @@
|
|
|
53
53
|
"url": "https://github.com/levino/shipyard"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@tailwindcss/typography": "^0.5.
|
|
57
|
-
"@types/ramda": "^0.
|
|
56
|
+
"@tailwindcss/typography": "^0.5.20",
|
|
57
|
+
"@types/ramda": "^0.32",
|
|
58
58
|
"daisyui": "^5",
|
|
59
59
|
"remark": "^15.0.1",
|
|
60
60
|
"remark-html": "^16.0.1",
|
|
61
61
|
"tailwindcss": "^4",
|
|
62
|
-
"typescript": "^
|
|
63
|
-
"vite": "^
|
|
64
|
-
"vitest": "^4.1.
|
|
62
|
+
"typescript": "^7.0.2",
|
|
63
|
+
"vite": "^8.2.2",
|
|
64
|
+
"vitest": "^4.1.11"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
|
+
"@astrojs/markdown-remark": "^7.2.4",
|
|
67
68
|
"clsx": "^2.1.0",
|
|
68
69
|
"mdast-util-directive": "^3.0.0",
|
|
69
70
|
"micromark-extension-directive": "^3.0.0",
|
|
70
|
-
"ramda": "^0.
|
|
71
|
+
"ramda": "^0.32.0",
|
|
71
72
|
"remark-directive": "^3.0.0",
|
|
72
73
|
"tailwind-merge": "^2.2.0",
|
|
73
74
|
"unified": "^11.0.0",
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fileURLToPath } from 'node:url'
|
|
2
|
+
import { isUnifiedProcessor, unified } from '@astrojs/markdown-remark'
|
|
2
3
|
import type { AstroIntegration } from 'astro'
|
|
3
4
|
import { remarkAdmonitions } from './remark/remarkAdmonitions'
|
|
4
5
|
import { remarkBlockDirective } from './remark/remarkBlockDirective'
|
|
@@ -28,7 +29,7 @@ export default (config: Config): AstroIntegration => {
|
|
|
28
29
|
return {
|
|
29
30
|
name: 'shipyard',
|
|
30
31
|
hooks: {
|
|
31
|
-
'astro:config:setup': ({ updateConfig, config: astroConfig }) => {
|
|
32
|
+
'astro:config:setup': ({ updateConfig, config: astroConfig, logger }) => {
|
|
32
33
|
// Detect server mode (output: 'server' or 'hybrid')
|
|
33
34
|
isServerMode = astroConfig.output === 'server'
|
|
34
35
|
|
|
@@ -45,13 +46,37 @@ export default (config: Config): AstroIntegration => {
|
|
|
45
46
|
[shipyardCssId]: config.css ? `import '${config.css}';` : '',
|
|
46
47
|
} as Record<string, string | undefined>
|
|
47
48
|
|
|
49
|
+
// Astro 7 renders Markdown with Sätteri by default, which does not run
|
|
50
|
+
// unified plugins. shipyard's admonitions, npm2yarn tabs and block
|
|
51
|
+
// directives are all remark plugins, so we pin the unified processor
|
|
52
|
+
// from @astrojs/markdown-remark. Any plugins the user already put on
|
|
53
|
+
// their own `unified()` processor are carried over so both sets run;
|
|
54
|
+
// plugins they pass via the deprecated `markdown.remarkPlugins` option
|
|
55
|
+
// are appended by Astro afterwards.
|
|
56
|
+
const userProcessor = astroConfig.markdown?.processor
|
|
57
|
+
const inherited =
|
|
58
|
+
userProcessor && isUnifiedProcessor(userProcessor)
|
|
59
|
+
? userProcessor.options
|
|
60
|
+
: undefined
|
|
61
|
+
|
|
62
|
+
if (userProcessor && !inherited) {
|
|
63
|
+
logger.warn(
|
|
64
|
+
`\`markdown.processor\` is set to \`${userProcessor.name}\`, which does not run remark plugins. ` +
|
|
65
|
+
'Overriding it with `unified()` so shipyard admonitions, npm2yarn tabs and block directives keep working.',
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
48
69
|
updateConfig({
|
|
49
70
|
markdown: {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
71
|
+
processor: unified({
|
|
72
|
+
...inherited,
|
|
73
|
+
remarkPlugins: [
|
|
74
|
+
...(inherited?.remarkPlugins ?? []),
|
|
75
|
+
remarkBlockDirective,
|
|
76
|
+
remarkAdmonitions,
|
|
77
|
+
remarkNpm2Yarn,
|
|
78
|
+
],
|
|
79
|
+
}),
|
|
55
80
|
},
|
|
56
81
|
vite: {
|
|
57
82
|
plugins: [
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { UnifiedResolvedOptions } from '@astrojs/markdown-remark'
|
|
2
|
+
import { unified } from '@astrojs/markdown-remark'
|
|
3
|
+
import { describe, expect, test, vi } from 'vitest'
|
|
4
|
+
import shipyard from './index'
|
|
5
|
+
import type { Config } from './schemas/config'
|
|
6
|
+
|
|
7
|
+
const SHIPYARD_PLUGIN_COUNT = 3
|
|
8
|
+
|
|
9
|
+
interface ConfigUpdate {
|
|
10
|
+
markdown?: {
|
|
11
|
+
remarkPlugins?: unknown
|
|
12
|
+
processor?: { name: string; options: UnifiedResolvedOptions }
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const baseConfig: Config = {
|
|
17
|
+
title: 'Test',
|
|
18
|
+
brand: 'Test',
|
|
19
|
+
navigation: {},
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Runs the integration's `astro:config:setup` hook against a fake Astro config
|
|
24
|
+
* and returns whatever it passed to `updateConfig`, plus the logger it used.
|
|
25
|
+
*/
|
|
26
|
+
const runConfigSetup = (astroConfig: Record<string, unknown> = {}) => {
|
|
27
|
+
const updates: ConfigUpdate[] = []
|
|
28
|
+
const logger = { warn: vi.fn(), info: vi.fn(), error: vi.fn() }
|
|
29
|
+
|
|
30
|
+
const integration = shipyard(baseConfig)
|
|
31
|
+
const hook = integration.hooks['astro:config:setup']
|
|
32
|
+
if (!hook) throw new Error('astro:config:setup hook missing')
|
|
33
|
+
|
|
34
|
+
hook({
|
|
35
|
+
updateConfig: (update: ConfigUpdate) => updates.push(update),
|
|
36
|
+
config: astroConfig,
|
|
37
|
+
logger,
|
|
38
|
+
} as never)
|
|
39
|
+
|
|
40
|
+
return { update: updates[0], logger }
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe('markdown processor', () => {
|
|
44
|
+
test('pins the unified processor so remark plugins run under Astro 7', () => {
|
|
45
|
+
const { update } = runConfigSetup()
|
|
46
|
+
|
|
47
|
+
expect(update?.markdown?.processor?.name).toBe(unified().name)
|
|
48
|
+
expect(update?.markdown?.processor?.options.remarkPlugins).toHaveLength(
|
|
49
|
+
SHIPYARD_PLUGIN_COUNT,
|
|
50
|
+
)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
test('does not use the deprecated markdown.remarkPlugins option', () => {
|
|
54
|
+
const { update } = runConfigSetup()
|
|
55
|
+
|
|
56
|
+
expect(update?.markdown).not.toHaveProperty('remarkPlugins')
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
test("keeps the user's own plugins on an existing unified processor", () => {
|
|
60
|
+
const userPlugin = () => undefined
|
|
61
|
+
const { update, logger } = runConfigSetup({
|
|
62
|
+
markdown: { processor: unified({ remarkPlugins: [userPlugin] }) },
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
const plugins = update?.markdown?.processor?.options.remarkPlugins
|
|
66
|
+
expect(plugins).toHaveLength(SHIPYARD_PLUGIN_COUNT + 1)
|
|
67
|
+
expect(plugins?.[0]).toBe(userPlugin)
|
|
68
|
+
expect(logger.warn).not.toHaveBeenCalled()
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
test("carries over the user's other unified options", () => {
|
|
72
|
+
const { update } = runConfigSetup({
|
|
73
|
+
markdown: { processor: unified({ gfm: false, smartypants: false }) },
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
expect(update?.markdown?.processor?.options.gfm).toBe(false)
|
|
77
|
+
expect(update?.markdown?.processor?.options.smartypants).toBe(false)
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
test('warns and overrides when a non-unified processor is configured', () => {
|
|
81
|
+
const { update, logger } = runConfigSetup({
|
|
82
|
+
markdown: { processor: { name: 'satteri', options: {} } },
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
expect(logger.warn).toHaveBeenCalledOnce()
|
|
86
|
+
expect(logger.warn.mock.calls[0][0]).toContain('satteri')
|
|
87
|
+
expect(update?.markdown?.processor?.name).toBe(unified().name)
|
|
88
|
+
expect(update?.markdown?.processor?.options.remarkPlugins).toHaveLength(
|
|
89
|
+
SHIPYARD_PLUGIN_COUNT,
|
|
90
|
+
)
|
|
91
|
+
})
|
|
92
|
+
})
|