import { HtmlElement, htmlElement, htmlElementNoEndTag } from "./data"; /** 多くのHTMLElementに指定できる属性 */ export type CommonAttributes = { id?: string; class?: string; }; const commonAttributesToMap = ( attributes: CommonAttributes ): ReadonlyMap => { const attributeMap: Map = new Map(); if (attributes.id !== undefined) { attributeMap.set("id", attributes.id); } if (attributes.class !== undefined) { attributeMap.set("class", attributes.class); } return attributeMap; }; /** * ページの見出し * ```html *

* ``` */ export const h1 = ( attributes: CommonAttributes, children: ReadonlyArray | string ): HtmlElement => htmlElement("h1", commonAttributesToMap(attributes), children); /** * 見出し * ```html *

* ``` */ export const h2 = ( attributes: CommonAttributes, children: ReadonlyArray | string ): HtmlElement => htmlElement("h2", commonAttributesToMap(attributes), children); /** * 見出し * ```html *

* ``` */ export const h3 = ( attributes: CommonAttributes, children: ReadonlyArray | string ): HtmlElement => htmlElement("h3", commonAttributesToMap(attributes), children); /** * ```html *
* ``` */ export const div = ( attributes: CommonAttributes, children: ReadonlyArray | string ): HtmlElement => htmlElement("div", commonAttributesToMap(attributes), children); /** * ```html * * ``` */ export const anchor = ( attributes: CommonAttributes & { url: URL; }, children: ReadonlyArray | string ): HtmlElement => htmlElement( "a", new Map([ ...commonAttributesToMap(attributes), ["href", attributes.url.toString()], ]), children ); /** * ```html * {attributes.alt} * ``` */ export const image = ( attributes: CommonAttributes & { /** 画像のテキストによる説明 */ alt: string; /** 画像のURL. */ src: URL; } ): HtmlElement => htmlElementNoEndTag( "img", new Map([ ...commonAttributesToMap(attributes), ["alt", attributes.alt], ["src", attributes.src.toString()], ]) ); /** * ```html * * ``` */ export const svg = ( attributes: CommonAttributes & { viewBox: { x: number; y: number; width: number; height: number }; }, children: ReadonlyArray ): HtmlElement => htmlElement( "svg", new Map([ ...commonAttributesToMap(attributes), [ "viewBox", [ attributes.viewBox.x, attributes.viewBox.y, attributes.viewBox.width, attributes.viewBox.height, ].join(" "), ], ]), children ); /** * ```html * * ``` */ export const path = ( attributes: CommonAttributes & { d: string; fill: string; } ): HtmlElement => htmlElement( "path", new Map([ ...commonAttributesToMap(attributes), ["d", attributes.d], ["fill", attributes.fill], ]), "" ); /** SVGの要素のアニメーションを指定する. 繰り返す回数は無限回と指定している */ type SvgAnimation = { attributeName: "cy" | "r" | "stroke"; /** 時間 */ dur: number; /** 開始時の値 */ from: number | string; /** 終了時の値 */ to: number | string; }; /** * ```html * * ``` */ export const circle = ( attributes: CommonAttributes & { cx: number; cy: number; fill: string; r: number; stroke: string; animations?: ReadonlyArray; } ): HtmlElement => { return htmlElement( "circle", new Map([ ...commonAttributesToMap(attributes), ["cx", attributes.cx.toString()], ["cy", attributes.cy.toString()], ["fill", attributes.fill], ["r", attributes.r.toString()], ["stroke", attributes.stroke], ]), attributes.animations === undefined ? "" : attributes.animations.map(animate) ); }; /** * ```html * * ``` */ const animate = (svgAnimation: SvgAnimation): HtmlElement => htmlElement( "animate", new Map([ ["attributeName", svgAnimation.attributeName], ["dur", svgAnimation.dur.toString()], ["from", svgAnimation.from.toString()], ["repeatCount", "indefinite"], ["to", svgAnimation.to.toString()], ]), "" );