remark-hatena-id
Version:
Hatena's id notation plugin for Remark
226 lines (225 loc) • 6.24 kB
JavaScript
const E = (
// Note: overloads in JSDoc can’t yet use different `@template`s.
/**
* @type {(
* (<Condition extends string>(test: Condition) => (node: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & {type: Condition}) &
* (<Condition extends Props>(test: Condition) => (node: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & Condition) &
* (<Condition extends TestFunction>(test: Condition) => (node: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node & Predicate<Condition, Node>) &
* ((test?: null | undefined) => (node?: unknown, index?: number | null | undefined, parent?: Parent | null | undefined, context?: unknown) => node is Node) &
* ((test?: Test) => Check)
* )}
*/
/**
* @param {Test} [test]
* @returns {Check}
*/
function(t) {
if (t == null)
return O;
if (typeof t == "function")
return x(t);
if (typeof t == "object")
return Array.isArray(t) ? R(t) : _(t);
if (typeof t == "string")
return L(t);
throw new Error("Expected function, string, or object as test");
}
);
function R(t) {
const n = [];
let e = -1;
for (; ++e < t.length; )
n[e] = E(t[e]);
return x(i);
function i(...c) {
let o = -1;
for (; ++o < n.length; )
if (n[o].apply(this, c)) return !0;
return !1;
}
}
function _(t) {
const n = (
/** @type {Record<string, unknown>} */
t
);
return x(e);
function e(i) {
const c = (
/** @type {Record<string, unknown>} */
/** @type {unknown} */
i
);
let o;
for (o in t)
if (c[o] !== n[o]) return !1;
return !0;
}
}
function L(t) {
return x(n);
function n(e) {
return e && e.type === t;
}
}
function x(t) {
return n;
function n(e, i, c) {
return !!($(e) && t.call(
this,
e,
typeof i == "number" ? i : void 0,
c || void 0
));
}
}
function O() {
return !0;
}
function $(t) {
return t !== null && typeof t == "object" && "type" in t;
}
const k = [], F = !0, N = !1, H = "skip";
function T(t, n, e, i) {
let c;
typeof n == "function" && typeof e != "function" ? (i = e, e = n) : c = n;
const o = E(c), f = i ? -1 : 1;
d(t, void 0, [])();
function d(r, p, u) {
const s = (
/** @type {Record<string, unknown>} */
r && typeof r == "object" ? r : {}
);
if (typeof s.type == "string") {
const a = (
// `hast`
typeof s.tagName == "string" ? s.tagName : (
// `xast`
typeof s.name == "string" ? s.name : void 0
)
);
Object.defineProperty(y, "name", {
value: "node (" + (r.type + (a ? "<" + a + ">" : "")) + ")"
});
}
return y;
function y() {
let a = k, h, l, m;
if ((!n || o(r, p, u[u.length - 1] || void 0)) && (a = z(e(r, u)), a[0] === N))
return a;
if ("children" in r && r.children) {
const g = (
/** @type {UnistParent} */
r
);
if (g.children && a[0] !== H)
for (l = (i ? g.children.length : -1) + f, m = u.concat(g); l > -1 && l < g.children.length; ) {
const A = g.children[l];
if (h = d(A, l, m)(), h[0] === N)
return h;
l = typeof h[1] == "number" ? h[1] : l + f;
}
}
return a;
}
}
}
function z(t) {
return Array.isArray(t) ? t : typeof t == "number" ? [F, t] : t == null ? k : [t];
}
function G(t, n, e, i) {
let c, o, f;
o = n, f = e, c = i, T(t, o, d, c);
function d(r, p) {
const u = p[p.length - 1], s = u ? u.children.indexOf(r) : void 0;
return f(r, s, u);
}
}
function b(t, n, e) {
const i = { type: String(t) };
return e == null && (typeof n == "string" || Array.isArray(n)) ? e = n : Object.assign(i, n), Array.isArray(e) ? i.children = e : e != null && (i.value = String(e)), i;
}
const w = /id:(?<hatenaId>[A-Za-z][0-9A-Za-z_-]{1,30}[0-9A-Za-z])(:(?<option>detail:large|detail|image))?/, S = new RegExp(w, "g"), X = (t, n) => {
const e = [];
let i;
return n === "detail" ? (e.push({
type: "image",
url: `https://cdn.profile-image.st-hatena.com/users/${t}/profile.png`,
data: {
hProperties: {
width: "16",
height: "16",
class: "hatena-id-icon"
}
}
}), i = "hatena-id-icon") : n === "detail:large" ? (e.push({
type: "image",
url: `https://cdn.profile-image.st-hatena.com/users/${t}/profile.png`,
data: {
hProperties: {
width: "60",
height: "60",
class: "hatena-id-icon"
}
}
}), i = "hatena-id-icon") : n === "image" && (e.push({
type: "image",
url: `https://cdn.profile-image.st-hatena.com/users/${t}/profile.png`,
data: {
hProperties: {
width: "60",
height: "60",
class: "hatena-id-image"
}
}
}), i = "hatena-id-image"), n !== "image" && e.push({
type: "text",
value: `id:${t}`
}), {
type: "paragraph",
children: e,
data: {
hName: "a",
hProperties: {
href: `https://profile.hatena.ne.jp/${t}/`,
class: i,
dataHatenaId: t
}
}
};
}, Z = () => {
let t = 0;
const n = (e, i, c) => {
if (t > 0) {
t--;
return;
}
if (!w.test(e.value) || !c || i == null) return;
const o = [...e.value.matchAll(S)], f = [], d = e.value;
let r = "", p = 0, u = 0;
for (let s = 0; s < o.length; s++) {
const y = o[s], a = y.index ?? 0, h = y[0].length, l = y.groups;
if (!l) continue;
const m = l.hatenaId, g = l.option, A = s === 0 ? 0 : p + u;
if (p = a, u = h, a > A) {
const P = d.substring(A, a), j = b("text", P);
f.push(j);
}
const I = X(m, g);
f.push(I), r = d.slice(a + h);
}
if (r) {
const s = b("text", r);
f.push(s);
}
f.length && (c.children.splice(i, 1, ...f), t = f.length - 1);
};
return (e) => {
G(e, "text", n);
};
};
export {
w as HATENA_ID_REGEX,
S as HATENA_ID_REGEX_GLOBAL,
Z as remarkHatenaId
};