@hagicode/hagilight-docusaurus 0.11.1-dev.129.1.ea757b8 → 0.12.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 CHANGED
@@ -147,6 +147,16 @@ Written per locale, into that locale's output directory, when feed items exist.
147
147
  - The `<link rel="alternate">` head tag is added when feed items exist or the site owns `rss.xml`.
148
148
  - With no items, the build logs an info message and writes nothing.
149
149
 
150
+ ### .well-known/hagilight.metadata.json
151
+
152
+ Written by the default-locale build, as the last discovery step. It lists every configured locale, the discovery files this build wrote, and build facts. The schema is in `@hagicode/hagilight-core`'s README.
153
+
154
+ - `metadata: false` opts out. `metadata: { name, description }` overrides the site name, which defaults to `title`, and the description, which defaults to `tagline`.
155
+ - Analytics flags are `true` only in production builds that load the provider. Non-production builds report `false`.
156
+ - A build of a non-default locale writes nothing and warns when the default-locale build has not written the file, the same rule as `robots.txt`.
157
+ - A site-owned `static/.well-known/hagilight.metadata.json` takes precedence, and this plugin keeps it untouched.
158
+ - GitHub Pages needs a `.nojekyll` file in the published root, or the `.well-known` directory is dropped.
159
+
150
160
  ## Configuration warnings
151
161
 
152
162
  The plugin prints a `[@hagicode/hagilight-docusaurus]` warning during the build when:
@@ -1,4 +1,5 @@
1
1
  import type { HtmlTagObject, LoadContext } from '@docusaurus/types';
2
+ import type { BuildInfo } from '@hagicode/hagilight-core/build-info';
2
3
  import { type RssFeedItem } from '@hagicode/hagilight-core/rss';
3
4
  import type { ResolvedHagilightOptions, ResolvedRssOptions } from './options.js';
4
5
  type Warn = (message: string) => void;
@@ -17,6 +18,9 @@ export interface DiscoverySite {
17
18
  export interface DiscoveryOutputs {
18
19
  options: ResolvedHagilightOptions;
19
20
  site: DiscoverySite;
21
+ /** Version of this package, recorded as the metadata generator. */
22
+ generatorVersion: string;
23
+ buildInfo: BuildInfo;
20
24
  outDir: string;
21
25
  production: boolean;
22
26
  plugins: readonly {
package/dist/discovery.js CHANGED
@@ -2,6 +2,8 @@ import { existsSync } from 'node:fs';
2
2
  import { writeFile } from 'node:fs/promises';
3
3
  import { join, resolve } from 'node:path';
4
4
  import { generateRssFeed, resolveRssLocales } from '@hagicode/hagilight-core/rss';
5
+ import { buildSiteMetadata, SITE_METADATA_PATH, } from '@hagicode/hagilight-core/site-metadata';
6
+ import { findDiscoveryOutputs, writeSiteMetadata } from '@hagicode/hagilight-core/site-metadata-writer';
5
7
  const SITEMAP_PLUGIN = 'docusaurus-plugin-sitemap';
6
8
  const DOCS_PLUGIN = 'docusaurus-plugin-content-docs';
7
9
  const BLOG_PLUGIN = 'docusaurus-plugin-content-blog';
@@ -174,6 +176,60 @@ async function renderFeed(site, items) {
174
176
  });
175
177
  return response.text();
176
178
  }
179
+ /** A locale's base path relative to the site base, with leading and trailing slashes. */
180
+ function localePathFromBase(localeBaseUrl, siteBaseUrl) {
181
+ const relative = localeBaseUrl.startsWith(siteBaseUrl) ? localeBaseUrl.slice(siteBaseUrl.length) : localeBaseUrl;
182
+ const trimmed = relative.replace(/^\/+|\/+$/gu, '');
183
+ return trimmed ? `/${trimmed}/` : '/';
184
+ }
185
+ function metadataLocales(site) {
186
+ return site.i18n.locales.map((locale) => {
187
+ const config = site.i18n.localeConfigs[locale];
188
+ return { code: locale, lang: config.htmlLang, path: localePathFromBase(config.baseUrl, site.baseUrl) };
189
+ });
190
+ }
191
+ /**
192
+ * Write the site metadata file as the last discovery step, so `sitemap.xml`, `robots.txt`
193
+ * and `rss.xml` are already in the output. Only the default locale build writes it, the same
194
+ * rule as `robots.txt`. Analytics flags are true only for production builds that load the provider.
195
+ */
196
+ async function writeSiteMetadataFile(outputs) {
197
+ const { options, site, outDir, report } = outputs;
198
+ if (!options.metadata.enabled)
199
+ return;
200
+ if (site.i18n.currentLocale !== site.i18n.defaultLocale) {
201
+ if (!existsSync(join(defaultLocaleOutDir(outDir, site.i18n), SITE_METADATA_PATH))) {
202
+ report.warn(`${SITE_METADATA_PATH} is written only by the default locale build (${site.i18n.defaultLocale}); build that locale to include it.`);
203
+ }
204
+ return;
205
+ }
206
+ const production = outputs.production;
207
+ const metadata = buildSiteMetadata({
208
+ generator: { name: '@hagicode/hagilight-docusaurus', version: outputs.generatorVersion },
209
+ site: {
210
+ name: options.metadata.name ?? site.title,
211
+ url: site.url,
212
+ base: site.baseUrl,
213
+ description: options.metadata.description ?? site.tagline,
214
+ },
215
+ locales: metadataLocales(site),
216
+ defaultLocale: site.i18n.defaultLocale,
217
+ build: outputs.buildInfo,
218
+ discovery: findDiscoveryOutputs(outDir),
219
+ analytics: {
220
+ googleAnalytics: production && options.googleAnalyticsId !== undefined,
221
+ fiftyOneLa: production && options.fiftyOneLaId !== undefined,
222
+ posthog: production && options.posthogApiKey !== undefined,
223
+ },
224
+ features: { seo: options.seo.enabled, promoto: options.promoto },
225
+ });
226
+ writeSiteMetadata({
227
+ outDir,
228
+ metadata,
229
+ siteOwnedFiles: [join(site.siteDir, 'static', SITE_METADATA_PATH)],
230
+ logger: report,
231
+ });
232
+ }
177
233
  export async function writeDiscoveryOutputs(outputs) {
178
234
  const { options, site, outDir, report } = outputs;
179
235
  const noIndex = options.noIndex;
@@ -197,4 +253,5 @@ export async function writeDiscoveryOutputs(outputs) {
197
253
  await writeFile(join(outDir, 'rss.xml'), await renderFeed(site, outputs.feedItems));
198
254
  }
199
255
  }
256
+ await writeSiteMetadataFile(outputs);
200
257
  }
package/dist/index.d.ts CHANGED
@@ -3,6 +3,6 @@ import { PLUGIN_NAME, type HagilightGlobalData } from './global-data.js';
3
3
  import { type HagilightDocusaurusOptions } from './options.js';
4
4
  export { PLUGIN_NAME };
5
5
  export type { HagilightGlobalData };
6
- export type { AnalyticsOptions, FeatureToggle, FiftyOneLaOptions, GoogleAnalyticsOptions, PostHogOptions, HagilightDocusaurusOptions, ResolvedHagilightOptions, RssOptions, SeoOptions, SeoOrganizationOptions, } from './options.js';
6
+ export type { AnalyticsOptions, FeatureToggle, FiftyOneLaOptions, GoogleAnalyticsOptions, MetadataOptions, PostHogOptions, HagilightDocusaurusOptions, ResolvedHagilightOptions, RssOptions, SeoOptions, SeoOrganizationOptions, } from './options.js';
7
7
  export declare function hagilightDocusaurus(options?: HagilightDocusaurusOptions): PluginModule;
8
8
  export default hagilightDocusaurus;
package/dist/index.js CHANGED
@@ -74,6 +74,8 @@ function createPlugin(context, options) {
74
74
  await writeDiscoveryOutputs({
75
75
  options,
76
76
  site,
77
+ generatorVersion: PACKAGE_VERSION,
78
+ buildInfo: globalData.buildInfo,
77
79
  outDir: props.outDir,
78
80
  production: process.env.NODE_ENV === 'production',
79
81
  plugins: props.plugins,
package/dist/options.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type { SiteLinksOptions } from '@hagicode/hagilight-core/links';
2
+ import { type SiteMetadataOption } from '@hagicode/hagilight-core/site-metadata';
2
3
  export interface FeatureToggle {
3
4
  enabled?: boolean;
4
5
  }
@@ -29,7 +30,19 @@ export interface RssOptions extends FeatureToggle {
29
30
  includeDocs?: boolean;
30
31
  includeBlog?: boolean;
31
32
  }
33
+ export interface MetadataOptions extends FeatureToggle {
34
+ /** Site name. Defaults to `siteConfig.title`. */
35
+ name?: string;
36
+ /** Site description. Defaults to `siteConfig.tagline`. */
37
+ description?: string;
38
+ }
32
39
  export interface HagilightDocusaurusOptions {
40
+ /**
41
+ * Write `.well-known/hagilight.metadata.json` at the end of the build. Defaults to `true`;
42
+ * `false` opts out, and an object may set `name` and `description`. A site-owned file in
43
+ * `static/.well-known/` is kept. Only the default locale build writes the file.
44
+ */
45
+ metadata?: boolean | MetadataOptions;
33
46
  footer?: FeatureToggle;
34
47
  links?: SiteLinksOptions;
35
48
  analytics?: AnalyticsOptions;
@@ -64,5 +77,6 @@ export interface ResolvedHagilightOptions {
64
77
  robots: boolean;
65
78
  rss: ResolvedRssOptions;
66
79
  noIndex: boolean;
80
+ metadata: SiteMetadataOption;
67
81
  }
68
82
  export declare function resolveOptions(input: HagilightDocusaurusOptions | undefined): ResolvedHagilightOptions;
package/dist/options.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { DEFAULT_POSTHOG_API_KEY, POSTHOG_API_KEY_PATTERN } from '@hagicode/hagilight-core/posthog';
2
2
  import { isValidSeoImageReference, resolveAbsoluteHttpUrl } from '@hagicode/hagilight-core/seo';
3
+ import { resolveSiteMetadataOption } from '@hagicode/hagilight-core/site-metadata';
3
4
  import { DEFAULT_FIFTY_ONE_LA_ID, DEFAULT_GOOGLE_ANALYTICS_ID, FIFTY_ONE_LA_ID_PATTERN, GOOGLE_ANALYTICS_ID_PATTERN, } from './analytics.js';
4
5
  function invalid(path, reason) {
5
6
  return new TypeError(`@hagicode/hagilight-docusaurus option "${path}" ${reason}.`);
@@ -99,5 +100,6 @@ export function resolveOptions(input) {
99
100
  robots: featureEnabled(options.robots, 'robots'),
100
101
  rss: resolveRss(options.rss),
101
102
  noIndex: booleanOption(options.noIndex, 'noIndex') ?? false,
103
+ metadata: resolveSiteMetadataOption(options.metadata),
102
104
  };
103
105
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hagicode/hagilight-docusaurus",
3
- "version": "0.11.1-dev.129.1.ea757b8",
3
+ "version": "0.12.0",
4
4
  "type": "module",
5
5
  "description": "Docusaurus plugin for HagiCode site features: footer, analytics, promote card, locales, SEO, sitemap, robots.txt, and RSS",
6
6
  "repository": {
@@ -38,7 +38,7 @@
38
38
  ],
39
39
  "dependencies": {
40
40
  "@docusaurus/types": "^3.9.2",
41
- "@hagicode/hagilight-core": "0.11.1-dev.129.1.ea757b8"
41
+ "@hagicode/hagilight-core": "0.12.0"
42
42
  },
43
43
  "peerDependencies": {
44
44
  "@docusaurus/core": "^3.9.2",