Skip to content

Commit

Permalink
Merge pull request #31 from HiDeoo/hd-feat-copy-frontmatter
Browse files Browse the repository at this point in the history
  • Loading branch information
HiDeoo authored Nov 6, 2024
2 parents 3a1c552 + 6969fe2 commit fe8d158
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 28 deletions.
11 changes: 6 additions & 5 deletions docs/src/content/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,15 @@ Add links to Starlight headings to make it easier to share a link to a specific

By default, Starlight will include an “Overview” heading at the top of each page’s table of contents. If your Obsidian vault pages already include a top-level heading named “Overview”, you can set this option to `'title'` to instead use the page title as the top-level heading in the table of contents.

### `copyStarlightFrontmatter`
### `copyFrontmatter`

**Type:** `boolean`
**Default:** `false`
**Type:** `'none' | 'starlight' | 'all'`
**Default:** `'none'`

By default, all unsupported [properties](/guides/features/#properties) are ignored and not exported. Set this option to `true` to copy all known [Starlight frontmatter fields](https://starlight.astro.build/reference/frontmatter/) from an Obsidian note to the associated generated page.
By default (`none`), all unsupported [properties](/guides/features/#properties) are ignored and not exported.
Set this option to `starlight` to copy all known [Starlight frontmatter fields](https://starlight.astro.build/reference/frontmatter/) from an Obsidian note to the associated generated page or to `all` to copy all frontmatter fields.

This is useful if you want to customize the generated Starlight pages from Obsidian.
This option is useful if you want to customize the generated Starlight pages from Obsidian.
Note that the values are not validated and are copied as-is so it's up to you to ensure they are compatible with Starlight.

## Sidebar configuration
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/guides/features.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ Some features may never be supported due to various reasons, e.g. accessibility
## Properties

By deault, all unsupported properties are ignored and not exported.
This behavior can be changed by setting the [`copyStarlightFrontmatter`](/configuration/#copystarlightfrontmatter) option to `true` to include all known [Starlight frontmatter fields](https://starlight.astro.build/reference/frontmatter/).
This behavior can be changed by setting the [`copyFrontmatter`](/configuration/#copyfrontmatter) option to `starlight` to include all known [Starlight frontmatter fields](https://starlight.astro.build/reference/frontmatter/) or `all` to include all frontmatter fields.

| Name | Supported |
| :------------------------------------------------------------------------------------------------ | :-------: |
Expand Down
6 changes: 6 additions & 0 deletions fixtures/basics/Starlight properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ unknown: this is a custom property
title: Custom Starlight Title
tableOfContents: false
lastUpdated: 2024-09-21
cover: https://history-computer.com/ModernComputer/Basis/images/Engelbart.jpg
head:
- tag: meta
attrs:
property: 'og:image'
content: 'https://example.com/og-image.png'
---

Test
31 changes: 25 additions & 6 deletions packages/starlight-obsidian/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,24 @@ const starlightObsidianConfigSchema = z.object({
*/
configFolder: z.string().startsWith('.').default('.obsidian'),
/**
* Whether the Starlight Obsidian plugin should copy known Starlight frontmatter fields from Obsidian notes to the
* generated pages.
* Defines which frontmatter fields the Starlight Obsidian plugin should copy from Obsidian notes to the generated
* pages.
*
* This is useful if you want to customize the generated Starlight pages from Obsidian. Note that the values are not
* validated and are copied as-is so it's up to you to ensure they are compatible with Starlight.
* By default (`none`), all unsupported properties are ignored and not exported. Set this option to `starlight` to
* copy all known Starlight frontmatter fields from an Obsidian note to the associated generated page or to `all` to
* copy all frontmatter fields.
*
* @default false
* This option is useful if you want to customize the generated Starlight pages from Obsidian. Note that the values
* are not validated and are copied as-is so it's up to you to ensure they are compatible with Starlight.
*
* @default 'none'
* @see https://starlight.astro.build/reference/frontmatter/
*/
copyStarlightFrontmatter: z.boolean().default(false),
copyFrontmatter: z.union([z.literal('none'), z.literal('starlight'), z.literal('all')]).default('none'),
/**
* @deprecated Use the {@link StarlightObsidianUserConfig.copyFrontmatter} option instead.
*/
copyStarlightFrontmatter: z.never().optional(),
/**
* A list of glob patterns to ignore when generating the Obsidian vault pages.
* This option can be used to ignore files or folders.
Expand Down Expand Up @@ -102,6 +110,17 @@ export default function starlightObsidianPlugin(userConfig: StarlightObsidianUse
const parsedConfig = starlightObsidianConfigSchema.safeParse(userConfig)

if (!parsedConfig.success) {
const isUsingDeprecatedCopyStarlightFrontmatter = parsedConfig.error.issues.some(
(issue) => issue.path.join('.') === 'copyStarlightFrontmatter',
)

if (isUsingDeprecatedCopyStarlightFrontmatter) {
throwUserError(
'The `copyStarlightFrontmatter` option has been deprecated in favor of the `copyFrontmatter` option.',
'For more information see https://starlight-obsidian.vercel.app/configuration/#copyfrontmatter',
)
}

throwUserError(
`The provided plugin configuration is invalid.\n${parsedConfig.error.issues.map((issue) => issue.message).join('\n')}`,
)
Expand Down
5 changes: 3 additions & 2 deletions packages/starlight-obsidian/libs/plugin.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { AstroError } from 'astro/errors'

export function throwUserError(message: string): never {
export function throwUserError(message: string, hint?: string): never {
throw new AstroError(
message,
`See the error report above for more informations.\n\nIf you believe this is a bug, please file an issue at https://github.com/HiDeoo/starlight-obsidian/issues/new/choose`,
hint ??
`See the error report above for more informations.\n\nIf you believe this is a bug, please file an issue at https://github.com/HiDeoo/starlight-obsidian/issues/new/choose`,
)
}
24 changes: 16 additions & 8 deletions packages/starlight-obsidian/libs/remark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -453,9 +453,14 @@ function getFrontmatterNodeValue(file: VFile, obsidianFrontmatter?: ObsidianFron
editUrl: false,
}

if (obsidianFrontmatter && file.data.copyStarlightFrontmatter) {
const starlightLikeFrontmatter = getStarlightLikeFrontmatter(obsidianFrontmatter.raw)
frontmatter = { ...frontmatter, ...starlightLikeFrontmatter }
if (obsidianFrontmatter && (file.data.copyFrontmatter === 'starlight' || file.data.copyFrontmatter === 'all')) {
if (file.data.copyFrontmatter === 'starlight') {
const starlightLikeFrontmatter = getStarlightLikeFrontmatter(obsidianFrontmatter.raw)
frontmatter = { ...frontmatter, ...starlightLikeFrontmatter }
} else {
const { cover, image, description, permalink, tags, ...restFrontmatter } = obsidianFrontmatter.raw
frontmatter = { ...frontmatter, ...restFrontmatter }
}
}

if (file.data.includeKatexStyles) {
Expand All @@ -479,10 +484,13 @@ function getFrontmatterNodeValue(file: VFile, obsidianFrontmatter?: ObsidianFron
frontmatter.head = []
}

frontmatter.head.push(
{ tag: 'meta', attrs: { property: 'og:image', content: ogImage } },
{ tag: 'meta', attrs: { name: 'twitter:image', content: ogImage } },
)
if (!frontmatter.head.some((tag) => tag.attrs['property'] === 'og:image')) {
frontmatter.head.push({ tag: 'meta', attrs: { property: 'og:image', content: ogImage } })
}

if (!frontmatter.head.some((tag) => tag.attrs['property'] === 'twitter:image')) {
frontmatter.head.push({ tag: 'meta', attrs: { name: 'twitter:image', content: ogImage } })
}
}

if (obsidianFrontmatter?.description && obsidianFrontmatter.description.length > 0) {
Expand Down Expand Up @@ -674,7 +682,7 @@ function ensureTransformContext(file: VFile): asserts file is VFile & { data: Tr
export interface TransformContext {
aliases?: string[]
assetImports?: [id: string, path: string][]
copyStarlightFrontmatter?: boolean
copyFrontmatter: StarlightObsidianConfig['copyFrontmatter']
embedded?: boolean
files: VaultFile[]
includeKatexStyles?: boolean
Expand Down
3 changes: 2 additions & 1 deletion packages/starlight-obsidian/libs/starlight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const starlightFrontmatterKeys = [
'prev',
'next',
'pagefind',
'draft',
'sidebar',
]

Expand Down Expand Up @@ -181,7 +182,7 @@ async function addContent(
type,
} = await transformMarkdownToString(vaultFile.fsPath, obsidianContent, {
files: vaultFiles,
copyStarlightFrontmatter: config.copyStarlightFrontmatter,
copyFrontmatter: config.copyFrontmatter,
output: config.output,
vault,
})
Expand Down
4 changes: 2 additions & 2 deletions packages/starlight-obsidian/tests/embeds.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ test.each(linkSyntaxAndFormats)('transforms embed URLs in %s with the %s format'
const vault = await getVault(getFixtureConfig(fixtureName))
const paths = await getObsidianPaths(vault)
const files = getObsidianVaultFiles(vault, paths)
const options = { context: { files, output: 'notes', vault } }
const options = { context: { copyFrontmatter: 'none', files, output: 'notes', vault } as const }

let result = await transformFixtureMdFile(fixtureName, 'root embeds.md', options)

Expand Down Expand Up @@ -142,7 +142,7 @@ test('applies transformers to embedded notes', async () => {
const paths = await getObsidianPaths(vault)
const files = getObsidianVaultFiles(vault, paths)
const options = {
context: { copyStarlightFrontmatter: true, files, output: 'notes', vault },
context: { copyFrontmatter: 'starlight', files, output: 'notes', vault } as const,
includeFrontmatter: true,
}

Expand Down
48 changes: 47 additions & 1 deletion packages/starlight-obsidian/tests/properties.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ test('includes known Starlight frontmatter fields if the option is enabled', asy
const paths = await getObsidianPaths(vault)
const files = getObsidianVaultFiles(vault, paths)
const options = {
context: { copyStarlightFrontmatter: true, files, output: 'notes', vault },
context: { copyFrontmatter: 'starlight', files, output: 'notes', vault } as const,
includeFrontmatter: true,
}

Expand All @@ -66,6 +66,15 @@ test('includes known Starlight frontmatter fields if the option is enabled', asy
title: Custom Starlight Title
editUrl: false
slug: custom-starlight-slug
head:
- tag: meta
attrs:
property: og:image
content: https://example.com/og-image.png
- tag: meta
attrs:
name: twitter:image
content: https://history-computer.com/ModernComputer/Basis/images/Engelbart.jpg
tableOfContents: false
lastUpdated: 2024-09-21
description: This is a custom description
Expand All @@ -75,3 +84,40 @@ test('includes known Starlight frontmatter fields if the option is enabled', asy
"
`)
})

test('includes all frontmatter fields if the option is enabled', async () => {
const fixtureName = 'basics'
const vault = await getVault(getFixtureConfig(fixtureName))
const paths = await getObsidianPaths(vault)
const files = getObsidianVaultFiles(vault, paths)
const options = {
context: { copyFrontmatter: 'all', files, output: 'notes', vault } as const,
includeFrontmatter: true,
}

const result = await transformFixtureMdFile(fixtureName, 'Starlight properties.md', options)

expect(result.content).toMatchInlineSnapshot(`
"---
title: Custom Starlight Title
editUrl: false
slug: custom-starlight-slug
unknown: this is a custom property
tableOfContents: false
lastUpdated: 2024-09-21
head:
- tag: meta
attrs:
property: og:image
content: https://example.com/og-image.png
- tag: meta
attrs:
name: twitter:image
content: https://history-computer.com/ModernComputer/Basis/images/Engelbart.jpg
description: This is a custom description
---
Test
"
`)
})
4 changes: 2 additions & 2 deletions packages/starlight-obsidian/tests/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function getFixtureConfig(
return {
autoLinkHeadings: false,
configFolder: '.obsidian',
copyStarlightFrontmatter: false,
copyFrontmatter: 'none',
ignore: [],
skipGeneration: false,
tableOfContentsOverview: 'default',
Expand Down Expand Up @@ -61,7 +61,7 @@ export async function transformFixtureMdFile(
const md = await getFixtureFile(fixtureName, filePath)
const fileName = path.basename(filePath)
const result = await transformMarkdownToString(fixtureFilePath, md, {
copyStarlightFrontmatter: options.context?.copyStarlightFrontmatter ?? false,
copyFrontmatter: options.context?.copyFrontmatter ?? 'none',
files: options.context?.files ?? [
createVaultFile({
fileName,
Expand Down

0 comments on commit fe8d158

Please sign in to comment.