@riebeckite/core 0.0.15 → 0.0.16

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/dist/index.d.ts CHANGED
@@ -21,7 +21,7 @@ export { getContentSourceEntry, readContentSourceEntry, } from "./src/content/co
21
21
  export { resolveContentStableId } from "./src/content/content_stable_id.js";
22
22
  export { FileSystemContentSource, INTERNAL_CONTENT_IGNORE_PATTERNS, isIgnoredContentPath, } from "./src/content/file_system_content_source.js";
23
23
  export type { FolderEntryCandidate, FolderEntryKind, FolderEntryResolution, FolderEntryScope, FolderLocationResolution, ResolveFolderEntryOptions, } from "./src/content/folder_entry.js";
24
- export { resolveFolderEntry, resolveFolderLocation, resolveGeneratedFolderLocation, } from "./src/content/folder_entry.js";
24
+ export { resolveFolderEntry, resolveFolderLocation, resolveGeneratedFolderLocation, resolvePublicFolderLocation, } from "./src/content/folder_entry.js";
25
25
  export type { ForceGraphLayoutOptions, GraphEdge, GraphLayoutNode, LinkableGraphNode, RadialGraphLayoutOptions, } from "./src/content/graph_layout.js";
26
26
  export { buildGraphEdges, layoutForceGraph, layoutRadialGraph, } from "./src/content/graph_layout.js";
27
27
  export { IMAGE_EXTENSIONS } from "./src/content/image_extensions.js";
@@ -46,6 +46,7 @@ export type { Diagnostic, DiagnosticCode, DiagnosticSeverity, } from "./src/type
46
46
  export type { ContentAssetOutputInput, GeneratedOutput, GeneratedOutputContent, GeneratedOutputInput, GeneratedOutputSink, } from "./src/types/generated_output.js";
47
47
  export { createUnavailableGeneratedOutputSink, normalizeContentAssetOutputPath, normalizeGeneratedOutputPath, } from "./src/types/generated_output.js";
48
48
  export type { JsonValue } from "./src/types/json_value.js";
49
+ export type { NavigationConfig, NavigationItem, } from "./src/types/navigation_config.js";
49
50
  export type { OutputDependency } from "./src/types/output_dependency.js";
50
51
  export type { PluginInput, ResolvedPluginMetadata, RiebeckitePlugin, } from "./src/types/plugin.js";
51
52
  export { definePlugin, getResolvedPluginMetadata, resolvePlugins, } from "./src/types/plugin.js";
package/dist/index.js CHANGED
@@ -18,11 +18,55 @@ function validateConfigIssues(config) {
18
18
  return [{ path: "config", message: "Expected an object." }];
19
19
  }
20
20
  validateSite(value.site, issues);
21
+ validateNavigation(value.navigation, issues);
21
22
  validateContent(value.content, issues);
22
23
  validateTheme(value.theme, issues);
23
24
  validatePlugins(value.plugins, issues);
24
25
  return issues;
25
26
  }
27
+ function validateNavigation(value, issues) {
28
+ if (value === void 0) return;
29
+ if (!isRecord(value)) {
30
+ issues.push({ path: "navigation", message: "Expected an object." });
31
+ return;
32
+ }
33
+ validateNavigationItems(value.header, "navigation.header", issues, /* @__PURE__ */ new Set());
34
+ validateNavigationItems(value.footer, "navigation.footer", issues, /* @__PURE__ */ new Set());
35
+ }
36
+ function validateNavigationItems(value, path5, issues, ancestors) {
37
+ if (value === void 0) return;
38
+ if (!Array.isArray(value)) {
39
+ issues.push({ path: path5, message: "Expected an array." });
40
+ return;
41
+ }
42
+ for (const [index, item] of value.entries()) {
43
+ const itemPath = `${path5}[${index}]`;
44
+ if (!isRecord(item)) {
45
+ issues.push({ path: itemPath, message: "Expected an object." });
46
+ continue;
47
+ }
48
+ if (ancestors.has(item)) {
49
+ issues.push({
50
+ path: itemPath,
51
+ message: "Navigation children must not be recursive."
52
+ });
53
+ continue;
54
+ }
55
+ validateRequiredString(item.label, `${itemPath}.label`, issues);
56
+ validateRequiredString(item.href, `${itemPath}.href`, issues);
57
+ validateOptionalBoolean(item.external, `${itemPath}.external`, issues);
58
+ if (item.children !== void 0) {
59
+ const nextAncestors = new Set(ancestors);
60
+ nextAncestors.add(item);
61
+ validateNavigationItems(
62
+ item.children,
63
+ `${itemPath}.children`,
64
+ issues,
65
+ nextAncestors
66
+ );
67
+ }
68
+ }
69
+ }
26
70
  function validateSite(value, issues) {
27
71
  if (!isRecord(value)) {
28
72
  issues.push({ path: "site", message: "Expected an object." });
@@ -625,6 +669,10 @@ function resolveConfig(config) {
625
669
  language: config.site?.feed?.language ?? config.site?.locale ?? "en"
626
670
  }
627
671
  },
672
+ navigation: {
673
+ header: config.navigation?.header ?? [],
674
+ footer: config.navigation?.footer ?? []
675
+ },
628
676
  content: {
629
677
  directory: config.content?.directory ?? "../../content",
630
678
  source: config.content?.source,
@@ -3766,6 +3814,7 @@ var ManifestBuilder = class {
3766
3814
  permalink: location.permalink,
3767
3815
  publicLocation: location,
3768
3816
  title: getManifestTitle(slug, processed.frontmatter.title),
3817
+ aliases: extractFrontmatterAliases(markdown),
3769
3818
  frontmatter: processed.frontmatter,
3770
3819
  publishing,
3771
3820
  html: processed.html,
@@ -3781,6 +3830,7 @@ var ManifestBuilder = class {
3781
3830
  build(entries, contentIndex) {
3782
3831
  const bySlug = new Map(entries.map((entry) => [entry.slug, entry]));
3783
3832
  const byContentId = createContentIdIndex(entries);
3833
+ const byAlias = createAliasIndex(entries);
3784
3834
  const byPermalink = new Map(
3785
3835
  entries.map((entry) => [entry.permalink, entry])
3786
3836
  );
@@ -3808,6 +3858,7 @@ var ManifestBuilder = class {
3808
3858
  discoverableEntries: [...entries],
3809
3859
  bySlug,
3810
3860
  byContentId,
3861
+ byAlias,
3811
3862
  byPermalink,
3812
3863
  byRoutablePermalink: new Map(byPermalink),
3813
3864
  redirects: /* @__PURE__ */ new Map(),
@@ -3828,6 +3879,14 @@ var ManifestBuilder = class {
3828
3879
  return { ...manifest, graph: createContentGraph(manifest) };
3829
3880
  }
3830
3881
  };
3882
+ function createAliasIndex(entries) {
3883
+ const byAlias = /* @__PURE__ */ new Map();
3884
+ for (const entry of entries) {
3885
+ for (const alias of entry.aliases ?? [])
3886
+ appendToMap(byAlias, alias.toLowerCase(), entry);
3887
+ }
3888
+ return byAlias;
3889
+ }
3831
3890
  function createContentIdIndex(entries) {
3832
3891
  const byContentId = /* @__PURE__ */ new Map();
3833
3892
  for (const entry of entries) {
@@ -4603,6 +4662,7 @@ function cloneManifestEntry(entry) {
4603
4662
  ...entry,
4604
4663
  publicLocation: { ...entry.publicLocation },
4605
4664
  frontmatter: { ...entry.frontmatter },
4665
+ aliases: [...entry.aliases ?? []],
4606
4666
  tags: [...entry.tags],
4607
4667
  links: entry.links.map((link) => ({ ...link })),
4608
4668
  backlinks: [...entry.backlinks],
@@ -4669,6 +4729,17 @@ function resolveFolderLocation(manifest, folder) {
4669
4729
  const location = manifest.folderLocations.get(normalizeFolder2(folder));
4670
4730
  return location ? { type: "generated", pathname: location.pathname } : { type: "none" };
4671
4731
  }
4732
+ function resolvePublicFolderLocation(manifest, pathname) {
4733
+ const normalizedPathname = normalizePathname(pathname);
4734
+ const entry = manifest.publicEntries.find(
4735
+ (candidate) => normalizePathname(candidate.publicLocation.permalink) === normalizedPathname
4736
+ );
4737
+ if (entry) return { type: "content", entry };
4738
+ const location = [...manifest.folderLocations.values()].find(
4739
+ (candidate) => normalizePathname(candidate.pathname) === normalizedPathname
4740
+ );
4741
+ return location ? { type: "generated", pathname: location.pathname } : { type: "none" };
4742
+ }
4672
4743
  function resolveGeneratedFolderLocation(manifest, folder) {
4673
4744
  const normalizedFolder = normalizeFolder2(folder);
4674
4745
  if (!normalizedFolder) return null;
@@ -4701,6 +4772,10 @@ function isInScope(entry, scope) {
4701
4772
  function normalizeFolder2(folder) {
4702
4773
  return folder.split("/").filter(Boolean).join("/");
4703
4774
  }
4775
+ function normalizePathname(pathname) {
4776
+ const segments = pathname.split("/").filter(Boolean);
4777
+ return segments.length === 0 ? "/" : `/${segments.join("/")}`;
4778
+ }
4704
4779
  function parentPath(pathname, levels) {
4705
4780
  const segments = pathname.split("/").filter(Boolean);
4706
4781
  if (segments.length < levels) return null;
@@ -4909,6 +4984,7 @@ function createGraphEntry(entry, markdown, contentIndex, locations) {
4909
4984
  permalink: location.permalink,
4910
4985
  publicLocation: location,
4911
4986
  title: slug,
4987
+ aliases: [],
4912
4988
  frontmatter: {},
4913
4989
  publishing: resolvePublishingState(
4914
4990
  {},
@@ -5052,6 +5128,7 @@ export {
5052
5128
  resolveFolderLocation,
5053
5129
  resolveGeneratedFolderLocation,
5054
5130
  resolvePlugins,
5131
+ resolvePublicFolderLocation,
5055
5132
  resolvePublishingBuildTime,
5056
5133
  resolvePublishingState,
5057
5134
  serializePublicClientConfig,
@@ -32,4 +32,5 @@ export type FolderLocationResolution = {
32
32
  };
33
33
  export declare function resolveFolderEntry(manifest: ContentManifest, folder: string, options?: ResolveFolderEntryOptions): FolderEntryResolution;
34
34
  export declare function resolveFolderLocation(manifest: ContentManifest, folder: string): FolderLocationResolution;
35
+ export declare function resolvePublicFolderLocation(manifest: ContentManifest, pathname: string): FolderLocationResolution;
35
36
  export declare function resolveGeneratedFolderLocation(manifest: ContentManifest, folder: string): string | null;
@@ -37,6 +37,7 @@ export type ContentManifestEntry = {
37
37
  permalink: string;
38
38
  publicLocation: ContentPublicLocation;
39
39
  title: string;
40
+ aliases?: readonly string[];
40
41
  frontmatter: PostFrontmatter;
41
42
  publishing: ResolvedPublishingState;
42
43
  html: string;
@@ -99,6 +100,7 @@ export type ContentManifest = {
99
100
  bySlug: Map<string, ContentManifestEntry>;
100
101
  /** Contains only entries with an explicit source-authored content ID. */
101
102
  byContentId: Map<string, ContentManifestEntry>;
103
+ byAlias: Map<string, ContentManifestEntry[]>;
102
104
  byPermalink: Map<string, ContentManifestEntry>;
103
105
  /** Contains only routable entries: public and unlisted, excluding draft and scheduled-before entries. */
104
106
  byRoutablePermalink: Map<string, ContentManifestEntry>;
@@ -0,0 +1,10 @@
1
+ export interface NavigationItem {
2
+ label: string;
3
+ href: string;
4
+ children?: readonly NavigationItem[];
5
+ external?: boolean;
6
+ }
7
+ export interface NavigationConfig {
8
+ header?: readonly NavigationItem[];
9
+ footer?: readonly NavigationItem[];
10
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ContentSource } from "../content/content_source.js";
2
+ import type { NavigationConfig } from "./navigation_config.js";
2
3
  import type { RiebeckitePlugin } from "./plugin.js";
3
4
  import type { PublishStrategy } from "./publish_strategy.js";
4
5
  import type { SiteConfig } from "./site_config.js";
@@ -10,6 +11,7 @@ export type ResolvedRiebeckiteConfig = {
10
11
  */
11
12
  buildDirectory?: string;
12
13
  site: Required<SiteConfig>;
14
+ navigation: Required<NavigationConfig>;
13
15
  content: {
14
16
  directory: string;
15
17
  source?: ContentSource;
@@ -1,10 +1,12 @@
1
1
  import type { ContentSource } from "../content/content_source.js";
2
+ import type { NavigationConfig } from "./navigation_config.js";
2
3
  import type { PluginInput } from "./plugin.js";
3
4
  import type { PublishStrategy } from "./publish_strategy.js";
4
5
  import type { SiteConfig } from "./site_config.js";
5
6
  import type { ThemeInput } from "./theme_config.js";
6
7
  export interface RiebeckiteConfig {
7
8
  site: SiteConfig;
9
+ navigation?: NavigationConfig;
8
10
  content?: {
9
11
  directory?: string;
10
12
  source?: ContentSource;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riebeckite/core",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -49,7 +49,7 @@
49
49
  },
50
50
  "devDependencies": {
51
51
  "tsx": "^4.22.4",
52
- "@riebeckite/test": "0.0.15"
52
+ "@riebeckite/test": "0.0.16"
53
53
  },
54
54
  "repository": {
55
55
  "type": "git",