pseudo-localization 2.3.5 → 2.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@ const getStdin = require('get-stdin');
6
6
  const flatten = require('flat');
7
7
  const unflatten = require('flat').unflatten;
8
8
 
9
- const { localize } = require('../lib/index');
9
+ const { localize } = require('../dist/cjs/index');
10
10
 
11
11
  const argv = require('yargs')
12
12
  .usage(
@@ -0,0 +1,2 @@
1
+ "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;
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +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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"}
@@ -1,2 +1,2 @@
1
- "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(opts.map[character]){var cl=character.toLowerCase();if(opts.elongate&&(cl==="a"||cl==="e"||cl==="o"||cl==="u")){pseudoLocalizedText+=opts.map[character]+opts.map[character]}else pseudoLocalizedText+=opts.map[character]}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;
1
+ "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;
2
2
  //# sourceMappingURL=localize.js.map
@@ -0,0 +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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"}
@@ -0,0 +1,19 @@
1
+ import { PseudoLocalizeStringOptions } from './localize.js';
2
+ /**
3
+ * export the underlying pseudo localization function so this import style
4
+ * import { localize } from 'pseudo-localization';
5
+ * can be used.
6
+ */
7
+ export { default as localize } from './localize.js';
8
+ declare type MutationObserverCallbackOptions = {
9
+ blacklistedNodeNames?: string[];
10
+ };
11
+ declare type StartOptions = MutationObserverCallbackOptions & PseudoLocalizeStringOptions;
12
+ declare const pseudoLocalization: {
13
+ start: ({ strategy, blacklistedNodeNames, }?: StartOptions) => void;
14
+ stop: () => void;
15
+ isEnabled: () => boolean;
16
+ localize: (string: string, { strategy }?: PseudoLocalizeStringOptions) => string;
17
+ };
18
+ export default pseudoLocalization;
19
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +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"}
package/dist/index.js ADDED
@@ -0,0 +1,117 @@
1
+ import pseudoLocalizeString from './localize.js';
2
+ /**
3
+ * export the underlying pseudo localization function so this import style
4
+ * import { localize } from 'pseudo-localization';
5
+ * can be used.
6
+ */
7
+ export { default as localize } from './localize.js';
8
+ const pseudoLocalization = (() => {
9
+ const mutationObserverOpts = {
10
+ blacklistedNodeNames: ['STYLE'],
11
+ };
12
+ const opts = {
13
+ strategy: 'accented',
14
+ };
15
+ // Indicates whether the pseudo-localization is currently enabled.
16
+ let enabled = false;
17
+ // Observer for dom updates. Initialization is defered to make parts
18
+ // of the API safe to use in non-browser environments like nodejs
19
+ let observer = null;
20
+ const observerConfig = {
21
+ characterData: true,
22
+ childList: true,
23
+ subtree: true,
24
+ };
25
+ const textNodesUnder = (element) => {
26
+ const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT, node => {
27
+ const isAllWhitespace = node.nodeValue && !/[^\s]/.test(node.nodeValue);
28
+ if (isAllWhitespace) {
29
+ return NodeFilter.FILTER_REJECT;
30
+ }
31
+ const isBlacklistedNode = node.parentElement &&
32
+ mutationObserverOpts.blacklistedNodeNames.includes(node.parentElement.nodeName);
33
+ if (isBlacklistedNode) {
34
+ return NodeFilter.FILTER_REJECT;
35
+ }
36
+ return NodeFilter.FILTER_ACCEPT;
37
+ });
38
+ let currNode;
39
+ const textNodes = [];
40
+ while ((currNode = walker.nextNode()))
41
+ textNodes.push(currNode);
42
+ return textNodes;
43
+ };
44
+ const isNonEmptyString = (str) => !!str && typeof str === 'string';
45
+ const pseudoLocalize = (element) => {
46
+ const textNodesUnderElement = textNodesUnder(element);
47
+ for (let textNode of textNodesUnderElement) {
48
+ const nodeValue = textNode.nodeValue;
49
+ if (isNonEmptyString(nodeValue)) {
50
+ textNode.nodeValue = pseudoLocalizeString(nodeValue, opts);
51
+ }
52
+ }
53
+ };
54
+ const domMutationCallback = mutationsList => {
55
+ if (!observer) {
56
+ return;
57
+ }
58
+ for (let mutation of mutationsList) {
59
+ if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
60
+ // Turn the observer off while performing dom manipulation to prevent
61
+ // infinite dom mutation callback loops
62
+ observer.disconnect();
63
+ // For every node added, recurse down it's subtree and convert
64
+ // all children as well
65
+ mutation.addedNodes.forEach(pseudoLocalize);
66
+ observer.observe(document.body, observerConfig);
67
+ }
68
+ else if (mutation.type === 'characterData') {
69
+ const nodeValue = mutation.target.nodeValue;
70
+ const isBlacklistedNode = !!mutation.target.parentElement &&
71
+ mutationObserverOpts.blacklistedNodeNames.includes(mutation.target.parentElement.nodeName);
72
+ if (isNonEmptyString(nodeValue) && !isBlacklistedNode) {
73
+ // Turn the observer off while performing dom manipulation to prevent
74
+ // infinite dom mutation callback loops
75
+ observer.disconnect();
76
+ // The target will always be a text node so it can be converted
77
+ // directly
78
+ mutation.target.nodeValue = pseudoLocalizeString(nodeValue, opts);
79
+ observer.observe(document.body, observerConfig);
80
+ }
81
+ }
82
+ }
83
+ };
84
+ const isEnabled = () => {
85
+ return enabled;
86
+ };
87
+ const start = ({ strategy = 'accented', blacklistedNodeNames = mutationObserverOpts.blacklistedNodeNames, } = {}) => {
88
+ if (isEnabled()) {
89
+ console.error('pseudo-localization is already enabled');
90
+ return;
91
+ }
92
+ mutationObserverOpts.blacklistedNodeNames = blacklistedNodeNames;
93
+ opts.strategy = strategy;
94
+ // Pseudo localize the DOM
95
+ pseudoLocalize(document.body);
96
+ // Start observing the DOM for changes and run
97
+ // pseudo localization on any added text nodes
98
+ observer = new MutationObserver(domMutationCallback);
99
+ observer.observe(document.body, observerConfig);
100
+ enabled = true;
101
+ };
102
+ const stop = () => {
103
+ if (!isEnabled()) {
104
+ console.error('pseudo-localization is already disabled');
105
+ return;
106
+ }
107
+ observer && observer.disconnect();
108
+ enabled = false;
109
+ };
110
+ return {
111
+ start,
112
+ stop,
113
+ isEnabled,
114
+ localize: pseudoLocalizeString,
115
+ };
116
+ })();
117
+ export default pseudoLocalization;
@@ -0,0 +1,7 @@
1
+ export declare type Strategy = "accented" | "bidi";
2
+ export declare type PseudoLocalizeStringOptions = {
3
+ strategy?: Strategy;
4
+ };
5
+ declare const pseudoLocalizeString: (string: string, { strategy }?: PseudoLocalizeStringOptions) => string;
6
+ export default pseudoLocalizeString;
7
+ //# sourceMappingURL=localize.d.ts.map
@@ -0,0 +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"}
@@ -0,0 +1,150 @@
1
+ const ACCENTED_MAP = {
2
+ a: "ȧ",
3
+ A: "Ȧ",
4
+ b: "ƀ",
5
+ B: "Ɓ",
6
+ c: "ƈ",
7
+ C: "Ƈ",
8
+ d: "ḓ",
9
+ D: "Ḓ",
10
+ e: "ḗ",
11
+ E: "Ḗ",
12
+ f: "ƒ",
13
+ F: "Ƒ",
14
+ g: "ɠ",
15
+ G: "Ɠ",
16
+ h: "ħ",
17
+ H: "Ħ",
18
+ i: "ī",
19
+ I: "Ī",
20
+ j: "ĵ",
21
+ J: "Ĵ",
22
+ k: "ķ",
23
+ K: "Ķ",
24
+ l: "ŀ",
25
+ L: "Ŀ",
26
+ m: "ḿ",
27
+ M: "Ḿ",
28
+ n: "ƞ",
29
+ N: "Ƞ",
30
+ o: "ǿ",
31
+ O: "Ǿ",
32
+ p: "ƥ",
33
+ P: "Ƥ",
34
+ q: "ɋ",
35
+ Q: "Ɋ",
36
+ r: "ř",
37
+ R: "Ř",
38
+ s: "ş",
39
+ S: "Ş",
40
+ t: "ŧ",
41
+ T: "Ŧ",
42
+ v: "ṽ",
43
+ V: "Ṽ",
44
+ u: "ŭ",
45
+ U: "Ŭ",
46
+ w: "ẇ",
47
+ W: "Ẇ",
48
+ x: "ẋ",
49
+ X: "Ẋ",
50
+ y: "ẏ",
51
+ Y: "Ẏ",
52
+ z: "ẑ",
53
+ Z: "Ẑ"
54
+ };
55
+ const BIDI_MAP = {
56
+ a: "ɐ",
57
+ A: "∀",
58
+ b: "q",
59
+ B: "Ԑ",
60
+ c: "ɔ",
61
+ C: "Ↄ",
62
+ d: "p",
63
+ D: "ᗡ",
64
+ e: "ǝ",
65
+ E: "Ǝ",
66
+ f: "ɟ",
67
+ F: "Ⅎ",
68
+ g: "ƃ",
69
+ G: "⅁",
70
+ h: "ɥ",
71
+ H: "H",
72
+ i: "ı",
73
+ I: "I",
74
+ j: "ɾ",
75
+ J: "ſ",
76
+ k: "ʞ",
77
+ K: "Ӽ",
78
+ l: "ʅ",
79
+ L: "⅂",
80
+ m: "ɯ",
81
+ M: "W",
82
+ n: "u",
83
+ N: "N",
84
+ o: "o",
85
+ O: "O",
86
+ p: "d",
87
+ P: "Ԁ",
88
+ q: "b",
89
+ Q: "Ò",
90
+ r: "ɹ",
91
+ R: "ᴚ",
92
+ s: "s",
93
+ S: "S",
94
+ t: "ʇ",
95
+ T: "⊥",
96
+ u: "n",
97
+ U: "∩",
98
+ v: "ʌ",
99
+ V: "Ʌ",
100
+ w: "ʍ",
101
+ W: "M",
102
+ x: "x",
103
+ X: "X",
104
+ y: "ʎ",
105
+ Y: "⅄",
106
+ z: "z",
107
+ Z: "Z"
108
+ };
109
+ const strategies = {
110
+ accented: {
111
+ prefix: "",
112
+ postfix: "",
113
+ map: ACCENTED_MAP,
114
+ elongate: true
115
+ },
116
+ bidi: {
117
+ // Surround words with Unicode formatting marks forcing
118
+ // right-to-left directionality of characters
119
+ prefix: "\u202e",
120
+ postfix: "\u202c",
121
+ map: BIDI_MAP,
122
+ elongate: false
123
+ }
124
+ };
125
+ const pseudoLocalizeString = (string, { strategy = "accented" } = {}) => {
126
+ let opts = strategies[strategy];
127
+ let pseudoLocalizedText = "";
128
+ for (let character of string) {
129
+ if (character in opts.map) {
130
+ let char = character;
131
+ const cl = char.toLowerCase();
132
+ // duplicate "a", "e", "o" and "u" to emulate ~30% longer text
133
+ if (opts.elongate &&
134
+ (cl === "a" || cl === "e" || cl === "o" || cl === "u")) {
135
+ pseudoLocalizedText += opts.map[char] + opts.map[char];
136
+ }
137
+ else
138
+ pseudoLocalizedText += opts.map[char];
139
+ }
140
+ else
141
+ pseudoLocalizedText += character;
142
+ }
143
+ // If this string is from the DOM, it should already contain the pre- and postfix
144
+ if (pseudoLocalizedText.startsWith(opts.prefix) &&
145
+ pseudoLocalizedText.endsWith(opts.postfix)) {
146
+ return pseudoLocalizedText;
147
+ }
148
+ return opts.prefix + pseudoLocalizedText + opts.postfix;
149
+ };
150
+ export default pseudoLocalizeString;
package/package.json CHANGED
@@ -1,20 +1,37 @@
1
1
  {
2
2
  "name": "pseudo-localization",
3
- "version": "2.3.5",
3
+ "version": "2.3.6",
4
4
  "description": "Dynamic pseudo-localization in the browser and nodejs",
5
- "main": "lib/index.js",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js",
10
+ "require": "./dist/cjs/index.js"
11
+ },
12
+ "./localize": {
13
+ "types": "./dist/localize.d.ts",
14
+ "import": "./dist/localize.js",
15
+ "require": "./dist/cjs/localize.js"
16
+ }
17
+ },
6
18
  "files": [
7
- "lib",
19
+ "dist",
8
20
  "bin"
9
21
  ],
10
22
  "bin": "./bin/pseudo-localize",
11
23
  "scripts": {
12
- "start": "node devserver.js",
13
- "prepare": "babel src --out-dir lib --minified --no-comments --source-maps --ignore '**/*.test.js'",
14
- "check-formatting": "prettier --list-different src/**/*.js",
24
+ "start": "node devserver.mjs",
25
+ "prepare": "npm run tsc && npm run transpile-cjs",
26
+ "transpile-cjs": "babel src --out-dir dist/cjs --minified --no-comments --source-maps --extensions '.ts'",
27
+ "generate-types": "tsc --emitDeclarationOnly",
28
+ "check-formatting": "prettier --list-different src/**/*.ts",
29
+ "format": "prettier --write src/**/*.ts",
15
30
  "lint": "eslint src/**/*.js",
16
31
  "test-js": "jest src/*",
17
- "test": "npm run test-js jest && npm run check-formatting && npm run lint"
32
+ "test": "npm run test-js jest && npm run check-formatting && npm run check-types && npm run lint",
33
+ "check-types": "tsc --noEmit",
34
+ "tsc": "tsc"
18
35
  },
19
36
  "author": "Tryggvi Gylfason (http://twitter.com/tryggvigy)",
20
37
  "keywords": [
@@ -36,15 +53,19 @@
36
53
  "devDependencies": {
37
54
  "@babel/cli": "^7.5.5",
38
55
  "@babel/core": "^7.5.5",
56
+ "@babel/plugin-transform-modules-commonjs": "^7.18.6",
39
57
  "@babel/preset-env": "^7.5.5",
40
- "babel-jest": "^24.8.0",
58
+ "@babel/preset-typescript": "^7.18.6",
59
+ "@types/node": "^18.7.9",
41
60
  "eslint": "^6.1.0",
42
- "jest-cli": "^24.8.0",
43
- "prettier": "^1.18.2"
61
+ "jest": "^28.1.3",
62
+ "jest-cli": "^28.1.3",
63
+ "prettier": "^1.19.1"
44
64
  },
45
65
  "dependencies": {
46
66
  "flat": "^5.0.2",
47
67
  "get-stdin": "^7.0.0",
68
+ "typescript": "^4.7.4",
48
69
  "yargs": "^17.2.1"
49
70
  }
50
71
  }
package/lib/index.js DELETED
@@ -1,2 +0,0 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"localize",{enumerable:true,get:function get(){return _localize.default}});exports.default=void 0;var _localize=_interopRequireDefault(require("./localize.js"));function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}var pseudoLocalization=function(){var opts={blacklistedNodeNames:["STYLE"]};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=!/[^\s]/.test(node.nodeValue);if(isAllWhitespace)return NodeFilter.FILTER_REJECT;var isBlacklistedNode=opts.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){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=opts.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?opts.blacklistedNodeNames:_ref$blacklistedNodeN;if(isEnabled()){console.error("pseudo-localization is already enabled");return}opts.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;
2
- //# sourceMappingURL=index.js.map
package/lib/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.js"],"names":["pseudoLocalization","opts","blacklistedNodeNames","enabled","observer","observerConfig","characterData","childList","subtree","textNodesUnder","element","walker","document","createTreeWalker","NodeFilter","SHOW_TEXT","node","isAllWhitespace","test","nodeValue","FILTER_REJECT","isBlacklistedNode","includes","parentElement","nodeName","FILTER_ACCEPT","currNode","textNodes","nextNode","push","isNonEmptyString","str","pseudoLocalize","textNodesUnderElement","textNode","domMutationCallback","mutationsList","mutation","type","addedNodes","length","disconnect","forEach","observe","body","target","isEnabled","start","strategy","console","error","MutationObserver","stop","localize","pseudoLocalizeString"],"mappings":"sMAAA,+D,kFASA,GAAMA,CAAAA,kBAAkB,CAAI,UAAM,CAChC,GAAMC,CAAAA,IAAI,CAAG,CACXC,oBAAoB,CAAE,CAAC,OAAD,CADX,CAAb,CAKA,GAAIC,CAAAA,OAAO,CAAG,KAAd,CAIA,GAAIC,CAAAA,QAAQ,CAAG,IAAf,CACA,GAAMC,CAAAA,cAAc,CAAG,CACrBC,aAAa,CAAE,IADM,CAErBC,SAAS,CAAE,IAFU,CAGrBC,OAAO,CAAE,IAHY,CAAvB,CAMA,GAAMC,CAAAA,cAAc,CAAG,QAAjBA,CAAAA,cAAiB,CAAAC,OAAO,CAAI,CAChC,GAAMC,CAAAA,MAAM,CAAGC,QAAQ,CAACC,gBAAT,CACbH,OADa,CAEbI,UAAU,CAACC,SAFE,CAGb,SAAAC,IAAI,CAAI,CACN,GAAMC,CAAAA,eAAe,CAAG,CAAC,QAAQC,IAAR,CAAaF,IAAI,CAACG,SAAlB,CAAzB,CACA,GAAIF,eAAJ,CAAqB,MAAOH,CAAAA,UAAU,CAACM,aAAlB,CAErB,GAAMC,CAAAA,iBAAiB,CAAGpB,IAAI,CAACC,oBAAL,CAA0BoB,QAA1B,CACxBN,IAAI,CAACO,aAAL,CAAmBC,QADK,CAA1B,CAGA,GAAIH,iBAAJ,CAAuB,MAAOP,CAAAA,UAAU,CAACM,aAAlB,CAEvB,MAAON,CAAAA,UAAU,CAACW,aACnB,CAbY,CAAf,CAgBA,GAAIC,CAAAA,QAAJ,CACA,GAAMC,CAAAA,SAAS,CAAG,EAAlB,CACA,MAAQD,QAAQ,CAAGf,MAAM,CAACiB,QAAP,EAAnB,EAAuCD,SAAS,CAACE,IAAV,CAAeH,QAAf,CAAvC,CACA,MAAOC,CAAAA,SACR,CArBD,CAuBA,GAAMG,CAAAA,gBAAgB,CAAG,QAAnBA,CAAAA,gBAAmB,CAAAC,GAAG,QAAIA,CAAAA,GAAG,EAAI,MAAOA,CAAAA,GAAP,GAAe,QAA1B,CAA5B,CAEA,GAAMC,CAAAA,cAAc,CAAG,QAAjBA,CAAAA,cAAiB,CAAAtB,OAAO,CAAI,CAChC,GAAMuB,CAAAA,qBAAqB,CAAGxB,cAAc,CAACC,OAAD,CAA5C,CADgC,gGAEhC,kBAAqBuB,qBAArB,oHAA4C,IAAnCC,CAAAA,QAAmC,aAC1C,GAAMf,CAAAA,SAAS,CAAGe,QAAQ,CAACf,SAA3B,CACA,GAAIW,gBAAgB,CAACX,SAAD,CAApB,CAAiC,CAC/Be,QAAQ,CAACf,SAAT,CAAqB,sBAAqBA,SAArB,CAAgClB,IAAhC,CACtB,CACF,CAP+B,kMAQjC,CARD,CAUA,GAAMkC,CAAAA,mBAAmB,CAAG,QAAtBA,CAAAA,mBAAsB,CAAAC,aAAa,CAAI,oGAC3C,mBAAqBA,aAArB,yHAAoC,IAA3BC,CAAAA,QAA2B,cAClC,GAAIA,QAAQ,CAACC,IAAT,GAAkB,WAAlB,EAAiCD,QAAQ,CAACE,UAAT,CAAoBC,MAApB,CAA6B,CAAlE,CAAqE,CAGnEpC,QAAQ,CAACqC,UAAT,GAGAJ,QAAQ,CAACE,UAAT,CAAoBG,OAApB,CAA4BV,cAA5B,EACA5B,QAAQ,CAACuC,OAAT,CAAiB/B,QAAQ,CAACgC,IAA1B,CAAgCvC,cAAhC,CACD,CARD,IAQO,IAAIgC,QAAQ,CAACC,IAAT,GAAkB,eAAtB,CAAuC,CAC5C,GAAMnB,CAAAA,SAAS,CAAGkB,QAAQ,CAACQ,MAAT,CAAgB1B,SAAlC,CACA,GAAME,CAAAA,iBAAiB,CAAGpB,IAAI,CAACC,oBAAL,CAA0BoB,QAA1B,CACxBe,QAAQ,CAACQ,MAAT,CAAgBtB,aAAhB,CAA8BC,QADN,CAA1B,CAGA,GAAIM,gBAAgB,CAACX,SAAD,CAAhB,EAA+B,CAACE,iBAApC,CAAuD,CAGrDjB,QAAQ,CAACqC,UAAT,GAGAJ,QAAQ,CAACQ,MAAT,CAAgB1B,SAAhB,CAA4B,sBAAqBA,SAArB,CAAgClB,IAAhC,CAA5B,CACAG,QAAQ,CAACuC,OAAT,CAAiB/B,QAAQ,CAACgC,IAA1B,CAAgCvC,cAAhC,CACD,CACF,CACF,CAzB0C,yMA0B5C,CA1BD,CA4BA,GAAMyC,CAAAA,SAAS,CAAG,QAAZA,CAAAA,SAAY,EAAM,CACtB,MAAO3C,CAAAA,OACR,CAFD,CAIA,GAAM4C,CAAAA,KAAK,CAAG,QAARA,CAAAA,KAAQ,EAGH,oEAAP,EAAO,oBAFTC,QAES,CAFTA,QAES,wBAFE,UAEF,0CADT9C,oBACS,CADTA,oBACS,gCADcD,IAAI,CAACC,oBACnB,uBACT,GAAI4C,SAAS,EAAb,CAAiB,CACfG,OAAO,CAACC,KAAR,CAAc,wCAAd,EACA,MACD,CAEDjD,IAAI,CAACC,oBAAL,CAA4BA,oBAA5B,CACAD,IAAI,CAAC+C,QAAL,CAAgBA,QAAhB,CAEAhB,cAAc,CAACpB,QAAQ,CAACgC,IAAV,CAAd,CAGAxC,QAAQ,CAAG,GAAI+C,CAAAA,gBAAJ,CAAqBhB,mBAArB,CAAX,CACA/B,QAAQ,CAACuC,OAAT,CAAiB/B,QAAQ,CAACgC,IAA1B,CAAgCvC,cAAhC,EACAF,OAAO,CAAG,IACX,CAlBD,CAoBA,GAAMiD,CAAAA,IAAI,CAAG,QAAPA,CAAAA,IAAO,EAAM,CACjB,GAAI,CAACN,SAAS,EAAd,CAAkB,CAChBG,OAAO,CAACC,KAAR,CAAc,yCAAd,EACA,MACD,CAED9C,QAAQ,EAAIA,QAAQ,CAACqC,UAAT,EAAZ,CACAtC,OAAO,CAAG,KACX,CARD,CAUA,MAAO,CACL4C,KAAK,CAALA,KADK,CAELK,IAAI,CAAJA,IAFK,CAGLN,SAAS,CAATA,SAHK,CAILO,QAAQ,CAAEC,iBAJL,CAMR,CAxH0B,EAA3B,C,aA0HetD,kB","sourcesContent":["import pseudoLocalizeString 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\nconst pseudoLocalization = (() => {\n const opts = {\n blacklistedNodeNames: ['STYLE'],\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 = null;\n const observerConfig = {\n characterData: true,\n childList: true,\n subtree: true,\n };\n\n const textNodesUnder = element => {\n const walker = document.createTreeWalker(\n element,\n NodeFilter.SHOW_TEXT,\n node => {\n const isAllWhitespace = !/[^\\s]/.test(node.nodeValue);\n if (isAllWhitespace) return NodeFilter.FILTER_REJECT;\n\n const isBlacklistedNode = opts.blacklistedNodeNames.includes(\n node.parentElement.nodeName\n );\n if (isBlacklistedNode) return NodeFilter.FILTER_REJECT;\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 => str && typeof str === 'string';\n\n const pseudoLocalize = element => {\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 = mutationsList => {\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 = opts.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 = opts.blacklistedNodeNames,\n } = {}) => {\n if (isEnabled()) {\n console.error('pseudo-localization is already enabled');\n return;\n }\n\n opts.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"],"file":"index.js"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/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","cl","toLowerCase","startsWith","endsWith"],"mappings":"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","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\nconst pseudoLocalizeString = (string, { strategy = 'accented' } = {}) => {\n let opts = strategies[strategy];\n\n let pseudoLocalizedText = '';\n for (let character of string) {\n if (opts.map[character]) {\n const cl = character.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[character] + opts.map[character];\n } else pseudoLocalizedText += opts.map[character];\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"],"file":"localize.js"}