diff --git a/lib/commons/record-util.d.ts b/lib/commons/record-util.d.ts index 4801616..5bf9914 100644 --- a/lib/commons/record-util.d.ts +++ b/lib/commons/record-util.d.ts @@ -1,11 +1,33 @@ -import { UnwrapNestedRefs } from 'vue'; -declare enum ClearMode { - clear = 3, +import { UnwrapNestedRefs } from "vue"; +export declare enum RecordClearMode { delete = 2, reset = 1 } export declare const withRecord: (obj: UnwrapNestedRefs>) => { - clear: (mode?: ClearMode) => void; + clear: (mode?: RecordClearMode) => void; replace: (newVal: UnwrapNestedRefs>) => void; }; -export {}; +/** + * 这是一个泛型函数,接受任意个数的数组作为参数,并返回一个对象。 + * 该对象包含两个方法:test 和 path。 + * test 方法用于测试所有数组的元素是否相等, + * path 方法用于测试所有数组的指定路径的值是否相等。 + + * @param arrays + * @returns + */ +export declare function assignRecords>(...arrays: T[][]): { + test: (equal?: ((l: T, r: T) => boolean) | undefined) => T[]; + path: (...paths: string[]) => T[]; +}; +/** + * + * 接受一个目标对象和多个源对象作为参数,并返回合并后的对象。 + * 它会将源对象的属性复制到目标对象中, + * 如果多个源对象有同名属性, + * 则最后的属性值将覆盖前面的属性值。 + * @param target 目标对象 + * @param sources 来源对象参数 + * @returns 目标对象 + */ +export declare const extend: >(target: T, ...sources: (T | undefined)[]) => T; diff --git a/lib/index.d.ts b/lib/index.d.ts index 09592a1..0d3af21 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -1,3 +1,3 @@ -import { withRecord } from "./commons/record-util"; +import { withRecord, assignRecords, RecordClearMode } from "./commons/record-util"; import { stringTokenizer, equalsIgnoreCase, includeIgnoreCase } from "./commons/str-utils"; -export { stringTokenizer, withRecord, equalsIgnoreCase, includeIgnoreCase }; +export { stringTokenizer, withRecord, equalsIgnoreCase, includeIgnoreCase, assignRecords, RecordClearMode }; diff --git a/lib/index.es.js b/lib/index.es.js index 01d886a..2f01d46 100644 --- a/lib/index.es.js +++ b/lib/index.es.js @@ -1,45 +1,66 @@ -const h = (e) => ({ +var c = /* @__PURE__ */ ((e) => (e[e.delete = 2] = "delete", e[e.reset = 1] = "reset", e))(c || {}); +const g = (e) => ({ clear: function(t = 2) { t === 1 ? Object.keys(e).forEach((n) => { e[n] = void 0; - }) : t === 2 ? Object.keys(e).forEach((n) => { + }) : t === 2 && Object.keys(e).forEach((n) => { delete e[n]; - }) : Object.assign(e, {}); + }); }, replace: function(t) { this.clear( - 3 - /* clear */ + 2 + /* delete */ ), Object.assign(e, t); } }); -function g(e, t, n) { - const f = t, o = n || t; - return function(i) { - const s = [], u = i.matchAll(e); - let r = 0; - for (const c of u) { - const l = i.slice(r, c.index); - l && s.push(o(l, !1)), s.push(f(c[0], !0)), r = c.index + c[0].length; +function p(...e) { + let t = e ?? []; + return { + test: function(n) { + if (t.length <= 1) + return t.length === 1 ? t[0] : []; + let i = n ?? function(s, r) { + return s === r; + }; + return t.reduce((s, r) => (r && r.length > 0 && (s.length === 0 ? s.push(...r) : r.forEach((u) => { + s.some((f) => i(f, u)) || s.push(u); + })), s), []); + }, + path: function(...n) { + return this.test((i, s) => n.every((r) => i[r] === s[r])); } - return r < i.length && s.push(o(i.slice(r), !1)), s; + }; +} +function y(e, t, n) { + const i = t, s = n || t; + return function(r) { + const u = [], l = r.matchAll(e); + let f = 0; + for (const o of l) { + const h = r.slice(f, o.index); + h && u.push(s(h, !1)), u.push(i(o[0], !0)), f = o.index + o[0].length; + } + return f < r.length && u.push(s(r.slice(f), !1)), u; }; } function a(e, t) { return typeof e == "string" && typeof t == "string" ? e.toLowerCase() === t.toLowerCase() : e === void 0 && t === void 0; } -const p = (e, t) => { +const m = (e, t) => { for (let n = 0; n < e.length; n++) { - let f = e[n]; - if (a(f, t)) + let i = e[n]; + if (a(i, t)) return !0; } return !1; }; export { + c as RecordClearMode, + p as assignRecords, a as equalsIgnoreCase, - p as includeIgnoreCase, - g as stringTokenizer, - h as withRecord + m as includeIgnoreCase, + y as stringTokenizer, + g as withRecord }; //# sourceMappingURL=index.es.js.map diff --git a/lib/index.es.js.map b/lib/index.es.js.map index 9402ca1..a06963f 100644 --- a/lib/index.es.js.map +++ b/lib/index.es.js.map @@ -1 +1 @@ -{"version":3,"file":"index.es.js","sources":["../src/commons/record-util.ts","../src/commons/str-utils.ts"],"sourcesContent":["import { UnwrapNestedRefs } from 'vue';\r\nenum ClearMode {\r\n clear = 3,\r\n delete = 2,\r\n reset = 1\r\n}\r\nexport const withRecord = (\r\n obj: UnwrapNestedRefs>,\r\n) => {\r\n\r\n return {\r\n clear: function (mode: ClearMode = ClearMode.delete) {\r\n if (mode === ClearMode.reset) {\r\n Object.keys(obj).forEach((key) => {\r\n obj[key] = undefined;\r\n });\r\n } else if (mode === ClearMode.delete) {\r\n Object.keys(obj).forEach((key) => {\r\n delete obj[key];\r\n });\r\n } else {\r\n Object.assign(obj, {});\r\n }\r\n },\r\n replace: function (newVal: UnwrapNestedRefs>) {\r\n this.clear(ClearMode.clear);\r\n Object.assign(obj, newVal);\r\n }\r\n };\r\n};","/**\r\n * 生成给定函数体的函数注释。\r\n *\r\n * @param {RegExp} regExp - 用于匹配的正则表达式。\r\n * @param {(text: string, match: boolean) => T} matchHandler - 处理匹配到的文本的函数。\r\n * @param {(text: string, match: boolean) => T} [textHandler] - 处理未匹配到的文本的函数。\r\n * @return {(str: string) => T[]} - 分词器函数。\r\n */\r\nexport function stringTokenizer(\r\n regExp: RegExp,\r\n matchHandler: (text: string, match: boolean) => T,\r\n textHandler?: (text: string, match: boolean) => T\r\n): (str: string) => T[] {\r\n\r\n const ifMatch = matchHandler;\r\n const ifText = textHandler?textHandler: matchHandler;\r\n\r\n return function (str: string) {\r\n const result: T[] = [];\r\n const matches = str.matchAll(regExp);\r\n let index = 0;\r\n for (const match of matches) {\r\n const before = str.slice(index, match.index);\r\n if (before) {\r\n result.push(ifText(before, false));\r\n }\r\n result.push(ifMatch(match[0], true));\r\n index = match.index! + match[0].length;\r\n }\r\n if (index < str.length) {\r\n result.push(ifText(str.slice(index), false));\r\n }\r\n return result;\r\n };\r\n}\r\n\r\n/**\r\n * 该函数接受两个参数,判断它们是否相等,不区分大小写。\r\n * 如果参数都是字符串类型,则将它们转换为小写后比较。\r\n * 如果两个参数都是undefined,则返回true,\r\n * 否则返回false。\r\n * @param source \r\n * @param target \r\n * @returns \r\n */\r\nexport function equalsIgnoreCase(\r\n source: string | undefined,\r\n target: string | undefined\r\n) {\r\n if (typeof source === \"string\" && typeof target === \"string\") {\r\n return source.toLowerCase() === target.toLowerCase();\r\n } else if (source === undefined && target === undefined) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * 这个函数接受一个字符串数组和一个字符串作为参数,\r\n * 在数组中判断是否存在与搜索字符串相同或相似的字符串,忽略大小写。\r\n * 如果找到匹配项则返回true,否则返回false。\r\n * @param list 字符串数组\r\n * @param search 用来搜索的字符串\r\n * @returns 是否包含\r\n */\r\nexport const includeIgnoreCase = (list: string[], search: string) => {\r\n for (let i = 0; i < list.length; i++) {\r\n let item = list[i];\r\n if (equalsIgnoreCase(item, search)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n"],"names":["withRecord","obj","mode","key","newVal","stringTokenizer","regExp","matchHandler","textHandler","ifMatch","ifText","str","result","matches","index","match","before","equalsIgnoreCase","source","target","includeIgnoreCase","list","search","i","item"],"mappings":"AAMa,MAAAA,IAAa,CACtBC,OAGO;AAAA,EACH,OAAO,SAAUC,IAAkB,GAAkB;AACjD,IAAIA,MAAS,IACT,OAAO,KAAKD,CAAG,EAAE,QAAQ,CAACE,MAAQ;AAC9B,MAAAF,EAAIE,CAAG,IAAI;AAAA,IAAA,CACd,IACMD,MAAS,IAChB,OAAO,KAAKD,CAAG,EAAE,QAAQ,CAACE,MAAQ;AAC9B,aAAOF,EAAIE,CAAG;AAAA,IAAA,CACjB,IAEM,OAAA,OAAOF,GAAK,CAAA,CAAE;AAAA,EAE7B;AAAA,EACA,SAAS,SAAUG,GAA+C;AAC9D,SAAK;AAAA,MAAM;AAAA;AAAA,OACJ,OAAA,OAAOH,GAAKG,CAAM;AAAA,EAC7B;AAAA;ACnBQ,SAAAC,EACdC,GACAC,GACAC,GACsB;AAEtB,QAAMC,IAAUF,GACVG,IAASF,KAAyBD;AAExC,SAAO,SAAUI,GAAa;AAC5B,UAAMC,IAAc,CAAA,GACdC,IAAUF,EAAI,SAASL,CAAM;AACnC,QAAIQ,IAAQ;AACZ,eAAWC,KAASF,GAAS;AAC3B,YAAMG,IAASL,EAAI,MAAMG,GAAOC,EAAM,KAAK;AAC3C,MAAIC,KACFJ,EAAO,KAAKF,EAAOM,GAAQ,EAAK,CAAC,GAEnCJ,EAAO,KAAKH,EAAQM,EAAM,CAAC,GAAG,EAAI,CAAC,GACnCD,IAAQC,EAAM,QAASA,EAAM,CAAC,EAAE;AAAA,IAClC;AACI,WAAAD,IAAQH,EAAI,UACdC,EAAO,KAAKF,EAAOC,EAAI,MAAMG,CAAK,GAAG,EAAK,CAAC,GAEtCF;AAAA,EAAA;AAEX;AAWgB,SAAAK,EACdC,GACAC,GACA;AACA,SAAI,OAAOD,KAAW,YAAY,OAAOC,KAAW,WAC3CD,EAAO,YAAA,MAAkBC,EAAO,YAAY,IAC1CD,MAAW,UAAaC,MAAW;AAIhD;AAUa,MAAAC,IAAoB,CAACC,GAAgBC,MAAmB;AACnE,WAASC,IAAI,GAAGA,IAAIF,EAAK,QAAQE,KAAK;AAChC,QAAAC,IAAOH,EAAKE,CAAC;AACb,QAAAN,EAAiBO,GAAMF,CAAM;AACxB,aAAA;AAAA,EAEX;AACO,SAAA;AACT;"} \ No newline at end of file +{"version":3,"file":"index.es.js","sources":["../src/commons/record-util.ts","../src/commons/str-utils.ts"],"sourcesContent":["import { UnwrapNestedRefs } from \"vue\";\r\nexport enum RecordClearMode {\r\n delete = 2,\r\n reset = 1,\r\n}\r\nexport const withRecord = (obj: UnwrapNestedRefs>) => {\r\n return {\r\n clear: function (mode: RecordClearMode = RecordClearMode.delete) {\r\n if (mode === RecordClearMode.reset) {\r\n Object.keys(obj).forEach((key) => {\r\n obj[key] = undefined;\r\n });\r\n } else if (mode === RecordClearMode.delete) {\r\n Object.keys(obj).forEach((key) => {\r\n delete obj[key];\r\n });\r\n }\r\n },\r\n replace: function (newVal: UnwrapNestedRefs>) {\r\n this.clear(RecordClearMode.delete);\r\n Object.assign(obj, newVal);\r\n },\r\n };\r\n};\r\n\r\n/**\r\n * 这是一个泛型函数,接受任意个数的数组作为参数,并返回一个对象。\r\n * 该对象包含两个方法:test 和 path。\r\n * test 方法用于测试所有数组的元素是否相等,\r\n * path 方法用于测试所有数组的指定路径的值是否相等。\r\n\r\n * @param arrays \r\n * @returns \r\n */\r\nexport function assignRecords>(...arrays: T[][]) {\r\n let _arrays = arrays ?? [];\r\n\r\n return {\r\n test: function (equal?: (l: T, r: T) => boolean) {\r\n if (_arrays.length <= 1) {\r\n return _arrays.length === 1 ? _arrays[0] : [];\r\n }\r\n\r\n let localEqual =\r\n equal ??\r\n function (ll: T, rr: T) {\r\n return ll === rr;\r\n };\r\n return _arrays.reduce((acc, crt) => {\r\n if (crt && crt.length > 0) {\r\n if (acc.length === 0) {\r\n acc.push(...crt);\r\n } else {\r\n crt.forEach((c) => {\r\n const some = acc.some((a) => localEqual(a, c));\r\n if (!some) {\r\n acc.push(c);\r\n }\r\n });\r\n }\r\n }\r\n return acc;\r\n }, []);\r\n },\r\n path: function (...paths: string[]) {\r\n return this.test((l, r) => {\r\n return paths.every((path) => {\r\n return l[path] === r[path];\r\n });\r\n });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n *\r\n * 接受一个目标对象和多个源对象作为参数,并返回合并后的对象。\r\n * 它会将源对象的属性复制到目标对象中,\r\n * 如果多个源对象有同名属性,\r\n * 则最后的属性值将覆盖前面的属性值。\r\n * @param target 目标对象\r\n * @param sources 来源对象参数\r\n * @returns 目标对象\r\n */\r\nexport const extend = >(\r\n // 目标对象\r\n target: T,\r\n // 其他对象参数\r\n ...sources: (T | undefined)[]\r\n): T => {\r\n // 遍历其他对象参数\r\n for (const source of sources) {\r\n if (source !== undefined) {\r\n // 遍历参数对象的属性\r\n for (const key in source) {\r\n // 判断属性存在于参数对象中且值不为 null\r\n if (source.hasOwnProperty(key) && source[key] != null) {\r\n // 将属性赋值给目标对象\r\n target[key] = source[key];\r\n }\r\n }\r\n }\r\n }\r\n // 返回目标对象\r\n return target;\r\n};\r\n","/**\r\n * 生成给定函数体的函数注释。\r\n *\r\n * @param {RegExp} regExp - 用于匹配的正则表达式。\r\n * @param {(text: string, match: boolean) => T} matchHandler - 处理匹配到的文本的函数。\r\n * @param {(text: string, match: boolean) => T} [textHandler] - 处理未匹配到的文本的函数。\r\n * @return {(str: string) => T[]} - 分词器函数。\r\n */\r\nexport function stringTokenizer(\r\n regExp: RegExp,\r\n matchHandler: (text: string, match: boolean) => T,\r\n textHandler?: (text: string, match: boolean) => T\r\n): (str: string) => T[] {\r\n\r\n const ifMatch = matchHandler;\r\n const ifText = textHandler?textHandler: matchHandler;\r\n\r\n return function (str: string) {\r\n const result: T[] = [];\r\n const matches = str.matchAll(regExp);\r\n let index = 0;\r\n for (const match of matches) {\r\n const before = str.slice(index, match.index);\r\n if (before) {\r\n result.push(ifText(before, false));\r\n }\r\n result.push(ifMatch(match[0], true));\r\n index = match.index! + match[0].length;\r\n }\r\n if (index < str.length) {\r\n result.push(ifText(str.slice(index), false));\r\n }\r\n return result;\r\n };\r\n}\r\n\r\n/**\r\n * 该函数接受两个参数,判断它们是否相等,不区分大小写。\r\n * 如果参数都是字符串类型,则将它们转换为小写后比较。\r\n * 如果两个参数都是undefined,则返回true,\r\n * 否则返回false。\r\n * @param source \r\n * @param target \r\n * @returns \r\n */\r\nexport function equalsIgnoreCase(\r\n source: string | undefined,\r\n target: string | undefined\r\n) {\r\n if (typeof source === \"string\" && typeof target === \"string\") {\r\n return source.toLowerCase() === target.toLowerCase();\r\n } else if (source === undefined && target === undefined) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * 这个函数接受一个字符串数组和一个字符串作为参数,\r\n * 在数组中判断是否存在与搜索字符串相同或相似的字符串,忽略大小写。\r\n * 如果找到匹配项则返回true,否则返回false。\r\n * @param list 字符串数组\r\n * @param search 用来搜索的字符串\r\n * @returns 是否包含\r\n */\r\nexport const includeIgnoreCase = (list: string[], search: string) => {\r\n for (let i = 0; i < list.length; i++) {\r\n let item = list[i];\r\n if (equalsIgnoreCase(item, search)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n"],"names":["RecordClearMode","withRecord","obj","mode","key","newVal","assignRecords","arrays","_arrays","equal","localEqual","ll","rr","acc","crt","c","a","paths","l","r","path","stringTokenizer","regExp","matchHandler","textHandler","ifMatch","ifText","str","result","matches","index","match","before","equalsIgnoreCase","source","target","includeIgnoreCase","list","search","i","item"],"mappings":"AACY,IAAAA,sBAAAA,OACVA,EAAAA,EAAA,SAAS,CAAT,IAAA,UACAA,EAAAA,EAAA,QAAQ,CAAR,IAAA,SAFUA,IAAAA,KAAA,CAAA,CAAA;AAIC,MAAAC,IAAa,CAACC,OAClB;AAAA,EACL,OAAO,SAAUC,IAAwB,GAAwB;AAC/D,IAAIA,MAAS,IACX,OAAO,KAAKD,CAAG,EAAE,QAAQ,CAACE,MAAQ;AAChC,MAAAF,EAAIE,CAAG,IAAI;AAAA,IAAA,CACZ,IACQD,MAAS,KAClB,OAAO,KAAKD,CAAG,EAAE,QAAQ,CAACE,MAAQ;AAChC,aAAOF,EAAIE,CAAG;AAAA,IAAA,CACf;AAAA,EAEL;AAAA,EACA,SAAS,SAAUC,GAA+C;AAChE,SAAK;AAAA,MAAM;AAAA;AAAA,OACJ,OAAA,OAAOH,GAAKG,CAAM;AAAA,EAC3B;AAAA;AAaG,SAASC,KAAgDC,GAAe;AACzE,MAAAC,IAAUD,KAAU;AAEjB,SAAA;AAAA,IACL,MAAM,SAAUE,GAAiC;AAC3C,UAAAD,EAAQ,UAAU;AACpB,eAAOA,EAAQ,WAAW,IAAIA,EAAQ,CAAC,IAAI;AAG7C,UAAIE,IACFD,KACA,SAAUE,GAAOC,GAAO;AACtB,eAAOD,MAAOC;AAAA,MAAA;AAElB,aAAOJ,EAAQ,OAAO,CAACK,GAAKC,OACtBA,KAAOA,EAAI,SAAS,MAClBD,EAAI,WAAW,IACbA,EAAA,KAAK,GAAGC,CAAG,IAEXA,EAAA,QAAQ,CAACC,MAAM;AAEjB,QADaF,EAAI,KAAK,CAACG,MAAMN,EAAWM,GAAGD,CAAC,CAAC,KAE3CF,EAAI,KAAKE,CAAC;AAAA,MACZ,CACD,IAGEF,IACN,CAAE,CAAA;AAAA,IACP;AAAA,IACA,MAAM,YAAaI,GAAiB;AAClC,aAAO,KAAK,KAAK,CAACC,GAAGC,MACZF,EAAM,MAAM,CAACG,MACXF,EAAEE,CAAI,MAAMD,EAAEC,CAAI,CAC1B,CACF;AAAA,IACH;AAAA,EAAA;AAEJ;AChEgB,SAAAC,EACdC,GACAC,GACAC,GACsB;AAEtB,QAAMC,IAAUF,GACVG,IAASF,KAAyBD;AAExC,SAAO,SAAUI,GAAa;AAC5B,UAAMC,IAAc,CAAA,GACdC,IAAUF,EAAI,SAASL,CAAM;AACnC,QAAIQ,IAAQ;AACZ,eAAWC,KAASF,GAAS;AAC3B,YAAMG,IAASL,EAAI,MAAMG,GAAOC,EAAM,KAAK;AAC3C,MAAIC,KACFJ,EAAO,KAAKF,EAAOM,GAAQ,EAAK,CAAC,GAEnCJ,EAAO,KAAKH,EAAQM,EAAM,CAAC,GAAG,EAAI,CAAC,GACnCD,IAAQC,EAAM,QAASA,EAAM,CAAC,EAAE;AAAA,IAClC;AACI,WAAAD,IAAQH,EAAI,UACdC,EAAO,KAAKF,EAAOC,EAAI,MAAMG,CAAK,GAAG,EAAK,CAAC,GAEtCF;AAAA,EAAA;AAEX;AAWgB,SAAAK,EACdC,GACAC,GACA;AACA,SAAI,OAAOD,KAAW,YAAY,OAAOC,KAAW,WAC3CD,EAAO,YAAA,MAAkBC,EAAO,YAAY,IAC1CD,MAAW,UAAaC,MAAW;AAIhD;AAUa,MAAAC,IAAoB,CAACC,GAAgBC,MAAmB;AACnE,WAASC,IAAI,GAAGA,IAAIF,EAAK,QAAQE,KAAK;AAChC,QAAAC,IAAOH,EAAKE,CAAC;AACb,QAAAN,EAAiBO,GAAMF,CAAM;AACxB,aAAA;AAAA,EAEX;AACO,SAAA;AACT;"} \ No newline at end of file diff --git a/lib/index.umd.js b/lib/index.umd.js index ead6daa..6f260a6 100644 --- a/lib/index.umd.js +++ b/lib/index.umd.js @@ -1,2 +1,2 @@ -(function(i,s){typeof exports=="object"&&typeof module<"u"?s(exports):typeof define=="function"&&define.amd?define(["exports"],s):(i=typeof globalThis<"u"?globalThis:i||self,s(i["ez-common-ts"]={}))})(this,function(i){"use strict";const s=e=>({clear:function(n=2){n===1?Object.keys(e).forEach(t=>{e[t]=void 0}):n===2?Object.keys(e).forEach(t=>{delete e[t]}):Object.assign(e,{})},replace:function(n){this.clear(3),Object.assign(e,n)}});function h(e,n,t){const u=n,a=t||n;return function(o){const f=[],p=o.matchAll(e);let c=0;for(const r of p){const d=o.slice(c,r.index);d&&f.push(a(d,!1)),f.push(u(r[0],!0)),c=r.index+r[0].length}return c{for(let t=0;t(e[e.delete=2]="delete",e[e.reset=1]="reset",e))(o||{});const g=e=>({clear:function(n=2){n===1?Object.keys(e).forEach(t=>{e[t]=void 0}):n===2&&Object.keys(e).forEach(t=>{delete e[t]})},replace:function(n){this.clear(2),Object.assign(e,n)}});function m(...e){let n=e??[];return{test:function(t){if(n.length<=1)return n.length===1?n[0]:[];let u=t??function(s,i){return s===i};return n.reduce((s,i)=>(i&&i.length>0&&(s.length===0?s.push(...i):i.forEach(f=>{s.some(l=>u(l,f))||s.push(f)})),s),[])},path:function(...t){return this.test((u,s)=>t.every(i=>u[i]===s[i]))}}}function p(e,n,t){const u=n,s=t||n;return function(i){const f=[],a=i.matchAll(e);let l=0;for(const c of a){const d=i.slice(l,c.index);d&&f.push(s(d,!1)),f.push(u(c[0],!0)),l=c.index+c[0].length}return l{for(let t=0;t>,\r\n) => {\r\n\r\n return {\r\n clear: function (mode: ClearMode = ClearMode.delete) {\r\n if (mode === ClearMode.reset) {\r\n Object.keys(obj).forEach((key) => {\r\n obj[key] = undefined;\r\n });\r\n } else if (mode === ClearMode.delete) {\r\n Object.keys(obj).forEach((key) => {\r\n delete obj[key];\r\n });\r\n } else {\r\n Object.assign(obj, {});\r\n }\r\n },\r\n replace: function (newVal: UnwrapNestedRefs>) {\r\n this.clear(ClearMode.clear);\r\n Object.assign(obj, newVal);\r\n }\r\n };\r\n};","/**\r\n * 生成给定函数体的函数注释。\r\n *\r\n * @param {RegExp} regExp - 用于匹配的正则表达式。\r\n * @param {(text: string, match: boolean) => T} matchHandler - 处理匹配到的文本的函数。\r\n * @param {(text: string, match: boolean) => T} [textHandler] - 处理未匹配到的文本的函数。\r\n * @return {(str: string) => T[]} - 分词器函数。\r\n */\r\nexport function stringTokenizer(\r\n regExp: RegExp,\r\n matchHandler: (text: string, match: boolean) => T,\r\n textHandler?: (text: string, match: boolean) => T\r\n): (str: string) => T[] {\r\n\r\n const ifMatch = matchHandler;\r\n const ifText = textHandler?textHandler: matchHandler;\r\n\r\n return function (str: string) {\r\n const result: T[] = [];\r\n const matches = str.matchAll(regExp);\r\n let index = 0;\r\n for (const match of matches) {\r\n const before = str.slice(index, match.index);\r\n if (before) {\r\n result.push(ifText(before, false));\r\n }\r\n result.push(ifMatch(match[0], true));\r\n index = match.index! + match[0].length;\r\n }\r\n if (index < str.length) {\r\n result.push(ifText(str.slice(index), false));\r\n }\r\n return result;\r\n };\r\n}\r\n\r\n/**\r\n * 该函数接受两个参数,判断它们是否相等,不区分大小写。\r\n * 如果参数都是字符串类型,则将它们转换为小写后比较。\r\n * 如果两个参数都是undefined,则返回true,\r\n * 否则返回false。\r\n * @param source \r\n * @param target \r\n * @returns \r\n */\r\nexport function equalsIgnoreCase(\r\n source: string | undefined,\r\n target: string | undefined\r\n) {\r\n if (typeof source === \"string\" && typeof target === \"string\") {\r\n return source.toLowerCase() === target.toLowerCase();\r\n } else if (source === undefined && target === undefined) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * 这个函数接受一个字符串数组和一个字符串作为参数,\r\n * 在数组中判断是否存在与搜索字符串相同或相似的字符串,忽略大小写。\r\n * 如果找到匹配项则返回true,否则返回false。\r\n * @param list 字符串数组\r\n * @param search 用来搜索的字符串\r\n * @returns 是否包含\r\n */\r\nexport const includeIgnoreCase = (list: string[], search: string) => {\r\n for (let i = 0; i < list.length; i++) {\r\n let item = list[i];\r\n if (equalsIgnoreCase(item, search)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n"],"names":["withRecord","obj","mode","key","newVal","stringTokenizer","regExp","matchHandler","textHandler","ifMatch","ifText","str","result","matches","index","match","before","equalsIgnoreCase","source","target","includeIgnoreCase","list","search","i","item"],"mappings":"uOAMa,MAAAA,EACTC,IAGO,CACH,MAAO,SAAUC,EAAkB,EAAkB,CAC7CA,IAAS,EACT,OAAO,KAAKD,CAAG,EAAE,QAASE,GAAQ,CAC9BF,EAAIE,CAAG,EAAI,MAAA,CACd,EACMD,IAAS,EAChB,OAAO,KAAKD,CAAG,EAAE,QAASE,GAAQ,CAC9B,OAAOF,EAAIE,CAAG,CAAA,CACjB,EAEM,OAAA,OAAOF,EAAK,CAAA,CAAE,CAE7B,EACA,QAAS,SAAUG,EAA+C,CAC9D,KAAK,MAAM,GACJ,OAAA,OAAOH,EAAKG,CAAM,CAC7B,CAAA,GCnBQ,SAAAC,EACdC,EACAC,EACAC,EACsB,CAEtB,MAAMC,EAAUF,EACVG,EAASF,GAAyBD,EAExC,OAAO,SAAUI,EAAa,CAC5B,MAAMC,EAAc,CAAA,EACdC,EAAUF,EAAI,SAASL,CAAM,EACnC,IAAIQ,EAAQ,EACZ,UAAWC,KAASF,EAAS,CAC3B,MAAMG,EAASL,EAAI,MAAMG,EAAOC,EAAM,KAAK,EACvCC,GACFJ,EAAO,KAAKF,EAAOM,EAAQ,EAAK,CAAC,EAEnCJ,EAAO,KAAKH,EAAQM,EAAM,CAAC,EAAG,EAAI,CAAC,EACnCD,EAAQC,EAAM,MAASA,EAAM,CAAC,EAAE,MAClC,CACI,OAAAD,EAAQH,EAAI,QACdC,EAAO,KAAKF,EAAOC,EAAI,MAAMG,CAAK,EAAG,EAAK,CAAC,EAEtCF,CAAA,CAEX,CAWgB,SAAAK,EACdC,EACAC,EACA,CACA,OAAI,OAAOD,GAAW,UAAY,OAAOC,GAAW,SAC3CD,EAAO,YAAA,IAAkBC,EAAO,YAAY,EAC1CD,IAAW,QAAaC,IAAW,MAIhD,CAUa,MAAAC,EAAoB,CAACC,EAAgBC,IAAmB,CACnE,QAASC,EAAI,EAAGA,EAAIF,EAAK,OAAQE,IAAK,CAChC,IAAAC,EAAOH,EAAKE,CAAC,EACb,GAAAN,EAAiBO,EAAMF,CAAM,EACxB,MAAA,EAEX,CACO,MAAA,EACT"} \ No newline at end of file +{"version":3,"file":"index.umd.js","sources":["../src/commons/record-util.ts","../src/commons/str-utils.ts"],"sourcesContent":["import { UnwrapNestedRefs } from \"vue\";\r\nexport enum RecordClearMode {\r\n delete = 2,\r\n reset = 1,\r\n}\r\nexport const withRecord = (obj: UnwrapNestedRefs>) => {\r\n return {\r\n clear: function (mode: RecordClearMode = RecordClearMode.delete) {\r\n if (mode === RecordClearMode.reset) {\r\n Object.keys(obj).forEach((key) => {\r\n obj[key] = undefined;\r\n });\r\n } else if (mode === RecordClearMode.delete) {\r\n Object.keys(obj).forEach((key) => {\r\n delete obj[key];\r\n });\r\n }\r\n },\r\n replace: function (newVal: UnwrapNestedRefs>) {\r\n this.clear(RecordClearMode.delete);\r\n Object.assign(obj, newVal);\r\n },\r\n };\r\n};\r\n\r\n/**\r\n * 这是一个泛型函数,接受任意个数的数组作为参数,并返回一个对象。\r\n * 该对象包含两个方法:test 和 path。\r\n * test 方法用于测试所有数组的元素是否相等,\r\n * path 方法用于测试所有数组的指定路径的值是否相等。\r\n\r\n * @param arrays \r\n * @returns \r\n */\r\nexport function assignRecords>(...arrays: T[][]) {\r\n let _arrays = arrays ?? [];\r\n\r\n return {\r\n test: function (equal?: (l: T, r: T) => boolean) {\r\n if (_arrays.length <= 1) {\r\n return _arrays.length === 1 ? _arrays[0] : [];\r\n }\r\n\r\n let localEqual =\r\n equal ??\r\n function (ll: T, rr: T) {\r\n return ll === rr;\r\n };\r\n return _arrays.reduce((acc, crt) => {\r\n if (crt && crt.length > 0) {\r\n if (acc.length === 0) {\r\n acc.push(...crt);\r\n } else {\r\n crt.forEach((c) => {\r\n const some = acc.some((a) => localEqual(a, c));\r\n if (!some) {\r\n acc.push(c);\r\n }\r\n });\r\n }\r\n }\r\n return acc;\r\n }, []);\r\n },\r\n path: function (...paths: string[]) {\r\n return this.test((l, r) => {\r\n return paths.every((path) => {\r\n return l[path] === r[path];\r\n });\r\n });\r\n },\r\n };\r\n}\r\n\r\n/**\r\n *\r\n * 接受一个目标对象和多个源对象作为参数,并返回合并后的对象。\r\n * 它会将源对象的属性复制到目标对象中,\r\n * 如果多个源对象有同名属性,\r\n * 则最后的属性值将覆盖前面的属性值。\r\n * @param target 目标对象\r\n * @param sources 来源对象参数\r\n * @returns 目标对象\r\n */\r\nexport const extend = >(\r\n // 目标对象\r\n target: T,\r\n // 其他对象参数\r\n ...sources: (T | undefined)[]\r\n): T => {\r\n // 遍历其他对象参数\r\n for (const source of sources) {\r\n if (source !== undefined) {\r\n // 遍历参数对象的属性\r\n for (const key in source) {\r\n // 判断属性存在于参数对象中且值不为 null\r\n if (source.hasOwnProperty(key) && source[key] != null) {\r\n // 将属性赋值给目标对象\r\n target[key] = source[key];\r\n }\r\n }\r\n }\r\n }\r\n // 返回目标对象\r\n return target;\r\n};\r\n","/**\r\n * 生成给定函数体的函数注释。\r\n *\r\n * @param {RegExp} regExp - 用于匹配的正则表达式。\r\n * @param {(text: string, match: boolean) => T} matchHandler - 处理匹配到的文本的函数。\r\n * @param {(text: string, match: boolean) => T} [textHandler] - 处理未匹配到的文本的函数。\r\n * @return {(str: string) => T[]} - 分词器函数。\r\n */\r\nexport function stringTokenizer(\r\n regExp: RegExp,\r\n matchHandler: (text: string, match: boolean) => T,\r\n textHandler?: (text: string, match: boolean) => T\r\n): (str: string) => T[] {\r\n\r\n const ifMatch = matchHandler;\r\n const ifText = textHandler?textHandler: matchHandler;\r\n\r\n return function (str: string) {\r\n const result: T[] = [];\r\n const matches = str.matchAll(regExp);\r\n let index = 0;\r\n for (const match of matches) {\r\n const before = str.slice(index, match.index);\r\n if (before) {\r\n result.push(ifText(before, false));\r\n }\r\n result.push(ifMatch(match[0], true));\r\n index = match.index! + match[0].length;\r\n }\r\n if (index < str.length) {\r\n result.push(ifText(str.slice(index), false));\r\n }\r\n return result;\r\n };\r\n}\r\n\r\n/**\r\n * 该函数接受两个参数,判断它们是否相等,不区分大小写。\r\n * 如果参数都是字符串类型,则将它们转换为小写后比较。\r\n * 如果两个参数都是undefined,则返回true,\r\n * 否则返回false。\r\n * @param source \r\n * @param target \r\n * @returns \r\n */\r\nexport function equalsIgnoreCase(\r\n source: string | undefined,\r\n target: string | undefined\r\n) {\r\n if (typeof source === \"string\" && typeof target === \"string\") {\r\n return source.toLowerCase() === target.toLowerCase();\r\n } else if (source === undefined && target === undefined) {\r\n return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * 这个函数接受一个字符串数组和一个字符串作为参数,\r\n * 在数组中判断是否存在与搜索字符串相同或相似的字符串,忽略大小写。\r\n * 如果找到匹配项则返回true,否则返回false。\r\n * @param list 字符串数组\r\n * @param search 用来搜索的字符串\r\n * @returns 是否包含\r\n */\r\nexport const includeIgnoreCase = (list: string[], search: string) => {\r\n for (let i = 0; i < list.length; i++) {\r\n let item = list[i];\r\n if (equalsIgnoreCase(item, search)) {\r\n return true;\r\n }\r\n }\r\n return false;\r\n};\r\n\r\n"],"names":["RecordClearMode","withRecord","obj","mode","key","newVal","assignRecords","arrays","_arrays","equal","localEqual","ll","rr","acc","crt","c","a","paths","l","r","path","stringTokenizer","regExp","matchHandler","textHandler","ifMatch","ifText","str","result","matches","index","match","before","equalsIgnoreCase","source","target","includeIgnoreCase","list","search","i","item"],"mappings":"uOACY,IAAAA,GAAAA,IACVA,EAAAA,EAAA,OAAS,CAAT,EAAA,SACAA,EAAAA,EAAA,MAAQ,CAAR,EAAA,QAFUA,IAAAA,GAAA,CAAA,CAAA,EAIC,MAAAC,EAAcC,IAClB,CACL,MAAO,SAAUC,EAAwB,EAAwB,CAC3DA,IAAS,EACX,OAAO,KAAKD,CAAG,EAAE,QAASE,GAAQ,CAChCF,EAAIE,CAAG,EAAI,MAAA,CACZ,EACQD,IAAS,GAClB,OAAO,KAAKD,CAAG,EAAE,QAASE,GAAQ,CAChC,OAAOF,EAAIE,CAAG,CAAA,CACf,CAEL,EACA,QAAS,SAAUC,EAA+C,CAChE,KAAK,MAAM,GACJ,OAAA,OAAOH,EAAKG,CAAM,CAC3B,CAAA,GAaG,SAASC,KAAgDC,EAAe,CACzE,IAAAC,EAAUD,GAAU,GAEjB,MAAA,CACL,KAAM,SAAUE,EAAiC,CAC3C,GAAAD,EAAQ,QAAU,EACpB,OAAOA,EAAQ,SAAW,EAAIA,EAAQ,CAAC,EAAI,GAG7C,IAAIE,EACFD,GACA,SAAUE,EAAOC,EAAO,CACtB,OAAOD,IAAOC,CAAA,EAElB,OAAOJ,EAAQ,OAAO,CAACK,EAAKC,KACtBA,GAAOA,EAAI,OAAS,IAClBD,EAAI,SAAW,EACbA,EAAA,KAAK,GAAGC,CAAG,EAEXA,EAAA,QAASC,GAAM,CACJF,EAAI,KAAMG,GAAMN,EAAWM,EAAGD,CAAC,CAAC,GAE3CF,EAAI,KAAKE,CAAC,CACZ,CACD,GAGEF,GACN,CAAE,CAAA,CACP,EACA,KAAM,YAAaI,EAAiB,CAClC,OAAO,KAAK,KAAK,CAACC,EAAGC,IACZF,EAAM,MAAOG,GACXF,EAAEE,CAAI,IAAMD,EAAEC,CAAI,CAC1B,CACF,CACH,CAAA,CAEJ,CChEgB,SAAAC,EACdC,EACAC,EACAC,EACsB,CAEtB,MAAMC,EAAUF,EACVG,EAASF,GAAyBD,EAExC,OAAO,SAAUI,EAAa,CAC5B,MAAMC,EAAc,CAAA,EACdC,EAAUF,EAAI,SAASL,CAAM,EACnC,IAAIQ,EAAQ,EACZ,UAAWC,KAASF,EAAS,CAC3B,MAAMG,EAASL,EAAI,MAAMG,EAAOC,EAAM,KAAK,EACvCC,GACFJ,EAAO,KAAKF,EAAOM,EAAQ,EAAK,CAAC,EAEnCJ,EAAO,KAAKH,EAAQM,EAAM,CAAC,EAAG,EAAI,CAAC,EACnCD,EAAQC,EAAM,MAASA,EAAM,CAAC,EAAE,MAClC,CACI,OAAAD,EAAQH,EAAI,QACdC,EAAO,KAAKF,EAAOC,EAAI,MAAMG,CAAK,EAAG,EAAK,CAAC,EAEtCF,CAAA,CAEX,CAWgB,SAAAK,EACdC,EACAC,EACA,CACA,OAAI,OAAOD,GAAW,UAAY,OAAOC,GAAW,SAC3CD,EAAO,YAAA,IAAkBC,EAAO,YAAY,EAC1CD,IAAW,QAAaC,IAAW,MAIhD,CAUa,MAAAC,EAAoB,CAACC,EAAgBC,IAAmB,CACnE,QAASC,EAAI,EAAGA,EAAIF,EAAK,OAAQE,IAAK,CAChC,IAAAC,EAAOH,EAAKE,CAAC,EACb,GAAAN,EAAiBO,EAAMF,CAAM,EACxB,MAAA,EAEX,CACO,MAAA,EACT"} \ No newline at end of file diff --git a/package.json b/package.json index 0f9e37b..9ae33d6 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "test": "vitest" }, "devDependencies": { + "prettier": "^3.0.3", "typescript": "^5.0.2", "vite": "^4.4.5", "vite-plugin-dts": "^3.6.3", @@ -20,7 +21,8 @@ "exports": { ".": { "import": "./lib/index.es.js", - "require": "./lib/index.umd.js" + "require": "./lib/index.umd.js", + "types": "./lib/index.d.ts" } }, "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a625d86..39936ac 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,9 @@ dependencies: version: registry.npmmirror.com/vitest@0.34.6 devDependencies: + prettier: + specifier: ^3.0.3 + version: registry.npmmirror.com/prettier@3.0.3 typescript: specifier: ^5.0.2 version: registry.npmmirror.com/typescript@5.2.2 @@ -1095,6 +1098,14 @@ packages: picocolors: registry.npmmirror.com/picocolors@1.0.0 source-map-js: registry.npmmirror.com/source-map-js@1.0.2 + registry.npmmirror.com/prettier@3.0.3: + resolution: {integrity: sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/prettier/-/prettier-3.0.3.tgz} + name: prettier + version: 3.0.3 + engines: {node: '>=14'} + hasBin: true + dev: true + registry.npmmirror.com/pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/pretty-format/-/pretty-format-29.7.0.tgz} name: pretty-format diff --git a/src/commons/record-util.ts b/src/commons/record-util.ts index 8654bf3..1b17613 100644 --- a/src/commons/record-util.ts +++ b/src/commons/record-util.ts @@ -1,30 +1,106 @@ -import { UnwrapNestedRefs } from 'vue'; -enum ClearMode { - clear = 3, - delete = 2, - reset = 1 +import { UnwrapNestedRefs } from "vue"; +export enum RecordClearMode { + delete = 2, + reset = 1, } -export const withRecord = ( - obj: UnwrapNestedRefs>, -) => { +export const withRecord = (obj: UnwrapNestedRefs>) => { + return { + clear: function (mode: RecordClearMode = RecordClearMode.delete) { + if (mode === RecordClearMode.reset) { + Object.keys(obj).forEach((key) => { + obj[key] = undefined; + }); + } else if (mode === RecordClearMode.delete) { + Object.keys(obj).forEach((key) => { + delete obj[key]; + }); + } + }, + replace: function (newVal: UnwrapNestedRefs>) { + this.clear(RecordClearMode.delete); + Object.assign(obj, newVal); + }, + }; +}; - return { - clear: function (mode: ClearMode = ClearMode.delete) { - if (mode === ClearMode.reset) { - Object.keys(obj).forEach((key) => { - obj[key] = undefined; - }); - } else if (mode === ClearMode.delete) { - Object.keys(obj).forEach((key) => { - delete obj[key]; - }); - } else { - Object.assign(obj, {}); - } - }, - replace: function (newVal: UnwrapNestedRefs>) { - this.clear(ClearMode.clear); - Object.assign(obj, newVal); +/** + * 这是一个泛型函数,接受任意个数的数组作为参数,并返回一个对象。 + * 该对象包含两个方法:test 和 path。 + * test 方法用于测试所有数组的元素是否相等, + * path 方法用于测试所有数组的指定路径的值是否相等。 + + * @param arrays + * @returns + */ +export function assignRecords>(...arrays: T[][]) { + let _arrays = arrays ?? []; + + return { + test: function (equal?: (l: T, r: T) => boolean) { + if (_arrays.length <= 1) { + return _arrays.length === 1 ? _arrays[0] : []; + } + + let localEqual = + equal ?? + function (ll: T, rr: T) { + return ll === rr; + }; + return _arrays.reduce((acc, crt) => { + if (crt && crt.length > 0) { + if (acc.length === 0) { + acc.push(...crt); + } else { + crt.forEach((c) => { + const some = acc.some((a) => localEqual(a, c)); + if (!some) { + acc.push(c); + } + }); + } } - }; -}; \ No newline at end of file + return acc; + }, []); + }, + path: function (...paths: string[]) { + return this.test((l, r) => { + return paths.every((path) => { + return l[path] === r[path]; + }); + }); + }, + }; +} + +/** + * + * 接受一个目标对象和多个源对象作为参数,并返回合并后的对象。 + * 它会将源对象的属性复制到目标对象中, + * 如果多个源对象有同名属性, + * 则最后的属性值将覆盖前面的属性值。 + * @param target 目标对象 + * @param sources 来源对象参数 + * @returns 目标对象 + */ +export const extend = >( + // 目标对象 + target: T, + // 其他对象参数 + ...sources: (T | undefined)[] +): T => { + // 遍历其他对象参数 + for (const source of sources) { + if (source !== undefined) { + // 遍历参数对象的属性 + for (const key in source) { + // 判断属性存在于参数对象中且值不为 null + if (source.hasOwnProperty(key) && source[key] != null) { + // 将属性赋值给目标对象 + target[key] = source[key]; + } + } + } + } + // 返回目标对象 + return target; +}; diff --git a/src/index.ts b/src/index.ts index 99941e0..5528c8f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { withRecord } from "./commons/record-util"; +import { withRecord, assignRecords, RecordClearMode } from "./commons/record-util"; import { stringTokenizer, equalsIgnoreCase, includeIgnoreCase } from "./commons/str-utils"; -export { stringTokenizer, withRecord, equalsIgnoreCase, includeIgnoreCase }; +export { stringTokenizer, withRecord, equalsIgnoreCase, includeIgnoreCase, assignRecords, RecordClearMode };