791dd025cdb047c0d77acd89974390307e29d65d921a7bd6d4ef0b3df76c974df4f748aae78392199a231a8ffcb0a690716c175732e0994fd081621becb81c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*!
  2. * shared v9.14.5
  3. * (c) 2025 kazuya kawaguchi
  4. * Released under the MIT License.
  5. */
  6. function warn(msg, err) {
  7. if (typeof console !== 'undefined') {
  8. console.warn(`[intlify] ` + msg);
  9. /* istanbul ignore if */
  10. if (err) {
  11. console.warn(err.stack);
  12. }
  13. }
  14. }
  15. const hasWarned = {};
  16. function warnOnce(msg) {
  17. if (!hasWarned[msg]) {
  18. hasWarned[msg] = true;
  19. warn(msg);
  20. }
  21. }
  22. /**
  23. * Original Utilities
  24. * written by kazuya kawaguchi
  25. */
  26. const inBrowser = typeof window !== 'undefined';
  27. let mark;
  28. let measure;
  29. if ((process.env.NODE_ENV !== 'production')) {
  30. const perf = inBrowser && window.performance;
  31. if (perf &&
  32. perf.mark &&
  33. perf.measure &&
  34. perf.clearMarks &&
  35. // @ts-ignore browser compat
  36. perf.clearMeasures) {
  37. mark = (tag) => {
  38. perf.mark(tag);
  39. };
  40. measure = (name, startTag, endTag) => {
  41. perf.measure(name, startTag, endTag);
  42. perf.clearMarks(startTag);
  43. perf.clearMarks(endTag);
  44. };
  45. }
  46. }
  47. const RE_ARGS = /\{([0-9a-zA-Z]+)\}/g;
  48. /* eslint-disable */
  49. function format(message, ...args) {
  50. if (args.length === 1 && isObject(args[0])) {
  51. args = args[0];
  52. }
  53. if (!args || !args.hasOwnProperty) {
  54. args = {};
  55. }
  56. return message.replace(RE_ARGS, (match, identifier) => {
  57. return args.hasOwnProperty(identifier) ? args[identifier] : '';
  58. });
  59. }
  60. const makeSymbol = (name, shareable = false) => !shareable ? Symbol(name) : Symbol.for(name);
  61. const generateFormatCacheKey = (locale, key, source) => friendlyJSONstringify({ l: locale, k: key, s: source });
  62. const friendlyJSONstringify = (json) => JSON.stringify(json)
  63. .replace(/\u2028/g, '\\u2028')
  64. .replace(/\u2029/g, '\\u2029')
  65. .replace(/\u0027/g, '\\u0027');
  66. const isNumber = (val) => typeof val === 'number' && isFinite(val);
  67. const isDate = (val) => toTypeString(val) === '[object Date]';
  68. const isRegExp = (val) => toTypeString(val) === '[object RegExp]';
  69. const isEmptyObject = (val) => isPlainObject(val) && Object.keys(val).length === 0;
  70. const assign = Object.assign;
  71. const _create = Object.create;
  72. const create = (obj = null) => _create(obj);
  73. let _globalThis;
  74. const getGlobalThis = () => {
  75. // prettier-ignore
  76. return (_globalThis ||
  77. (_globalThis =
  78. typeof globalThis !== 'undefined'
  79. ? globalThis
  80. : typeof self !== 'undefined'
  81. ? self
  82. : typeof window !== 'undefined'
  83. ? window
  84. : typeof global !== 'undefined'
  85. ? global
  86. : create()));
  87. };
  88. function escapeHtml(rawText) {
  89. return rawText
  90. .replace(/&/g, '&') // escape `&` first to avoid double escaping
  91. .replace(/</g, '&lt;')
  92. .replace(/>/g, '&gt;')
  93. .replace(/"/g, '&quot;')
  94. .replace(/'/g, '&apos;')
  95. .replace(/\//g, '&#x2F;') // escape `/` to prevent closing tags or JavaScript URLs
  96. .replace(/=/g, '&#x3D;'); // escape `=` to prevent attribute injection
  97. }
  98. function escapeAttributeValue(value) {
  99. return value
  100. .replace(/&(?![a-zA-Z0-9#]{2,6};)/g, '&amp;') // escape unescaped `&`
  101. .replace(/"/g, '&quot;')
  102. .replace(/'/g, '&apos;')
  103. .replace(/</g, '&lt;')
  104. .replace(/>/g, '&gt;');
  105. }
  106. function sanitizeTranslatedHtml(html) {
  107. // Escape dangerous characters in attribute values
  108. // Process attributes with double quotes
  109. html = html.replace(/(\w+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${escapeAttributeValue(attrValue)}"`);
  110. // Process attributes with single quotes
  111. html = html.replace(/(\w+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${escapeAttributeValue(attrValue)}'`);
  112. // Detect and neutralize event handler attributes
  113. const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi;
  114. if (eventHandlerPattern.test(html)) {
  115. if ((process.env.NODE_ENV !== 'production')) {
  116. warn('Potentially dangerous event handlers detected in translation. ' +
  117. 'Consider removing onclick, onerror, etc. from your translation messages.');
  118. }
  119. // Neutralize event handler attributes by escaping 'on'
  120. html = html.replace(/(\s+)(on)(\w+\s*=)/gi, '$1&#111;n$3');
  121. }
  122. // Disable javascript: URLs in various contexts
  123. const javascriptUrlPattern = [
  124. // In href, src, action, formaction attributes
  125. /(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi,
  126. // In style attributes within url()
  127. /(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi
  128. ];
  129. javascriptUrlPattern.forEach(pattern => {
  130. html = html.replace(pattern, '$1javascript&#58;');
  131. });
  132. return html;
  133. }
  134. const hasOwnProperty = Object.prototype.hasOwnProperty;
  135. function hasOwn(obj, key) {
  136. return hasOwnProperty.call(obj, key);
  137. }
  138. /* eslint-enable */
  139. /**
  140. * Useful Utilities By Evan you
  141. * Modified by kazuya kawaguchi
  142. * MIT License
  143. * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
  144. * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
  145. */
  146. const isArray = Array.isArray;
  147. const isFunction = (val) => typeof val === 'function';
  148. const isString = (val) => typeof val === 'string';
  149. const isBoolean = (val) => typeof val === 'boolean';
  150. const isSymbol = (val) => typeof val === 'symbol';
  151. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  152. const isObject = (val) => val !== null && typeof val === 'object';
  153. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  154. const isPromise = (val) => {
  155. return isObject(val) && isFunction(val.then) && isFunction(val.catch);
  156. };
  157. const objectToString = Object.prototype.toString;
  158. const toTypeString = (value) => objectToString.call(value);
  159. const isPlainObject = (val) => {
  160. if (!isObject(val))
  161. return false;
  162. const proto = Object.getPrototypeOf(val);
  163. return proto === null || proto.constructor === Object;
  164. };
  165. // for converting list and named values to displayed strings.
  166. const toDisplayString = (val) => {
  167. return val == null
  168. ? ''
  169. : isArray(val) || (isPlainObject(val) && val.toString === objectToString)
  170. ? JSON.stringify(val, null, 2)
  171. : String(val);
  172. };
  173. function join(items, separator = '') {
  174. return items.reduce((str, item, index) => (index === 0 ? str + item : str + separator + item), '');
  175. }
  176. const RANGE = 2;
  177. function generateCodeFrame(source, start = 0, end = source.length) {
  178. const lines = source.split(/\r?\n/);
  179. let count = 0;
  180. const res = [];
  181. for (let i = 0; i < lines.length; i++) {
  182. count += lines[i].length + 1;
  183. if (count >= start) {
  184. for (let j = i - RANGE; j <= i + RANGE || end > count; j++) {
  185. if (j < 0 || j >= lines.length)
  186. continue;
  187. const line = j + 1;
  188. res.push(`${line}${' '.repeat(3 - String(line).length)}| ${lines[j]}`);
  189. const lineLength = lines[j].length;
  190. if (j === i) {
  191. // push underline
  192. const pad = start - (count - lineLength) + 1;
  193. const length = Math.max(1, end > count ? lineLength - pad : end - start);
  194. res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
  195. }
  196. else if (j > i) {
  197. if (end > count) {
  198. const length = Math.max(Math.min(end - count, lineLength), 1);
  199. res.push(` | ` + '^'.repeat(length));
  200. }
  201. count += lineLength + 1;
  202. }
  203. }
  204. break;
  205. }
  206. }
  207. return res.join('\n');
  208. }
  209. function incrementer(code) {
  210. let current = code;
  211. return () => ++current;
  212. }
  213. /**
  214. * Event emitter, forked from the below:
  215. * - original repository url: https://github.com/developit/mitt
  216. * - code url: https://github.com/developit/mitt/blob/master/src/index.ts
  217. * - author: Jason Miller (https://github.com/developit)
  218. * - license: MIT
  219. */
  220. /**
  221. * Create a event emitter
  222. *
  223. * @returns An event emitter
  224. */
  225. function createEmitter() {
  226. const events = new Map();
  227. const emitter = {
  228. events,
  229. on(event, handler) {
  230. const handlers = events.get(event);
  231. const added = handlers && handlers.push(handler);
  232. if (!added) {
  233. events.set(event, [handler]);
  234. }
  235. },
  236. off(event, handler) {
  237. const handlers = events.get(event);
  238. if (handlers) {
  239. handlers.splice(handlers.indexOf(handler) >>> 0, 1);
  240. }
  241. },
  242. emit(event, payload) {
  243. (events.get(event) || [])
  244. .slice()
  245. .map(handler => handler(payload));
  246. (events.get('*') || [])
  247. .slice()
  248. .map(handler => handler(event, payload));
  249. }
  250. };
  251. return emitter;
  252. }
  253. const isNotObjectOrIsArray = (val) => !isObject(val) || isArray(val);
  254. // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
  255. function deepCopy(src, des) {
  256. // src and des should both be objects, and none of them can be a array
  257. if (isNotObjectOrIsArray(src) || isNotObjectOrIsArray(des)) {
  258. throw new Error('Invalid value');
  259. }
  260. const stack = [{ src, des }];
  261. while (stack.length) {
  262. const { src, des } = stack.pop();
  263. // using `Object.keys` which skips prototype properties
  264. Object.keys(src).forEach(key => {
  265. if (key === '__proto__') {
  266. return;
  267. }
  268. // if src[key] is an object/array, set des[key]
  269. // to empty object/array to prevent setting by reference
  270. if (isObject(src[key]) && !isObject(des[key])) {
  271. des[key] = Array.isArray(src[key]) ? [] : create();
  272. }
  273. if (isNotObjectOrIsArray(des[key]) || isNotObjectOrIsArray(src[key])) {
  274. // replace with src[key] when:
  275. // src[key] or des[key] is not an object, or
  276. // src[key] or des[key] is an array
  277. des[key] = src[key];
  278. }
  279. else {
  280. // src[key] and des[key] are both objects, merge them
  281. stack.push({ src: src[key], des: des[key] });
  282. }
  283. });
  284. }
  285. }
  286. export { assign, create, createEmitter, deepCopy, escapeHtml, format, friendlyJSONstringify, generateCodeFrame, generateFormatCacheKey, getGlobalThis, hasOwn, inBrowser, incrementer, isArray, isBoolean, isDate, isEmptyObject, isFunction, isNumber, isObject, isPlainObject, isPromise, isRegExp, isString, isSymbol, join, makeSymbol, mark, measure, objectToString, sanitizeTranslatedHtml, toDisplayString, toTypeString, warn, warnOnce };