@altano/astro-opengraph 3.0.0 → 3.1.1

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/config.d.ts CHANGED
@@ -1,6 +1,4 @@
1
- import { OpengraphImageConfigDeserialized, OpengraphImageConfigResolved, OpengraphImageConfigSerializableMaybeMocked } from "./types-5FZPWj11.js";
2
- //#region src/config.d.ts
1
+ import { OpengraphImageConfigDeserialized, OpengraphImageConfigResolved, OpengraphImageConfigSerializableMaybeMocked } from "./types-BFKV60-c.js";
3
2
  export declare function deserializeVirtualConfig(configMaybeMocked: OpengraphImageConfigSerializableMaybeMocked): Promise<OpengraphImageConfigDeserialized>;
4
3
  export declare function getResolvedConfig(): Promise<OpengraphImageConfigResolved>;
5
- //#endregion
6
4
  //# sourceMappingURL=config.d.ts.map
package/dist/config.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { readFile } from "node:fs/promises";
2
- //#region src/config.ts
2
+ // src/config.ts
3
3
  async function deserializeVirtualConfig(configMaybeMocked) {
4
4
  const config = typeof configMaybeMocked === "function" ? configMaybeMocked() : configMaybeMocked;
5
5
  const fontsWithBuffers = await Promise.all(config.imageOptions.fonts.map(async (font) => {
@@ -37,7 +37,6 @@ async function getResolvedConfig() {
37
37
  }
38
38
  };
39
39
  }
40
- //#endregion
41
40
  export { deserializeVirtualConfig, getResolvedConfig };
42
41
 
43
42
  //# sourceMappingURL=config.js.map
@@ -1,6 +1,5 @@
1
- import { ImageOptions } from "./types-5FZPWj11.js";
1
+ import { ImageOptions } from "./types-BFKV60-c.js";
2
2
  import { APIRoute } from "astro";
3
- //#region src/endpoint.d.ts
4
3
  type Options = {
5
4
  /**
6
5
  * We don't just type this as `AstroComponentFactory` because astro typing is
@@ -16,5 +15,5 @@ type Options = {
16
15
  };
17
16
  export declare function makeOpengraphDevEndpoint({ template, contentType }: Options): APIRoute;
18
17
  export declare function makeOpengraphEndpoint({ template, imageOptionOverrides, contentType }: Options): APIRoute;
19
- //#endregion
18
+ export {};
20
19
  //# sourceMappingURL=endpoint.d.ts.map
package/dist/endpoint.js CHANGED
@@ -5,7 +5,7 @@ import { getConfiguredImageService, imageConfig } from "astro:assets";
5
5
  import satori from "satori";
6
6
  import { html } from "satori-html";
7
7
  import { decode } from "he";
8
- //#region src/image.ts
8
+ // src/image.ts
9
9
  /**
10
10
  * Convert an html string to an image
11
11
  */
@@ -33,8 +33,7 @@ async function bufferToTransformedPNG(imageBuffer) {
33
33
  dangerouslyProcessSVG: true
34
34
  }, consoleLogger);
35
35
  }
36
- //#endregion
37
- //#region src/endpoint.ts
36
+ // src/endpoint.ts
38
37
  function makeOpengraphDevEndpoint({ template, contentType = "text/html" }) {
39
38
  return async ({ locals, params, props, request }) => {
40
39
  if ((await getResolvedConfig()).command !== "dev") return new Response(null, { status: 404 });
@@ -65,7 +64,6 @@ function makeOpengraphEndpoint({ template, imageOptionOverrides, contentType = "
65
64
  return new Response(new Uint8Array(png.data), { headers: { "Content-Type": contentType } });
66
65
  };
67
66
  }
68
- //#endregion
69
67
  export { makeOpengraphDevEndpoint, makeOpengraphEndpoint };
70
68
 
71
69
  //# sourceMappingURL=endpoint.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint.js","names":["html","htmlToVNode"],"sources":["../src/image.ts","../src/endpoint.ts"],"sourcesContent":["import { getConfiguredImageService, imageConfig } from \"astro:assets\";\nimport satori, { type SatoriOptions } from \"satori\";\nimport { html as htmlToVNode } from \"satori-html\";\nimport { decode } from \"he\";\n\nimport type { LocalImageService } from \"astro\";\n\n/**\n * Convert an html string to an image\n */\nexport async function htmlToPNG(\n html: string,\n satoriOptions: SatoriOptions,\n): Promise<ReturnType<LocalImageService[\"transform\"]>> {\n // html text => vnode\n const responseTextWithDecodedHtmlEntities = decode(html);\n const vnode = htmlToVNode(responseTextWithDecodedHtmlEntities);\n\n // vnode => svg\n const svg = await satori(vnode as React.ReactNode, satoriOptions);\n\n // svg => buffer\n const fileBuffer = Buffer.from(svg, \"utf-8\");\n const uint8Array = new Uint8Array(\n fileBuffer.buffer,\n fileBuffer.byteOffset,\n fileBuffer.byteLength,\n );\n\n // buffer => transformed png\n return bufferToTransformedPNG(uint8Array);\n}\n\ntype Logger = Parameters<LocalImageService[\"transform\"]>[3];\n\nconst consoleLogger: Logger = {\n /* eslint-disable no-console */\n info: (msg) => console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n /* eslint-enable no-console */\n};\n\n/**\n * Convert a buffer to an image using the astro local image service\n */\nasync function bufferToTransformedPNG(\n imageBuffer: Uint8Array,\n): ReturnType<LocalImageService[\"transform\"]> {\n const imageService = (await getConfiguredImageService()) as LocalImageService;\n\n // Astro 7 disables SVG rasterization in the sharp image service by default\n // (`image.dangerouslyProcessSVG`). Our input is an SVG we produced ourselves\n // with satori, so enable rasterization for *this transform only* by passing a\n // scoped config override. We intentionally do NOT flip the global\n // `image.dangerouslyProcessSVG` config, which is a project-wide security\n // decision the user must make for the other SVGs they process.\n return imageService.transform(\n imageBuffer,\n { src: \"\", format: \"png\" },\n { ...imageConfig, dangerouslyProcessSVG: true },\n // Astro 7.3 added a required logger parameter (the sharp service calls\n // `logger.warn`). Older Astro versions ignore the extra argument.\n consoleLogger,\n );\n}\n","import type { APIRoute } from \"astro\";\nimport { experimental_AstroContainer } from \"astro/container\";\nimport { isAstroComponentFactory } from \"astro/runtime/server/render/astro/factory.js\";\nimport { getResolvedConfig } from \"./config.js\";\nimport type { ImageOptions } from \"./types.js\";\nimport { htmlToPNG } from \"./image.js\";\n\ntype Options = {\n /**\n * We don't just type this as `AstroComponentFactory` because astro typing is\n * hard to get right and simply importing a .astro file doesn't give you\n * something typed as a factory.\n */\n template: unknown;\n /**\n * Custom \"Content-Type\" header, only used in SSR. Defaults to \"image/png\"\n */\n contentType?: string;\n imageOptionOverrides?: Partial<ImageOptions>;\n};\n\nexport function makeOpengraphDevEndpoint({\n template,\n contentType = \"text/html\",\n}: Options): APIRoute {\n return async ({ locals, params, props, request }) => {\n const config = await getResolvedConfig();\n if (config.command !== \"dev\") {\n return new Response(null, { status: 404 });\n }\n\n if (!isAstroComponentFactory(template)) {\n throw new Error(`Given is not an Astro template.`);\n }\n\n const container = await experimental_AstroContainer.create();\n const templateStr = await container.renderToString(template, {\n partial: false,\n request,\n params,\n locals,\n props,\n });\n\n return new Response(templateStr, {\n headers: {\n \"Content-Type\": contentType,\n },\n });\n };\n}\n\nexport function makeOpengraphEndpoint({\n template,\n imageOptionOverrides,\n contentType = \"image/png\",\n}: Options): APIRoute {\n return async ({ locals, params, props, request }) => {\n if (!isAstroComponentFactory(template)) {\n throw new Error(`Given is not an Astro template.`);\n }\n\n const container = await experimental_AstroContainer.create();\n const templateStr = await container.renderToString(template, {\n partial: false,\n request,\n params,\n locals,\n props,\n });\n\n const config = await getResolvedConfig();\n const imageOptions = {\n ...config.imageOptions,\n ...imageOptionOverrides,\n };\n const png = await htmlToPNG(templateStr, imageOptions);\n\n return new Response(new Uint8Array(png.data), {\n headers: {\n \"Content-Type\": contentType,\n },\n });\n };\n}\n"],"mappings":";;;;;;;;;;;AAUA,eAAsB,UACpB,QACA,eACqD;CAErD,MAAM,sCAAsC,OAAOA,MAAI;CACvD,MAAM,QAAQC,KAAY,mCAAmC;CAG7D,MAAM,MAAM,MAAM,OAAO,OAA0B,aAAa;CAGhE,MAAM,aAAa,OAAO,KAAK,KAAK,OAAO;CAQ3C,OAAO,uBAAuB,IAPP,WACrB,WAAW,QACX,WAAW,YACX,WAAW,UAI0B,CAAC;AAC1C;AAIA,MAAM,gBAAwB;CAE5B,OAAO,QAAQ,QAAQ,KAAK,GAAG;CAC/B,OAAO,QAAQ,QAAQ,KAAK,GAAG;CAC/B,QAAQ,QAAQ,QAAQ,MAAM,GAAG;AAEnC;;;;AAKA,eAAe,uBACb,aAC4C;CAS5C,QAAO,MARqB,0BAA0B,EAAA,CAQlC,UAClB,aACA;EAAE,KAAK;EAAI,QAAQ;CAAM,GACzB;EAAE,GAAG;EAAa,uBAAuB;CAAK,GAG9C,aACF;AACF;;;AC5CA,SAAgB,yBAAyB,EACvC,UACA,cAAc,eACM;CACpB,OAAO,OAAO,EAAE,QAAQ,QAAQ,OAAO,cAAc;EAEnD,KAAI,MADiB,kBAAkB,EAAA,CAC5B,YAAY,OACrB,OAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;EAG3C,IAAI,CAAC,wBAAwB,QAAQ,GACnC,MAAM,IAAI,MAAM,iCAAiC;EAInD,MAAM,cAAc,OAAM,MADF,4BAA4B,OAAO,EAAA,CACvB,eAAe,UAAU;GAC3D,SAAS;GACT;GACA;GACA;GACA;EACF,CAAC;EAED,OAAO,IAAI,SAAS,aAAa,EAC/B,SAAS,EACP,gBAAgB,YAClB,EACF,CAAC;CACH;AACF;AAEA,SAAgB,sBAAsB,EACpC,UACA,sBACA,cAAc,eACM;CACpB,OAAO,OAAO,EAAE,QAAQ,QAAQ,OAAO,cAAc;EACnD,IAAI,CAAC,wBAAwB,QAAQ,GACnC,MAAM,IAAI,MAAM,iCAAiC;EAiBnD,MAAM,MAAM,MAAM,UAAU,OAbF,MADF,4BAA4B,OAAO,EAAA,CACvB,eAAe,UAAU;GAC3D,SAAS;GACT;GACA;GACA;GACA;EACF,CAAC,GAOwC;GAHvC,IAAG,MAFgB,kBAAkB,EAAA,CAE3B;GACV,GAAG;EAEoC,CAAY;EAErD,OAAO,IAAI,SAAS,IAAI,WAAW,IAAI,IAAI,GAAG,EAC5C,SAAS,EACP,gBAAgB,YAClB,EACF,CAAC;CACH;AACF"}
1
+ {"version":3,"file":"endpoint.js","names":["html","htmlToVNode"],"sources":["../src/image.ts","../src/endpoint.ts"],"sourcesContent":["import { getConfiguredImageService, imageConfig } from \"astro:assets\";\nimport satori, { type SatoriOptions } from \"satori\";\nimport { html as htmlToVNode } from \"satori-html\";\nimport { decode } from \"he\";\n\nimport type { LocalImageService } from \"astro\";\n\n/**\n * Convert an html string to an image\n */\nexport async function htmlToPNG(\n html: string,\n satoriOptions: SatoriOptions,\n): Promise<ReturnType<LocalImageService[\"transform\"]>> {\n // html text => vnode\n const responseTextWithDecodedHtmlEntities = decode(html);\n const vnode = htmlToVNode(responseTextWithDecodedHtmlEntities);\n\n // vnode => svg\n const svg = await satori(vnode as React.ReactNode, satoriOptions);\n\n // svg => buffer\n const fileBuffer = Buffer.from(svg, \"utf-8\");\n const uint8Array = new Uint8Array(\n fileBuffer.buffer,\n fileBuffer.byteOffset,\n fileBuffer.byteLength,\n );\n\n // buffer => transformed png\n return bufferToTransformedPNG(uint8Array);\n}\n\ntype TransformImageConfig = Parameters<LocalImageService[\"transform\"]>[2];\ntype Logger = Parameters<LocalImageService[\"transform\"]>[3];\n\nconst consoleLogger: Logger = {\n /* eslint-disable no-console */\n info: (msg) => console.info(msg),\n warn: (msg) => console.warn(msg),\n error: (msg) => console.error(msg),\n /* eslint-enable no-console */\n};\n\n/**\n * Convert a buffer to an image using the astro local image service\n */\nasync function bufferToTransformedPNG(\n imageBuffer: Uint8Array,\n): ReturnType<LocalImageService[\"transform\"]> {\n const imageService = (await getConfiguredImageService()) as LocalImageService;\n\n // Astro 7 disables SVG rasterization in the sharp image service by default\n // (`image.dangerouslyProcessSVG`). Our input is an SVG we produced ourselves\n // with satori, so enable rasterization for *this transform only* by passing a\n // scoped config override. We intentionally do NOT flip the global\n // `image.dangerouslyProcessSVG` config, which is a project-wide security\n // decision the user must make for the other SVGs they process.\n return imageService.transform(\n imageBuffer,\n { src: \"\", format: \"png\" },\n // Astro 7.4 types `imageConfig.service` as either one service or a\n // `{ build, runtime }` pair, but the `astro:assets` module always exports\n // the single service it resolved for the current environment.\n { ...imageConfig, dangerouslyProcessSVG: true } as TransformImageConfig,\n // Astro 7.3 added a required logger parameter (the sharp service calls\n // `logger.warn`). Older Astro versions ignore the extra argument.\n consoleLogger,\n );\n}\n","import type { APIRoute } from \"astro\";\nimport { experimental_AstroContainer } from \"astro/container\";\nimport { isAstroComponentFactory } from \"astro/runtime/server/render/astro/factory.js\";\nimport { getResolvedConfig } from \"./config.js\";\nimport type { ImageOptions } from \"./types.js\";\nimport { htmlToPNG } from \"./image.js\";\n\ntype Options = {\n /**\n * We don't just type this as `AstroComponentFactory` because astro typing is\n * hard to get right and simply importing a .astro file doesn't give you\n * something typed as a factory.\n */\n template: unknown;\n /**\n * Custom \"Content-Type\" header, only used in SSR. Defaults to \"image/png\"\n */\n contentType?: string;\n imageOptionOverrides?: Partial<ImageOptions>;\n};\n\nexport function makeOpengraphDevEndpoint({\n template,\n contentType = \"text/html\",\n}: Options): APIRoute {\n return async ({ locals, params, props, request }) => {\n const config = await getResolvedConfig();\n if (config.command !== \"dev\") {\n return new Response(null, { status: 404 });\n }\n\n if (!isAstroComponentFactory(template)) {\n throw new Error(`Given is not an Astro template.`);\n }\n\n const container = await experimental_AstroContainer.create();\n const templateStr = await container.renderToString(template, {\n partial: false,\n request,\n params,\n locals,\n props,\n });\n\n return new Response(templateStr, {\n headers: {\n \"Content-Type\": contentType,\n },\n });\n };\n}\n\nexport function makeOpengraphEndpoint({\n template,\n imageOptionOverrides,\n contentType = \"image/png\",\n}: Options): APIRoute {\n return async ({ locals, params, props, request }) => {\n if (!isAstroComponentFactory(template)) {\n throw new Error(`Given is not an Astro template.`);\n }\n\n const container = await experimental_AstroContainer.create();\n const templateStr = await container.renderToString(template, {\n partial: false,\n request,\n params,\n locals,\n props,\n });\n\n const config = await getResolvedConfig();\n const imageOptions = {\n ...config.imageOptions,\n ...imageOptionOverrides,\n };\n const png = await htmlToPNG(templateStr, imageOptions);\n\n return new Response(new Uint8Array(png.data), {\n headers: {\n \"Content-Type\": contentType,\n },\n });\n };\n}\n"],"mappings":";;;;;;;;;;;AAUA,eAAsB,UACpB,QACA,eACqD;CAErD,MAAM,sCAAsC,OAAOA,MAAI;CACvD,MAAM,QAAQC,KAAY,mCAAmC;CAG7D,MAAM,MAAM,MAAM,OAAO,OAA0B,aAAa;CAGhE,MAAM,aAAa,OAAO,KAAK,KAAK,OAAO;CAQ3C,OAAO,uBAAuB,IAPP,WACrB,WAAW,QACX,WAAW,YACX,WAAW,UAI0B,CAAC;AAC1C;AAKA,MAAM,gBAAwB;CAE5B,OAAO,QAAQ,QAAQ,KAAK,GAAG;CAC/B,OAAO,QAAQ,QAAQ,KAAK,GAAG;CAC/B,QAAQ,QAAQ,QAAQ,MAAM,GAAG;AAEnC;;;;AAKA,eAAe,uBACb,aAC4C;CAS5C,QAAO,MARqB,0BAA0B,EAAA,CAQlC,UAClB,aACA;EAAE,KAAK;EAAI,QAAQ;CAAM,GAIzB;EAAE,GAAG;EAAa,uBAAuB;CAAK,GAG9C,aACF;AACF;;AChDA,SAAgB,yBAAyB,EACvC,UACA,cAAc,eACM;CACpB,OAAO,OAAO,EAAE,QAAQ,QAAQ,OAAO,cAAc;EAEnD,KAAI,MADiB,kBAAkB,EAAA,CAC5B,YAAY,OACrB,OAAO,IAAI,SAAS,MAAM,EAAE,QAAQ,IAAI,CAAC;EAG3C,IAAI,CAAC,wBAAwB,QAAQ,GACnC,MAAM,IAAI,MAAM,iCAAiC;EAInD,MAAM,cAAc,OAAM,MADF,4BAA4B,OAAO,EAAA,CACvB,eAAe,UAAU;GAC3D,SAAS;GACT;GACA;GACA;GACA;EACF,CAAC;EAED,OAAO,IAAI,SAAS,aAAa,EAC/B,SAAS,EACP,gBAAgB,YAClB,EACF,CAAC;CACH;AACF;AAEA,SAAgB,sBAAsB,EACpC,UACA,sBACA,cAAc,eACM;CACpB,OAAO,OAAO,EAAE,QAAQ,QAAQ,OAAO,cAAc;EACnD,IAAI,CAAC,wBAAwB,QAAQ,GACnC,MAAM,IAAI,MAAM,iCAAiC;EAiBnD,MAAM,MAAM,MAAM,UAAU,OAbF,MADF,4BAA4B,OAAO,EAAA,CACvB,eAAe,UAAU;GAC3D,SAAS;GACT;GACA;GACA;GACA;EACF,CAAC,GAOwC;GAHvC,IAAG,MAFgB,kBAAkB,EAAA,CAE3B;GACV,GAAG;EAEoC,CAAY;EAErD,OAAO,IAAI,SAAS,IAAI,WAAW,IAAI,IAAI,GAAG,EAC5C,SAAS,EACP,gBAAgB,YAClB,EACF,CAAC;CACH;AACF"}
package/dist/index.d.ts CHANGED
@@ -1,7 +1,5 @@
1
- import { ComponentMetaTagFallbacks, ImageOptionsWithFontPaths, OpengraphImageConfig } from "./types-5FZPWj11.js";
1
+ import { ComponentMetaTagFallbacks, ImageOptionsWithFontPaths, OpengraphImageConfig } from "./types-BFKV60-c.js";
2
2
  import { AstroIntegration } from "astro";
3
- //#region src/integration.d.ts
4
3
  declare const _default: (config: OpengraphImageConfig) => AstroIntegration;
5
- //#endregion
6
4
  export { type ComponentMetaTagFallbacks, type ImageOptionsWithFontPaths, type OpengraphImageConfig, _default as default };
7
5
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/virtual-user-config.ts
1
+ // src/virtual-user-config.ts
2
2
  function resolveVirtualModuleId(id) {
3
3
  return `\0${id}`;
4
4
  }
@@ -22,8 +22,7 @@ function vitePluginOpengraphImageUserConfig(config) {
22
22
  }
23
23
  };
24
24
  }
25
- //#endregion
26
- //#region src/integration.ts
25
+ // src/integration.ts
27
26
  var integration_default = (config) => ({
28
27
  name: "@altano/astro-opengraph",
29
28
  hooks: { async "astro:config:setup"({ updateConfig, command, addDevToolbarApp }) {
@@ -39,7 +38,6 @@ var integration_default = (config) => ({
39
38
  });
40
39
  } }
41
40
  });
42
- //#endregion
43
41
  export { integration_default as default };
44
42
 
45
43
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/virtual-user-config.ts","../src/integration.ts"],"sourcesContent":["import type { ViteUserConfig } from \"astro\";\n\nimport type { OpengraphImageConfigSerializable } from \"./types.js\";\n\nfunction resolveVirtualModuleId<T extends string>(id: T): `\\0${T}` {\n return `\\0${id}`;\n}\n\n/**\n * Vite plugin that exposes OpengraphImage user config and project context via\n * virtual modules.\n */\nexport function vitePluginOpengraphImageUserConfig(\n config: OpengraphImageConfigSerializable,\n): NonNullable<ViteUserConfig[\"plugins\"]>[number] {\n /** Map of virtual module names to their code contents as strings. */\n const modules = {\n \"virtual:astro-opengraph/user-config\": `export default ${JSON.stringify(\n config,\n )}`,\n } satisfies Record<string, string>;\n\n /** Mapping names prefixed with `\\0` to their original form. */\n const resolutionMap = Object.fromEntries(\n (Object.keys(modules) as (keyof typeof modules)[]).map((key) => [\n resolveVirtualModuleId(key),\n key,\n ]),\n );\n\n return {\n name: \"vite-plugin-astro-opengraph-user-config\",\n resolveId(id): string | void {\n if (id in modules) return resolveVirtualModuleId(id);\n },\n load(id): string | void {\n const resolution = resolutionMap[id];\n if (resolution) return modules[resolution];\n },\n };\n}\n","import type { AstroIntegration } from \"astro\";\nimport type {\n OpengraphImageConfig,\n OpengraphImageConfigSerializable,\n} from \"./types.js\";\nimport { vitePluginOpengraphImageUserConfig } from \"./virtual-user-config.js\";\n\nexport default (config: OpengraphImageConfig): AstroIntegration => ({\n name: \"@altano/astro-opengraph\",\n hooks: {\n async \"astro:config:setup\"({\n updateConfig,\n command,\n addDevToolbarApp,\n }): Promise<void> {\n const imageOptions = await config.getImageOptions();\n const configSerializable: OpengraphImageConfigSerializable = {\n imageOptions,\n command,\n };\n updateConfig({\n vite: {\n // Shove the serializable config into the virtual module for later\n // retrieval in the middleware\n plugins: [vitePluginOpengraphImageUserConfig(configSerializable)],\n },\n });\n addDevToolbarApp({\n id: \"@altano/astro-opengraph\",\n name: \"Open Graph\",\n // icon: \"🌠\",\n icon: \"image\",\n // We don't use `@altano/astro-opengraph/toolbar` because that won't\n // resolve when serving the test fixture for e2e runs (`pnpm\n // test:e2e:server`)\n entrypoint: new URL(\"./toolbar/index.js\", import.meta.url),\n });\n },\n },\n});\n"],"mappings":";AAIA,SAAS,uBAAyC,IAAiB;CACjE,OAAO,KAAK;AACd;;;;;AAMA,SAAgB,mCACd,QACgD;;CAEhD,MAAM,UAAU,EACd,uCAAuC,kBAAkB,KAAK,UAC5D,MACF,IACF;;CAGA,MAAM,gBAAgB,OAAO,YAC1B,OAAO,KAAK,OAAO,CAAC,CAA8B,KAAK,QAAQ,CAC9D,uBAAuB,GAAG,GAC1B,GACF,CAAC,CACH;CAEA,OAAO;EACL,MAAM;EACN,UAAU,IAAmB;GAC3B,IAAI,MAAM,SAAS,OAAO,uBAAuB,EAAE;EACrD;EACA,KAAK,IAAmB;GACtB,MAAM,aAAa,cAAc;GACjC,IAAI,YAAY,OAAO,QAAQ;EACjC;CACF;AACF;;;ACjCA,IAAA,uBAAgB,YAAoD;CAClE,MAAM;CACN,OAAO,EACL,MAAM,qBAAqB,EACzB,cACA,SACA,oBACgB;EAMhB,aAAa,EACX,MAAM,EAGJ,SAAS,CAAC,mCAAmC;GAP/C,cAAA,MAFyB,OAAO,gBAAgB;GAGhD;EAM+C,CAAkB,CAAC,EAClE,EACF,CAAC;EACD,iBAAiB;GACf,IAAI;GACJ,MAAM;GAEN,MAAM;GAIN,YAAY,IAAI,IAAI,sBAAsB,YAAY,GAAG;EAC3D,CAAC;CACH,EACF;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/virtual-user-config.ts","../src/integration.ts"],"sourcesContent":["import type { ViteUserConfig } from \"astro\";\n\nimport type { OpengraphImageConfigSerializable } from \"./types.js\";\n\nfunction resolveVirtualModuleId<T extends string>(id: T): `\\0${T}` {\n return `\\0${id}`;\n}\n\n/**\n * Vite plugin that exposes OpengraphImage user config and project context via\n * virtual modules.\n */\nexport function vitePluginOpengraphImageUserConfig(\n config: OpengraphImageConfigSerializable,\n): NonNullable<ViteUserConfig[\"plugins\"]>[number] {\n /** Map of virtual module names to their code contents as strings. */\n const modules = {\n \"virtual:astro-opengraph/user-config\": `export default ${JSON.stringify(\n config,\n )}`,\n } satisfies Record<string, string>;\n\n /** Mapping names prefixed with `\\0` to their original form. */\n const resolutionMap = Object.fromEntries(\n (Object.keys(modules) as (keyof typeof modules)[]).map((key) => [\n resolveVirtualModuleId(key),\n key,\n ]),\n );\n\n return {\n name: \"vite-plugin-astro-opengraph-user-config\",\n resolveId(id): string | void {\n if (id in modules) return resolveVirtualModuleId(id);\n },\n load(id): string | void {\n const resolution = resolutionMap[id];\n if (resolution) return modules[resolution];\n },\n };\n}\n","import type { AstroIntegration } from \"astro\";\nimport type {\n OpengraphImageConfig,\n OpengraphImageConfigSerializable,\n} from \"./types.js\";\nimport { vitePluginOpengraphImageUserConfig } from \"./virtual-user-config.js\";\n\nexport default (config: OpengraphImageConfig): AstroIntegration => ({\n name: \"@altano/astro-opengraph\",\n hooks: {\n async \"astro:config:setup\"({\n updateConfig,\n command,\n addDevToolbarApp,\n }): Promise<void> {\n const imageOptions = await config.getImageOptions();\n const configSerializable: OpengraphImageConfigSerializable = {\n imageOptions,\n command,\n };\n updateConfig({\n vite: {\n // Shove the serializable config into the virtual module for later\n // retrieval in the middleware\n plugins: [vitePluginOpengraphImageUserConfig(configSerializable)],\n },\n });\n addDevToolbarApp({\n id: \"@altano/astro-opengraph\",\n name: \"Open Graph\",\n // icon: \"🌠\",\n icon: \"image\",\n // We don't use `@altano/astro-opengraph/toolbar` because that won't\n // resolve when serving the test fixture for e2e runs (`pnpm\n // test:e2e:server`)\n entrypoint: new URL(\"./toolbar/index.js\", import.meta.url),\n });\n },\n },\n});\n"],"mappings":";AAIA,SAAS,uBAAyC,IAAiB;CACjE,OAAO,KAAK;AACd;;;;;AAMA,SAAgB,mCACd,QACgD;;CAEhD,MAAM,UAAU,EACd,uCAAuC,kBAAkB,KAAK,UAC5D,MACF,IACF;;CAGA,MAAM,gBAAgB,OAAO,YAC1B,OAAO,KAAK,OAAO,CAAC,CAA8B,KAAK,QAAQ,CAC9D,uBAAuB,GAAG,GAC1B,GACF,CAAC,CACH;CAEA,OAAO;EACL,MAAM;EACN,UAAU,IAAmB;GAC3B,IAAI,MAAM,SAAS,OAAO,uBAAuB,EAAE;EACrD;EACA,KAAK,IAAmB;GACtB,MAAM,aAAa,cAAc;GACjC,IAAI,YAAY,OAAO,QAAQ;EACjC;CACF;AACF;;ACjCA,IAAA,uBAAgB,YAAoD;CAClE,MAAM;CACN,OAAO,EACL,MAAM,qBAAqB,EACzB,cACA,SACA,oBACgB;EAMhB,aAAa,EACX,MAAM,EAGJ,SAAS,CAAC,mCAAmC;GAP/C,cAAA,MAFyB,OAAO,gBAAgB;GAGhD;EAM+C,CAAkB,CAAC,EAClE,EACF,CAAC;EACD,iBAAiB;GACf,IAAI;GACJ,MAAM;GAEN,MAAM;GAIN,YAAY,IAAI,IAAI,sBAAsB,YAAY,GAAG;EAC3D,CAAC;CACH,EACF;AACF"}
@@ -1,6 +1,4 @@
1
1
  import { DevToolbarApp } from "astro";
2
- //#region src/toolbar/index.d.ts
3
2
  declare const app: DevToolbarApp;
4
- //#endregion
5
3
  export { app as default };
6
4
  //# sourceMappingURL=index.d.ts.map
@@ -2,7 +2,7 @@ import { render } from "preact";
2
2
  import { defineToolbarApp } from "astro/toolbar";
3
3
  import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks";
4
4
  import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
5
- //#region src/toolbar/styles.tsx
5
+ // src/toolbar/styles.tsx
6
6
  const styles = `
7
7
  :host astro-dev-toolbar-window {
8
8
  max-height: calc(100vh - 80px);
@@ -33,8 +33,7 @@ const styles = `
33
33
  transition: max-width 0.1s;
34
34
  }
35
35
  `;
36
- //#endregion
37
- //#region src/toolbar/components/Summary.tsx
36
+ // src/toolbar/components/Summary.tsx
38
37
  function Summary({ children }) {
39
38
  return /* @__PURE__ */ jsx("summary", {
40
39
  style: {
@@ -45,8 +44,7 @@ function Summary({ children }) {
45
44
  children
46
45
  });
47
46
  }
48
- //#endregion
49
- //#region src/toolbar/components/ExternalLinkicon.tsx
47
+ // src/toolbar/components/ExternalLinkicon.tsx
50
48
  function ExternalLinkicon({ width = 27, height = 27, fill = "#020202" }) {
51
49
  return /* @__PURE__ */ jsx("span", {
52
50
  style: {
@@ -78,8 +76,7 @@ function ExternalLinkicon({ width = 27, height = 27, fill = "#020202" }) {
78
76
  })
79
77
  });
80
78
  }
81
- //#endregion
82
- //#region src/toolbar/components/LinkOrText.tsx
79
+ // src/toolbar/components/LinkOrText.tsx
83
80
  function LinkOrText({ maybeLinkText }) {
84
81
  if (maybeLinkText == null) return null;
85
82
  let url;
@@ -102,8 +99,7 @@ function LinkOrText({ maybeLinkText }) {
102
99
  ]
103
100
  });
104
101
  }
105
- //#endregion
106
- //#region src/toolbar/hooks/useMetaTagInfo.tsx
102
+ // src/toolbar/hooks/useMetaTagInfo.tsx
107
103
  const useHeadObserver = () => {
108
104
  const [_generation, setGeneration] = useState(0);
109
105
  const forceRerender = () => setGeneration((old) => old + 1);
@@ -128,8 +124,7 @@ function useMetaTagInfo() {
128
124
  }, [headRef]);
129
125
  return Array.from(opengraphMetaTags).map((tag) => [tag.getAttribute("content"), tag.getAttribute("property")]);
130
126
  }
131
- //#endregion
132
- //#region src/toolbar/components/MetaTags.tsx
127
+ // src/toolbar/components/MetaTags.tsx
133
128
  function MetaTags() {
134
129
  const tags = useMetaTagInfo();
135
130
  return /* @__PURE__ */ jsx("dl", {
@@ -158,8 +153,7 @@ function MetaTagContent({ tag }) {
158
153
  children: /* @__PURE__ */ jsx(LinkOrText, { maybeLinkText: content })
159
154
  })] });
160
155
  }
161
- //#endregion
162
- //#region src/toolbar/hooks/useHoverState.tsx
156
+ // src/toolbar/hooks/useHoverState.tsx
163
157
  function useHoverState(setHoverState) {
164
158
  const ref = useRef(null);
165
159
  useEffect(() => {
@@ -171,8 +165,7 @@ function useHoverState(setHoverState) {
171
165
  }, [setHoverState]);
172
166
  return ref;
173
167
  }
174
- //#endregion
175
- //#region src/toolbar/hooks/useImageURL.tsx
168
+ // src/toolbar/hooks/useImageURL.tsx
176
169
  function useImageURL() {
177
170
  const imageUrl = useImageURLIfAvailable();
178
171
  if (imageUrl == null) throw new Error(`Shouldn't be rendering this component without an image URL`);
@@ -184,8 +177,7 @@ function useImageURLIfAvailable() {
184
177
  });
185
178
  return imageUrlRef;
186
179
  }
187
- //#endregion
188
- //#region src/toolbar/components/Image.tsx
180
+ // src/toolbar/components/Image.tsx
189
181
  function Image({ imageSize, handleLoadError }) {
190
182
  const imageUrl = useImageURL();
191
183
  return /* @__PURE__ */ jsx("div", {
@@ -206,13 +198,11 @@ function Image({ imageSize, handleLoadError }) {
206
198
  })
207
199
  });
208
200
  }
209
- //#endregion
210
- //#region src/toolbar/components/ZoomLabel.tsx
201
+ // src/toolbar/components/ZoomLabel.tsx
211
202
  function ZoomLabel({ imageSize }) {
212
203
  return `${(imageSize / 100).toLocaleString(void 0, { minimumFractionDigits: 2 })}x`;
213
204
  }
214
- //#endregion
215
- //#region src/toolbar/components/ZoomButton.tsx
205
+ // src/toolbar/components/ZoomButton.tsx
216
206
  function ZoomButton({ value, imageSize, setImageSize }) {
217
207
  return /* @__PURE__ */ jsx("astro-dev-toolbar-button", {
218
208
  size: "small",
@@ -227,8 +217,7 @@ function ZoomButton({ value, imageSize, setImageSize }) {
227
217
  children: /* @__PURE__ */ jsx(ZoomLabel, { imageSize: value })
228
218
  });
229
219
  }
230
- //#endregion
231
- //#region src/toolbar/components/ToolbarSection.tsx
220
+ // src/toolbar/components/ToolbarSection.tsx
232
221
  function ToolbarSection({ icon, children }) {
233
222
  return /* @__PURE__ */ jsxs("div", {
234
223
  style: {
@@ -247,8 +236,7 @@ function ToolbarSection({ icon, children }) {
247
236
  }), children]
248
237
  });
249
238
  }
250
- //#endregion
251
- //#region src/toolbar/components/ImageZoomToolbar.tsx
239
+ // src/toolbar/components/ImageZoomToolbar.tsx
252
240
  function ImageZoomToolbar({ isHovered, imageSize, setImageSize }) {
253
241
  return /* @__PURE__ */ jsx(ToolbarSection, {
254
242
  icon: /* @__PURE__ */ jsx("astro-dev-toolbar-icon", { icon: "gear" }),
@@ -280,8 +268,7 @@ function ImageZoomToolbar({ isHovered, imageSize, setImageSize }) {
280
268
  ] })
281
269
  });
282
270
  }
283
- //#endregion
284
- //#region src/toolbar/components/CopyImageUrlButton.tsx
271
+ // src/toolbar/components/CopyImageUrlButton.tsx
285
272
  function CopyImageUrlButton() {
286
273
  const imageUrl = useImageURL();
287
274
  const [wasRecentlyClicked, setWasRecentlyClicked] = useState(false);
@@ -312,8 +299,7 @@ function CopyImageUrlButton() {
312
299
  })
313
300
  });
314
301
  }
315
- //#endregion
316
- //#region src/toolbar/components/ImageSection.tsx
302
+ // src/toolbar/components/ImageSection.tsx
317
303
  function ImageSection({ isHovered, handleLoadError }) {
318
304
  const [imageSize, setImageSize] = useState(100);
319
305
  return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Image, {
@@ -334,8 +320,7 @@ function ImageSection({ isHovered, handleLoadError }) {
334
320
  })]
335
321
  })] });
336
322
  }
337
- //#endregion
338
- //#region src/toolbar/components/Error.tsx
323
+ // src/toolbar/components/Error.tsx
339
324
  function Error$1({ message, icon }) {
340
325
  return /* @__PURE__ */ jsxs("div", {
341
326
  style: {
@@ -356,13 +341,11 @@ function Error$1({ message, icon }) {
356
341
  ]
357
342
  });
358
343
  }
359
- //#endregion
360
- //#region src/toolbar/components/getRelativeUrl.tsx
344
+ // src/toolbar/components/getRelativeUrl.tsx
361
345
  function getRelativeUrl(absoluteUrl) {
362
346
  return new URL(absoluteUrl).pathname;
363
347
  }
364
- //#endregion
365
- //#region src/toolbar/components/ToolbarApp.tsx
348
+ // src/toolbar/components/ToolbarApp.tsx
366
349
  function ToolbarApp() {
367
350
  const [isImageDetailsHovered, setIsImageDetailsHovered] = useState(false);
368
351
  const imageDetailsRef = useHoverState(setIsImageDetailsHovered);
@@ -386,13 +369,11 @@ function ToolbarApp() {
386
369
  })]
387
370
  }), /* @__PURE__ */ jsxs("details", { children: [/* @__PURE__ */ jsx(Summary, { children: "Meta Tags" }), /* @__PURE__ */ jsx(MetaTags, {})] })] });
388
371
  }
389
- //#endregion
390
- //#region src/toolbar/components/ToolbarAppWindow.tsx
372
+ // src/toolbar/components/ToolbarAppWindow.tsx
391
373
  function ToolbarAppWindow() {
392
374
  return /* @__PURE__ */ jsxs("astro-dev-toolbar-window", { children: [/* @__PURE__ */ jsx("style", { children: styles }), /* @__PURE__ */ jsx(ToolbarApp, {})] });
393
375
  }
394
- //#endregion
395
- //#region src/toolbar/index.tsx
376
+ // src/toolbar/index.tsx
396
377
  const SESSION_KEY_OPEN = "@altano/astro-opengraph/toolbar:is-open";
397
378
  const app = defineToolbarApp({ init(canvas, app) {
398
379
  app.onToggled((event) => {
@@ -407,7 +388,6 @@ const app = defineToolbarApp({ init(canvas, app) {
407
388
  });
408
389
  if (sessionStorage.getItem(SESSION_KEY_OPEN) != null) app.toggleState({ state: true });
409
390
  } });
410
- //#endregion
411
391
  export { app as default };
412
392
 
413
393
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["Error","Error"],"sources":["../../src/toolbar/styles.tsx","../../src/toolbar/components/Summary.tsx","../../src/toolbar/components/ExternalLinkicon.tsx","../../src/toolbar/components/LinkOrText.tsx","../../src/toolbar/hooks/useMetaTagInfo.tsx","../../src/toolbar/components/MetaTags.tsx","../../src/toolbar/hooks/useHoverState.tsx","../../src/toolbar/hooks/useImageURL.tsx","../../src/toolbar/components/Image.tsx","../../src/toolbar/components/ZoomLabel.tsx","../../src/toolbar/components/ZoomButton.tsx","../../src/toolbar/components/ToolbarSection.tsx","../../src/toolbar/components/ImageZoomToolbar.tsx","../../src/toolbar/components/CopyImageUrlButton.tsx","../../src/toolbar/components/ImageSection.tsx","../../src/toolbar/components/Error.tsx","../../src/toolbar/components/getRelativeUrl.tsx","../../src/toolbar/components/ToolbarApp.tsx","../../src/toolbar/components/ToolbarAppWindow.tsx","../../src/toolbar/index.tsx"],"sourcesContent":["export const styles = /* css */ `\n :host astro-dev-toolbar-window {\n max-height: calc(100vh - 80px);\n overflow-y: auto;\n }\n\n button {\n background: none;\n color: inherit;\n border: none;\n font: inherit;\n cursor: pointer;\n outline: inherit;\n }\n\n details {\n margin-block-end: 10px;\n }\n details:last-of-type {\n margin-block-end: 0;\n }\n\n details[open] summary, .image {\n margin-block-end: 7px;\n }\n\n .image img {\n transition: max-width 0.1s;\n }\n`;\n","import type Preact from \"preact\";\n\nexport function Summary({\n children,\n}: {\n children: string;\n}): Preact.JSX.Element {\n return (\n <summary\n style={{\n cursor: \"pointer\",\n fontWeight: 700,\n color: \"white\",\n }}\n >\n {children}\n </summary>\n );\n}\n","import type Preact from \"preact\";\n\nexport function ExternalLinkicon({\n width = 27,\n height = 27,\n fill = \"#020202\",\n}: {\n width?: number;\n height?: number;\n fill?: string;\n}): Preact.JSX.Element {\n return (\n <span\n style={{\n display: \"inline-block\",\n width,\n height,\n }}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 120 120\">\n <path d=\"M120.09 16.696H60.256V.096L120.09.09z\" fill={fill} />\n <path\n d=\"M57.99 48.64l42.573-42.574 13.475 13.475-42.574 42.58z\"\n fill={fill}\n />\n <path\n d=\"M119.98.107l.02 59.83-16.59.013-.02-59.846zM3 23.5h17v87H3zm83.49 52.56h17V113h-17z\"\n fill={fill}\n />\n <path d=\"M3 16.692h40.655v17H3zM3 96h100.49v17H3z\" fill={fill} />\n </svg>\n </span>\n );\n}\n","import type Preact from \"preact\";\nimport { ExternalLinkicon } from \"./ExternalLinkicon.js\";\n\ntype LinkOrTextType = Preact.JSX.Element | string | null;\n\nexport function LinkOrText({\n maybeLinkText,\n}: {\n maybeLinkText: string | null;\n}): LinkOrTextType {\n if (maybeLinkText == null) {\n return null;\n }\n // Only the parse goes in the try. Constructing JSX inside a try/catch doesn't\n // do what it looks like it does -- React renders the element later, so render\n // errors escape the catch (react-hooks/error-boundaries).\n let url: URL;\n try {\n url = new URL(maybeLinkText);\n } catch (_) {\n return maybeLinkText;\n }\n return (\n <a href={url.toString()} target=\"_blank\">\n {maybeLinkText} <ExternalLinkicon width={10} height={10} fill=\"white\" />\n </a>\n );\n}\n","import { useEffect, useMemo, useRef, useState } from \"preact/hooks\";\n\nexport type MetaTagInfo = [content: string | null, property: string | null];\n\nconst useHeadObserver = (): React.RefObject<HTMLHeadElement | null> => {\n const [_generation, setGeneration] = useState<number>(0);\n const forceRerender = (): void => setGeneration((old) => old + 1);\n const headRef = useRef(document.querySelector(\"head\"));\n\n // useEffect(() => {\n // console.log({ generation });\n // }, [generation]);\n\n useEffect(() => {\n // console.log({ \"headRef.current\": headRef.current });\n if (headRef.current == null) {\n // assume we must have a head by now, and if we don't, we will never get\n // one.\n return;\n }\n const observer = new MutationObserver(forceRerender);\n observer.observe(headRef.current, {\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n });\n return () => observer.disconnect();\n }, []);\n\n return headRef;\n};\n\nexport function useMetaTagInfo(): MetaTagInfo[] {\n const headRef = useHeadObserver();\n // TODO: This works because the MutationObserver above forces a re-render on\n // every <head> change, but the supported shape for this is\n // useSyncExternalStore.\n const opengraphMetaTags = useMemo(() => {\n return headRef?.current?.querySelectorAll(\"meta[property^='og:']\") ?? [];\n }, [headRef]);\n\n // console.log({\n // opengraphMetaTags: opengraphMetaTags,\n // opengraphMetaTagsLength: opengraphMetaTags.length,\n // });\n return Array.from(opengraphMetaTags).map((tag: Element): MetaTagInfo => [\n tag.getAttribute(\"content\"),\n tag.getAttribute(\"property\"),\n ]);\n}\n","import type Preact from \"preact\";\nimport { LinkOrText } from \"./LinkOrText.js\";\nimport { useMetaTagInfo, type MetaTagInfo } from \"../hooks/useMetaTagInfo.js\";\n\nexport function MetaTags(): Preact.JSX.Element {\n const tags = useMetaTagInfo();\n\n return (\n <dl\n data-testid=\"astro-opengraph-toolbar\"\n style={{\n margin: 0,\n display: \"grid\",\n gridTemplateColumns: \"max-content 1fr\",\n gap: 7,\n columnGap: 13,\n }}\n >\n {tags.map((tag) => (\n <MetaTagContent key={tag[1]} tag={tag} />\n ))}\n </dl>\n );\n}\n\nfunction MetaTagContent({ tag }: { tag: MetaTagInfo }): Preact.JSX.Element {\n const [content, property] = tag;\n return (\n <>\n <dt\n style={{\n color: \"white\",\n textAlign: \"right\",\n fontWeight: 500,\n }}\n >\n {property}\n </dt>\n <dd style={{ margin: 0 }}>\n <LinkOrText maybeLinkText={content} />\n </dd>\n </>\n );\n}\n","import type Preact from \"preact\";\nimport { useRef, useEffect } from \"preact/hooks\";\n\nexport function useHoverState<TElement extends HTMLElement>(\n setHoverState: (isHover: boolean) => void,\n): Preact.RefObject<TElement> {\n const ref = useRef<TElement>(null);\n\n useEffect(() => {\n const controller = new AbortController();\n const { signal } = controller;\n ref.current?.addEventListener(\"mouseenter\", () => setHoverState(true), {\n signal,\n });\n ref.current?.addEventListener(\"mouseleave\", () => setHoverState(false), {\n signal,\n });\n\n return () => controller.abort();\n }, [setHoverState]);\n\n return ref;\n}\n","import { useState } from \"preact/hooks\";\n\nexport function useImageURL(): string {\n const imageUrl = useImageURLIfAvailable();\n if (imageUrl == null) {\n throw new Error(\n `Shouldn't be rendering this component without an image URL`,\n );\n }\n return imageUrl;\n}\n\nexport function useImageURLIfAvailable(): string | null {\n const [imageUrlRef] = useState(() => {\n const meta = document.querySelector('meta[property=\"og:image\"]');\n return meta?.getAttribute(\"content\") ?? null;\n });\n return imageUrlRef;\n}\n","import type Preact from \"preact\";\nimport { useImageURL } from \"../hooks/useImageURL.js\";\n\nexport function Image({\n imageSize,\n handleLoadError,\n}: {\n imageSize: number;\n handleLoadError: () => void;\n}): Preact.JSX.Element {\n const imageUrl = useImageURL();\n return (\n <div className=\"image\">\n <a href={imageUrl} target=\"_blank\" title=\"Open image in new tab\">\n <img\n onError={handleLoadError}\n alt=\"Open Graph\"\n src={imageUrl}\n style={{\n maxHeight: \"100%\",\n maxWidth: `${imageSize}%`,\n }}\n />\n </a>\n </div>\n );\n}\n","export function ZoomLabel({ imageSize }: { imageSize: number }): string {\n const formattedNumber = (imageSize / 100).toLocaleString(undefined, {\n minimumFractionDigits: 2,\n });\n return `${formattedNumber}x`;\n}\n","import type Preact from \"preact\";\nimport { ZoomLabel } from \"./ZoomLabel.js\";\n\nexport function ZoomButton({\n value,\n imageSize,\n setImageSize,\n}: {\n value: number;\n imageSize: number;\n setImageSize: (size: number) => void;\n}): Preact.JSX.Element {\n const isSelected = value === imageSize;\n return (\n <astro-dev-toolbar-button\n size=\"small\"\n style={{ padding: 0, margin: 0 }}\n buttonStyle={isSelected ? \"gray\" : \"ghost\"}\n className=\"zoom-button\"\n role=\"radio\"\n onClick={() => setImageSize(value)}\n >\n <ZoomLabel imageSize={value} />\n </astro-dev-toolbar-button>\n );\n}\n","import type { ComponentChildren } from \"preact\";\nimport type Preact from \"preact\";\n\nexport function ToolbarSection({\n icon,\n children,\n}: {\n icon: Preact.JSX.Element;\n children: ComponentChildren;\n}): Preact.JSX.Element {\n return (\n <div\n style={{\n fontSize: 12,\n display: \"flex\",\n alignItems: \"center\",\n columnGap: 5,\n }}\n >\n <div\n style={{\n display: \"inline-block\",\n width: 12,\n height: 12,\n }}\n >\n {icon}\n </div>\n {children}\n </div>\n );\n}\n","import type Preact from \"preact\";\nimport { ZoomButton } from \"./ZoomButton.js\";\nimport { ToolbarSection } from \"./ToolbarSection.js\";\n\nexport function ImageZoomToolbar({\n isHovered,\n imageSize,\n setImageSize,\n}: {\n isHovered: boolean;\n imageSize: number;\n setImageSize: (size: number) => void;\n}): Preact.JSX.Element {\n return (\n <ToolbarSection icon={<astro-dev-toolbar-icon icon=\"gear\" />}>\n {!isHovered ? (\n <ZoomButton\n value={imageSize}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n ) : (\n <>\n <ZoomButton\n value={25}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n <ZoomButton\n value={50}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n <ZoomButton\n value={75}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n <ZoomButton\n value={100}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n </>\n )}\n </ToolbarSection>\n );\n}\n","import { useState, useEffect, useCallback } from \"preact/hooks\";\nimport type Preact from \"preact\";\nimport type { DevToolbarButton } from \"astro/runtime/client/dev-toolbar/ui-library/button.js\";\nimport { useImageURL } from \"../hooks/useImageURL.js\";\nimport { ToolbarSection } from \"./ToolbarSection.js\";\n\nexport function CopyImageUrlButton(): Preact.JSX.Element {\n const imageUrl = useImageURL();\n const [wasRecentlyClicked, setWasRecentlyClicked] = useState(false);\n\n useEffect(() => {\n if (!wasRecentlyClicked) return;\n const timer = setTimeout(() => setWasRecentlyClicked(false), 3_000);\n return () => clearTimeout(timer);\n }, [wasRecentlyClicked]);\n\n const handleClick: Preact.MouseEventHandler<DevToolbarButton> = useCallback(\n (evt) => {\n // Copy the text inside the text field\n void navigator.clipboard.writeText(imageUrl);\n setWasRecentlyClicked(true);\n evt.stopPropagation();\n evt.preventDefault();\n },\n [imageUrl],\n );\n\n return (\n <ToolbarSection icon={<astro-dev-toolbar-icon icon=\"copy\" />}>\n <div style={{ display: \"flex\", alignItems: \"center\" }}>\n <astro-dev-toolbar-button\n size=\"small\"\n buttonStyle=\"gray\"\n onClick={handleClick}\n >\n {wasRecentlyClicked ? \"Copied to clipboard\" : \"Copy image URL\"}\n </astro-dev-toolbar-button>\n </div>\n </ToolbarSection>\n );\n}\n","import { Image } from \"./Image.js\";\nimport { ImageZoomToolbar } from \"./ImageZoomToolbar.js\";\nimport { CopyImageUrlButton } from \"./CopyImageUrlButton.js\";\nimport type Preact from \"preact\";\nimport { useState } from \"preact/hooks\";\n\nexport function ImageSection({\n isHovered,\n handleLoadError,\n}: {\n isHovered: boolean;\n handleLoadError: () => void;\n}): Preact.JSX.Element {\n const [imageSize, setImageSize] = useState(100);\n\n return (\n <>\n <Image imageSize={imageSize} handleLoadError={handleLoadError} />\n <div\n data-testid=\"image-section-toolbar\"\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n columnGap: 15,\n }}\n >\n <CopyImageUrlButton />\n <ImageZoomToolbar\n isHovered={isHovered}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n </div>\n </>\n );\n}\n","import type { Icon } from \"astro/runtime/client/dev-toolbar/ui-library/icons.js\";\nimport type Preact from \"preact\";\n\nexport function Error({\n message,\n icon,\n}: {\n message: string;\n icon: Icon;\n}): Preact.JSX.Element {\n return (\n <div\n style={{\n display: \"flex\",\n gap: 10,\n alignItems: \"center\",\n }}\n >\n <astro-dev-toolbar-icon style={{ width: 24, height: 24 }} icon={icon} />{\" \"}\n {message}\n </div>\n );\n}\n","export function getRelativeUrl(absoluteUrl: string): string {\n const url = new URL(absoluteUrl);\n return url.pathname;\n}\n","import type Preact from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { Summary } from \"./Summary.js\";\nimport { MetaTags } from \"./MetaTags.js\";\nimport { useHoverState } from \"../hooks/useHoverState.js\";\nimport { useImageURLIfAvailable } from \"../hooks/useImageURL.js\";\nimport { ImageSection } from \"./ImageSection.js\";\nimport { Error } from \"./Error.js\";\nimport { getRelativeUrl } from \"./getRelativeUrl.js\";\n\nexport function ToolbarApp(): Preact.JSX.Element {\n const [isImageDetailsHovered, setIsImageDetailsHovered] = useState(false);\n const imageDetailsRef = useHoverState<HTMLDetailsElement>(\n setIsImageDetailsHovered,\n );\n const imageUrl = useImageURLIfAvailable();\n const [imageLoadStatus, setImageLoadStatus] = useState<\"pending\" | \"error\">(\n \"pending\",\n );\n\n if (imageUrl == null) {\n return (\n <Error icon=\"warning\" message=\"No Open Graph image found on this page\" />\n );\n } else if (imageLoadStatus === \"error\") {\n return (\n <Error\n icon=\"bug\"\n message={`Error loading image at ${getRelativeUrl(imageUrl)}`}\n />\n );\n }\n\n return (\n <>\n <details open className=\"image\" ref={imageDetailsRef}>\n <Summary>Image</Summary>\n <ImageSection\n isHovered={isImageDetailsHovered}\n handleLoadError={() => setImageLoadStatus(\"error\")}\n />\n </details>\n\n <details>\n <Summary>Meta Tags</Summary>\n <MetaTags />\n </details>\n </>\n );\n}\n","import type Preact from \"preact\";\nimport { styles } from \"../styles.js\";\nimport { ToolbarApp } from \"./ToolbarApp.js\";\n\nexport function ToolbarAppWindow(): Preact.JSX.Element {\n return (\n <astro-dev-toolbar-window>\n <style>{styles}</style>\n <ToolbarApp />\n </astro-dev-toolbar-window>\n );\n}\n","import { render } from \"preact\";\n\nimport { defineToolbarApp } from \"astro/toolbar\";\nimport { ToolbarAppWindow } from \"./components/ToolbarAppWindow.js\";\nimport type { DevToolbarApp } from \"astro\";\n\nconst SESSION_KEY_OPEN = \"@altano/astro-opengraph/toolbar:is-open\";\n\nconst app: DevToolbarApp = defineToolbarApp({\n init(canvas, app) {\n app.onToggled((event) => {\n if (event.state) {\n sessionStorage.setItem(SESSION_KEY_OPEN, \"true\");\n render(<ToolbarAppWindow />, canvas);\n } else {\n sessionStorage.removeItem(SESSION_KEY_OPEN);\n }\n });\n\n app.toggleNotification({\n state: document.querySelector('meta[property=\"og:image\"]') != null,\n level: \"info\",\n });\n\n if (sessionStorage.getItem(SESSION_KEY_OPEN) != null) {\n app.toggleState({ state: true });\n }\n },\n});\n\nexport default app;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["Error","Error"],"sources":["../../src/toolbar/styles.tsx","../../src/toolbar/components/Summary.tsx","../../src/toolbar/components/ExternalLinkicon.tsx","../../src/toolbar/components/LinkOrText.tsx","../../src/toolbar/hooks/useMetaTagInfo.tsx","../../src/toolbar/components/MetaTags.tsx","../../src/toolbar/hooks/useHoverState.tsx","../../src/toolbar/hooks/useImageURL.tsx","../../src/toolbar/components/Image.tsx","../../src/toolbar/components/ZoomLabel.tsx","../../src/toolbar/components/ZoomButton.tsx","../../src/toolbar/components/ToolbarSection.tsx","../../src/toolbar/components/ImageZoomToolbar.tsx","../../src/toolbar/components/CopyImageUrlButton.tsx","../../src/toolbar/components/ImageSection.tsx","../../src/toolbar/components/Error.tsx","../../src/toolbar/components/getRelativeUrl.tsx","../../src/toolbar/components/ToolbarApp.tsx","../../src/toolbar/components/ToolbarAppWindow.tsx","../../src/toolbar/index.tsx"],"sourcesContent":["export const styles = /* css */ `\n :host astro-dev-toolbar-window {\n max-height: calc(100vh - 80px);\n overflow-y: auto;\n }\n\n button {\n background: none;\n color: inherit;\n border: none;\n font: inherit;\n cursor: pointer;\n outline: inherit;\n }\n\n details {\n margin-block-end: 10px;\n }\n details:last-of-type {\n margin-block-end: 0;\n }\n\n details[open] summary, .image {\n margin-block-end: 7px;\n }\n\n .image img {\n transition: max-width 0.1s;\n }\n`;\n","import type Preact from \"preact\";\n\nexport function Summary({\n children,\n}: {\n children: string;\n}): Preact.JSX.Element {\n return (\n <summary\n style={{\n cursor: \"pointer\",\n fontWeight: 700,\n color: \"white\",\n }}\n >\n {children}\n </summary>\n );\n}\n","import type Preact from \"preact\";\n\nexport function ExternalLinkicon({\n width = 27,\n height = 27,\n fill = \"#020202\",\n}: {\n width?: number;\n height?: number;\n fill?: string;\n}): Preact.JSX.Element {\n return (\n <span\n style={{\n display: \"inline-block\",\n width,\n height,\n }}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 120 120\">\n <path d=\"M120.09 16.696H60.256V.096L120.09.09z\" fill={fill} />\n <path\n d=\"M57.99 48.64l42.573-42.574 13.475 13.475-42.574 42.58z\"\n fill={fill}\n />\n <path\n d=\"M119.98.107l.02 59.83-16.59.013-.02-59.846zM3 23.5h17v87H3zm83.49 52.56h17V113h-17z\"\n fill={fill}\n />\n <path d=\"M3 16.692h40.655v17H3zM3 96h100.49v17H3z\" fill={fill} />\n </svg>\n </span>\n );\n}\n","import type Preact from \"preact\";\nimport { ExternalLinkicon } from \"./ExternalLinkicon.js\";\n\ntype LinkOrTextType = Preact.JSX.Element | string | null;\n\nexport function LinkOrText({\n maybeLinkText,\n}: {\n maybeLinkText: string | null;\n}): LinkOrTextType {\n if (maybeLinkText == null) {\n return null;\n }\n // Only the parse goes in the try. Constructing JSX inside a try/catch doesn't\n // do what it looks like it does -- React renders the element later, so render\n // errors escape the catch (react-hooks/error-boundaries).\n let url: URL;\n try {\n url = new URL(maybeLinkText);\n } catch (_) {\n return maybeLinkText;\n }\n return (\n <a href={url.toString()} target=\"_blank\">\n {maybeLinkText} <ExternalLinkicon width={10} height={10} fill=\"white\" />\n </a>\n );\n}\n","import { useEffect, useMemo, useRef, useState } from \"preact/hooks\";\n\nexport type MetaTagInfo = [content: string | null, property: string | null];\n\nconst useHeadObserver = (): React.RefObject<HTMLHeadElement | null> => {\n const [_generation, setGeneration] = useState<number>(0);\n const forceRerender = (): void => setGeneration((old) => old + 1);\n const headRef = useRef(document.querySelector(\"head\"));\n\n // useEffect(() => {\n // console.log({ generation });\n // }, [generation]);\n\n useEffect(() => {\n // console.log({ \"headRef.current\": headRef.current });\n if (headRef.current == null) {\n // assume we must have a head by now, and if we don't, we will never get\n // one.\n return;\n }\n const observer = new MutationObserver(forceRerender);\n observer.observe(headRef.current, {\n attributes: true,\n characterData: true,\n childList: true,\n subtree: true,\n });\n return () => observer.disconnect();\n }, []);\n\n return headRef;\n};\n\nexport function useMetaTagInfo(): MetaTagInfo[] {\n const headRef = useHeadObserver();\n // TODO: This works because the MutationObserver above forces a re-render on\n // every <head> change, but the supported shape for this is\n // useSyncExternalStore.\n const opengraphMetaTags = useMemo(() => {\n return headRef?.current?.querySelectorAll(\"meta[property^='og:']\") ?? [];\n }, [headRef]);\n\n // console.log({\n // opengraphMetaTags: opengraphMetaTags,\n // opengraphMetaTagsLength: opengraphMetaTags.length,\n // });\n return Array.from(opengraphMetaTags).map((tag: Element): MetaTagInfo => [\n tag.getAttribute(\"content\"),\n tag.getAttribute(\"property\"),\n ]);\n}\n","import type Preact from \"preact\";\nimport { LinkOrText } from \"./LinkOrText.js\";\nimport { useMetaTagInfo, type MetaTagInfo } from \"../hooks/useMetaTagInfo.js\";\n\nexport function MetaTags(): Preact.JSX.Element {\n const tags = useMetaTagInfo();\n\n return (\n <dl\n data-testid=\"astro-opengraph-toolbar\"\n style={{\n margin: 0,\n display: \"grid\",\n gridTemplateColumns: \"max-content 1fr\",\n gap: 7,\n columnGap: 13,\n }}\n >\n {tags.map((tag) => (\n <MetaTagContent key={tag[1]} tag={tag} />\n ))}\n </dl>\n );\n}\n\nfunction MetaTagContent({ tag }: { tag: MetaTagInfo }): Preact.JSX.Element {\n const [content, property] = tag;\n return (\n <>\n <dt\n style={{\n color: \"white\",\n textAlign: \"right\",\n fontWeight: 500,\n }}\n >\n {property}\n </dt>\n <dd style={{ margin: 0 }}>\n <LinkOrText maybeLinkText={content} />\n </dd>\n </>\n );\n}\n","import type Preact from \"preact\";\nimport { useRef, useEffect } from \"preact/hooks\";\n\nexport function useHoverState<TElement extends HTMLElement>(\n setHoverState: (isHover: boolean) => void,\n): Preact.RefObject<TElement | null> {\n const ref = useRef<TElement>(null);\n\n useEffect(() => {\n const controller = new AbortController();\n const { signal } = controller;\n ref.current?.addEventListener(\"mouseenter\", () => setHoverState(true), {\n signal,\n });\n ref.current?.addEventListener(\"mouseleave\", () => setHoverState(false), {\n signal,\n });\n\n return () => controller.abort();\n }, [setHoverState]);\n\n return ref;\n}\n","import { useState } from \"preact/hooks\";\n\nexport function useImageURL(): string {\n const imageUrl = useImageURLIfAvailable();\n if (imageUrl == null) {\n throw new Error(\n `Shouldn't be rendering this component without an image URL`,\n );\n }\n return imageUrl;\n}\n\nexport function useImageURLIfAvailable(): string | null {\n const [imageUrlRef] = useState(() => {\n const meta = document.querySelector('meta[property=\"og:image\"]');\n return meta?.getAttribute(\"content\") ?? null;\n });\n return imageUrlRef;\n}\n","import type Preact from \"preact\";\nimport { useImageURL } from \"../hooks/useImageURL.js\";\n\nexport function Image({\n imageSize,\n handleLoadError,\n}: {\n imageSize: number;\n handleLoadError: () => void;\n}): Preact.JSX.Element {\n const imageUrl = useImageURL();\n return (\n <div className=\"image\">\n <a href={imageUrl} target=\"_blank\" title=\"Open image in new tab\">\n <img\n onError={handleLoadError}\n alt=\"Open Graph\"\n src={imageUrl}\n style={{\n maxHeight: \"100%\",\n maxWidth: `${imageSize}%`,\n }}\n />\n </a>\n </div>\n );\n}\n","export function ZoomLabel({ imageSize }: { imageSize: number }): string {\n const formattedNumber = (imageSize / 100).toLocaleString(undefined, {\n minimumFractionDigits: 2,\n });\n return `${formattedNumber}x`;\n}\n","import type Preact from \"preact\";\nimport { ZoomLabel } from \"./ZoomLabel.js\";\n\nexport function ZoomButton({\n value,\n imageSize,\n setImageSize,\n}: {\n value: number;\n imageSize: number;\n setImageSize: (size: number) => void;\n}): Preact.JSX.Element {\n const isSelected = value === imageSize;\n return (\n <astro-dev-toolbar-button\n size=\"small\"\n style={{ padding: 0, margin: 0 }}\n buttonStyle={isSelected ? \"gray\" : \"ghost\"}\n className=\"zoom-button\"\n role=\"radio\"\n onClick={() => setImageSize(value)}\n >\n <ZoomLabel imageSize={value} />\n </astro-dev-toolbar-button>\n );\n}\n","import type { ComponentChildren } from \"preact\";\nimport type Preact from \"preact\";\n\nexport function ToolbarSection({\n icon,\n children,\n}: {\n icon: Preact.JSX.Element;\n children: ComponentChildren;\n}): Preact.JSX.Element {\n return (\n <div\n style={{\n fontSize: 12,\n display: \"flex\",\n alignItems: \"center\",\n columnGap: 5,\n }}\n >\n <div\n style={{\n display: \"inline-block\",\n width: 12,\n height: 12,\n }}\n >\n {icon}\n </div>\n {children}\n </div>\n );\n}\n","import type Preact from \"preact\";\nimport { ZoomButton } from \"./ZoomButton.js\";\nimport { ToolbarSection } from \"./ToolbarSection.js\";\n\nexport function ImageZoomToolbar({\n isHovered,\n imageSize,\n setImageSize,\n}: {\n isHovered: boolean;\n imageSize: number;\n setImageSize: (size: number) => void;\n}): Preact.JSX.Element {\n return (\n <ToolbarSection icon={<astro-dev-toolbar-icon icon=\"gear\" />}>\n {!isHovered ? (\n <ZoomButton\n value={imageSize}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n ) : (\n <>\n <ZoomButton\n value={25}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n <ZoomButton\n value={50}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n <ZoomButton\n value={75}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n <ZoomButton\n value={100}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n </>\n )}\n </ToolbarSection>\n );\n}\n","import { useState, useEffect, useCallback } from \"preact/hooks\";\nimport type Preact from \"preact\";\nimport type { DevToolbarButton } from \"astro/runtime/client/dev-toolbar/ui-library/button.js\";\nimport { useImageURL } from \"../hooks/useImageURL.js\";\nimport { ToolbarSection } from \"./ToolbarSection.js\";\n\nexport function CopyImageUrlButton(): Preact.JSX.Element {\n const imageUrl = useImageURL();\n const [wasRecentlyClicked, setWasRecentlyClicked] = useState(false);\n\n useEffect(() => {\n if (!wasRecentlyClicked) return;\n const timer = setTimeout(() => setWasRecentlyClicked(false), 3_000);\n return () => clearTimeout(timer);\n }, [wasRecentlyClicked]);\n\n const handleClick: Preact.MouseEventHandler<DevToolbarButton> = useCallback(\n (evt) => {\n // Copy the text inside the text field\n void navigator.clipboard.writeText(imageUrl);\n setWasRecentlyClicked(true);\n evt.stopPropagation();\n evt.preventDefault();\n },\n [imageUrl],\n );\n\n return (\n <ToolbarSection icon={<astro-dev-toolbar-icon icon=\"copy\" />}>\n <div style={{ display: \"flex\", alignItems: \"center\" }}>\n <astro-dev-toolbar-button\n size=\"small\"\n buttonStyle=\"gray\"\n onClick={handleClick}\n >\n {wasRecentlyClicked ? \"Copied to clipboard\" : \"Copy image URL\"}\n </astro-dev-toolbar-button>\n </div>\n </ToolbarSection>\n );\n}\n","import { Image } from \"./Image.js\";\nimport { ImageZoomToolbar } from \"./ImageZoomToolbar.js\";\nimport { CopyImageUrlButton } from \"./CopyImageUrlButton.js\";\nimport type Preact from \"preact\";\nimport { useState } from \"preact/hooks\";\n\nexport function ImageSection({\n isHovered,\n handleLoadError,\n}: {\n isHovered: boolean;\n handleLoadError: () => void;\n}): Preact.JSX.Element {\n const [imageSize, setImageSize] = useState(100);\n\n return (\n <>\n <Image imageSize={imageSize} handleLoadError={handleLoadError} />\n <div\n data-testid=\"image-section-toolbar\"\n style={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: \"center\",\n columnGap: 15,\n }}\n >\n <CopyImageUrlButton />\n <ImageZoomToolbar\n isHovered={isHovered}\n imageSize={imageSize}\n setImageSize={setImageSize}\n />\n </div>\n </>\n );\n}\n","import type { Icon } from \"astro/runtime/client/dev-toolbar/ui-library/icons.js\";\nimport type Preact from \"preact\";\n\nexport function Error({\n message,\n icon,\n}: {\n message: string;\n icon: Icon;\n}): Preact.JSX.Element {\n return (\n <div\n style={{\n display: \"flex\",\n gap: 10,\n alignItems: \"center\",\n }}\n >\n <astro-dev-toolbar-icon style={{ width: 24, height: 24 }} icon={icon} />{\" \"}\n {message}\n </div>\n );\n}\n","export function getRelativeUrl(absoluteUrl: string): string {\n const url = new URL(absoluteUrl);\n return url.pathname;\n}\n","import type Preact from \"preact\";\nimport { useState } from \"preact/hooks\";\nimport { Summary } from \"./Summary.js\";\nimport { MetaTags } from \"./MetaTags.js\";\nimport { useHoverState } from \"../hooks/useHoverState.js\";\nimport { useImageURLIfAvailable } from \"../hooks/useImageURL.js\";\nimport { ImageSection } from \"./ImageSection.js\";\nimport { Error } from \"./Error.js\";\nimport { getRelativeUrl } from \"./getRelativeUrl.js\";\n\nexport function ToolbarApp(): Preact.JSX.Element {\n const [isImageDetailsHovered, setIsImageDetailsHovered] = useState(false);\n const imageDetailsRef = useHoverState<HTMLDetailsElement>(\n setIsImageDetailsHovered,\n );\n const imageUrl = useImageURLIfAvailable();\n const [imageLoadStatus, setImageLoadStatus] = useState<\"pending\" | \"error\">(\n \"pending\",\n );\n\n if (imageUrl == null) {\n return (\n <Error icon=\"warning\" message=\"No Open Graph image found on this page\" />\n );\n } else if (imageLoadStatus === \"error\") {\n return (\n <Error\n icon=\"bug\"\n message={`Error loading image at ${getRelativeUrl(imageUrl)}`}\n />\n );\n }\n\n return (\n <>\n <details open className=\"image\" ref={imageDetailsRef}>\n <Summary>Image</Summary>\n <ImageSection\n isHovered={isImageDetailsHovered}\n handleLoadError={() => setImageLoadStatus(\"error\")}\n />\n </details>\n\n <details>\n <Summary>Meta Tags</Summary>\n <MetaTags />\n </details>\n </>\n );\n}\n","import type Preact from \"preact\";\nimport { styles } from \"../styles.js\";\nimport { ToolbarApp } from \"./ToolbarApp.js\";\n\nexport function ToolbarAppWindow(): Preact.JSX.Element {\n return (\n <astro-dev-toolbar-window>\n <style>{styles}</style>\n <ToolbarApp />\n </astro-dev-toolbar-window>\n );\n}\n","import { render } from \"preact\";\n\nimport { defineToolbarApp } from \"astro/toolbar\";\nimport { ToolbarAppWindow } from \"./components/ToolbarAppWindow.js\";\nimport type { DevToolbarApp } from \"astro\";\n\nconst SESSION_KEY_OPEN = \"@altano/astro-opengraph/toolbar:is-open\";\n\nconst app: DevToolbarApp = defineToolbarApp({\n init(canvas, app) {\n app.onToggled((event) => {\n if (event.state) {\n sessionStorage.setItem(SESSION_KEY_OPEN, \"true\");\n render(<ToolbarAppWindow />, canvas);\n } else {\n sessionStorage.removeItem(SESSION_KEY_OPEN);\n }\n });\n\n app.toggleNotification({\n state: document.querySelector('meta[property=\"og:image\"]') != null,\n level: \"info\",\n });\n\n if (sessionStorage.getItem(SESSION_KEY_OPEN) != null) {\n app.toggleState({ state: true });\n }\n },\n});\n\nexport default app;\n"],"mappings":"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"}
@@ -1,5 +1,4 @@
1
1
  import { SatoriOptions } from "satori";
2
- //#region src/types.d.ts
3
2
  export type ImageOptions = SatoriOptions;
4
3
  type FontWithBuffer = ImageOptions["fonts"][0];
5
4
  type FontWithPath = Omit<FontWithBuffer, "data"> & {
@@ -64,5 +63,5 @@ export type OpengraphImageConfigResolved = {
64
63
  componentMetaTagFallbacks: ComponentMetaTagFallbacks & MetaTagDefaults;
65
64
  command: Command;
66
65
  };
67
- //#endregion
68
- //# sourceMappingURL=types-5FZPWj11.d.ts.map
66
+ export {};
67
+ //# sourceMappingURL=types-BFKV60-c.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@altano/astro-opengraph",
3
- "version": "3.0.0",
3
+ "version": "3.1.1",
4
4
  "description": "Open Graph Tools for Astro",
5
5
  "keywords": [
6
6
  "astro",
@@ -41,39 +41,39 @@
41
41
  ],
42
42
  "dependencies": {
43
43
  "he": "^2.0.0",
44
- "satori": "^0.55.5",
44
+ "satori": "^0.63.2",
45
45
  "satori-html": "^0.3.2"
46
46
  },
47
47
  "devDependencies": {
48
- "@astrojs/check": "^0.9.10",
49
- "@astrojs/preact": "^6.0.5",
50
- "@astrojs/svelte": "^9.0.1",
51
- "@astrojs/vue": "^7.0.3",
48
+ "@astrojs/check": "^0.9.12",
49
+ "@astrojs/preact": "^6.1.1",
50
+ "@astrojs/svelte": "^9.1.2",
51
+ "@astrojs/vue": "^7.1.2",
52
52
  "@inox-tools/astro-tests": "^2.0.0",
53
53
  "@playwright/test": "1.59.1",
54
54
  "@types/he": "^1.2.3",
55
55
  "@types/jest-image-snapshot": "^6.4.2",
56
- "@types/node": "^26.6.4",
57
- "@vitest/coverage-v8": "^5.0.3",
58
- "astro": "^7.3.5",
56
+ "@types/node": "^26.6.6",
57
+ "@vitest/coverage-v8": "^5.1.0",
58
+ "astro": "^7.4.5",
59
59
  "depcheck": "^1.4.7",
60
60
  "jest-image-snapshot": "^6.5.2",
61
- "preact": "^10.29.7",
62
- "prettier": "3.9.9",
61
+ "preact": "^11.1.1",
62
+ "prettier": "3.9.10",
63
63
  "sharp": "^0.35.5",
64
- "svelte": "^5.57.1",
65
- "tsdown": "^0.23.0",
64
+ "svelte": "^5.57.3",
65
+ "tsdown": "^0.23.5",
66
66
  "typescript": "^6.0.3",
67
- "vite": "^8.3.2",
68
- "vitest": "^5.0.3",
69
- "vue": "^3.5.43",
67
+ "vite": "^8.3.5",
68
+ "vitest": "^5.1.0",
69
+ "vue": "^3.5.44",
70
70
  "zx": "^8.8.5",
71
71
  "@altano/assets": "0.0.1",
72
72
  "@altano/build-config": "0.0.1",
73
73
  "@altano/testing": "0.0.1",
74
- "@altano/tiny-async-pool": "4.0.3",
74
+ "@altano/tiny-async-pool": "4.0.4",
75
75
  "@altano/tsconfig": "0.0.1",
76
- "@altano/vitest-plugins": "2.0.0"
76
+ "@altano/vitest-plugins": "2.0.1"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "astro": "7.x.x",