@intlify/shared
Advanced tools
+65
-13
| /*! | ||
| * shared v11.4.3 | ||
| * shared v11.4.4 | ||
| * (c) 2026 kazuya kawaguchi | ||
@@ -109,8 +109,68 @@ * Released under the MIT License. | ||
| } | ||
| const javascriptSchemePattern = /^\s*javascript\s*(?::|�*58;?|�*3a;?|:?)/i; | ||
| const urlAttributePattern = /^(?:href|src|action|formaction)$/i; | ||
| function hasJavascriptScheme(value) { | ||
| return javascriptSchemePattern.test(value); | ||
| } | ||
| function sanitizeStyleValue(value) { | ||
| const urlPattern = /url\s*\(/gi; | ||
| let sanitized = ''; | ||
| let cursor = 0; | ||
| let match; | ||
| while ((match = urlPattern.exec(value)) !== null) { | ||
| const urlStart = match.index; | ||
| const openParenIndex = urlPattern.lastIndex - 1; | ||
| let index = openParenIndex + 1; | ||
| let depth = 1; | ||
| let quote = null; | ||
| for (; index < value.length; index++) { | ||
| const char = value[index]; | ||
| if (quote) { | ||
| if (char === quote) { | ||
| quote = null; | ||
| } | ||
| continue; | ||
| } | ||
| if (char === '"' || char === "'") { | ||
| quote = char; | ||
| } | ||
| else if (char === '(') { | ||
| depth++; | ||
| } | ||
| else if (char === ')') { | ||
| depth--; | ||
| if (depth === 0) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (depth !== 0) { | ||
| break; | ||
| } | ||
| const rawUrlValue = value.slice(openParenIndex + 1, index).trim(); | ||
| const unquotedUrlValue = (rawUrlValue.startsWith('"') && rawUrlValue.endsWith('"')) || | ||
| (rawUrlValue.startsWith("'") && rawUrlValue.endsWith("'")) | ||
| ? rawUrlValue.slice(1, -1).trim() | ||
| : rawUrlValue; | ||
| sanitized += value.slice(cursor, urlStart); | ||
| sanitized += hasJavascriptScheme(unquotedUrlValue) | ||
| ? 'url(about:blank)' | ||
| : value.slice(urlStart, index + 1); | ||
| cursor = index + 1; | ||
| } | ||
| return sanitized + value.slice(cursor); | ||
| } | ||
| function sanitizeAttributeValue(attrName, value) { | ||
| if (urlAttributePattern.test(attrName) && hasJavascriptScheme(value)) { | ||
| return 'about:blank'; | ||
| } | ||
| const sanitizedValue = attrName.toLowerCase() === 'style' ? sanitizeStyleValue(value) : value; | ||
| return escapeAttributeValue(sanitizedValue); | ||
| } | ||
| function sanitizeTranslatedHtml(html) { | ||
| // Escape dangerous characters in attribute values | ||
| // Process attributes with double quotes | ||
| html = html.replace(/(\w+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${escapeAttributeValue(attrValue)}"`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${sanitizeAttributeValue(attrName, attrValue)}"`); | ||
| // Process attributes with single quotes | ||
| html = html.replace(/(\w+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${escapeAttributeValue(attrValue)}'`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${sanitizeAttributeValue(attrName, attrValue)}'`); | ||
| // Detect and neutralize event handler attributes | ||
@@ -126,12 +186,4 @@ const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi; | ||
| } | ||
| // Disable javascript: URLs in various contexts | ||
| const javascriptUrlPattern = [ | ||
| // In href, src, action, formaction attributes | ||
| /(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi, | ||
| // In style attributes within url() | ||
| /(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi | ||
| ]; | ||
| javascriptUrlPattern.forEach(pattern => { | ||
| html = html.replace(pattern, '$1javascript:'); | ||
| }); | ||
| // Disable javascript: URLs in unquoted attributes | ||
| html = html.replace(/(\s+(?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi, (match, prefix, attrValue) => hasJavascriptScheme(attrValue) ? `${prefix}about:blank` : match); | ||
| return html; | ||
@@ -138,0 +190,0 @@ } |
| /*! | ||
| * shared v11.4.3 | ||
| * shared v11.4.4 | ||
| * (c) 2026 kazuya kawaguchi | ||
@@ -107,8 +107,68 @@ * Released under the MIT License. | ||
| } | ||
| const javascriptSchemePattern = /^\s*javascript\s*(?::|�*58;?|�*3a;?|:?)/i; | ||
| const urlAttributePattern = /^(?:href|src|action|formaction)$/i; | ||
| function hasJavascriptScheme(value) { | ||
| return javascriptSchemePattern.test(value); | ||
| } | ||
| function sanitizeStyleValue(value) { | ||
| const urlPattern = /url\s*\(/gi; | ||
| let sanitized = ''; | ||
| let cursor = 0; | ||
| let match; | ||
| while ((match = urlPattern.exec(value)) !== null) { | ||
| const urlStart = match.index; | ||
| const openParenIndex = urlPattern.lastIndex - 1; | ||
| let index = openParenIndex + 1; | ||
| let depth = 1; | ||
| let quote = null; | ||
| for (; index < value.length; index++) { | ||
| const char = value[index]; | ||
| if (quote) { | ||
| if (char === quote) { | ||
| quote = null; | ||
| } | ||
| continue; | ||
| } | ||
| if (char === '"' || char === "'") { | ||
| quote = char; | ||
| } | ||
| else if (char === '(') { | ||
| depth++; | ||
| } | ||
| else if (char === ')') { | ||
| depth--; | ||
| if (depth === 0) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (depth !== 0) { | ||
| break; | ||
| } | ||
| const rawUrlValue = value.slice(openParenIndex + 1, index).trim(); | ||
| const unquotedUrlValue = (rawUrlValue.startsWith('"') && rawUrlValue.endsWith('"')) || | ||
| (rawUrlValue.startsWith("'") && rawUrlValue.endsWith("'")) | ||
| ? rawUrlValue.slice(1, -1).trim() | ||
| : rawUrlValue; | ||
| sanitized += value.slice(cursor, urlStart); | ||
| sanitized += hasJavascriptScheme(unquotedUrlValue) | ||
| ? 'url(about:blank)' | ||
| : value.slice(urlStart, index + 1); | ||
| cursor = index + 1; | ||
| } | ||
| return sanitized + value.slice(cursor); | ||
| } | ||
| function sanitizeAttributeValue(attrName, value) { | ||
| if (urlAttributePattern.test(attrName) && hasJavascriptScheme(value)) { | ||
| return 'about:blank'; | ||
| } | ||
| const sanitizedValue = attrName.toLowerCase() === 'style' ? sanitizeStyleValue(value) : value; | ||
| return escapeAttributeValue(sanitizedValue); | ||
| } | ||
| function sanitizeTranslatedHtml(html) { | ||
| // Escape dangerous characters in attribute values | ||
| // Process attributes with double quotes | ||
| html = html.replace(/(\w+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${escapeAttributeValue(attrValue)}"`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${sanitizeAttributeValue(attrName, attrValue)}"`); | ||
| // Process attributes with single quotes | ||
| html = html.replace(/(\w+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${escapeAttributeValue(attrValue)}'`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${sanitizeAttributeValue(attrName, attrValue)}'`); | ||
| // Detect and neutralize event handler attributes | ||
@@ -124,12 +184,4 @@ const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi; | ||
| } | ||
| // Disable javascript: URLs in various contexts | ||
| const javascriptUrlPattern = [ | ||
| // In href, src, action, formaction attributes | ||
| /(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi, | ||
| // In style attributes within url() | ||
| /(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi | ||
| ]; | ||
| javascriptUrlPattern.forEach(pattern => { | ||
| html = html.replace(pattern, '$1javascript:'); | ||
| }); | ||
| // Disable javascript: URLs in unquoted attributes | ||
| html = html.replace(/(\s+(?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi, (match, prefix, attrValue) => hasJavascriptScheme(attrValue) ? `${prefix}about:blank` : match); | ||
| return html; | ||
@@ -136,0 +188,0 @@ } |
| /*! | ||
| * shared v11.4.3 | ||
| * shared v11.4.4 | ||
| * (c) 2026 kazuya kawaguchi | ||
| * Released under the MIT License. | ||
| */ | ||
| function warn(e,t){"undefined"!=typeof console&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}const hasWarned={};function warnOnce(e){hasWarned[e]||(hasWarned[e]=!0,warn(e))}const inBrowser="undefined"!=typeof window;let mark,measure;const RE_ARGS=/\{([0-9a-zA-Z]+)\}/g;function format(e,...t){return 1===t.length&&isObject(t[0])&&(t=t[0]),t&&t.hasOwnProperty||(t={}),e.replace(RE_ARGS,((e,r)=>t.hasOwnProperty(r)?t[r]:""))}const makeSymbol=(e,t=!1)=>t?Symbol.for(e):Symbol(e),generateFormatCacheKey=(e,t,r)=>friendlyJSONstringify({l:e,k:t,s:r}),friendlyJSONstringify=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),isNumber=e=>"number"==typeof e&&isFinite(e),isDate=e=>"[object Date]"===toTypeString(e),isRegExp=e=>"[object RegExp]"===toTypeString(e),isEmptyObject=e=>isPlainObject(e)&&0===Object.keys(e).length,assign=Object.assign,_create=Object.create,create=(e=null)=>_create(e);let _globalThis;const getGlobalThis=()=>_globalThis||(_globalThis="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:create());function escapeHtml(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/").replace(/=/g,"=")}function escapeAttributeValue(e){return e.replace(/&(?![a-zA-Z0-9#]{2,6};)/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function sanitizeTranslatedHtml(e){e=(e=e.replace(/(\w+)\s*=\s*"([^"]*)"/g,((e,t,r)=>`${t}="${escapeAttributeValue(r)}"`))).replace(/(\w+)\s*=\s*'([^']*)'/g,((e,t,r)=>`${t}='${escapeAttributeValue(r)}'`));/\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi.test(e)&&(e=e.replace(/(\s+)(on)(\w+\s*=)/gi,"$1on$3"));return[/(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi,/(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi].forEach((t=>{e=e.replace(t,"$1javascript:")})),e}const hasOwnProperty=Object.prototype.hasOwnProperty;function hasOwn(e,t){return hasOwnProperty.call(e,t)}const isArray=Array.isArray,isFunction=e=>"function"==typeof e,isString=e=>"string"==typeof e,isBoolean=e=>"boolean"==typeof e,isSymbol=e=>"symbol"==typeof e,isObject=e=>null!==e&&"object"==typeof e,isPromise=e=>isObject(e)&&isFunction(e.then)&&isFunction(e.catch),objectToString=Object.prototype.toString,toTypeString=e=>objectToString.call(e),isPlainObject=e=>"[object Object]"===toTypeString(e),toDisplayString=e=>null==e?"":isArray(e)||isPlainObject(e)&&e.toString===objectToString?JSON.stringify(e,null,2):String(e);function join(e,t=""){return e.reduce(((e,r,n)=>0===n?e+r:e+t+r),"")}const RANGE=2;function generateCodeFrame(e,t=0,r=e.length){const n=e.split(/\r?\n/);let s=0;const i=[];for(let a=0;a<n.length;a++)if(s+=n[a].length+1,s>=t){for(let e=a-2;e<=a+2||r>s;e++){if(e<0||e>=n.length)continue;const o=e+1;i.push(`${o}${" ".repeat(3-String(o).length)}| ${n[e]}`);const c=n[e].length;if(e===a){const e=t-(s-c)+1,n=Math.max(1,r>s?c-e:r-t);i.push(" | "+" ".repeat(e)+"^".repeat(n))}else if(e>a){if(r>s){const e=Math.max(Math.min(r-s,c),1);i.push(" | "+"^".repeat(e))}s+=c+1}}break}return i.join("\n")}function createEmitter(){const e=new Map;return{events:e,on(t,r){const n=e.get(t);n&&n.push(r)||e.set(t,[r])},off(t,r){const n=e.get(t);n&&n.splice(n.indexOf(r)>>>0,1)},emit(t,r){(e.get(t)||[]).slice().map((e=>e(r))),(e.get("*")||[]).slice().map((e=>e(t,r)))}}}const isNotObjectOrIsArray=e=>!isObject(e)||isArray(e);function deepCopy(e,t){if(isNotObjectOrIsArray(e)||isNotObjectOrIsArray(t))throw new Error("Invalid value");const r=[{src:e,des:t}];for(;r.length;){const{src:e,des:t}=r.pop();Object.keys(e).forEach((n=>{"__proto__"!==n&&(isObject(e[n])&&!isObject(t[n])&&(t[n]=Array.isArray(e[n])?[]:create()),isNotObjectOrIsArray(t[n])||isNotObjectOrIsArray(e[n])?t[n]=e[n]:r.push({src:e[n],des:t[n]}))}))}}export{assign,create,createEmitter,deepCopy,escapeHtml,format,friendlyJSONstringify,generateCodeFrame,generateFormatCacheKey,getGlobalThis,hasOwn,inBrowser,isArray,isBoolean,isDate,isEmptyObject,isFunction,isNumber,isObject,isPlainObject,isPromise,isRegExp,isString,isSymbol,join,makeSymbol,mark,measure,objectToString,sanitizeTranslatedHtml,toDisplayString,toTypeString,warn,warnOnce}; | ||
| function warn(e,t){"undefined"!=typeof console&&(console.warn("[intlify] "+e),t&&console.warn(t.stack))}const hasWarned={};function warnOnce(e){hasWarned[e]||(hasWarned[e]=!0,warn(e))}const inBrowser="undefined"!=typeof window;let mark,measure;const RE_ARGS=/\{([0-9a-zA-Z]+)\}/g;function format(e,...t){return 1===t.length&&isObject(t[0])&&(t=t[0]),t&&t.hasOwnProperty||(t={}),e.replace(RE_ARGS,((e,n)=>t.hasOwnProperty(n)?t[n]:""))}const makeSymbol=(e,t=!1)=>t?Symbol.for(e):Symbol(e),generateFormatCacheKey=(e,t,n)=>friendlyJSONstringify({l:e,k:t,s:n}),friendlyJSONstringify=e=>JSON.stringify(e).replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029").replace(/\u0027/g,"\\u0027"),isNumber=e=>"number"==typeof e&&isFinite(e),isDate=e=>"[object Date]"===toTypeString(e),isRegExp=e=>"[object RegExp]"===toTypeString(e),isEmptyObject=e=>isPlainObject(e)&&0===Object.keys(e).length,assign=Object.assign,_create=Object.create,create=(e=null)=>_create(e);let _globalThis;const getGlobalThis=()=>_globalThis||(_globalThis="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:create());function escapeHtml(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'").replace(/\//g,"/").replace(/=/g,"=")}function escapeAttributeValue(e){return e.replace(/&(?![a-zA-Z0-9#]{2,6};)/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}const javascriptSchemePattern=/^\s*javascript\s*(?::|�*58;?|�*3a;?|:?)/i,urlAttributePattern=/^(?:href|src|action|formaction)$/i;function hasJavascriptScheme(e){return javascriptSchemePattern.test(e)}function sanitizeStyleValue(e){const t=/url\s*\(/gi;let n,r="",i=0;for(;null!==(n=t.exec(e));){const s=n.index,a=t.lastIndex-1;let o=a+1,c=1,l=null;for(;o<e.length;o++){const t=e[o];if(l)t===l&&(l=null);else if('"'===t||"'"===t)l=t;else if("("===t)c++;else if(")"===t&&(c--,0===c))break}if(0!==c)break;const p=e.slice(a+1,o).trim(),u=p.startsWith('"')&&p.endsWith('"')||p.startsWith("'")&&p.endsWith("'")?p.slice(1,-1).trim():p;r+=e.slice(i,s),r+=hasJavascriptScheme(u)?"url(about:blank)":e.slice(s,o+1),i=o+1}return r+e.slice(i)}function sanitizeAttributeValue(e,t){if(urlAttributePattern.test(e)&&hasJavascriptScheme(t))return"about:blank";return escapeAttributeValue("style"===e.toLowerCase()?sanitizeStyleValue(t):t)}function sanitizeTranslatedHtml(e){e=(e=e.replace(/([\w:-]+)\s*=\s*"([^"]*)"/g,((e,t,n)=>`${t}="${sanitizeAttributeValue(t,n)}"`))).replace(/([\w:-]+)\s*=\s*'([^']*)'/g,((e,t,n)=>`${t}='${sanitizeAttributeValue(t,n)}'`));return/\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi.test(e)&&(e=e.replace(/(\s+)(on)(\w+\s*=)/gi,"$1on$3")),e=e.replace(/(\s+(?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi,((e,t,n)=>hasJavascriptScheme(n)?`${t}about:blank`:e))}const hasOwnProperty=Object.prototype.hasOwnProperty;function hasOwn(e,t){return hasOwnProperty.call(e,t)}const isArray=Array.isArray,isFunction=e=>"function"==typeof e,isString=e=>"string"==typeof e,isBoolean=e=>"boolean"==typeof e,isSymbol=e=>"symbol"==typeof e,isObject=e=>null!==e&&"object"==typeof e,isPromise=e=>isObject(e)&&isFunction(e.then)&&isFunction(e.catch),objectToString=Object.prototype.toString,toTypeString=e=>objectToString.call(e),isPlainObject=e=>"[object Object]"===toTypeString(e),toDisplayString=e=>null==e?"":isArray(e)||isPlainObject(e)&&e.toString===objectToString?JSON.stringify(e,null,2):String(e);function join(e,t=""){return e.reduce(((e,n,r)=>0===r?e+n:e+t+n),"")}const RANGE=2;function generateCodeFrame(e,t=0,n=e.length){const r=e.split(/\r?\n/);let i=0;const s=[];for(let a=0;a<r.length;a++)if(i+=r[a].length+1,i>=t){for(let e=a-2;e<=a+2||n>i;e++){if(e<0||e>=r.length)continue;const o=e+1;s.push(`${o}${" ".repeat(3-String(o).length)}| ${r[e]}`);const c=r[e].length;if(e===a){const e=t-(i-c)+1,r=Math.max(1,n>i?c-e:n-t);s.push(" | "+" ".repeat(e)+"^".repeat(r))}else if(e>a){if(n>i){const e=Math.max(Math.min(n-i,c),1);s.push(" | "+"^".repeat(e))}i+=c+1}}break}return s.join("\n")}function createEmitter(){const e=new Map;return{events:e,on(t,n){const r=e.get(t);r&&r.push(n)||e.set(t,[n])},off(t,n){const r=e.get(t);r&&r.splice(r.indexOf(n)>>>0,1)},emit(t,n){(e.get(t)||[]).slice().map((e=>e(n))),(e.get("*")||[]).slice().map((e=>e(t,n)))}}}const isNotObjectOrIsArray=e=>!isObject(e)||isArray(e);function deepCopy(e,t){if(isNotObjectOrIsArray(e)||isNotObjectOrIsArray(t))throw new Error("Invalid value");const n=[{src:e,des:t}];for(;n.length;){const{src:e,des:t}=n.pop();Object.keys(e).forEach((r=>{"__proto__"!==r&&(isObject(e[r])&&!isObject(t[r])&&(t[r]=Array.isArray(e[r])?[]:create()),isNotObjectOrIsArray(t[r])||isNotObjectOrIsArray(e[r])?t[r]=e[r]:n.push({src:e[r],des:t[r]}))}))}}export{assign,create,createEmitter,deepCopy,escapeHtml,format,friendlyJSONstringify,generateCodeFrame,generateFormatCacheKey,getGlobalThis,hasOwn,inBrowser,isArray,isBoolean,isDate,isEmptyObject,isFunction,isNumber,isObject,isPlainObject,isPromise,isRegExp,isString,isSymbol,join,makeSymbol,mark,measure,objectToString,sanitizeTranslatedHtml,toDisplayString,toTypeString,warn,warnOnce}; |
+65
-13
| /*! | ||
| * shared v11.4.3 | ||
| * shared v11.4.4 | ||
| * (c) 2026 kazuya kawaguchi | ||
@@ -107,8 +107,68 @@ * Released under the MIT License. | ||
| } | ||
| const javascriptSchemePattern = /^\s*javascript\s*(?::|�*58;?|�*3a;?|:?)/i; | ||
| const urlAttributePattern = /^(?:href|src|action|formaction)$/i; | ||
| function hasJavascriptScheme(value) { | ||
| return javascriptSchemePattern.test(value); | ||
| } | ||
| function sanitizeStyleValue(value) { | ||
| const urlPattern = /url\s*\(/gi; | ||
| let sanitized = ''; | ||
| let cursor = 0; | ||
| let match; | ||
| while ((match = urlPattern.exec(value)) !== null) { | ||
| const urlStart = match.index; | ||
| const openParenIndex = urlPattern.lastIndex - 1; | ||
| let index = openParenIndex + 1; | ||
| let depth = 1; | ||
| let quote = null; | ||
| for (; index < value.length; index++) { | ||
| const char = value[index]; | ||
| if (quote) { | ||
| if (char === quote) { | ||
| quote = null; | ||
| } | ||
| continue; | ||
| } | ||
| if (char === '"' || char === "'") { | ||
| quote = char; | ||
| } | ||
| else if (char === '(') { | ||
| depth++; | ||
| } | ||
| else if (char === ')') { | ||
| depth--; | ||
| if (depth === 0) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (depth !== 0) { | ||
| break; | ||
| } | ||
| const rawUrlValue = value.slice(openParenIndex + 1, index).trim(); | ||
| const unquotedUrlValue = (rawUrlValue.startsWith('"') && rawUrlValue.endsWith('"')) || | ||
| (rawUrlValue.startsWith("'") && rawUrlValue.endsWith("'")) | ||
| ? rawUrlValue.slice(1, -1).trim() | ||
| : rawUrlValue; | ||
| sanitized += value.slice(cursor, urlStart); | ||
| sanitized += hasJavascriptScheme(unquotedUrlValue) | ||
| ? 'url(about:blank)' | ||
| : value.slice(urlStart, index + 1); | ||
| cursor = index + 1; | ||
| } | ||
| return sanitized + value.slice(cursor); | ||
| } | ||
| function sanitizeAttributeValue(attrName, value) { | ||
| if (urlAttributePattern.test(attrName) && hasJavascriptScheme(value)) { | ||
| return 'about:blank'; | ||
| } | ||
| const sanitizedValue = attrName.toLowerCase() === 'style' ? sanitizeStyleValue(value) : value; | ||
| return escapeAttributeValue(sanitizedValue); | ||
| } | ||
| function sanitizeTranslatedHtml(html) { | ||
| // Escape dangerous characters in attribute values | ||
| // Process attributes with double quotes | ||
| html = html.replace(/(\w+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${escapeAttributeValue(attrValue)}"`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${sanitizeAttributeValue(attrName, attrValue)}"`); | ||
| // Process attributes with single quotes | ||
| html = html.replace(/(\w+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${escapeAttributeValue(attrValue)}'`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${sanitizeAttributeValue(attrName, attrValue)}'`); | ||
| // Detect and neutralize event handler attributes | ||
@@ -124,12 +184,4 @@ const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi; | ||
| } | ||
| // Disable javascript: URLs in various contexts | ||
| const javascriptUrlPattern = [ | ||
| // In href, src, action, formaction attributes | ||
| /(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi, | ||
| // In style attributes within url() | ||
| /(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi | ||
| ]; | ||
| javascriptUrlPattern.forEach(pattern => { | ||
| html = html.replace(pattern, '$1javascript:'); | ||
| }); | ||
| // Disable javascript: URLs in unquoted attributes | ||
| html = html.replace(/(\s+(?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi, (match, prefix, attrValue) => hasJavascriptScheme(attrValue) ? `${prefix}about:blank` : match); | ||
| return html; | ||
@@ -136,0 +188,0 @@ } |
+65
-13
| /*! | ||
| * shared v11.4.3 | ||
| * shared v11.4.4 | ||
| * (c) 2026 kazuya kawaguchi | ||
@@ -91,8 +91,68 @@ * Released under the MIT License. | ||
| } | ||
| const javascriptSchemePattern = /^\s*javascript\s*(?::|�*58;?|�*3a;?|:?)/i; | ||
| const urlAttributePattern = /^(?:href|src|action|formaction)$/i; | ||
| function hasJavascriptScheme(value) { | ||
| return javascriptSchemePattern.test(value); | ||
| } | ||
| function sanitizeStyleValue(value) { | ||
| const urlPattern = /url\s*\(/gi; | ||
| let sanitized = ''; | ||
| let cursor = 0; | ||
| let match; | ||
| while ((match = urlPattern.exec(value)) !== null) { | ||
| const urlStart = match.index; | ||
| const openParenIndex = urlPattern.lastIndex - 1; | ||
| let index = openParenIndex + 1; | ||
| let depth = 1; | ||
| let quote = null; | ||
| for (; index < value.length; index++) { | ||
| const char = value[index]; | ||
| if (quote) { | ||
| if (char === quote) { | ||
| quote = null; | ||
| } | ||
| continue; | ||
| } | ||
| if (char === '"' || char === "'") { | ||
| quote = char; | ||
| } | ||
| else if (char === '(') { | ||
| depth++; | ||
| } | ||
| else if (char === ')') { | ||
| depth--; | ||
| if (depth === 0) { | ||
| break; | ||
| } | ||
| } | ||
| } | ||
| if (depth !== 0) { | ||
| break; | ||
| } | ||
| const rawUrlValue = value.slice(openParenIndex + 1, index).trim(); | ||
| const unquotedUrlValue = (rawUrlValue.startsWith('"') && rawUrlValue.endsWith('"')) || | ||
| (rawUrlValue.startsWith("'") && rawUrlValue.endsWith("'")) | ||
| ? rawUrlValue.slice(1, -1).trim() | ||
| : rawUrlValue; | ||
| sanitized += value.slice(cursor, urlStart); | ||
| sanitized += hasJavascriptScheme(unquotedUrlValue) | ||
| ? 'url(about:blank)' | ||
| : value.slice(urlStart, index + 1); | ||
| cursor = index + 1; | ||
| } | ||
| return sanitized + value.slice(cursor); | ||
| } | ||
| function sanitizeAttributeValue(attrName, value) { | ||
| if (urlAttributePattern.test(attrName) && hasJavascriptScheme(value)) { | ||
| return 'about:blank'; | ||
| } | ||
| const sanitizedValue = attrName.toLowerCase() === 'style' ? sanitizeStyleValue(value) : value; | ||
| return escapeAttributeValue(sanitizedValue); | ||
| } | ||
| function sanitizeTranslatedHtml(html) { | ||
| // Escape dangerous characters in attribute values | ||
| // Process attributes with double quotes | ||
| html = html.replace(/(\w+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${escapeAttributeValue(attrValue)}"`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*"([^"]*)"/g, (_, attrName, attrValue) => `${attrName}="${sanitizeAttributeValue(attrName, attrValue)}"`); | ||
| // Process attributes with single quotes | ||
| html = html.replace(/(\w+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${escapeAttributeValue(attrValue)}'`); | ||
| html = html.replace(/([\w:-]+)\s*=\s*'([^']*)'/g, (_, attrName, attrValue) => `${attrName}='${sanitizeAttributeValue(attrName, attrValue)}'`); | ||
| // Detect and neutralize event handler attributes | ||
@@ -104,12 +164,4 @@ const eventHandlerPattern = /\s*on\w+\s*=\s*["']?[^"'>]+["']?/gi; | ||
| } | ||
| // Disable javascript: URLs in various contexts | ||
| const javascriptUrlPattern = [ | ||
| // In href, src, action, formaction attributes | ||
| /(\s+(?:href|src|action|formaction)\s*=\s*["']?)\s*javascript:/gi, | ||
| // In style attributes within url() | ||
| /(style\s*=\s*["'][^"']*url\s*\(\s*)javascript:/gi | ||
| ]; | ||
| javascriptUrlPattern.forEach(pattern => { | ||
| html = html.replace(pattern, '$1javascript:'); | ||
| }); | ||
| // Disable javascript: URLs in unquoted attributes | ||
| html = html.replace(/(\s+(?:href|src|action|formaction)\s*=\s*)([^\s"'=<>`]+)/gi, (match, prefix, attrValue) => hasJavascriptScheme(attrValue) ? `${prefix}about:blank` : match); | ||
| return html; | ||
@@ -116,0 +168,0 @@ } |
+1
-1
| { | ||
| "name": "@intlify/shared", | ||
| "version": "11.4.3", | ||
| "version": "11.4.4", | ||
| "description": "@intlify/shared", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
65347
15.55%1510
16.33%