@digitalwalletcorp/utils 0.12.0 → 0.13.0
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/lib/html-util--mpzaYuJ.cjs +2 -0
- package/lib/html-util--mpzaYuJ.cjs.map +1 -0
- package/lib/html-util-B8sdLw9I.js +60 -0
- package/lib/html-util-B8sdLw9I.js.map +1 -0
- package/lib/html-util.cjs +1 -1
- package/lib/html-util.d.cts +3 -1
- package/lib/html-util.d.ts +3 -1
- package/lib/html-util.js +1 -1
- package/lib/index.cjs +1 -1
- package/lib/index.js +1 -1
- package/package.json +1 -1
- package/src/html-util.ts +7 -2
- package/lib/html-util-BctKzfnH.js +0 -60
- package/lib/html-util-BctKzfnH.js.map +0 -1
- package/lib/html-util-ELyFVsxl.cjs +0 -2
- package/lib/html-util-ELyFVsxl.cjs.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";const S=require("diff"),j=require("./json-util-CKnsxu1e.cjs"),m=/(<!--[\s\S]*?-->|<[^>]*>|&(?:#\d+|#x[\da-f]+|\w+);)/i,y={'"':""","&":"&","'":"'","<":"<",">":">"},a=r=>r.replace(/["&'<>]/g,e=>y[e]),$=r=>typeof r=="string"?r:Array.isArray(r)?r.filter(Boolean).join(" "):Object.keys(r).filter(e=>r[e]).join(" "),x=r=>typeof r=="string"?r:Object.entries(r).map(([e,t])=>`${e.startsWith("--")?e:e.replace(/[A-Z]/g,n=>`-${n.toLowerCase()}`)}: ${t}`).join("; "),d={added:"color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))",removed:"color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))",same:"color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))"},T="background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)",f=(r,e,t,o)=>{let n="";const i=t?.class==null?"":$(t.class);i&&(n+=` class="${a(i)}"`);const l=[o,t?.style==null?"":x(t.style)].filter(Boolean).join("; ");return l&&(n+=` style="${a(l)}"`),`<${r}${n}>${a(e)}</${r}>`};function g(r,e){if(!r)return"";const t=o=>o.replace(/\r\n|\r|\n/g,"<br>").replace(/\t/g," ").replace(/ /g," ");return e?.html?r.split(m).map((o,n)=>n%2===1?o:t(o)).join(""):t(a(r))}function u(r,e){const{html:t,...o}=e??{},n=j.formatJsonString(r,o);return n==null?"":g(String(n),{html:t})}function h(r,e,t){if(!r)return"";const o=s=>t?.html?s:a(s);if(!e)return o(r);const n=e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d"),i=new RegExp(`(${n})`,t?.caseInsensitive?"i":""),l=s=>s.split(i).map((c,b)=>b%2===0?o(c):f("mark",c,t,T)).join("");return t?.html?r.split(m).map((s,c)=>c%2===1?s:l(s)).join(""):l(r)}function p(r,e,t){const o=S.diffChars(r??"",e??"",{ignoreCase:t?.ignoreCase});let n="";for(const i of o)i.added?n+=f("span",i.value,t?.added,d.added):i.removed?n+=f("span",i.value,t?.removed,d.removed):n+=f("span",i.value,t?.same,d.same);return n}const W=Object.freeze(Object.defineProperty({__proto__:null,diffForWeb:p,formatJsonStringForWeb:u,formatStringForWeb:g,highlightWord:h},Symbol.toStringTag,{value:"Module"}));exports.diffForWeb=p;exports.formatJsonStringForWeb=u;exports.formatStringForWeb=g;exports.highlightWord=h;exports.htmlUtil=W;
|
|
2
|
+
//# sourceMappingURL=html-util--mpzaYuJ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-util--mpzaYuJ.cjs","sources":["../src/html-util.ts"],"sourcesContent":["import { diffChars } from 'diff';\nimport { formatJsonString } from './json-util';\nimport type { FormatJsonStringOptions } from './json-util';\n\n/**\n * class属性に指定する値\n * 配列は要素を空白区切りで連結し、Recordは値がtrueのキーだけを連結する\n */\nexport type HtmlClassValue = string | string[] | Record<string, boolean>;\n\n/**\n * style属性に指定する値\n * Recordのキーはキャメルケースをケバブケースに変換する。数値には単位を付けない\n */\nexport type HtmlStyleValue = string | Record<string, string | number>;\n\n/**\n * 生成するタグに付与する属性\n */\nexport interface HtmlTagOptions {\n class?: HtmlClassValue;\n style?: HtmlStyleValue;\n}\n\nconst HTML_TOKEN = /(<!--[\\s\\S]*?-->|<[^>]*>|&(?:#\\d+|#x[\\da-f]+|\\w+);)/i;\n\nconst HTML_ESCAPE_CHARS: Record<string, string> = {\n '\"': '"',\n '&': '&',\n '\\'': ''',\n '<': '<',\n '>': '>'\n};\n\nconst escapeHtml = (str: string): string => str.replace(/[\"&'<>]/g, (c) => HTML_ESCAPE_CHARS[c]);\n\nconst toClassString = (value: HtmlClassValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n if (Array.isArray(value)) {\n return value.filter(Boolean).join(' ');\n }\n return Object.keys(value).filter(key => value[key]).join(' ');\n};\n\nconst toStyleString = (value: HtmlStyleValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n return Object.entries(value)\n .map(([key, v]) => {\n // カスタムプロパティ(--xxx)は大文字小文字を区別するため変換しない\n const property = key.startsWith('--') ? key : key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);\n return `${property}: ${v}`;\n })\n .join('; ');\n};\n\n/** diffForWebの既定の文字色 */\nconst DIFF_STYLES = {\n added: 'color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))',\n removed: 'color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))',\n same: 'color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))'\n};\n\n/** highlightWordの既定の背景色・文字色。markタグのブラウザ標準の色をフォールバックにする */\nconst HIGHLIGHT_STYLE = 'background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)';\n\n/**\n * 値をエスケープしたタグを返す\n *\n * @param {string} tagName\n * @param {string} value\n * @param {HtmlTagOptions} [options]\n * @param {string} [defaultStyle] optionsのstyleより前に出力するstyle\n * @returns {string}\n */\nconst toElement = (tagName: string, value: string, options?: HtmlTagOptions, defaultStyle?: string): string => {\n let attributes = '';\n const className = options?.class == null ? '' : toClassString(options.class);\n if (className) {\n attributes += ` class=\"${escapeHtml(className)}\"`;\n }\n const style = [defaultStyle, options?.style == null ? '' : toStyleString(options.style)].filter(Boolean).join('; ');\n if (style) {\n attributes += ` style=\"${escapeHtml(style)}\"`;\n }\n return `<${tagName}${attributes}>${escapeHtml(value)}</${tagName}>`;\n};\n\n/**\n * 文字列をWEB表示用にフォーマットする\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * @param {string | null | undefined} str\n * @param {*} [options]\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatStringForWeb(str: string | null | undefined, options?: {\n html?: boolean;\n}): string {\n if (!str) {\n return '';\n }\n\n const formatText = (text: string): string => text\n .replace(/\\r\\n|\\r|\\n/g, '<br>')\n .replace(/\\t/g, ' ')\n .replace(/ /g, ' ');\n\n if (options?.html) {\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをフォーマットする\n return str\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : formatText(segment))\n .join('');\n }\n\n return formatText(escapeHtml(str));\n}\n\n/**\n * 値を整形したJSON文字列にしてWEB表示用にフォーマットする\n * formatJsonStringで整形した文字列をformatStringForWebで変換する\n *\n * @param {any} value\n * @param {*} [options] formatJsonStringのオプションに以下を加えたもの\n * ├ html boolean trueを指定した場合、文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatJsonStringForWeb(value: any, options?: FormatJsonStringOptions & {\n html?: boolean;\n}): string {\n const { html, ...formatOptions } = options ?? {};\n const json = formatJsonString(value, formatOptions);\n return json == null ? '' : formatStringForWeb(String(json), { html });\n}\n\n/**\n * 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す\n * markタグは既定の背景色・文字色を持つ。色はCSS変数(--dwui-background-highlight / --dwui-color-text-highlight)で変更できる\n * styleは既定の背景色・文字色より後に出力する\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * 例)\n * HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });\n * → 'This is a <mark class=\"highlight\" style=\"background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)\">test</mark> message'\n *\n * @param {string | null | undefined} value\n * @param {string | null | undefined} word\n * @param {*} [options] markタグに付与するclass, styleのほか、以下を指定できる\n * ├ class string | string[] | Record<string, boolean>\n * ├ style string | Record<string, string | number>\n * ├ caseInsensitive boolean trueを指定した場合、大文字小文字を区別しない\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function highlightWord(\n value: string | null | undefined,\n word: string | null | undefined,\n options?: HtmlTagOptions & {\n caseInsensitive?: boolean;\n html?: boolean;\n }\n): string {\n if (!value) {\n return '';\n }\n\n const toHtml = (text: string): string => options?.html ? text : escapeHtml(text);\n if (!word) {\n return toHtml(value);\n }\n\n const pattern = word.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&').replace(/-/g, '\\\\x2d');\n const regex = new RegExp(`(${pattern})`, options?.caseInsensitive ? 'i' : '');\n // キャプチャグループで分割すると、奇数番目の要素が一致した部分になる\n const highlight = (text: string): string => text\n .split(regex)\n .map((part, i) => i % 2 === 0 ? toHtml(part) : toElement('mark', part, options, HIGHLIGHT_STYLE))\n .join('');\n\n if (!options?.html) {\n return highlight(value);\n }\n\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをハイライトする\n return value\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : highlight(segment))\n .join('');\n}\n\n/**\n * 文字列を1文字ずつ比較し、差分をspanタグで囲んだHTML文字列を返す\n * 追加・削除・一致の部分ごとに既定の文字色を持つ。文字色はCSS変数(--dwui-color-text-diff-added / --dwui-color-text-diff-removed / --dwui-color-text-diff-same)で変更できる\n * 追加・削除・一致の部分ごとに、spanタグに付与するclass, styleを指定できる。styleは既定の文字色より後に出力する\n * 入力文字列はプレーンなテキストであるとみなす\n * 出力される文字列は、diffで埋め込まれるHTMLタグ以外はHTMLエスケープされ、HTMLセーフな文字列となる\n *\n * @param {string | null | undefined} text1 比較元の文字列\n * @param {string | null | undefined} text2 比較される文字列(通常、入力値はこちらに渡す)\n * @param {*} [options]\n * ├ ignoreCase boolean trueを指定した場合、大文字小文字を区別しない\n * ├ added HtmlTagOptions text2で追加された部分のspanタグに付与する属性\n * ├ removed HtmlTagOptions text2で削除された部分のspanタグに付与する属性\n * ├ same HtmlTagOptions 一致した部分のspanタグに付与する属性\n * @returns {string}\n */\nexport function diffForWeb(text1: string | null | undefined, text2: string | null | undefined, options?: {\n ignoreCase?: boolean;\n added?: HtmlTagOptions;\n removed?: HtmlTagOptions;\n same?: HtmlTagOptions;\n}): string {\n const changes = diffChars(text1 ?? '', text2 ?? '', { ignoreCase: options?.ignoreCase });\n let html = '';\n for (const change of changes) {\n if (change.added) {\n html += toElement('span', change.value, options?.added, DIFF_STYLES.added);\n } else if (change.removed) {\n html += toElement('span', change.value, options?.removed, DIFF_STYLES.removed);\n } else {\n html += toElement('span', change.value, options?.same, DIFF_STYLES.same);\n }\n }\n return html;\n}\n"],"names":["HTML_TOKEN","HTML_ESCAPE_CHARS","escapeHtml","str","c","toClassString","value","key","toStyleString","v","DIFF_STYLES","HIGHLIGHT_STYLE","toElement","tagName","options","defaultStyle","attributes","className","style","formatStringForWeb","formatText","text","segment","i","formatJsonStringForWeb","html","formatOptions","json","formatJsonString","highlightWord","word","toHtml","pattern","regex","highlight","part","diffForWeb","text1","text2","changes","diffChars","change"],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { diffChars as h } from "diff";
|
|
2
|
+
import { f as p } from "./json-util-C_Pm1BpJ.js";
|
|
3
|
+
const g = /(<!--[\s\S]*?-->|<[^>]*>|&(?:#\d+|#x[\da-f]+|\w+);)/i, b = {
|
|
4
|
+
'"': """,
|
|
5
|
+
"&": "&",
|
|
6
|
+
"'": "'",
|
|
7
|
+
"<": "<",
|
|
8
|
+
">": ">"
|
|
9
|
+
}, l = (r) => r.replace(/["&'<>]/g, (e) => b[e]), S = (r) => typeof r == "string" ? r : Array.isArray(r) ? r.filter(Boolean).join(" ") : Object.keys(r).filter((e) => r[e]).join(" "), j = (r) => typeof r == "string" ? r : Object.entries(r).map(([e, t]) => `${e.startsWith("--") ? e : e.replace(/[A-Z]/g, (n) => `-${n.toLowerCase()}`)}: ${t}`).join("; "), d = {
|
|
10
|
+
added: "color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))",
|
|
11
|
+
removed: "color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))",
|
|
12
|
+
same: "color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))"
|
|
13
|
+
}, y = "background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)", f = (r, e, t, o) => {
|
|
14
|
+
let n = "";
|
|
15
|
+
const i = t?.class == null ? "" : S(t.class);
|
|
16
|
+
i && (n += ` class="${l(i)}"`);
|
|
17
|
+
const a = [o, t?.style == null ? "" : j(t.style)].filter(Boolean).join("; ");
|
|
18
|
+
return a && (n += ` style="${l(a)}"`), `<${r}${n}>${l(e)}</${r}>`;
|
|
19
|
+
};
|
|
20
|
+
function m(r, e) {
|
|
21
|
+
if (!r)
|
|
22
|
+
return "";
|
|
23
|
+
const t = (o) => o.replace(/\r\n|\r|\n/g, "<br>").replace(/\t/g, " ").replace(/ /g, " ");
|
|
24
|
+
return e?.html ? r.split(g).map((o, n) => n % 2 === 1 ? o : t(o)).join("") : t(l(r));
|
|
25
|
+
}
|
|
26
|
+
function $(r, e) {
|
|
27
|
+
const { html: t, ...o } = e ?? {}, n = p(r, o);
|
|
28
|
+
return n == null ? "" : m(String(n), { html: t });
|
|
29
|
+
}
|
|
30
|
+
function x(r, e, t) {
|
|
31
|
+
if (!r)
|
|
32
|
+
return "";
|
|
33
|
+
const o = (s) => t?.html ? s : l(s);
|
|
34
|
+
if (!e)
|
|
35
|
+
return o(r);
|
|
36
|
+
const n = e.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d"), i = new RegExp(`(${n})`, t?.caseInsensitive ? "i" : ""), a = (s) => s.split(i).map((c, u) => u % 2 === 0 ? o(c) : f("mark", c, t, y)).join("");
|
|
37
|
+
return t?.html ? r.split(g).map((s, c) => c % 2 === 1 ? s : a(s)).join("") : a(r);
|
|
38
|
+
}
|
|
39
|
+
function T(r, e, t) {
|
|
40
|
+
const o = h(r ?? "", e ?? "", { ignoreCase: t?.ignoreCase });
|
|
41
|
+
let n = "";
|
|
42
|
+
for (const i of o)
|
|
43
|
+
i.added ? n += f("span", i.value, t?.added, d.added) : i.removed ? n += f("span", i.value, t?.removed, d.removed) : n += f("span", i.value, t?.same, d.same);
|
|
44
|
+
return n;
|
|
45
|
+
}
|
|
46
|
+
const k = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
47
|
+
__proto__: null,
|
|
48
|
+
diffForWeb: T,
|
|
49
|
+
formatJsonStringForWeb: $,
|
|
50
|
+
formatStringForWeb: m,
|
|
51
|
+
highlightWord: x
|
|
52
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
53
|
+
export {
|
|
54
|
+
m as a,
|
|
55
|
+
x as b,
|
|
56
|
+
T as d,
|
|
57
|
+
$ as f,
|
|
58
|
+
k as h
|
|
59
|
+
};
|
|
60
|
+
//# sourceMappingURL=html-util-B8sdLw9I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"html-util-B8sdLw9I.js","sources":["../src/html-util.ts"],"sourcesContent":["import { diffChars } from 'diff';\nimport { formatJsonString } from './json-util';\nimport type { FormatJsonStringOptions } from './json-util';\n\n/**\n * class属性に指定する値\n * 配列は要素を空白区切りで連結し、Recordは値がtrueのキーだけを連結する\n */\nexport type HtmlClassValue = string | string[] | Record<string, boolean>;\n\n/**\n * style属性に指定する値\n * Recordのキーはキャメルケースをケバブケースに変換する。数値には単位を付けない\n */\nexport type HtmlStyleValue = string | Record<string, string | number>;\n\n/**\n * 生成するタグに付与する属性\n */\nexport interface HtmlTagOptions {\n class?: HtmlClassValue;\n style?: HtmlStyleValue;\n}\n\nconst HTML_TOKEN = /(<!--[\\s\\S]*?-->|<[^>]*>|&(?:#\\d+|#x[\\da-f]+|\\w+);)/i;\n\nconst HTML_ESCAPE_CHARS: Record<string, string> = {\n '\"': '"',\n '&': '&',\n '\\'': ''',\n '<': '<',\n '>': '>'\n};\n\nconst escapeHtml = (str: string): string => str.replace(/[\"&'<>]/g, (c) => HTML_ESCAPE_CHARS[c]);\n\nconst toClassString = (value: HtmlClassValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n if (Array.isArray(value)) {\n return value.filter(Boolean).join(' ');\n }\n return Object.keys(value).filter(key => value[key]).join(' ');\n};\n\nconst toStyleString = (value: HtmlStyleValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n return Object.entries(value)\n .map(([key, v]) => {\n // カスタムプロパティ(--xxx)は大文字小文字を区別するため変換しない\n const property = key.startsWith('--') ? key : key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);\n return `${property}: ${v}`;\n })\n .join('; ');\n};\n\n/** diffForWebの既定の文字色 */\nconst DIFF_STYLES = {\n added: 'color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))',\n removed: 'color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))',\n same: 'color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))'\n};\n\n/** highlightWordの既定の背景色・文字色。markタグのブラウザ標準の色をフォールバックにする */\nconst HIGHLIGHT_STYLE = 'background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)';\n\n/**\n * 値をエスケープしたタグを返す\n *\n * @param {string} tagName\n * @param {string} value\n * @param {HtmlTagOptions} [options]\n * @param {string} [defaultStyle] optionsのstyleより前に出力するstyle\n * @returns {string}\n */\nconst toElement = (tagName: string, value: string, options?: HtmlTagOptions, defaultStyle?: string): string => {\n let attributes = '';\n const className = options?.class == null ? '' : toClassString(options.class);\n if (className) {\n attributes += ` class=\"${escapeHtml(className)}\"`;\n }\n const style = [defaultStyle, options?.style == null ? '' : toStyleString(options.style)].filter(Boolean).join('; ');\n if (style) {\n attributes += ` style=\"${escapeHtml(style)}\"`;\n }\n return `<${tagName}${attributes}>${escapeHtml(value)}</${tagName}>`;\n};\n\n/**\n * 文字列をWEB表示用にフォーマットする\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * @param {string | null | undefined} str\n * @param {*} [options]\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatStringForWeb(str: string | null | undefined, options?: {\n html?: boolean;\n}): string {\n if (!str) {\n return '';\n }\n\n const formatText = (text: string): string => text\n .replace(/\\r\\n|\\r|\\n/g, '<br>')\n .replace(/\\t/g, ' ')\n .replace(/ /g, ' ');\n\n if (options?.html) {\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをフォーマットする\n return str\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : formatText(segment))\n .join('');\n }\n\n return formatText(escapeHtml(str));\n}\n\n/**\n * 値を整形したJSON文字列にしてWEB表示用にフォーマットする\n * formatJsonStringで整形した文字列をformatStringForWebで変換する\n *\n * @param {any} value\n * @param {*} [options] formatJsonStringのオプションに以下を加えたもの\n * ├ html boolean trueを指定した場合、文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatJsonStringForWeb(value: any, options?: FormatJsonStringOptions & {\n html?: boolean;\n}): string {\n const { html, ...formatOptions } = options ?? {};\n const json = formatJsonString(value, formatOptions);\n return json == null ? '' : formatStringForWeb(String(json), { html });\n}\n\n/**\n * 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す\n * markタグは既定の背景色・文字色を持つ。色はCSS変数(--dwui-background-highlight / --dwui-color-text-highlight)で変更できる\n * styleは既定の背景色・文字色より後に出力する\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * 例)\n * HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });\n * → 'This is a <mark class=\"highlight\" style=\"background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)\">test</mark> message'\n *\n * @param {string | null | undefined} value\n * @param {string | null | undefined} word\n * @param {*} [options] markタグに付与するclass, styleのほか、以下を指定できる\n * ├ class string | string[] | Record<string, boolean>\n * ├ style string | Record<string, string | number>\n * ├ caseInsensitive boolean trueを指定した場合、大文字小文字を区別しない\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function highlightWord(\n value: string | null | undefined,\n word: string | null | undefined,\n options?: HtmlTagOptions & {\n caseInsensitive?: boolean;\n html?: boolean;\n }\n): string {\n if (!value) {\n return '';\n }\n\n const toHtml = (text: string): string => options?.html ? text : escapeHtml(text);\n if (!word) {\n return toHtml(value);\n }\n\n const pattern = word.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&').replace(/-/g, '\\\\x2d');\n const regex = new RegExp(`(${pattern})`, options?.caseInsensitive ? 'i' : '');\n // キャプチャグループで分割すると、奇数番目の要素が一致した部分になる\n const highlight = (text: string): string => text\n .split(regex)\n .map((part, i) => i % 2 === 0 ? toHtml(part) : toElement('mark', part, options, HIGHLIGHT_STYLE))\n .join('');\n\n if (!options?.html) {\n return highlight(value);\n }\n\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをハイライトする\n return value\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : highlight(segment))\n .join('');\n}\n\n/**\n * 文字列を1文字ずつ比較し、差分をspanタグで囲んだHTML文字列を返す\n * 追加・削除・一致の部分ごとに既定の文字色を持つ。文字色はCSS変数(--dwui-color-text-diff-added / --dwui-color-text-diff-removed / --dwui-color-text-diff-same)で変更できる\n * 追加・削除・一致の部分ごとに、spanタグに付与するclass, styleを指定できる。styleは既定の文字色より後に出力する\n * 入力文字列はプレーンなテキストであるとみなす\n * 出力される文字列は、diffで埋め込まれるHTMLタグ以外はHTMLエスケープされ、HTMLセーフな文字列となる\n *\n * @param {string | null | undefined} text1 比較元の文字列\n * @param {string | null | undefined} text2 比較される文字列(通常、入力値はこちらに渡す)\n * @param {*} [options]\n * ├ ignoreCase boolean trueを指定した場合、大文字小文字を区別しない\n * ├ added HtmlTagOptions text2で追加された部分のspanタグに付与する属性\n * ├ removed HtmlTagOptions text2で削除された部分のspanタグに付与する属性\n * ├ same HtmlTagOptions 一致した部分のspanタグに付与する属性\n * @returns {string}\n */\nexport function diffForWeb(text1: string | null | undefined, text2: string | null | undefined, options?: {\n ignoreCase?: boolean;\n added?: HtmlTagOptions;\n removed?: HtmlTagOptions;\n same?: HtmlTagOptions;\n}): string {\n const changes = diffChars(text1 ?? '', text2 ?? '', { ignoreCase: options?.ignoreCase });\n let html = '';\n for (const change of changes) {\n if (change.added) {\n html += toElement('span', change.value, options?.added, DIFF_STYLES.added);\n } else if (change.removed) {\n html += toElement('span', change.value, options?.removed, DIFF_STYLES.removed);\n } else {\n html += toElement('span', change.value, options?.same, DIFF_STYLES.same);\n }\n }\n return html;\n}\n"],"names":["HTML_TOKEN","HTML_ESCAPE_CHARS","escapeHtml","str","c","toClassString","value","key","toStyleString","v","DIFF_STYLES","HIGHLIGHT_STYLE","toElement","tagName","options","defaultStyle","attributes","className","style","formatStringForWeb","formatText","text","segment","i","formatJsonStringForWeb","html","formatOptions","json","formatJsonString","highlightWord","word","toHtml","pattern","regex","highlight","part","diffForWeb","text1","text2","changes","diffChars","change"],"mappings":"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"}
|
package/lib/html-util.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("diff");require("./json-util-CKnsxu1e.cjs");const r=require("./html-util
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});require("diff");require("./json-util-CKnsxu1e.cjs");const r=require("./html-util--mpzaYuJ.cjs");exports.diffForWeb=r.diffForWeb;exports.formatJsonStringForWeb=r.formatJsonStringForWeb;exports.formatStringForWeb=r.formatStringForWeb;exports.highlightWord=r.highlightWord;
|
|
2
2
|
//# sourceMappingURL=html-util.cjs.map
|
package/lib/html-util.d.cts
CHANGED
|
@@ -42,11 +42,13 @@ export declare function formatJsonStringForWeb(value: any, options?: FormatJsonS
|
|
|
42
42
|
}): string;
|
|
43
43
|
/**
|
|
44
44
|
* 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す
|
|
45
|
+
* markタグは既定の背景色・文字色を持つ。色はCSS変数(--dwui-background-highlight / --dwui-color-text-highlight)で変更できる
|
|
46
|
+
* styleは既定の背景色・文字色より後に出力する
|
|
45
47
|
* オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能
|
|
46
48
|
*
|
|
47
49
|
* 例)
|
|
48
50
|
* HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });
|
|
49
|
-
* → 'This is a <mark class="highlight">test</mark> message'
|
|
51
|
+
* → 'This is a <mark class="highlight" style="background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)">test</mark> message'
|
|
50
52
|
*
|
|
51
53
|
* @param {string | null | undefined} value
|
|
52
54
|
* @param {string | null | undefined} word
|
package/lib/html-util.d.ts
CHANGED
|
@@ -42,11 +42,13 @@ export declare function formatJsonStringForWeb(value: any, options?: FormatJsonS
|
|
|
42
42
|
}): string;
|
|
43
43
|
/**
|
|
44
44
|
* 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す
|
|
45
|
+
* markタグは既定の背景色・文字色を持つ。色はCSS変数(--dwui-background-highlight / --dwui-color-text-highlight)で変更できる
|
|
46
|
+
* styleは既定の背景色・文字色より後に出力する
|
|
45
47
|
* オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能
|
|
46
48
|
*
|
|
47
49
|
* 例)
|
|
48
50
|
* HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });
|
|
49
|
-
* → 'This is a <mark class="highlight">test</mark> message'
|
|
51
|
+
* → 'This is a <mark class="highlight" style="background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)">test</mark> message'
|
|
50
52
|
*
|
|
51
53
|
* @param {string | null | undefined} value
|
|
52
54
|
* @param {string | null | undefined} word
|
package/lib/html-util.js
CHANGED
package/lib/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./crypto-util-BcHurtbE.cjs"),e=require("./zoned-date-time.cjs"),i=require("./date-util-CZmiQEYH.cjs"),l=require("./decimal.cjs"),r=require("./file-util-Dqiw5tBQ.cjs"),o=require("./html-util
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./crypto-util-BcHurtbE.cjs"),e=require("./zoned-date-time.cjs"),i=require("./date-util-CZmiQEYH.cjs"),l=require("./decimal.cjs"),r=require("./file-util-Dqiw5tBQ.cjs"),o=require("./html-util--mpzaYuJ.cjs"),U=require("./json-util-CKnsxu1e.cjs"),n=require("./number-util-BrDEKYJo.cjs"),c=require("./object-util-BHg61ifG.cjs"),s=require("./string-util-w2I5EYuY.cjs");exports.CryptoUtil=t.cryptoUtil;exports.ZonedDateTime=e.ZonedDateTime;exports.DateUtil=i.dateUtil;exports.Decimal=l.Decimal;exports.FileUtil=r.fileUtil;exports.HtmlUtil=o.htmlUtil;exports.JsonUtil=U.jsonUtil;exports.NumberUtil=n.numberUtil;exports.ObjectUtil=c.objectUtil;exports.StringUtil=s.stringUtil;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/lib/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { ZonedDateTime as m } from "./zoned-date-time.js";
|
|
|
3
3
|
import { d as a } from "./date-util-BNe2E-tA.js";
|
|
4
4
|
import { Decimal as l } from "./decimal.js";
|
|
5
5
|
import { f as s } from "./file-util-CO5vjmkO.js";
|
|
6
|
-
import { h as U } from "./html-util-
|
|
6
|
+
import { h as U } from "./html-util-B8sdLw9I.js";
|
|
7
7
|
import { j as c } from "./json-util-C_Pm1BpJ.js";
|
|
8
8
|
import { n as b } from "./number-util-Wpubbqr4.js";
|
|
9
9
|
import { o as j } from "./object-util-wOMJtGK3.js";
|
package/package.json
CHANGED
package/src/html-util.ts
CHANGED
|
@@ -64,6 +64,9 @@ const DIFF_STYLES = {
|
|
|
64
64
|
same: 'color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))'
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
+
/** highlightWordの既定の背景色・文字色。markタグのブラウザ標準の色をフォールバックにする */
|
|
68
|
+
const HIGHLIGHT_STYLE = 'background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)';
|
|
69
|
+
|
|
67
70
|
/**
|
|
68
71
|
* 値をエスケープしたタグを返す
|
|
69
72
|
*
|
|
@@ -137,11 +140,13 @@ export function formatJsonStringForWeb(value: any, options?: FormatJsonStringOpt
|
|
|
137
140
|
|
|
138
141
|
/**
|
|
139
142
|
* 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す
|
|
143
|
+
* markタグは既定の背景色・文字色を持つ。色はCSS変数(--dwui-background-highlight / --dwui-color-text-highlight)で変更できる
|
|
144
|
+
* styleは既定の背景色・文字色より後に出力する
|
|
140
145
|
* オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能
|
|
141
146
|
*
|
|
142
147
|
* 例)
|
|
143
148
|
* HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });
|
|
144
|
-
* → 'This is a <mark class="highlight">test</mark> message'
|
|
149
|
+
* → 'This is a <mark class="highlight" style="background: var(--dwui-background-highlight, Mark); color: var(--dwui-color-text-highlight, MarkText)">test</mark> message'
|
|
145
150
|
*
|
|
146
151
|
* @param {string | null | undefined} value
|
|
147
152
|
* @param {string | null | undefined} word
|
|
@@ -174,7 +179,7 @@ export function highlightWord(
|
|
|
174
179
|
// キャプチャグループで分割すると、奇数番目の要素が一致した部分になる
|
|
175
180
|
const highlight = (text: string): string => text
|
|
176
181
|
.split(regex)
|
|
177
|
-
.map((part, i) => i % 2 === 0 ? toHtml(part) : toElement('mark', part, options))
|
|
182
|
+
.map((part, i) => i % 2 === 0 ? toHtml(part) : toElement('mark', part, options, HIGHLIGHT_STYLE))
|
|
178
183
|
.join('');
|
|
179
184
|
|
|
180
185
|
if (!options?.html) {
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { diffChars as u } from "diff";
|
|
2
|
-
import { f as h } from "./json-util-C_Pm1BpJ.js";
|
|
3
|
-
const m = /(<!--[\s\S]*?-->|<[^>]*>|&(?:#\d+|#x[\da-f]+|\w+);)/i, b = {
|
|
4
|
-
'"': """,
|
|
5
|
-
"&": "&",
|
|
6
|
-
"'": "'",
|
|
7
|
-
"<": "<",
|
|
8
|
-
">": ">"
|
|
9
|
-
}, l = (r) => r.replace(/["&'<>]/g, (e) => b[e]), S = (r) => typeof r == "string" ? r : Array.isArray(r) ? r.filter(Boolean).join(" ") : Object.keys(r).filter((e) => r[e]).join(" "), j = (r) => typeof r == "string" ? r : Object.entries(r).map(([e, t]) => `${e.startsWith("--") ? e : e.replace(/[A-Z]/g, (n) => `-${n.toLowerCase()}`)}: ${t}`).join("; "), d = {
|
|
10
|
-
added: "color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))",
|
|
11
|
-
removed: "color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))",
|
|
12
|
-
same: "color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))"
|
|
13
|
-
}, f = (r, e, t, o) => {
|
|
14
|
-
let n = "";
|
|
15
|
-
const s = t?.class == null ? "" : S(t.class);
|
|
16
|
-
s && (n += ` class="${l(s)}"`);
|
|
17
|
-
const a = [o, t?.style == null ? "" : j(t.style)].filter(Boolean).join("; ");
|
|
18
|
-
return a && (n += ` style="${l(a)}"`), `<${r}${n}>${l(e)}</${r}>`;
|
|
19
|
-
};
|
|
20
|
-
function g(r, e) {
|
|
21
|
-
if (!r)
|
|
22
|
-
return "";
|
|
23
|
-
const t = (o) => o.replace(/\r\n|\r|\n/g, "<br>").replace(/\t/g, " ").replace(/ /g, " ");
|
|
24
|
-
return e?.html ? r.split(m).map((o, n) => n % 2 === 1 ? o : t(o)).join("") : t(l(r));
|
|
25
|
-
}
|
|
26
|
-
function y(r, e) {
|
|
27
|
-
const { html: t, ...o } = e ?? {}, n = h(r, o);
|
|
28
|
-
return n == null ? "" : g(String(n), { html: t });
|
|
29
|
-
}
|
|
30
|
-
function $(r, e, t) {
|
|
31
|
-
if (!r)
|
|
32
|
-
return "";
|
|
33
|
-
const o = (i) => t?.html ? i : l(i);
|
|
34
|
-
if (!e)
|
|
35
|
-
return o(r);
|
|
36
|
-
const n = e.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&").replace(/-/g, "\\x2d"), s = new RegExp(`(${n})`, t?.caseInsensitive ? "i" : ""), a = (i) => i.split(s).map((c, p) => p % 2 === 0 ? o(c) : f("mark", c, t)).join("");
|
|
37
|
-
return t?.html ? r.split(m).map((i, c) => c % 2 === 1 ? i : a(i)).join("") : a(r);
|
|
38
|
-
}
|
|
39
|
-
function x(r, e, t) {
|
|
40
|
-
const o = u(r ?? "", e ?? "", { ignoreCase: t?.ignoreCase });
|
|
41
|
-
let n = "";
|
|
42
|
-
for (const s of o)
|
|
43
|
-
s.added ? n += f("span", s.value, t?.added, d.added) : s.removed ? n += f("span", s.value, t?.removed, d.removed) : n += f("span", s.value, t?.same, d.same);
|
|
44
|
-
return n;
|
|
45
|
-
}
|
|
46
|
-
const E = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
47
|
-
__proto__: null,
|
|
48
|
-
diffForWeb: x,
|
|
49
|
-
formatJsonStringForWeb: y,
|
|
50
|
-
formatStringForWeb: g,
|
|
51
|
-
highlightWord: $
|
|
52
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
53
|
-
export {
|
|
54
|
-
g as a,
|
|
55
|
-
$ as b,
|
|
56
|
-
x as d,
|
|
57
|
-
y as f,
|
|
58
|
-
E as h
|
|
59
|
-
};
|
|
60
|
-
//# sourceMappingURL=html-util-BctKzfnH.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"html-util-BctKzfnH.js","sources":["../src/html-util.ts"],"sourcesContent":["import { diffChars } from 'diff';\nimport { formatJsonString } from './json-util';\nimport type { FormatJsonStringOptions } from './json-util';\n\n/**\n * class属性に指定する値\n * 配列は要素を空白区切りで連結し、Recordは値がtrueのキーだけを連結する\n */\nexport type HtmlClassValue = string | string[] | Record<string, boolean>;\n\n/**\n * style属性に指定する値\n * Recordのキーはキャメルケースをケバブケースに変換する。数値には単位を付けない\n */\nexport type HtmlStyleValue = string | Record<string, string | number>;\n\n/**\n * 生成するタグに付与する属性\n */\nexport interface HtmlTagOptions {\n class?: HtmlClassValue;\n style?: HtmlStyleValue;\n}\n\nconst HTML_TOKEN = /(<!--[\\s\\S]*?-->|<[^>]*>|&(?:#\\d+|#x[\\da-f]+|\\w+);)/i;\n\nconst HTML_ESCAPE_CHARS: Record<string, string> = {\n '\"': '"',\n '&': '&',\n '\\'': ''',\n '<': '<',\n '>': '>'\n};\n\nconst escapeHtml = (str: string): string => str.replace(/[\"&'<>]/g, (c) => HTML_ESCAPE_CHARS[c]);\n\nconst toClassString = (value: HtmlClassValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n if (Array.isArray(value)) {\n return value.filter(Boolean).join(' ');\n }\n return Object.keys(value).filter(key => value[key]).join(' ');\n};\n\nconst toStyleString = (value: HtmlStyleValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n return Object.entries(value)\n .map(([key, v]) => {\n // カスタムプロパティ(--xxx)は大文字小文字を区別するため変換しない\n const property = key.startsWith('--') ? key : key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);\n return `${property}: ${v}`;\n })\n .join('; ');\n};\n\n/** diffForWebの既定の文字色 */\nconst DIFF_STYLES = {\n added: 'color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))',\n removed: 'color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))',\n same: 'color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))'\n};\n\n/**\n * 値をエスケープしたタグを返す\n *\n * @param {string} tagName\n * @param {string} value\n * @param {HtmlTagOptions} [options]\n * @param {string} [defaultStyle] optionsのstyleより前に出力するstyle\n * @returns {string}\n */\nconst toElement = (tagName: string, value: string, options?: HtmlTagOptions, defaultStyle?: string): string => {\n let attributes = '';\n const className = options?.class == null ? '' : toClassString(options.class);\n if (className) {\n attributes += ` class=\"${escapeHtml(className)}\"`;\n }\n const style = [defaultStyle, options?.style == null ? '' : toStyleString(options.style)].filter(Boolean).join('; ');\n if (style) {\n attributes += ` style=\"${escapeHtml(style)}\"`;\n }\n return `<${tagName}${attributes}>${escapeHtml(value)}</${tagName}>`;\n};\n\n/**\n * 文字列をWEB表示用にフォーマットする\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * @param {string | null | undefined} str\n * @param {*} [options]\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatStringForWeb(str: string | null | undefined, options?: {\n html?: boolean;\n}): string {\n if (!str) {\n return '';\n }\n\n const formatText = (text: string): string => text\n .replace(/\\r\\n|\\r|\\n/g, '<br>')\n .replace(/\\t/g, ' ')\n .replace(/ /g, ' ');\n\n if (options?.html) {\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをフォーマットする\n return str\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : formatText(segment))\n .join('');\n }\n\n return formatText(escapeHtml(str));\n}\n\n/**\n * 値を整形したJSON文字列にしてWEB表示用にフォーマットする\n * formatJsonStringで整形した文字列をformatStringForWebで変換する\n *\n * @param {any} value\n * @param {*} [options] formatJsonStringのオプションに以下を加えたもの\n * ├ html boolean trueを指定した場合、文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatJsonStringForWeb(value: any, options?: FormatJsonStringOptions & {\n html?: boolean;\n}): string {\n const { html, ...formatOptions } = options ?? {};\n const json = formatJsonString(value, formatOptions);\n return json == null ? '' : formatStringForWeb(String(json), { html });\n}\n\n/**\n * 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * 例)\n * HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });\n * → 'This is a <mark class=\"highlight\">test</mark> message'\n *\n * @param {string | null | undefined} value\n * @param {string | null | undefined} word\n * @param {*} [options] markタグに付与するclass, styleのほか、以下を指定できる\n * ├ class string | string[] | Record<string, boolean>\n * ├ style string | Record<string, string | number>\n * ├ caseInsensitive boolean trueを指定した場合、大文字小文字を区別しない\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function highlightWord(\n value: string | null | undefined,\n word: string | null | undefined,\n options?: HtmlTagOptions & {\n caseInsensitive?: boolean;\n html?: boolean;\n }\n): string {\n if (!value) {\n return '';\n }\n\n const toHtml = (text: string): string => options?.html ? text : escapeHtml(text);\n if (!word) {\n return toHtml(value);\n }\n\n const pattern = word.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&').replace(/-/g, '\\\\x2d');\n const regex = new RegExp(`(${pattern})`, options?.caseInsensitive ? 'i' : '');\n // キャプチャグループで分割すると、奇数番目の要素が一致した部分になる\n const highlight = (text: string): string => text\n .split(regex)\n .map((part, i) => i % 2 === 0 ? toHtml(part) : toElement('mark', part, options))\n .join('');\n\n if (!options?.html) {\n return highlight(value);\n }\n\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをハイライトする\n return value\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : highlight(segment))\n .join('');\n}\n\n/**\n * 文字列を1文字ずつ比較し、差分をspanタグで囲んだHTML文字列を返す\n * 追加・削除・一致の部分ごとに既定の文字色を持つ。文字色はCSS変数(--dwui-color-text-diff-added / --dwui-color-text-diff-removed / --dwui-color-text-diff-same)で変更できる\n * 追加・削除・一致の部分ごとに、spanタグに付与するclass, styleを指定できる。styleは既定の文字色より後に出力する\n * 入力文字列はプレーンなテキストであるとみなす\n * 出力される文字列は、diffで埋め込まれるHTMLタグ以外はHTMLエスケープされ、HTMLセーフな文字列となる\n *\n * @param {string | null | undefined} text1 比較元の文字列\n * @param {string | null | undefined} text2 比較される文字列(通常、入力値はこちらに渡す)\n * @param {*} [options]\n * ├ ignoreCase boolean trueを指定した場合、大文字小文字を区別しない\n * ├ added HtmlTagOptions text2で追加された部分のspanタグに付与する属性\n * ├ removed HtmlTagOptions text2で削除された部分のspanタグに付与する属性\n * ├ same HtmlTagOptions 一致した部分のspanタグに付与する属性\n * @returns {string}\n */\nexport function diffForWeb(text1: string | null | undefined, text2: string | null | undefined, options?: {\n ignoreCase?: boolean;\n added?: HtmlTagOptions;\n removed?: HtmlTagOptions;\n same?: HtmlTagOptions;\n}): string {\n const changes = diffChars(text1 ?? '', text2 ?? '', { ignoreCase: options?.ignoreCase });\n let html = '';\n for (const change of changes) {\n if (change.added) {\n html += toElement('span', change.value, options?.added, DIFF_STYLES.added);\n } else if (change.removed) {\n html += toElement('span', change.value, options?.removed, DIFF_STYLES.removed);\n } else {\n html += toElement('span', change.value, options?.same, DIFF_STYLES.same);\n }\n }\n return html;\n}\n"],"names":["HTML_TOKEN","HTML_ESCAPE_CHARS","escapeHtml","str","c","toClassString","value","key","toStyleString","v","DIFF_STYLES","toElement","tagName","options","defaultStyle","attributes","className","style","formatStringForWeb","formatText","text","segment","i","formatJsonStringForWeb","html","formatOptions","json","formatJsonString","highlightWord","word","toHtml","pattern","regex","highlight","part","diffForWeb","text1","text2","changes","diffChars","change"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
"use strict";const S=require("diff"),j=require("./json-util-CKnsxu1e.cjs"),m=/(<!--[\s\S]*?-->|<[^>]*>|&(?:#\d+|#x[\da-f]+|\w+);)/i,y={'"':""","&":"&","'":"'","<":"<",">":">"},a=t=>t.replace(/["&'<>]/g,e=>y[e]),$=t=>typeof t=="string"?t:Array.isArray(t)?t.filter(Boolean).join(" "):Object.keys(t).filter(e=>t[e]).join(" "),W=t=>typeof t=="string"?t:Object.entries(t).map(([e,r])=>`${e.startsWith("--")?e:e.replace(/[A-Z]/g,n=>`-${n.toLowerCase()}`)}: ${r}`).join("; "),d={added:"color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))",removed:"color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))",same:"color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))"},f=(t,e,r,o)=>{let n="";const i=r?.class==null?"":$(r.class);i&&(n+=` class="${a(i)}"`);const l=[o,r?.style==null?"":W(r.style)].filter(Boolean).join("; ");return l&&(n+=` style="${a(l)}"`),`<${t}${n}>${a(e)}</${t}>`};function g(t,e){if(!t)return"";const r=o=>o.replace(/\r\n|\r|\n/g,"<br>").replace(/\t/g," ").replace(/ /g," ");return e?.html?t.split(m).map((o,n)=>n%2===1?o:r(o)).join(""):r(a(t))}function u(t,e){const{html:r,...o}=e??{},n=j.formatJsonString(t,o);return n==null?"":g(String(n),{html:r})}function h(t,e,r){if(!t)return"";const o=s=>r?.html?s:a(s);if(!e)return o(t);const n=e.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&").replace(/-/g,"\\x2d"),i=new RegExp(`(${n})`,r?.caseInsensitive?"i":""),l=s=>s.split(i).map((c,b)=>b%2===0?o(c):f("mark",c,r)).join("");return r?.html?t.split(m).map((s,c)=>c%2===1?s:l(s)).join(""):l(t)}function p(t,e,r){const o=S.diffChars(t??"",e??"",{ignoreCase:r?.ignoreCase});let n="";for(const i of o)i.added?n+=f("span",i.value,r?.added,d.added):i.removed?n+=f("span",i.value,r?.removed,d.removed):n+=f("span",i.value,r?.same,d.same);return n}const F=Object.freeze(Object.defineProperty({__proto__:null,diffForWeb:p,formatJsonStringForWeb:u,formatStringForWeb:g,highlightWord:h},Symbol.toStringTag,{value:"Module"}));exports.diffForWeb=p;exports.formatJsonStringForWeb=u;exports.formatStringForWeb=g;exports.highlightWord=h;exports.htmlUtil=F;
|
|
2
|
-
//# sourceMappingURL=html-util-ELyFVsxl.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"html-util-ELyFVsxl.cjs","sources":["../src/html-util.ts"],"sourcesContent":["import { diffChars } from 'diff';\nimport { formatJsonString } from './json-util';\nimport type { FormatJsonStringOptions } from './json-util';\n\n/**\n * class属性に指定する値\n * 配列は要素を空白区切りで連結し、Recordは値がtrueのキーだけを連結する\n */\nexport type HtmlClassValue = string | string[] | Record<string, boolean>;\n\n/**\n * style属性に指定する値\n * Recordのキーはキャメルケースをケバブケースに変換する。数値には単位を付けない\n */\nexport type HtmlStyleValue = string | Record<string, string | number>;\n\n/**\n * 生成するタグに付与する属性\n */\nexport interface HtmlTagOptions {\n class?: HtmlClassValue;\n style?: HtmlStyleValue;\n}\n\nconst HTML_TOKEN = /(<!--[\\s\\S]*?-->|<[^>]*>|&(?:#\\d+|#x[\\da-f]+|\\w+);)/i;\n\nconst HTML_ESCAPE_CHARS: Record<string, string> = {\n '\"': '"',\n '&': '&',\n '\\'': ''',\n '<': '<',\n '>': '>'\n};\n\nconst escapeHtml = (str: string): string => str.replace(/[\"&'<>]/g, (c) => HTML_ESCAPE_CHARS[c]);\n\nconst toClassString = (value: HtmlClassValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n if (Array.isArray(value)) {\n return value.filter(Boolean).join(' ');\n }\n return Object.keys(value).filter(key => value[key]).join(' ');\n};\n\nconst toStyleString = (value: HtmlStyleValue): string => {\n if (typeof value === 'string') {\n return value;\n }\n return Object.entries(value)\n .map(([key, v]) => {\n // カスタムプロパティ(--xxx)は大文字小文字を区別するため変換しない\n const property = key.startsWith('--') ? key : key.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);\n return `${property}: ${v}`;\n })\n .join('; ');\n};\n\n/** diffForWebの既定の文字色 */\nconst DIFF_STYLES = {\n added: 'color: var(--dwui-color-text-diff-added, light-dark(#006400, rgb(121, 227, 121)))',\n removed: 'color: var(--dwui-color-text-diff-removed, light-dark(#ff0000, rgb(222, 109, 109)))',\n same: 'color: var(--dwui-color-text-diff-same, light-dark(#838383, #808080))'\n};\n\n/**\n * 値をエスケープしたタグを返す\n *\n * @param {string} tagName\n * @param {string} value\n * @param {HtmlTagOptions} [options]\n * @param {string} [defaultStyle] optionsのstyleより前に出力するstyle\n * @returns {string}\n */\nconst toElement = (tagName: string, value: string, options?: HtmlTagOptions, defaultStyle?: string): string => {\n let attributes = '';\n const className = options?.class == null ? '' : toClassString(options.class);\n if (className) {\n attributes += ` class=\"${escapeHtml(className)}\"`;\n }\n const style = [defaultStyle, options?.style == null ? '' : toStyleString(options.style)].filter(Boolean).join('; ');\n if (style) {\n attributes += ` style=\"${escapeHtml(style)}\"`;\n }\n return `<${tagName}${attributes}>${escapeHtml(value)}</${tagName}>`;\n};\n\n/**\n * 文字列をWEB表示用にフォーマットする\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * @param {string | null | undefined} str\n * @param {*} [options]\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatStringForWeb(str: string | null | undefined, options?: {\n html?: boolean;\n}): string {\n if (!str) {\n return '';\n }\n\n const formatText = (text: string): string => text\n .replace(/\\r\\n|\\r|\\n/g, '<br>')\n .replace(/\\t/g, ' ')\n .replace(/ /g, ' ');\n\n if (options?.html) {\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをフォーマットする\n return str\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : formatText(segment))\n .join('');\n }\n\n return formatText(escapeHtml(str));\n}\n\n/**\n * 値を整形したJSON文字列にしてWEB表示用にフォーマットする\n * formatJsonStringで整形した文字列をformatStringForWebで変換する\n *\n * @param {any} value\n * @param {*} [options] formatJsonStringのオプションに以下を加えたもの\n * ├ html boolean trueを指定した場合、文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function formatJsonStringForWeb(value: any, options?: FormatJsonStringOptions & {\n html?: boolean;\n}): string {\n const { html, ...formatOptions } = options ?? {};\n const json = formatJsonString(value, formatOptions);\n return json == null ? '' : formatStringForWeb(String(json), { html });\n}\n\n/**\n * 文字列の中で一致したワードをmarkタグで囲んだHTML文字列を返す\n * オプションのhtmlにより、入力文字列がHTMLなのかプレーンテキストなのかを指定可能\n *\n * 例)\n * HtmlUtil.highlightWord('This is a test message', 'test', { class: 'highlight' });\n * → 'This is a <mark class=\"highlight\">test</mark> message'\n *\n * @param {string | null | undefined} value\n * @param {string | null | undefined} word\n * @param {*} [options] markタグに付与するclass, styleのほか、以下を指定できる\n * ├ class string | string[] | Record<string, boolean>\n * ├ style string | Record<string, string | number>\n * ├ caseInsensitive boolean trueを指定した場合、大文字小文字を区別しない\n * ├ html boolean trueを指定した場合、入力された文字列をHTMLとして扱う\n * @returns {string}\n */\nexport function highlightWord(\n value: string | null | undefined,\n word: string | null | undefined,\n options?: HtmlTagOptions & {\n caseInsensitive?: boolean;\n html?: boolean;\n }\n): string {\n if (!value) {\n return '';\n }\n\n const toHtml = (text: string): string => options?.html ? text : escapeHtml(text);\n if (!word) {\n return toHtml(value);\n }\n\n const pattern = word.replace(/[|\\\\{}()[\\]^$+*?.]/g, '\\\\$&').replace(/-/g, '\\\\x2d');\n const regex = new RegExp(`(${pattern})`, options?.caseInsensitive ? 'i' : '');\n // キャプチャグループで分割すると、奇数番目の要素が一致した部分になる\n const highlight = (text: string): string => text\n .split(regex)\n .map((part, i) => i % 2 === 0 ? toHtml(part) : toElement('mark', part, options))\n .join('');\n\n if (!options?.html) {\n return highlight(value);\n }\n\n // 奇数番目がタグ・コメント・文字参照。偶数番目のテキスト部分だけをハイライトする\n return value\n .split(HTML_TOKEN)\n .map((segment, i) => i % 2 === 1 ? segment : highlight(segment))\n .join('');\n}\n\n/**\n * 文字列を1文字ずつ比較し、差分をspanタグで囲んだHTML文字列を返す\n * 追加・削除・一致の部分ごとに既定の文字色を持つ。文字色はCSS変数(--dwui-color-text-diff-added / --dwui-color-text-diff-removed / --dwui-color-text-diff-same)で変更できる\n * 追加・削除・一致の部分ごとに、spanタグに付与するclass, styleを指定できる。styleは既定の文字色より後に出力する\n * 入力文字列はプレーンなテキストであるとみなす\n * 出力される文字列は、diffで埋め込まれるHTMLタグ以外はHTMLエスケープされ、HTMLセーフな文字列となる\n *\n * @param {string | null | undefined} text1 比較元の文字列\n * @param {string | null | undefined} text2 比較される文字列(通常、入力値はこちらに渡す)\n * @param {*} [options]\n * ├ ignoreCase boolean trueを指定した場合、大文字小文字を区別しない\n * ├ added HtmlTagOptions text2で追加された部分のspanタグに付与する属性\n * ├ removed HtmlTagOptions text2で削除された部分のspanタグに付与する属性\n * ├ same HtmlTagOptions 一致した部分のspanタグに付与する属性\n * @returns {string}\n */\nexport function diffForWeb(text1: string | null | undefined, text2: string | null | undefined, options?: {\n ignoreCase?: boolean;\n added?: HtmlTagOptions;\n removed?: HtmlTagOptions;\n same?: HtmlTagOptions;\n}): string {\n const changes = diffChars(text1 ?? '', text2 ?? '', { ignoreCase: options?.ignoreCase });\n let html = '';\n for (const change of changes) {\n if (change.added) {\n html += toElement('span', change.value, options?.added, DIFF_STYLES.added);\n } else if (change.removed) {\n html += toElement('span', change.value, options?.removed, DIFF_STYLES.removed);\n } else {\n html += toElement('span', change.value, options?.same, DIFF_STYLES.same);\n }\n }\n return html;\n}\n"],"names":["HTML_TOKEN","HTML_ESCAPE_CHARS","escapeHtml","str","c","toClassString","value","key","toStyleString","v","DIFF_STYLES","toElement","tagName","options","defaultStyle","attributes","className","style","formatStringForWeb","formatText","text","segment","i","formatJsonStringForWeb","html","formatOptions","json","formatJsonString","highlightWord","word","toHtml","pattern","regex","highlight","part","diffForWeb","text1","text2","changes","diffChars","change"],"mappings":"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"}
|