diff --git a/astro.config.ts b/astro.config.ts index c4bf52f..ed4e822 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -1,8 +1,9 @@ import type { AstroIntegration } from "astro"; +import icon from "astro-icon"; import { defineConfig } from "astro/config"; import astrobook from "astrobook"; -const integrations: AstroIntegration[] = []; +const integrations: AstroIntegration[] = [icon()]; if (process.env.ASTROBOOK) { integrations.push(astrobook({ directory: "src/components" })); diff --git a/bun.lockb b/bun.lockb index 94591ff..78bfedb 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 3c4d18e..034bb14 100644 --- a/package.json +++ b/package.json @@ -13,13 +13,18 @@ "test:cov": "vitest run --coverage" }, "dependencies": { + "@cxa/astro-inline-svg": "0.5.1", + "@iconify-json/mingcute": "1.2.1", "astro": "4.16.10", + "astro-icon": "1.1.2", + "qrcode": "1.5.4", "typescript": "5.6.3" }, "devDependencies": { "@astrojs/check": "0.9.4", "@biomejs/biome": "1.9.4", "@types/node": "22.9.0", + "@types/qrcode": "1.5.5", "@vitest/coverage-v8": "2.1.4", "astrobook": "0.5.1", "vitest": "2.1.4" diff --git a/src/components/Homepage/Homepage.astro b/src/components/Homepage/Homepage.astro new file mode 100644 index 0000000..43e2ea6 --- /dev/null +++ b/src/components/Homepage/Homepage.astro @@ -0,0 +1,68 @@ +--- +import Svg from "@cxa/astro-inline-svg"; +import { Icon } from "astro-icon/components"; + +import "../../styles/global.css"; +import { generateQRCode } from "../../libs/qrcode.ts"; + +export type Props = { url: string }; +const props = Astro.props; + +const url = new URL(props.url); +const qrCode: string = await generateQRCode(props.url); +--- + + + +
+ + +
+
+ + diff --git a/src/components/Homepage/Homepage.stories.ts b/src/components/Homepage/Homepage.stories.ts new file mode 100644 index 0000000..5cffc9c --- /dev/null +++ b/src/components/Homepage/Homepage.stories.ts @@ -0,0 +1,11 @@ +import Homepage from "./Homepage.astro"; +import * as stories from "./story.ts"; + +export default { + title: "Homepage", + component: Homepage, +}; + +export const Domain = { args: stories.Domain }; +export const Path = { args: stories.Path }; +export const Japanese = { args: stories.Japanese }; diff --git a/src/components/Homepage/Homepage.test.ts b/src/components/Homepage/Homepage.test.ts new file mode 100644 index 0000000..613f3bf --- /dev/null +++ b/src/components/Homepage/Homepage.test.ts @@ -0,0 +1,23 @@ +import { experimental_AstroContainer as AstroContainer } from "astro/container"; +import { describe, expect, test } from "vitest"; + +import Homepage from "./Homepage.astro"; +import * as stories from "./story.ts"; + +describe("Homepage", () => { + for (const [name, props] of Object.entries(stories)) { + test(name, async () => { + const container: AstroContainer = await AstroContainer.create(); + const result: string = await container.renderToString(Homepage, { + props, + }); + const url = new URL(props.url); + + expect(result).toContain( + `> ${encodeURI(url.hostname)}${ + url.pathname === "/" ? "" : url.pathname + } `, + ); + }); + } +}); diff --git a/src/components/Homepage/story.ts b/src/components/Homepage/story.ts new file mode 100644 index 0000000..0b3fc24 --- /dev/null +++ b/src/components/Homepage/story.ts @@ -0,0 +1,5 @@ +import type { Props } from "./Homepage.astro"; + +export const Domain: Props = { url: "https://example.com" }; +export const Path: Props = { url: "https://www.example.com/path" }; +export const Japanese: Props = { url: "https://www.example.com/パス" }; diff --git a/src/libs/qrcode.ts b/src/libs/qrcode.ts new file mode 100644 index 0000000..cd63edc --- /dev/null +++ b/src/libs/qrcode.ts @@ -0,0 +1,8 @@ +import QRCode from "qrcode"; + +export const generateQRCode = async (url: string): Promise => + await QRCode.toString(url, { + type: "svg", + margin: 0, + color: { light: "#00000000" }, + });