///
///
import { ChildStyle, Style } from "./deps.ts";
export type AttributeSelectorOperator = "^=" | "=" | "$=" | "*=" | "~=" | "|=";
export interface URLInit {
url: string;
/**
* 属性セレクタに使用する演算子
* 指定しない場合は`^=`が用いられる
*/
selectorSyntax: AttributeSelectorOperator;
}
export interface LinkInit {
url: string | URLInit | (string | URLInit)[];
style: ChildStyle;
}
/**
* 外部リンクを区別するUserCSSを生成する関数
*/
export function generateExternalLinkStyle(
/** アイコンを付与しないURLが入ったオブジェクト */
links: LinkInit[],
/** オプションで設定するスタイル(CSS) */
style?: {
/** 外部リンクを区別するアイコンに設定するスタイル */
icon?: ChildStyle;
},
): Style {
const urls = getURLFromLinkInit(links);
const selector =
".line span:not(.modal-image):not(.pointing-device-map) > a.link:not(.icon):not(:is(" +
urls.reduce(
(pre, crt) => `${pre}[href${crt.selectorSyntax}"${crt.url}"],`,
"",
) +
"))::after";
const iconStyleDefault: ChildStyle = {
"display": "inline-block",
"padding-right": "2px",
"font-size": ".5em",
"font-weight": "bold",
"font-family": "'Font Awesome 5 Free', 'Font Awesome 5 Brands'",
"content": "'\\f35d'",
"cursor": "text",
};
const iconStyle: Style = {
[selector]: style?.icon === undefined
? iconStyleDefault
: { ...iconStyleDefault, ...style.icon },
};
return iconStyle;
}
/**
* 特定のリンクにアイコンをつけるUserCSSを生成する関数
*/
export function generateLinkIconStyle(
/** アイコンを付与するリンクの情報 */
links: LinkInit[],
/** オプションで設定するスタイル(CSS) */
style?: {
/** アイコンに共通で設定するスタイル */
iconBase?: ChildStyle;
},
): Style {
const allURLs = getURLFromLinkInit(links);
const baseSelector = ".line span:not(.deco-\\.) > span > a.link:is(" +
allURLs.reduce(
(pre, crt) => `${pre}[href${crt.selectorSyntax}"${crt.url}"],`,
"",
) +
")::before";
const baseStyleDefault: ChildStyle = {
"display": "inline-block",
"width": "auto",
"height": "1em",
"line-height": "1em",
"vertical-align": "middle",
"text-align": "center",
"background-size": "contain",
"background-repeat": "no-repeat",
"font-family": "'Font Awesome 5 Free', 'Font Awesome 5 Brands'",
"cursor": "text",
};
/** 先頭にアイコンを付けるための共通のスタイル */
const baseStyle: Style = {
[baseSelector]: style?.iconBase === undefined
? baseStyleDefault
: { ...baseStyleDefault, ...style.iconBase },
};
const individualStyle: Style = {};
for (const link of links) {
const urls = getURLFromLinkInit([link]);
const selector = ":is(.line, .line .deco) a.link:is(" +
urls.reduce(
(pre, crt) => `${pre}[href${crt.selectorSyntax}"${crt.url}"],`,
"",
) +
")::before";
individualStyle[selector] = link.style;
}
return { ...baseStyle, ...individualStyle };
}
/**
* LinkInitの配列からURLを取り出す
* @param {LinkInit[]} links 取り出し元のオブジェクト
* @param {AttributeSelectorOperator} [defaultOperator="^="] selectorSyntaxが指定されていなかった際に使用するデフォルト値
* @return {URLInit[]}
*/
function getURLFromLinkInit(
links: LinkInit[],
defaultOperator: AttributeSelectorOperator = "^=",
): URLInit[] {
const resultURLs: URLInit[] = [];
for (const link of links) {
if (Array.isArray(link.url)) {
for (const url of link.url) {
if (typeof url === "string") {
resultURLs.push({ url: url, selectorSyntax: defaultOperator });
} else {
resultURLs.push(url);
}
}
} else {
const url = link.url;
if (typeof url === "string") {
resultURLs.push({ url: url, selectorSyntax: defaultOperator });
} else {
resultURLs.push(url);
}
}
}
return resultURLs;
}