diff --git a/bin/pseudo-localize b/bin/pseudo-localize index a41bdf9..e32d016 100755 --- a/bin/pseudo-localize +++ b/bin/pseudo-localize @@ -48,6 +48,11 @@ const argv = require('yargs') choices: ['accented', 'bidi'], default: 'accented', }, + extendParams: { + describe: + 'Override strategy parameters. Separate with dots: --extendParams.prefix --extendParams.postfix --extendParams.elongate', + type: 'object', + }, }) .help() .version().argv; @@ -64,7 +69,13 @@ const write = function(output) { const convert = function(input) { const options = { strategy: argv.strategy }; - + if (argv.extendParams) { + options.extendParams = { + prefix: argv.extendParams.prefix, + postfix: argv.extendParams.postfix, + elongate: argv.extendParams.elongate, + }; + } if (typeof input === 'string') { write(localize(input, options)); return; diff --git a/dist/cjs/index.js b/dist/cjs/index.js index 14baa41..c5df678 100644 --- a/dist/cjs/index.js +++ b/dist/cjs/index.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;Object.defineProperty(exports,"localize",{enumerable:true,get:function get(){return _localize.default}});var _localize=_interopRequireDefault(require("./localize.js"));function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var pseudoLocalization=function(){var mutationObserverOpts={blacklistedNodeNames:["STYLE"]};var opts={strategy:"accented"};var enabled=false;var observer=null;var observerConfig={characterData:true,childList:true,subtree:true};var textNodesUnder=function textNodesUnder(element){var walker=document.createTreeWalker(element,NodeFilter.SHOW_TEXT,function(node){var isAllWhitespace=node.nodeValue&&!/[^\s]/.test(node.nodeValue);if(isAllWhitespace){return NodeFilter.FILTER_REJECT}var isBlacklistedNode=node.parentElement&&mutationObserverOpts.blacklistedNodeNames.includes(node.parentElement.nodeName);if(isBlacklistedNode){return NodeFilter.FILTER_REJECT}return NodeFilter.FILTER_ACCEPT});var currNode;var textNodes=[];while(currNode=walker.nextNode()){textNodes.push(currNode)}return textNodes};var isNonEmptyString=function isNonEmptyString(str){return!!str&&typeof str==="string"};var pseudoLocalize=function pseudoLocalize(element){var textNodesUnderElement=textNodesUnder(element);var _iteratorNormalCompletion=true;var _didIteratorError=false;var _iteratorError=undefined;try{for(var _iterator=textNodesUnderElement[Symbol.iterator](),_step;!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=true){var textNode=_step.value;var nodeValue=textNode.nodeValue;if(isNonEmptyString(nodeValue)){textNode.nodeValue=(0,_localize.default)(nodeValue,opts)}}}catch(err){_didIteratorError=true;_iteratorError=err}finally{try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}}};var domMutationCallback=function domMutationCallback(mutationsList){if(!observer){return}var _iteratorNormalCompletion2=true;var _didIteratorError2=false;var _iteratorError2=undefined;try{for(var _iterator2=mutationsList[Symbol.iterator](),_step2;!(_iteratorNormalCompletion2=(_step2=_iterator2.next()).done);_iteratorNormalCompletion2=true){var mutation=_step2.value;if(mutation.type==="childList"&&mutation.addedNodes.length>0){observer.disconnect();mutation.addedNodes.forEach(pseudoLocalize);observer.observe(document.body,observerConfig)}else if(mutation.type==="characterData"){var nodeValue=mutation.target.nodeValue;var isBlacklistedNode=!!mutation.target.parentElement&&mutationObserverOpts.blacklistedNodeNames.includes(mutation.target.parentElement.nodeName);if(isNonEmptyString(nodeValue)&&!isBlacklistedNode){observer.disconnect();mutation.target.nodeValue=(0,_localize.default)(nodeValue,opts);observer.observe(document.body,observerConfig)}}}}catch(err){_didIteratorError2=true;_iteratorError2=err}finally{try{if(!_iteratorNormalCompletion2&&_iterator2.return!=null){_iterator2.return()}}finally{if(_didIteratorError2){throw _iteratorError2}}}};var isEnabled=function isEnabled(){return enabled};var start=function start(){var _ref=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{},_ref$strategy=_ref.strategy,strategy=_ref$strategy===void 0?"accented":_ref$strategy,_ref$blacklistedNodeN=_ref.blacklistedNodeNames,blacklistedNodeNames=_ref$blacklistedNodeN===void 0?mutationObserverOpts.blacklistedNodeNames:_ref$blacklistedNodeN;if(isEnabled()){console.error("pseudo-localization is already enabled");return}mutationObserverOpts.blacklistedNodeNames=blacklistedNodeNames;opts.strategy=strategy;pseudoLocalize(document.body);observer=new MutationObserver(domMutationCallback);observer.observe(document.body,observerConfig);enabled=true};var stop=function stop(){if(!isEnabled()){console.error("pseudo-localization is already disabled");return}observer&&observer.disconnect();enabled=false};return{start:start,stop:stop,isEnabled:isEnabled,localize:_localize.default}}();var _default=pseudoLocalization;exports.default=_default; +"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;Object.defineProperty(exports,"localize",{enumerable:true,get:function get(){return _localize.default}});var _localize=_interopRequireDefault(require("./localize.js"));function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _createForOfIteratorHelper(o,allowArrayLike){var it=typeof Symbol!=="undefined"&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=_unsupportedIterableToArray(o))||allowArrayLike&&o&&typeof o.length==="number"){if(it)o=it;var i=0;var F=function F(){};return{s:F,n:function n(){if(i>=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e2){didErr=true;err=_e2},f:function f(){try{if(!normalCompletion&&it.return!=null)it.return()}finally{if(didErr)throw err}}}}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i0){observer.disconnect();mutation.addedNodes.forEach(pseudoLocalize);observer.observe(document.body,observerConfig)}else if(mutation.type==="characterData"){var nodeValue=mutation.target.nodeValue;var isBlacklistedNode=!!mutation.target.parentElement&&mutationObserverOpts.blacklistedNodeNames.includes(mutation.target.parentElement.nodeName);if(isNonEmptyString(nodeValue)&&!isBlacklistedNode){observer.disconnect();mutation.target.nodeValue=(0,_localize.default)(nodeValue,opts);observer.observe(document.body,observerConfig)}}}}catch(err){_iterator2.e(err)}finally{_iterator2.f()}};var isEnabled=function isEnabled(){return enabled};var start=function start(){var _ref=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{},_ref$strategy=_ref.strategy,strategy=_ref$strategy===void 0?"accented":_ref$strategy,extendParams=_ref.extendParams,_ref$blacklistedNodeN=_ref.blacklistedNodeNames,blacklistedNodeNames=_ref$blacklistedNodeN===void 0?mutationObserverOpts.blacklistedNodeNames:_ref$blacklistedNodeN;if(isEnabled()){console.error("pseudo-localization is already enabled");return}mutationObserverOpts.blacklistedNodeNames=blacklistedNodeNames;opts.strategy=strategy;opts.extendParams=extendParams;pseudoLocalize(document.body);observer=new MutationObserver(domMutationCallback);observer.observe(document.body,observerConfig);enabled=true};var stop=function stop(){if(!isEnabled()){console.error("pseudo-localization is already disabled");return}observer&&observer.disconnect();enabled=false};return{start:start,stop:stop,isEnabled:isEnabled,localize:_localize.default}}();var _default=pseudoLocalization;exports.default=_default; //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/cjs/index.js.map b/dist/cjs/index.js.map index 8d1757b..8b06922 100644 --- a/dist/cjs/index.js.map +++ b/dist/cjs/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","names":["pseudoLocalization","mutationObserverOpts","blacklistedNodeNames","opts","strategy","enabled","observer","observerConfig","characterData","childList","subtree","textNodesUnder","element","walker","document","createTreeWalker","NodeFilter","SHOW_TEXT","node","isAllWhitespace","nodeValue","test","FILTER_REJECT","isBlacklistedNode","parentElement","includes","nodeName","FILTER_ACCEPT","currNode","textNodes","nextNode","push","isNonEmptyString","str","pseudoLocalize","textNodesUnderElement","textNode","pseudoLocalizeString","domMutationCallback","mutationsList","mutation","type","addedNodes","length","disconnect","forEach","observe","body","target","isEnabled","start","console","error","MutationObserver","stop","localize"],"sources":["../../src/index.ts"],"sourcesContent":["import pseudoLocalizeString, {\n PseudoLocalizeStringOptions,\n} from './localize.js';\n\n/**\n * export the underlying pseudo localization function so this import style\n * import { localize } from 'pseudo-localization';\n * can be used.\n */\nexport { default as localize } from './localize.js';\n\ntype MutationObserverCallbackOptions = {\n blacklistedNodeNames?: string[];\n};\n\ntype StartOptions = MutationObserverCallbackOptions &\n PseudoLocalizeStringOptions;\n\nconst pseudoLocalization = (() => {\n const mutationObserverOpts = {\n blacklistedNodeNames: ['STYLE'],\n };\n\n const opts: PseudoLocalizeStringOptions = {\n strategy: 'accented',\n };\n\n // Indicates whether the pseudo-localization is currently enabled.\n let enabled = false;\n\n // Observer for dom updates. Initialization is defered to make parts\n // of the API safe to use in non-browser environments like nodejs\n let observer: MutationObserver | null = null;\n const observerConfig = {\n characterData: true,\n childList: true,\n subtree: true,\n };\n\n const textNodesUnder = (element: Node) => {\n const walker = document.createTreeWalker(\n element,\n NodeFilter.SHOW_TEXT,\n node => {\n const isAllWhitespace = node.nodeValue && !/[^\\s]/.test(node.nodeValue);\n if (isAllWhitespace) {\n return NodeFilter.FILTER_REJECT;\n }\n\n const isBlacklistedNode =\n node.parentElement &&\n mutationObserverOpts.blacklistedNodeNames.includes(\n node.parentElement.nodeName\n );\n if (isBlacklistedNode) {\n return NodeFilter.FILTER_REJECT;\n }\n\n return NodeFilter.FILTER_ACCEPT;\n }\n );\n\n let currNode;\n const textNodes = [];\n while ((currNode = walker.nextNode())) textNodes.push(currNode);\n return textNodes;\n };\n\n const isNonEmptyString = (str: unknown): str is string =>\n !!str && typeof str === 'string';\n\n const pseudoLocalize = (element: Node) => {\n const textNodesUnderElement = textNodesUnder(element);\n for (let textNode of textNodesUnderElement) {\n const nodeValue = textNode.nodeValue;\n if (isNonEmptyString(nodeValue)) {\n textNode.nodeValue = pseudoLocalizeString(nodeValue, opts);\n }\n }\n };\n\n const domMutationCallback: MutationCallback = mutationsList => {\n if (!observer) {\n return;\n }\n for (let mutation of mutationsList) {\n if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n // Turn the observer off while performing dom manipulation to prevent\n // infinite dom mutation callback loops\n observer.disconnect();\n // For every node added, recurse down it's subtree and convert\n // all children as well\n mutation.addedNodes.forEach(pseudoLocalize);\n observer.observe(document.body, observerConfig);\n } else if (mutation.type === 'characterData') {\n const nodeValue = mutation.target.nodeValue;\n const isBlacklistedNode =\n !!mutation.target.parentElement &&\n mutationObserverOpts.blacklistedNodeNames.includes(\n mutation.target.parentElement.nodeName\n );\n if (isNonEmptyString(nodeValue) && !isBlacklistedNode) {\n // Turn the observer off while performing dom manipulation to prevent\n // infinite dom mutation callback loops\n observer.disconnect();\n // The target will always be a text node so it can be converted\n // directly\n mutation.target.nodeValue = pseudoLocalizeString(nodeValue, opts);\n observer.observe(document.body, observerConfig);\n }\n }\n }\n };\n\n const isEnabled = () => {\n return enabled;\n };\n\n const start = ({\n strategy = 'accented',\n blacklistedNodeNames = mutationObserverOpts.blacklistedNodeNames,\n }: StartOptions = {}) => {\n if (isEnabled()) {\n console.error('pseudo-localization is already enabled');\n return;\n }\n\n mutationObserverOpts.blacklistedNodeNames = blacklistedNodeNames;\n opts.strategy = strategy;\n // Pseudo localize the DOM\n pseudoLocalize(document.body);\n // Start observing the DOM for changes and run\n // pseudo localization on any added text nodes\n observer = new MutationObserver(domMutationCallback);\n observer.observe(document.body, observerConfig);\n enabled = true;\n };\n\n const stop = () => {\n if (!isEnabled()) {\n console.error('pseudo-localization is already disabled');\n return;\n }\n\n observer && observer.disconnect();\n enabled = false;\n };\n\n return {\n start,\n stop,\n isEnabled,\n localize: pseudoLocalizeString,\n };\n})();\n\nexport default pseudoLocalization;\n"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.js","names":["pseudoLocalization","mutationObserverOpts","blacklistedNodeNames","opts","strategy","enabled","observer","observerConfig","characterData","childList","subtree","textNodesUnder","element","walker","document","createTreeWalker","NodeFilter","SHOW_TEXT","node","isAllWhitespace","nodeValue","test","FILTER_REJECT","isBlacklistedNode","parentElement","includes","nodeName","FILTER_ACCEPT","currNode","textNodes","nextNode","push","isNonEmptyString","str","pseudoLocalize","textNodesUnderElement","textNode","pseudoLocalizeString","domMutationCallback","mutationsList","mutation","type","addedNodes","length","disconnect","forEach","observe","body","target","isEnabled","start","extendParams","console","error","MutationObserver","stop","localize"],"sources":["../../src/index.ts"],"sourcesContent":["import pseudoLocalizeString, {\n getStrategy,\n PseudoLocalizeStringOptions,\n} from './localize.js';\n\n/**\n * export the underlying pseudo localization function so this import style\n * import { localize } from 'pseudo-localization';\n * can be used.\n */\nexport { default as localize } from './localize.js';\n\ntype MutationObserverCallbackOptions = {\n blacklistedNodeNames?: string[];\n};\n\ntype StartOptions = MutationObserverCallbackOptions &\n PseudoLocalizeStringOptions;\n\nconst pseudoLocalization = (() => {\n const mutationObserverOpts = {\n blacklistedNodeNames: ['STYLE'],\n };\n\n const opts: PseudoLocalizeStringOptions = {\n strategy: 'accented',\n };\n\n // Indicates whether the pseudo-localization is currently enabled.\n let enabled = false;\n\n // Observer for dom updates. Initialization is defered to make parts\n // of the API safe to use in non-browser environments like nodejs\n let observer: MutationObserver | null = null;\n const observerConfig = {\n characterData: true,\n childList: true,\n subtree: true,\n };\n\n const textNodesUnder = (element: Node) => {\n const walker = document.createTreeWalker(\n element,\n NodeFilter.SHOW_TEXT,\n node => {\n const isAllWhitespace = node.nodeValue && !/[^\\s]/.test(node.nodeValue);\n if (isAllWhitespace) {\n return NodeFilter.FILTER_REJECT;\n }\n\n const isBlacklistedNode =\n node.parentElement &&\n mutationObserverOpts.blacklistedNodeNames.includes(\n node.parentElement.nodeName\n );\n if (isBlacklistedNode) {\n return NodeFilter.FILTER_REJECT;\n }\n\n return NodeFilter.FILTER_ACCEPT;\n }\n );\n\n let currNode;\n const textNodes = [];\n while ((currNode = walker.nextNode())) textNodes.push(currNode);\n return textNodes;\n };\n\n const isNonEmptyString = (str: unknown): str is string =>\n !!str && typeof str === 'string';\n\n const pseudoLocalize = (element: Node) => {\n const textNodesUnderElement = textNodesUnder(element);\n for (let textNode of textNodesUnderElement) {\n const nodeValue = textNode.nodeValue;\n if (isNonEmptyString(nodeValue)) {\n textNode.nodeValue = pseudoLocalizeString(nodeValue, opts);\n }\n }\n };\n\n const domMutationCallback: MutationCallback = mutationsList => {\n if (!observer) {\n return;\n }\n for (let mutation of mutationsList) {\n if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n // Turn the observer off while performing dom manipulation to prevent\n // infinite dom mutation callback loops\n observer.disconnect();\n // For every node added, recurse down it's subtree and convert\n // all children as well\n mutation.addedNodes.forEach(pseudoLocalize);\n observer.observe(document.body, observerConfig);\n } else if (mutation.type === 'characterData') {\n const nodeValue = mutation.target.nodeValue;\n const isBlacklistedNode =\n !!mutation.target.parentElement &&\n mutationObserverOpts.blacklistedNodeNames.includes(\n mutation.target.parentElement.nodeName\n );\n if (isNonEmptyString(nodeValue) && !isBlacklistedNode) {\n // Turn the observer off while performing dom manipulation to prevent\n // infinite dom mutation callback loops\n observer.disconnect();\n // The target will always be a text node so it can be converted\n // directly\n mutation.target.nodeValue = pseudoLocalizeString(nodeValue, opts);\n observer.observe(document.body, observerConfig);\n }\n }\n }\n };\n\n const isEnabled = () => {\n return enabled;\n };\n\n const start = ({\n strategy = 'accented',\n extendParams,\n blacklistedNodeNames = mutationObserverOpts.blacklistedNodeNames,\n }: StartOptions = {}) => {\n if (isEnabled()) {\n console.error('pseudo-localization is already enabled');\n return;\n }\n\n mutationObserverOpts.blacklistedNodeNames = blacklistedNodeNames;\n opts.strategy = strategy;\n opts.extendParams = extendParams;\n // Pseudo localize the DOM\n pseudoLocalize(document.body);\n // Start observing the DOM for changes and run\n // pseudo localization on any added text nodes\n observer = new MutationObserver(domMutationCallback);\n observer.observe(document.body, observerConfig);\n enabled = true;\n };\n\n const stop = () => {\n if (!isEnabled()) {\n console.error('pseudo-localization is already disabled');\n return;\n }\n\n observer && observer.disconnect();\n enabled = false;\n };\n\n return {\n start,\n stop,\n isEnabled,\n localize: pseudoLocalizeString,\n };\n})();\n\nexport default pseudoLocalization;\n"],"mappings":"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"} \ No newline at end of file diff --git a/dist/cjs/localize.js b/dist/cjs/localize.js index c331ddb..9e6bc20 100644 --- a/dist/cjs/localize.js +++ b/dist/cjs/localize.js @@ -1,2 +1,2 @@ -"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var ACCENTED_MAP={a:"\u0227",A:"\u0226",b:"\u0180",B:"\u0181",c:"\u0188",C:"\u0187",d:"\u1E13",D:"\u1E12",e:"\u1E17",E:"\u1E16",f:"\u0192",F:"\u0191",g:"\u0260",G:"\u0193",h:"\u0127",H:"\u0126",i:"\u012B",I:"\u012A",j:"\u0135",J:"\u0134",k:"\u0137",K:"\u0136",l:"\u0140",L:"\u013F",m:"\u1E3F",M:"\u1E3E",n:"\u019E",N:"\u0220",o:"\u01FF",O:"\u01FE",p:"\u01A5",P:"\u01A4",q:"\u024B",Q:"\u024A",r:"\u0159",R:"\u0158",s:"\u015F",S:"\u015E",t:"\u0167",T:"\u0166",v:"\u1E7D",V:"\u1E7C",u:"\u016D",U:"\u016C",w:"\u1E87",W:"\u1E86",x:"\u1E8B",X:"\u1E8A",y:"\u1E8F",Y:"\u1E8E",z:"\u1E91",Z:"\u1E90"};var BIDI_MAP={a:"\u0250",A:"\u2200",b:"q",B:"\u0510",c:"\u0254",C:"\u2183",d:"p",D:"\u15E1",e:"\u01DD",E:"\u018E",f:"\u025F",F:"\u2132",g:"\u0183",G:"\u2141",h:"\u0265",H:"H",i:"\u0131",I:"I",j:"\u027E",J:"\u017F",k:"\u029E",K:"\u04FC",l:"\u0285",L:"\u2142",m:"\u026F",M:"W",n:"u",N:"N",o:"o",O:"O",p:"d",P:"\u0500",q:"b",Q:"\xD2",r:"\u0279",R:"\u1D1A",s:"s",S:"S",t:"\u0287",T:"\u22A5",u:"n",U:"\u2229",v:"\u028C",V:"\u0245",w:"\u028D",W:"M",x:"x",X:"X",y:"\u028E",Y:"\u2144",z:"z",Z:"Z"};var strategies={accented:{prefix:"",postfix:"",map:ACCENTED_MAP,elongate:true},bidi:{prefix:"\u202E",postfix:"\u202C",map:BIDI_MAP,elongate:false}};var pseudoLocalizeString=function pseudoLocalizeString(string){var _ref=arguments.length>1&&arguments[1]!==undefined?arguments[1]:{},_ref$strategy=_ref.strategy,strategy=_ref$strategy===void 0?"accented":_ref$strategy;var opts=strategies[strategy];var pseudoLocalizedText="";var _iteratorNormalCompletion=true;var _didIteratorError=false;var _iteratorError=undefined;try{for(var _iterator=string[Symbol.iterator](),_step;!(_iteratorNormalCompletion=(_step=_iterator.next()).done);_iteratorNormalCompletion=true){var character=_step.value;if(character in opts.map){var char=character;var cl=char.toLowerCase();if(opts.elongate&&(cl==="a"||cl==="e"||cl==="o"||cl==="u")){pseudoLocalizedText+=opts.map[char]+opts.map[char]}else pseudoLocalizedText+=opts.map[char]}else pseudoLocalizedText+=character}}catch(err){_didIteratorError=true;_iteratorError=err}finally{try{if(!_iteratorNormalCompletion&&_iterator.return!=null){_iterator.return()}}finally{if(_didIteratorError){throw _iteratorError}}}if(pseudoLocalizedText.startsWith(opts.prefix)&&pseudoLocalizedText.endsWith(opts.postfix)){return pseudoLocalizedText}return opts.prefix+pseudoLocalizedText+opts.postfix};var _default=pseudoLocalizeString;exports.default=_default; +"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.getStrategy=exports.default=void 0;function _createForOfIteratorHelper(o,allowArrayLike){var it=typeof Symbol!=="undefined"&&o[Symbol.iterator]||o["@@iterator"];if(!it){if(Array.isArray(o)||(it=_unsupportedIterableToArray(o))||allowArrayLike&&o&&typeof o.length==="number"){if(it)o=it;var i=0;var F=function F(){};return{s:F,n:function n(){if(i>=o.length)return{done:true};return{done:false,value:o[i++]}},e:function e(_e){throw _e},f:F}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var normalCompletion=true,didErr=false,err;return{s:function s(){it=it.call(o)},n:function n(){var step=it.next();normalCompletion=step.done;return step},e:function e(_e2){didErr=true;err=_e2},f:function f(){try{if(!normalCompletion&&it.return!=null)it.return()}finally{if(didErr)throw err}}}}function _unsupportedIterableToArray(o,minLen){if(!o)return;if(typeof o==="string")return _arrayLikeToArray(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);if(n==="Object"&&o.constructor)n=o.constructor.name;if(n==="Map"||n==="Set")return Array.from(o);if(n==="Arguments"||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _arrayLikeToArray(o,minLen)}function _arrayLikeToArray(arr,len){if(len==null||len>arr.length)len=arr.length;for(var i=0,arr2=new Array(len);i1&&arguments[1]!==undefined?arguments[1]:{};var opts=getStrategy(options);var pseudoLocalizedText="";var _iterator=_createForOfIteratorHelper(string),_step;try{for(_iterator.s();!(_step=_iterator.n()).done;){var character=_step.value;if(character in opts.map){var char=character;var cl=char.toLowerCase();if(opts.elongate&&(cl==="a"||cl==="e"||cl==="o"||cl==="u")){pseudoLocalizedText+=opts.map[char]+opts.map[char]}else pseudoLocalizedText+=opts.map[char]}else pseudoLocalizedText+=character}}catch(err){_iterator.e(err)}finally{_iterator.f()}if(pseudoLocalizedText.startsWith(opts.prefix)&&pseudoLocalizedText.endsWith(opts.postfix)){return pseudoLocalizedText}return opts.prefix+pseudoLocalizedText+opts.postfix};var _default=pseudoLocalizeString;exports.default=_default; //# sourceMappingURL=localize.js.map \ No newline at end of file diff --git a/dist/cjs/localize.js.map b/dist/cjs/localize.js.map index 3d32b5f..0c0b80c 100644 --- a/dist/cjs/localize.js.map +++ b/dist/cjs/localize.js.map @@ -1 +1 @@ -{"version":3,"file":"localize.js","names":["ACCENTED_MAP","a","A","b","B","c","C","d","D","e","E","f","F","g","G","h","H","i","I","j","J","k","K","l","L","m","M","n","N","o","O","p","P","q","Q","r","R","s","S","t","T","v","V","u","U","w","W","x","X","y","Y","z","Z","BIDI_MAP","strategies","accented","prefix","postfix","map","elongate","bidi","pseudoLocalizeString","string","strategy","opts","pseudoLocalizedText","character","char","cl","toLowerCase","startsWith","endsWith"],"sources":["../../src/localize.ts"],"sourcesContent":["const ACCENTED_MAP = {\n a: \"ȧ\",\n A: \"Ȧ\",\n b: \"ƀ\",\n B: \"Ɓ\",\n c: \"ƈ\",\n C: \"Ƈ\",\n d: \"ḓ\",\n D: \"Ḓ\",\n e: \"ḗ\",\n E: \"Ḗ\",\n f: \"ƒ\",\n F: \"Ƒ\",\n g: \"ɠ\",\n G: \"Ɠ\",\n h: \"ħ\",\n H: \"Ħ\",\n i: \"ī\",\n I: \"Ī\",\n j: \"ĵ\",\n J: \"Ĵ\",\n k: \"ķ\",\n K: \"Ķ\",\n l: \"ŀ\",\n L: \"Ŀ\",\n m: \"ḿ\",\n M: \"Ḿ\",\n n: \"ƞ\",\n N: \"Ƞ\",\n o: \"ǿ\",\n O: \"Ǿ\",\n p: \"ƥ\",\n P: \"Ƥ\",\n q: \"ɋ\",\n Q: \"Ɋ\",\n r: \"ř\",\n R: \"Ř\",\n s: \"ş\",\n S: \"Ş\",\n t: \"ŧ\",\n T: \"Ŧ\",\n v: \"ṽ\",\n V: \"Ṽ\",\n u: \"ŭ\",\n U: \"Ŭ\",\n w: \"ẇ\",\n W: \"Ẇ\",\n x: \"ẋ\",\n X: \"Ẋ\",\n y: \"ẏ\",\n Y: \"Ẏ\",\n z: \"ẑ\",\n Z: \"Ẑ\"\n};\n\nconst BIDI_MAP = {\n a: \"ɐ\",\n A: \"∀\",\n b: \"q\",\n B: \"Ԑ\",\n c: \"ɔ\",\n C: \"Ↄ\",\n d: \"p\",\n D: \"ᗡ\",\n e: \"ǝ\",\n E: \"Ǝ\",\n f: \"ɟ\",\n F: \"Ⅎ\",\n g: \"ƃ\",\n G: \"⅁\",\n h: \"ɥ\",\n H: \"H\",\n i: \"ı\",\n I: \"I\",\n j: \"ɾ\",\n J: \"ſ\",\n k: \"ʞ\",\n K: \"Ӽ\",\n l: \"ʅ\",\n L: \"⅂\",\n m: \"ɯ\",\n M: \"W\",\n n: \"u\",\n N: \"N\",\n o: \"o\",\n O: \"O\",\n p: \"d\",\n P: \"Ԁ\",\n q: \"b\",\n Q: \"Ò\",\n r: \"ɹ\",\n R: \"ᴚ\",\n s: \"s\",\n S: \"S\",\n t: \"ʇ\",\n T: \"⊥\",\n u: \"n\",\n U: \"∩\",\n v: \"ʌ\",\n V: \"Ʌ\",\n w: \"ʍ\",\n W: \"M\",\n x: \"x\",\n X: \"X\",\n y: \"ʎ\",\n Y: \"⅄\",\n z: \"z\",\n Z: \"Z\"\n};\n\nconst strategies = {\n accented: {\n prefix: \"\",\n postfix: \"\",\n map: ACCENTED_MAP,\n elongate: true\n },\n bidi: {\n // Surround words with Unicode formatting marks forcing\n // right-to-left directionality of characters\n prefix: \"\\u202e\",\n postfix: \"\\u202c\",\n map: BIDI_MAP,\n elongate: false\n }\n};\n\nexport type Strategy = \"accented\" | \"bidi\";\nexport type PseudoLocalizeStringOptions = {\n strategy?: Strategy;\n};\n\nconst pseudoLocalizeString = (\n string: string,\n { strategy = \"accented\" }: PseudoLocalizeStringOptions = {}\n): string => {\n let opts = strategies[strategy];\n\n let pseudoLocalizedText = \"\";\n for (let character of string) {\n if (character in opts.map) {\n let char = character as keyof typeof opts.map;\n const cl = char.toLowerCase();\n // duplicate \"a\", \"e\", \"o\" and \"u\" to emulate ~30% longer text\n if (\n opts.elongate &&\n (cl === \"a\" || cl === \"e\" || cl === \"o\" || cl === \"u\")\n ) {\n pseudoLocalizedText += opts.map[char] + opts.map[char];\n } else pseudoLocalizedText += opts.map[char];\n } else pseudoLocalizedText += character;\n }\n\n // If this string is from the DOM, it should already contain the pre- and postfix\n if (\n pseudoLocalizedText.startsWith(opts.prefix) &&\n pseudoLocalizedText.endsWith(opts.postfix)\n ) {\n return pseudoLocalizedText;\n }\n return opts.prefix + pseudoLocalizedText + opts.postfix;\n};\n\nexport default pseudoLocalizeString;\n"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"localize.js","names":["ACCENTED_MAP","a","A","b","B","c","C","d","D","e","E","f","F","g","G","h","H","i","I","j","J","k","K","l","L","m","M","n","N","o","O","p","P","q","Q","r","R","s","S","t","T","v","V","u","U","w","W","x","X","y","Y","z","Z","BIDI_MAP","strategies","accented","prefix","postfix","map","elongate","bidi","getStrategy","strategy","extendParams","opts","Object","assign","pseudoLocalizeString","string","options","pseudoLocalizedText","character","char","cl","toLowerCase","startsWith","endsWith"],"sources":["../../src/localize.ts"],"sourcesContent":["const ACCENTED_MAP = {\n a: 'ȧ',\n A: 'Ȧ',\n b: 'ƀ',\n B: 'Ɓ',\n c: 'ƈ',\n C: 'Ƈ',\n d: 'ḓ',\n D: 'Ḓ',\n e: 'ḗ',\n E: 'Ḗ',\n f: 'ƒ',\n F: 'Ƒ',\n g: 'ɠ',\n G: 'Ɠ',\n h: 'ħ',\n H: 'Ħ',\n i: 'ī',\n I: 'Ī',\n j: 'ĵ',\n J: 'Ĵ',\n k: 'ķ',\n K: 'Ķ',\n l: 'ŀ',\n L: 'Ŀ',\n m: 'ḿ',\n M: 'Ḿ',\n n: 'ƞ',\n N: 'Ƞ',\n o: 'ǿ',\n O: 'Ǿ',\n p: 'ƥ',\n P: 'Ƥ',\n q: 'ɋ',\n Q: 'Ɋ',\n r: 'ř',\n R: 'Ř',\n s: 'ş',\n S: 'Ş',\n t: 'ŧ',\n T: 'Ŧ',\n v: 'ṽ',\n V: 'Ṽ',\n u: 'ŭ',\n U: 'Ŭ',\n w: 'ẇ',\n W: 'Ẇ',\n x: 'ẋ',\n X: 'Ẋ',\n y: 'ẏ',\n Y: 'Ẏ',\n z: 'ẑ',\n Z: 'Ẑ',\n};\n\nconst BIDI_MAP = {\n a: 'ɐ',\n A: '∀',\n b: 'q',\n B: 'Ԑ',\n c: 'ɔ',\n C: 'Ↄ',\n d: 'p',\n D: 'ᗡ',\n e: 'ǝ',\n E: 'Ǝ',\n f: 'ɟ',\n F: 'Ⅎ',\n g: 'ƃ',\n G: '⅁',\n h: 'ɥ',\n H: 'H',\n i: 'ı',\n I: 'I',\n j: 'ɾ',\n J: 'ſ',\n k: 'ʞ',\n K: 'Ӽ',\n l: 'ʅ',\n L: '⅂',\n m: 'ɯ',\n M: 'W',\n n: 'u',\n N: 'N',\n o: 'o',\n O: 'O',\n p: 'd',\n P: 'Ԁ',\n q: 'b',\n Q: 'Ò',\n r: 'ɹ',\n R: 'ᴚ',\n s: 's',\n S: 'S',\n t: 'ʇ',\n T: '⊥',\n u: 'n',\n U: '∩',\n v: 'ʌ',\n V: 'Ʌ',\n w: 'ʍ',\n W: 'M',\n x: 'x',\n X: 'X',\n y: 'ʎ',\n Y: '⅄',\n z: 'z',\n Z: 'Z',\n};\n\ninterface StrategyOptions {\n map: typeof ACCENTED_MAP | typeof BIDI_MAP;\n prefix: string;\n postfix: string;\n elongate: boolean;\n}\n\nconst strategies = {\n accented: {\n prefix: '',\n postfix: '',\n map: ACCENTED_MAP,\n elongate: true,\n },\n bidi: {\n // Surround words with Unicode formatting marks forcing\n // right-to-left directionality of characters\n prefix: '\\u202e',\n postfix: '\\u202c',\n map: BIDI_MAP,\n elongate: false,\n },\n};\n\nexport type Strategy = 'accented' | 'bidi';\n\nexport interface ExtendStrategy {\n prefix: string;\n postfix: string;\n elongate: boolean;\n}\n\nexport type PseudoLocalizeStringOptions = {\n strategy?: Strategy;\n extendParams?: ExtendStrategy;\n};\n\nexport const getStrategy = ({\n strategy = 'accented',\n extendParams = { prefix: '', postfix: '', elongate: false },\n}: PseudoLocalizeStringOptions): StrategyOptions => {\n let opts = Object.assign({}, strategies[strategy]);\n if (typeof extendParams === 'object') {\n const { prefix, postfix, elongate } = extendParams;\n Object.assign(opts, { prefix, postfix, elongate });\n }\n return opts;\n};\n\nconst pseudoLocalizeString = (\n string: string,\n options: PseudoLocalizeStringOptions = {}\n): string => {\n let opts = getStrategy(options);\n let pseudoLocalizedText = '';\n for (let character of string) {\n if (character in opts.map) {\n let char = character as keyof typeof opts.map;\n const cl = char.toLowerCase();\n // duplicate \"a\", \"e\", \"o\" and \"u\" to emulate ~30% longer text\n if (\n opts.elongate &&\n (cl === 'a' || cl === 'e' || cl === 'o' || cl === 'u')\n ) {\n pseudoLocalizedText += opts.map[char] + opts.map[char];\n } else pseudoLocalizedText += opts.map[char];\n } else pseudoLocalizedText += character;\n }\n\n // If this string is from the DOM, it should already contain the pre- and postfix\n if (\n pseudoLocalizedText.startsWith(opts.prefix) &&\n pseudoLocalizedText.endsWith(opts.postfix)\n ) {\n return pseudoLocalizedText;\n }\n return opts.prefix + pseudoLocalizedText + opts.postfix;\n};\n\nexport default pseudoLocalizeString;\n"],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts index 6d6450c..d03b146 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -10,10 +10,10 @@ declare type MutationObserverCallbackOptions = { }; declare type StartOptions = MutationObserverCallbackOptions & PseudoLocalizeStringOptions; declare const pseudoLocalization: { - start: ({ strategy, blacklistedNodeNames, }?: StartOptions) => void; + start: ({ strategy, extendParams, blacklistedNodeNames, }?: StartOptions) => void; stop: () => void; isEnabled: () => boolean; - localize: (string: string, { strategy }?: PseudoLocalizeStringOptions) => string; + localize: (string: string, options?: PseudoLocalizeStringOptions) => string; }; export default pseudoLocalization; //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map index c37d0f5..faf61b2 100644 --- a/dist/index.d.ts.map +++ b/dist/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAA6B,EAC3B,2BAA2B,EAC5B,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,aAAK,+BAA+B,GAAG;IACrC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AAEF,aAAK,YAAY,GAAG,+BAA+B,GACjD,2BAA2B,CAAC;AAE9B,QAAA,MAAM,kBAAkB;kDAuGnB,YAAY;;;;CAiCb,CAAC;AAEL,eAAe,kBAAkB,CAAC"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAA6B,EAE3B,2BAA2B,EAC5B,MAAM,eAAe,CAAC;AAEvB;;;;GAIG;AACH,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,aAAK,+BAA+B,GAAG;IACrC,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACjC,CAAC;AAEF,aAAK,YAAY,GAAG,+BAA+B,GACjD,2BAA2B,CAAC;AAE9B,QAAA,MAAM,kBAAkB;gEAwGnB,YAAY;;;;CAkCb,CAAC;AAEL,eAAe,kBAAkB,CAAC"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 18f9cf3..f47f5e1 100644 --- a/dist/index.js +++ b/dist/index.js @@ -84,13 +84,14 @@ const pseudoLocalization = (() => { const isEnabled = () => { return enabled; }; - const start = ({ strategy = 'accented', blacklistedNodeNames = mutationObserverOpts.blacklistedNodeNames, } = {}) => { + const start = ({ strategy = 'accented', extendParams, blacklistedNodeNames = mutationObserverOpts.blacklistedNodeNames, } = {}) => { if (isEnabled()) { console.error('pseudo-localization is already enabled'); return; } mutationObserverOpts.blacklistedNodeNames = blacklistedNodeNames; opts.strategy = strategy; + opts.extendParams = extendParams; // Pseudo localize the DOM pseudoLocalize(document.body); // Start observing the DOM for changes and run diff --git a/dist/localize.d.ts b/dist/localize.d.ts index b67d9f7..97e8c67 100644 --- a/dist/localize.d.ts +++ b/dist/localize.d.ts @@ -1,7 +1,128 @@ -export declare type Strategy = "accented" | "bidi"; +declare const ACCENTED_MAP: { + a: string; + A: string; + b: string; + B: string; + c: string; + C: string; + d: string; + D: string; + e: string; + E: string; + f: string; + F: string; + g: string; + G: string; + h: string; + H: string; + i: string; + I: string; + j: string; + J: string; + k: string; + K: string; + l: string; + L: string; + m: string; + M: string; + n: string; + N: string; + o: string; + O: string; + p: string; + P: string; + q: string; + Q: string; + r: string; + R: string; + s: string; + S: string; + t: string; + T: string; + v: string; + V: string; + u: string; + U: string; + w: string; + W: string; + x: string; + X: string; + y: string; + Y: string; + z: string; + Z: string; +}; +declare const BIDI_MAP: { + a: string; + A: string; + b: string; + B: string; + c: string; + C: string; + d: string; + D: string; + e: string; + E: string; + f: string; + F: string; + g: string; + G: string; + h: string; + H: string; + i: string; + I: string; + j: string; + J: string; + k: string; + K: string; + l: string; + L: string; + m: string; + M: string; + n: string; + N: string; + o: string; + O: string; + p: string; + P: string; + q: string; + Q: string; + r: string; + R: string; + s: string; + S: string; + t: string; + T: string; + u: string; + U: string; + v: string; + V: string; + w: string; + W: string; + x: string; + X: string; + y: string; + Y: string; + z: string; + Z: string; +}; +interface StrategyOptions { + map: typeof ACCENTED_MAP | typeof BIDI_MAP; + prefix: string; + postfix: string; + elongate: boolean; +} +export declare type Strategy = 'accented' | 'bidi'; +export interface ExtendStrategy { + prefix: string; + postfix: string; + elongate: boolean; +} export declare type PseudoLocalizeStringOptions = { strategy?: Strategy; + extendParams?: ExtendStrategy; }; -declare const pseudoLocalizeString: (string: string, { strategy }?: PseudoLocalizeStringOptions) => string; +export declare const getStrategy: ({ strategy, extendParams, }: PseudoLocalizeStringOptions) => StrategyOptions; +declare const pseudoLocalizeString: (string: string, options?: PseudoLocalizeStringOptions) => string; export default pseudoLocalizeString; //# sourceMappingURL=localize.d.ts.map \ No newline at end of file diff --git a/dist/localize.d.ts.map b/dist/localize.d.ts.map index 55f9341..4d3c710 100644 --- a/dist/localize.d.ts.map +++ b/dist/localize.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"localize.d.ts","sourceRoot":"","sources":["../src/localize.ts"],"names":[],"mappings":"AA+HA,oBAAY,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAC3C,oBAAY,2BAA2B,GAAG;IACxC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC;AAEF,QAAA,MAAM,oBAAoB,WAChB,MAAM,iBACa,2BAA2B,KACrD,MA0BF,CAAC;AAEF,eAAe,oBAAoB,CAAC"} \ No newline at end of file +{"version":3,"file":"localize.d.ts","sourceRoot":"","sources":["../src/localize.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDjB,CAAC;AAEF,QAAA,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAqDb,CAAC;AAEF,UAAU,eAAe;IACvB,GAAG,EAAE,OAAO,YAAY,GAAG,OAAO,QAAQ,CAAC;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAmBD,oBAAY,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,oBAAY,2BAA2B,GAAG;IACxC,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,YAAY,CAAC,EAAE,cAAc,CAAC;CAC/B,CAAC;AAEF,eAAO,MAAM,WAAW,gCAGrB,2BAA2B,KAAG,eAOhC,CAAC;AAEF,QAAA,MAAM,oBAAoB,WAChB,MAAM,YACL,2BAA2B,KACnC,MAyBF,CAAC;AAEF,eAAe,oBAAoB,CAAC"} \ No newline at end of file diff --git a/dist/localize.js b/dist/localize.js index 2f1108b..6abc869 100644 --- a/dist/localize.js +++ b/dist/localize.js @@ -1,137 +1,145 @@ const ACCENTED_MAP = { - a: "ȧ", - A: "Ȧ", - b: "ƀ", - B: "Ɓ", - c: "ƈ", - C: "Ƈ", - d: "ḓ", - D: "Ḓ", - e: "ḗ", - E: "Ḗ", - f: "ƒ", - F: "Ƒ", - g: "ɠ", - G: "Ɠ", - h: "ħ", - H: "Ħ", - i: "ī", - I: "Ī", - j: "ĵ", - J: "Ĵ", - k: "ķ", - K: "Ķ", - l: "ŀ", - L: "Ŀ", - m: "ḿ", - M: "Ḿ", - n: "ƞ", - N: "Ƞ", - o: "ǿ", - O: "Ǿ", - p: "ƥ", - P: "Ƥ", - q: "ɋ", - Q: "Ɋ", - r: "ř", - R: "Ř", - s: "ş", - S: "Ş", - t: "ŧ", - T: "Ŧ", - v: "ṽ", - V: "Ṽ", - u: "ŭ", - U: "Ŭ", - w: "ẇ", - W: "Ẇ", - x: "ẋ", - X: "Ẋ", - y: "ẏ", - Y: "Ẏ", - z: "ẑ", - Z: "Ẑ" + a: 'ȧ', + A: 'Ȧ', + b: 'ƀ', + B: 'Ɓ', + c: 'ƈ', + C: 'Ƈ', + d: 'ḓ', + D: 'Ḓ', + e: 'ḗ', + E: 'Ḗ', + f: 'ƒ', + F: 'Ƒ', + g: 'ɠ', + G: 'Ɠ', + h: 'ħ', + H: 'Ħ', + i: 'ī', + I: 'Ī', + j: 'ĵ', + J: 'Ĵ', + k: 'ķ', + K: 'Ķ', + l: 'ŀ', + L: 'Ŀ', + m: 'ḿ', + M: 'Ḿ', + n: 'ƞ', + N: 'Ƞ', + o: 'ǿ', + O: 'Ǿ', + p: 'ƥ', + P: 'Ƥ', + q: 'ɋ', + Q: 'Ɋ', + r: 'ř', + R: 'Ř', + s: 'ş', + S: 'Ş', + t: 'ŧ', + T: 'Ŧ', + v: 'ṽ', + V: 'Ṽ', + u: 'ŭ', + U: 'Ŭ', + w: 'ẇ', + W: 'Ẇ', + x: 'ẋ', + X: 'Ẋ', + y: 'ẏ', + Y: 'Ẏ', + z: 'ẑ', + Z: 'Ẑ', }; const BIDI_MAP = { - a: "ɐ", - A: "∀", - b: "q", - B: "Ԑ", - c: "ɔ", - C: "Ↄ", - d: "p", - D: "ᗡ", - e: "ǝ", - E: "Ǝ", - f: "ɟ", - F: "Ⅎ", - g: "ƃ", - G: "⅁", - h: "ɥ", - H: "H", - i: "ı", - I: "I", - j: "ɾ", - J: "ſ", - k: "ʞ", - K: "Ӽ", - l: "ʅ", - L: "⅂", - m: "ɯ", - M: "W", - n: "u", - N: "N", - o: "o", - O: "O", - p: "d", - P: "Ԁ", - q: "b", - Q: "Ò", - r: "ɹ", - R: "ᴚ", - s: "s", - S: "S", - t: "ʇ", - T: "⊥", - u: "n", - U: "∩", - v: "ʌ", - V: "Ʌ", - w: "ʍ", - W: "M", - x: "x", - X: "X", - y: "ʎ", - Y: "⅄", - z: "z", - Z: "Z" + a: 'ɐ', + A: '∀', + b: 'q', + B: 'Ԑ', + c: 'ɔ', + C: 'Ↄ', + d: 'p', + D: 'ᗡ', + e: 'ǝ', + E: 'Ǝ', + f: 'ɟ', + F: 'Ⅎ', + g: 'ƃ', + G: '⅁', + h: 'ɥ', + H: 'H', + i: 'ı', + I: 'I', + j: 'ɾ', + J: 'ſ', + k: 'ʞ', + K: 'Ӽ', + l: 'ʅ', + L: '⅂', + m: 'ɯ', + M: 'W', + n: 'u', + N: 'N', + o: 'o', + O: 'O', + p: 'd', + P: 'Ԁ', + q: 'b', + Q: 'Ò', + r: 'ɹ', + R: 'ᴚ', + s: 's', + S: 'S', + t: 'ʇ', + T: '⊥', + u: 'n', + U: '∩', + v: 'ʌ', + V: 'Ʌ', + w: 'ʍ', + W: 'M', + x: 'x', + X: 'X', + y: 'ʎ', + Y: '⅄', + z: 'z', + Z: 'Z', }; const strategies = { accented: { - prefix: "", - postfix: "", + prefix: '', + postfix: '', map: ACCENTED_MAP, - elongate: true + elongate: true, }, bidi: { // Surround words with Unicode formatting marks forcing // right-to-left directionality of characters - prefix: "\u202e", - postfix: "\u202c", + prefix: '\u202e', + postfix: '\u202c', map: BIDI_MAP, - elongate: false + elongate: false, + }, +}; +export const getStrategy = ({ strategy = 'accented', extendParams = { prefix: '', postfix: '', elongate: false }, }) => { + let opts = Object.assign({}, strategies[strategy]); + if (typeof extendParams === 'object') { + const { prefix, postfix, elongate } = extendParams; + Object.assign(opts, { prefix, postfix, elongate }); } + return opts; }; -const pseudoLocalizeString = (string, { strategy = "accented" } = {}) => { - let opts = strategies[strategy]; - let pseudoLocalizedText = ""; +const pseudoLocalizeString = (string, options = {}) => { + let opts = getStrategy(options); + let pseudoLocalizedText = ''; for (let character of string) { if (character in opts.map) { let char = character; const cl = char.toLowerCase(); // duplicate "a", "e", "o" and "u" to emulate ~30% longer text if (opts.elongate && - (cl === "a" || cl === "e" || cl === "o" || cl === "u")) { + (cl === 'a' || cl === 'e' || cl === 'o' || cl === 'u')) { pseudoLocalizedText += opts.map[char] + opts.map[char]; } else diff --git a/src/index.ts b/src/index.ts index 96c4a7c..2231488 100644 --- a/src/index.ts +++ b/src/index.ts @@ -118,6 +118,7 @@ const pseudoLocalization = (() => { const start = ({ strategy = 'accented', + extendParams, blacklistedNodeNames = mutationObserverOpts.blacklistedNodeNames, }: StartOptions = {}) => { if (isEnabled()) { @@ -127,6 +128,7 @@ const pseudoLocalization = (() => { mutationObserverOpts.blacklistedNodeNames = blacklistedNodeNames; opts.strategy = strategy; + opts.extendParams = extendParams; // Pseudo localize the DOM pseudoLocalize(document.body); // Start observing the DOM for changes and run diff --git a/src/localize.ts b/src/localize.ts index fd18e73..58f3e4a 100644 --- a/src/localize.ts +++ b/src/localize.ts @@ -1,142 +1,168 @@ const ACCENTED_MAP = { - a: "ȧ", - A: "Ȧ", - b: "ƀ", - B: "Ɓ", - c: "ƈ", - C: "Ƈ", - d: "ḓ", - D: "Ḓ", - e: "ḗ", - E: "Ḗ", - f: "ƒ", - F: "Ƒ", - g: "ɠ", - G: "Ɠ", - h: "ħ", - H: "Ħ", - i: "ī", - I: "Ī", - j: "ĵ", - J: "Ĵ", - k: "ķ", - K: "Ķ", - l: "ŀ", - L: "Ŀ", - m: "ḿ", - M: "Ḿ", - n: "ƞ", - N: "Ƞ", - o: "ǿ", - O: "Ǿ", - p: "ƥ", - P: "Ƥ", - q: "ɋ", - Q: "Ɋ", - r: "ř", - R: "Ř", - s: "ş", - S: "Ş", - t: "ŧ", - T: "Ŧ", - v: "ṽ", - V: "Ṽ", - u: "ŭ", - U: "Ŭ", - w: "ẇ", - W: "Ẇ", - x: "ẋ", - X: "Ẋ", - y: "ẏ", - Y: "Ẏ", - z: "ẑ", - Z: "Ẑ" + a: 'ȧ', + A: 'Ȧ', + b: 'ƀ', + B: 'Ɓ', + c: 'ƈ', + C: 'Ƈ', + d: 'ḓ', + D: 'Ḓ', + e: 'ḗ', + E: 'Ḗ', + f: 'ƒ', + F: 'Ƒ', + g: 'ɠ', + G: 'Ɠ', + h: 'ħ', + H: 'Ħ', + i: 'ī', + I: 'Ī', + j: 'ĵ', + J: 'Ĵ', + k: 'ķ', + K: 'Ķ', + l: 'ŀ', + L: 'Ŀ', + m: 'ḿ', + M: 'Ḿ', + n: 'ƞ', + N: 'Ƞ', + o: 'ǿ', + O: 'Ǿ', + p: 'ƥ', + P: 'Ƥ', + q: 'ɋ', + Q: 'Ɋ', + r: 'ř', + R: 'Ř', + s: 'ş', + S: 'Ş', + t: 'ŧ', + T: 'Ŧ', + v: 'ṽ', + V: 'Ṽ', + u: 'ŭ', + U: 'Ŭ', + w: 'ẇ', + W: 'Ẇ', + x: 'ẋ', + X: 'Ẋ', + y: 'ẏ', + Y: 'Ẏ', + z: 'ẑ', + Z: 'Ẑ', }; const BIDI_MAP = { - a: "ɐ", - A: "∀", - b: "q", - B: "Ԑ", - c: "ɔ", - C: "Ↄ", - d: "p", - D: "ᗡ", - e: "ǝ", - E: "Ǝ", - f: "ɟ", - F: "Ⅎ", - g: "ƃ", - G: "⅁", - h: "ɥ", - H: "H", - i: "ı", - I: "I", - j: "ɾ", - J: "ſ", - k: "ʞ", - K: "Ӽ", - l: "ʅ", - L: "⅂", - m: "ɯ", - M: "W", - n: "u", - N: "N", - o: "o", - O: "O", - p: "d", - P: "Ԁ", - q: "b", - Q: "Ò", - r: "ɹ", - R: "ᴚ", - s: "s", - S: "S", - t: "ʇ", - T: "⊥", - u: "n", - U: "∩", - v: "ʌ", - V: "Ʌ", - w: "ʍ", - W: "M", - x: "x", - X: "X", - y: "ʎ", - Y: "⅄", - z: "z", - Z: "Z" + a: 'ɐ', + A: '∀', + b: 'q', + B: 'Ԑ', + c: 'ɔ', + C: 'Ↄ', + d: 'p', + D: 'ᗡ', + e: 'ǝ', + E: 'Ǝ', + f: 'ɟ', + F: 'Ⅎ', + g: 'ƃ', + G: '⅁', + h: 'ɥ', + H: 'H', + i: 'ı', + I: 'I', + j: 'ɾ', + J: 'ſ', + k: 'ʞ', + K: 'Ӽ', + l: 'ʅ', + L: '⅂', + m: 'ɯ', + M: 'W', + n: 'u', + N: 'N', + o: 'o', + O: 'O', + p: 'd', + P: 'Ԁ', + q: 'b', + Q: 'Ò', + r: 'ɹ', + R: 'ᴚ', + s: 's', + S: 'S', + t: 'ʇ', + T: '⊥', + u: 'n', + U: '∩', + v: 'ʌ', + V: 'Ʌ', + w: 'ʍ', + W: 'M', + x: 'x', + X: 'X', + y: 'ʎ', + Y: '⅄', + z: 'z', + Z: 'Z', }; +interface StrategyOptions { + map: typeof ACCENTED_MAP | typeof BIDI_MAP; + prefix: string; + postfix: string; + elongate: boolean; +} + const strategies = { accented: { - prefix: "", - postfix: "", + prefix: '', + postfix: '', map: ACCENTED_MAP, - elongate: true + elongate: true, }, bidi: { // Surround words with Unicode formatting marks forcing // right-to-left directionality of characters - prefix: "\u202e", - postfix: "\u202c", + prefix: '\u202e', + postfix: '\u202c', map: BIDI_MAP, - elongate: false - } + elongate: false, + }, }; -export type Strategy = "accented" | "bidi"; +export type Strategy = 'accented' | 'bidi'; + +export interface ExtendStrategy { + prefix: string; + postfix: string; + elongate: boolean; +} + export type PseudoLocalizeStringOptions = { strategy?: Strategy; + extendParams?: ExtendStrategy; +}; + +const getStrategy = ({ + strategy = 'accented', + extendParams = { prefix: '', postfix: '', elongate: false }, +}: PseudoLocalizeStringOptions): StrategyOptions => { + let opts = Object.assign({}, strategies[strategy]); + if (typeof extendParams === 'object') { + const { prefix, postfix, elongate } = extendParams; + Object.assign(opts, { prefix, postfix, elongate }); + } + return opts; }; const pseudoLocalizeString = ( string: string, - { strategy = "accented" }: PseudoLocalizeStringOptions = {} + options: PseudoLocalizeStringOptions = {} ): string => { - let opts = strategies[strategy]; - - let pseudoLocalizedText = ""; + let opts = getStrategy(options); + let pseudoLocalizedText = ''; for (let character of string) { if (character in opts.map) { let char = character as keyof typeof opts.map; @@ -144,7 +170,7 @@ const pseudoLocalizeString = ( // duplicate "a", "e", "o" and "u" to emulate ~30% longer text if ( opts.elongate && - (cl === "a" || cl === "e" || cl === "o" || cl === "u") + (cl === 'a' || cl === 'e' || cl === 'o' || cl === 'u') ) { pseudoLocalizedText += opts.map[char] + opts.map[char]; } else pseudoLocalizedText += opts.map[char];