Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 50 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@
"is-svg": "6.0.0",
"javascript-stringify": "^2.1.0",
"js-cookie": "^3.0.7",
"js-yaml": "^4.2.0",
"js-yaml": "^5.1.0",
"liquidjs": "^10.27.0",
"lodash": "^4.18.0",
"lodash-es": "^4.18.0",
Expand Down
4 changes: 2 additions & 2 deletions src/data-directory/lib/data-directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert from 'assert'
import fs from 'fs'
import path from 'path'
import walk from 'walk-sync'
import { load } from 'js-yaml'
import { loadYaml } from '@/frame/lib/load-yaml'
import { isRegExp, setWith } from 'lodash-es'
import filenameToKey from './filename-to-key'
import matter from '@gr2m/gray-matter'
Expand Down Expand Up @@ -74,7 +74,7 @@ export default function dataDirectory(
setWith(data, key, JSON.parse(processedContent), Object)
break
case '.yml':
setWith(data, key, load(processedContent, { filename }), Object)
setWith(data, key, loadYaml(processedContent, { filename }), Object)
break
case '.md':
case '.markdown':
Expand Down
4 changes: 2 additions & 2 deletions src/data-directory/lib/get-data.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import fs from 'fs'
import path from 'path'

import { load } from 'js-yaml'
import { loadYaml } from '@/frame/lib/load-yaml'
import matter from '@gr2m/gray-matter'
import { merge, get } from 'lodash-es'

Expand Down Expand Up @@ -331,7 +331,7 @@ const getYamlContent = memoize(
root = englishRoot
}
const fileContent = getFileContent(root, relPath, englishRoot)
return load(fileContent, { filename: relPath })
return loadYaml(fileContent, { filename: relPath })
},
)

Expand Down
25 changes: 25 additions & 0 deletions src/frame/lib/load-yaml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { load, loadAll, type LoadOptions } from 'js-yaml'

// js-yaml v5's `load()` throws a `YAMLException` ("expected a document, but
// the input is empty") when the input contains no YAML document — i.e. when
// it is empty, whitespace-only, or comments-only. js-yaml v4 returned
// `undefined` in those cases. This wrapper restores the v4 behavior so callers
// that read arbitrary (possibly empty) YAML files keep working across the
// major version bump.
//
// For any input that does contain a document, this behaves exactly like
// `load()` — including throwing on genuinely malformed YAML.
export function loadYaml(content: string, options?: LoadOptions): unknown {
// `loadAll` invokes the iterator once per document and, unlike `load`, does
// not throw when there are zero documents. Collect the documents so we can
// reproduce `load`'s single-document semantics without parsing twice.
const documents: unknown[] = []
loadAll(content, (doc) => documents.push(doc), options)
// No document (empty / whitespace-only / comments-only): v4 returned
// `undefined`.
if (documents.length === 0) return undefined
// Multiple documents: defer to `load` so it throws the same "expected a
// single document" error that v4 did.
if (documents.length > 1) return load(content, options)
return documents[0]
}
15 changes: 15 additions & 0 deletions src/frame/tests/load-yaml.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, test } from 'vitest'

import { loadYaml } from '@/frame/lib/load-yaml'

describe('loadYaml', () => {
test('returns undefined for empty or document-less content', () => {
expect(loadYaml('')).toBeUndefined()
expect(loadYaml(' \n\t')).toBeUndefined()
expect(loadYaml('# comment only\n# another comment')).toBeUndefined()
})

test('throws on multiple YAML documents', () => {
expect(() => loadYaml('a: 1\n---\nb: 2\n')).toThrow()
})
})
4 changes: 2 additions & 2 deletions src/links/lib/update-internal-links.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import fs from 'fs'
import { visit, Test } from 'unist-util-visit'
import { fromMarkdown } from 'mdast-util-from-markdown'
import { toMarkdown } from 'mdast-util-to-markdown'
import { load } from 'js-yaml'
import { loadYaml } from '@/frame/lib/load-yaml'
import { type Node, type Nodes, type Definition, type Link } from 'mdast'

import type { Context, Page } from '@/types'
Expand Down Expand Up @@ -101,7 +101,7 @@ async function updateFile(file: string, context: LinkContext, opts: typeof Optio
// And since the Yaml file might contain arrays of internal linked
// pathnames, we have to re-read it fully.
if (file.endsWith('.yml')) {
Object.assign(data, load(content))
Object.assign(data, loadYaml(content))
}

let newContent = content
Expand Down
6 changes: 3 additions & 3 deletions src/workflows/generate-llms-txt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

import fs from 'fs'

import { load } from 'js-yaml'
import { loadYaml } from '@/frame/lib/load-yaml'

import { loadPageMap } from '@/frame/lib/page-data'
import { renderContent } from '@/content-render/index'
Expand Down Expand Up @@ -44,11 +44,11 @@ export const ROLLUP_URL =
const BASE_URL = 'https://docs.github.com'

export function loadConfig(overridePath?: string): LlmsTxtConfig {
const defaults = load(fs.readFileSync(DEFAULT_CONFIG_PATH, 'utf8')) as Partial<LlmsTxtConfig>
const defaults = loadYaml(fs.readFileSync(DEFAULT_CONFIG_PATH, 'utf8')) as Partial<LlmsTxtConfig>
if (!overridePath || overridePath === DEFAULT_CONFIG_PATH) {
return defaults as LlmsTxtConfig
}
const overrides = load(fs.readFileSync(overridePath, 'utf8')) as Partial<LlmsTxtConfig> | null
const overrides = loadYaml(fs.readFileSync(overridePath, 'utf8')) as Partial<LlmsTxtConfig> | null
return { ...(defaults as LlmsTxtConfig), ...(overrides || {}) }
}

Expand Down
Loading