├── .gitattributes ├── .gitignore ├── .npmignore ├── .travis.yml ├── examples ├── yaml-ts │ ├── text-context.tsx │ ├── tsconfig.json │ ├── index.html │ ├── texts.yml │ ├── index.tsx │ └── hello-block.tsx ├── yaml │ ├── text-context.jsx │ ├── index.html │ ├── texts.yml │ ├── index.jsx │ └── hello-block.jsx ├── syntaxV1 │ ├── tsconfig.json │ ├── index.html │ └── index.tsx ├── hello │ ├── index.html │ └── index.jsx └── umd │ └── index.html ├── tests ├── reference.d.ts ├── tsconfig.json ├── renderElement.ts ├── formatHTML.ts ├── react-tree_test.ts ├── syntaxv1_test.ts ├── tags_test.tsx ├── react_test.ts ├── context_test.ts └── basic_test.ts ├── src ├── tsconfig.json ├── mdflavors.ts └── i18n-react.ts ├── dist ├── mdflavors.d.ts ├── i18n-react.d.ts ├── mdflavors.js ├── i18n-react.umd.min.js ├── i18n-react.js ├── i18n-react.umd.js ├── i18n-react.umd.js.map └── i18n-react.umd.min.js.map ├── .editorconfig ├── webpack-umd.config.js ├── webpack-ex.config.js ├── LICENSE ├── karma.config.js ├── package.json └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf 2 | 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | build 4 | npm-debug.log 5 | *.sublime-workspace 6 | 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | tests 2 | examples 3 | webpack*.* 4 | karma.* 5 | .git* 6 | .editor* 7 | .vscode 8 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - 8 4 | env: 5 | - MOZ_HEADLESS=1 6 | addons: 7 | firefox: latest 8 | -------------------------------------------------------------------------------- /examples/yaml-ts/text-context.tsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | import T from '../../dist/i18n-react'; 3 | export default React.createContext(T); 4 | 5 | -------------------------------------------------------------------------------- /tests/reference.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'react-dom-server' { 2 | function renderToStaticMarkup(el: any): string; 3 | function isValidElement(e: any): boolean; 4 | } 5 | -------------------------------------------------------------------------------- /tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "jsx": "react", 5 | "strict": true, 6 | "strictNullChecks": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/yaml/text-context.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var T = require('i18n-react').default; 3 | 4 | var MDTextContext = React.createContext(T); 5 | 6 | module.exports = MDTextContext; 7 | -------------------------------------------------------------------------------- /examples/syntaxV1/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "module": "commonjs", 5 | "strict": true, 6 | "strictNullChecks": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /examples/yaml-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "module": "commonjs", 5 | "strict": true, 6 | "strictNullChecks": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/renderElement.ts: -------------------------------------------------------------------------------- 1 | import * as ReactDOMServer from 'react-dom-server'; 2 | 3 | export default function renderElement(element: any): string { 4 | return ReactDOMServer.renderToStaticMarkup(element); 5 | } 6 | -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "strict": true, 5 | "strictNullChecks": false, 6 | "preserveConstEnums": true, 7 | "outDir": "../dist/", 8 | "declaration": false 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tests/formatHTML.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import renderElement from './renderElement'; 3 | import T from '../src/i18n-react'; 4 | 5 | export default function formatHTML(text: string, o?: any): string { 6 | return renderElement(T.format(text, o)); 7 | } 8 | 9 | export function textHTML(o?: any): string { 10 | return renderElement(React.createElement(T.text, o)); 11 | } 12 | -------------------------------------------------------------------------------- /examples/yaml/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | I18N-React 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dist/mdflavors.d.ts: -------------------------------------------------------------------------------- 1 | declare type RegExpEx = RegExp | [RegExp, [number, number, number]]; 2 | export interface MDFlavor { 3 | maybe: RegExp; 4 | tags: { 5 | [type: string]: RegExpEx; 6 | }; 7 | } 8 | export declare const mdFlavors: MDFlavor[]; 9 | declare type MDMatch = { 10 | tag: string; 11 | head: string; 12 | body: string; 13 | tail: string; 14 | }; 15 | export declare function mdMatch(md: MDFlavor, value: string): MDMatch | null; 16 | export {}; 17 | -------------------------------------------------------------------------------- /examples/yaml-ts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | I18N-React 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | 8 | [*] 9 | 10 | # Change these settings to your own preference 11 | indent_style = space 12 | indent_size = 2 13 | 14 | # We recommend you to keep these unchanged 15 | end_of_line = lf 16 | charset = utf-8 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | 20 | [*.md] 21 | trim_trailing_whitespace = false 22 | -------------------------------------------------------------------------------- /examples/hello/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello I18N-React 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /webpack-umd.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require("webpack"); 2 | 3 | module.exports = { 4 | entry: { 5 | "i18n-react": "./src/i18n-react.ts", 6 | }, 7 | output: { 8 | path: __dirname + '/dist/', 9 | filename: 'i18n-react.umd.js', 10 | library: 'i18n-react', 11 | libraryTarget: "umd" 12 | }, 13 | externals: { 14 | "react": "React" 15 | }, 16 | resolve: { 17 | extensions: ['.js', '.jsx', '.ts'], 18 | }, 19 | module: { 20 | loaders: [ 21 | { test: /\.tsx?$/, loader: 'ts-loader' } 22 | ] 23 | }, 24 | devtool: "source-map", 25 | }; 26 | -------------------------------------------------------------------------------- /examples/yaml-ts/texts.yml: -------------------------------------------------------------------------------- 1 | greetings: 2 | hello: Hi, {who}! 3 | howdy: 4 | formal: How do you do? 5 | normal: How are you, {who}? 6 | informal: "What's up?" 7 | bye: Bye 8 | 9 | longTime: 10 | 0: Not a day no see 11 | 1: 1 day no see 12 | '2..4': A few days no see 13 | _: "[{context} days][Long time no see]" 14 | 15 | lorem: | 16 | # Lorem 17 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. 18 | ## Quisque 19 | Quisque sit amet nisi quis eros cursus finibus quis sed nisl. 20 | ### Integer 21 | Integer efficitur pharetra pretium. 22 | Sed semper dui vitae nibh scelerisque sodales. 23 | -------------------------------------------------------------------------------- /examples/yaml/texts.yml: -------------------------------------------------------------------------------- 1 | greetings: 2 | hello: Hi, {who}! 3 | howdy: 4 | formal: How do you do? 5 | normal: How are you, {who}? 6 | informal: "What's up?" 7 | bye: Bye 8 | 9 | longTime: 10 | 0: Not a day no see 11 | 1: 1 day no see 12 | '2..4': A few days no see 13 | _: "[{context} days][Long time no see]" 14 | 15 | lorem: | 16 | # Lorem 17 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. 18 | ## Quisque 19 | Quisque sit amet nisi quis eros cursus finibus quis sed nisl. 20 | ### Integer 21 | Integer efficitur pharetra pretium. 22 | Sed semper dui vitae nibh scelerisque sodales. 23 | -------------------------------------------------------------------------------- /tests/react-tree_test.ts: -------------------------------------------------------------------------------- 1 | import formatHTML from './formatHTML'; 2 | 3 | describe("i18n-react", () => { 4 | it("format renders tree 1", () => { 5 | expect(formatHTML("a *{v} _{q}_* z", { v: 1, q: 2 })).toBe("a 1 2 z"); 6 | expect(formatHTML("[a *{v} _{q}_* z]", { v: 1, q: 2 })).toBe("

a 1 2 z

"); 7 | expect(formatHTML("[a *{v} _{q}_* z][${q}]", { v: 1, q: 2 })).toBe("

a 1 2 z

$2

"); 8 | }); 9 | 10 | it("format renders tree 2", () => { 11 | expect(formatHTML("_a *{v} {q}* z_", { v: 1, q: 2 })).toBe("a 1 2 z"); 12 | expect(formatHTML("_a *{v} [{q}]* z_", { v: 1, q: 2 })).toBe("a 1

2

z
"); 13 | }); 14 | }); 15 | 16 | -------------------------------------------------------------------------------- /examples/yaml/index.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | var MDText = require('i18n-react').MDText; 4 | var HelloBlock = require('./hello-block'); 5 | var MDTextContext = require('text-context'); 6 | 7 | /* Initialize once - probably in entry point js somwehere near the router */ 8 | var T = new MDText(require('./texts.yml')); 9 | 10 | ReactDOM.render( 11 | 12 |
13 | 14 | 15 | 16 | 17 |
18 |
, 19 | document.getElementById('content') 20 | ); 21 | 22 | -------------------------------------------------------------------------------- /examples/yaml-ts/index.tsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var ReactDOM = require('react-dom'); 3 | import { MDText } from '../../dist/i18n-react'; 4 | import HelloBlock from './hello-block'; 5 | import MDTextContext from './text-context'; 6 | 7 | 8 | /* Initialize once - probably in entry point js somwehere near the router */ 9 | var T = new MDText(require('./texts.yml')); 10 | 11 | ReactDOM.render( 12 | 13 |
14 | 15 | 16 | 17 | 18 |
19 |
, 20 | document.getElementById('content') 21 | ); 22 | 23 | -------------------------------------------------------------------------------- /examples/yaml/hello-block.jsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var MDTextContext = require('text-context'); 3 | 4 | function HelloBlock(props) { 5 | return ( 6 | { (T) => 7 |
8 | 9 | 10 | 11 | 12 | alert("Cya")} href="#"/> 13 |
14 | }
15 | ); 16 | } 17 | 18 | module.exports = HelloBlock 19 | -------------------------------------------------------------------------------- /examples/syntaxV1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | I18N-React Syntax v1 5 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /webpack-ex.config.js: -------------------------------------------------------------------------------- 1 | var webpack = require("webpack"); 2 | 3 | module.exports = { 4 | entry: { 5 | hello: './examples/hello/index.jsx', 6 | syntaxV1: './examples/syntaxV1/index.tsx', 7 | yaml: './examples/yaml/index.jsx', 8 | "yaml-ts": './examples/yaml-ts/index.tsx' 9 | }, 10 | output: { 11 | filename: './examples/[name]/build/index.js' 12 | }, 13 | externals: { 14 | "react": "React", 15 | "react-dom": "ReactDOM", 16 | }, 17 | resolve: { 18 | extensions: ['.js', '.jsx', '.tsx'], 19 | modules: [ '.', 'node_modules' ], 20 | }, 21 | module: { 22 | loaders: [ 23 | { test: /\.tsx?$/, loader: 'ts-loader' }, 24 | { test: /\.jsx$/, loader: 'jsx-loader?harmony' }, 25 | { test: /\.ya?ml$/, loader: 'json-loader!yaml-loader' } 26 | ] 27 | }, 28 | devtool: "eval", 29 | devServer: { 30 | noInfo: false, 31 | stats: true 32 | } 33 | }; 34 | -------------------------------------------------------------------------------- /examples/umd/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Hello I18N-React 6 | 7 | 8 | 9 | 10 | 11 |
12 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /examples/yaml-ts/hello-block.tsx: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | import MDTextContext from './text-context'; 3 | import { MDText } from '../../dist/i18n-react'; 4 | export default function HelloBlock(props: { name: string, days: number, style: string }) { 5 | return ( 6 | {(T: MDText) => 7 |
8 | 9 | 10 | 11 | 12 | alert("Cya")} href="#" /> 13 |
14 | }
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /dist/i18n-react.d.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | export declare type NotFound = string | ((key: string, context?: any) => string); 3 | export interface MDTextOpts { 4 | MDFlavor?: 0 | 1; 5 | notFound?: NotFound; 6 | } 7 | export declare class MDText { 8 | texts: object; 9 | constructor(texts: object, opt?: MDTextOpts); 10 | setTexts(texts: object, opt?: MDTextOpts): void; 11 | setOpts(opt: MDTextOpts): void; 12 | private MDFlavor; 13 | notFound: NotFound; 14 | interpolate(exp: string, vars: object): any; 15 | format(value: string, vars?: object): React.ReactNode; 16 | translate(key: string, options?: any): React.ReactNode; 17 | factory(tagF: string): React.StatelessComponent; 18 | p: React.StatelessComponent; 19 | span: React.StatelessComponent; 20 | li: React.StatelessComponent; 21 | div: React.StatelessComponent; 22 | button: React.StatelessComponent; 23 | a: React.StatelessComponent; 24 | text: React.StatelessComponent; 25 | } 26 | declare var singleton: MDText; 27 | export default singleton; 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (C) 2015 Alex Drel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/syntaxV1/index.tsx: -------------------------------------------------------------------------------- 1 | import React = require('react'); 2 | import ReactDOM = require('react-dom'); 3 | import { MDText } from '../../dist/i18n-react'; 4 | 5 | 6 | const styles = { 7 | em: "an *italic* style", 8 | i: "an _italic_ style", 9 | strong: "a **bold** move", 10 | b: "a __bold__ move", 11 | u: "an ~underlined~ word", 12 | strike: "a ~~strike~~ out", 13 | br: "New \n Line", 14 | p: "[Paragraph 1][Paragraph 2]", 15 | h1: "# Header\nText", 16 | h2: "## Header\nText", 17 | h3: "### Header\nText", 18 | h4: "#### Header\nText", 19 | '': "`` [*as*]_``_[is] ``", 20 | }; 21 | 22 | const T = new MDText({ 23 | title: "Supported Markdown syntax *(V1 flavor)*", 24 | styles: styles, 25 | }, { MDFlavor: 1 }); 26 | 27 | ReactDOM.render( 28 |
29 | 30 |
    { 31 | Object.keys(styles).map(n => 32 |
  • 33 | 34 | {'"' + (styles as any)[n].replace('\n', "\\n") + '" '} 35 | {n && [{` <${n}>`}, " tag"]} 36 |
  • 37 | )} 38 |
39 |
, 40 | document.getElementById('content') 41 | ); 42 | 43 | -------------------------------------------------------------------------------- /examples/hello/index.jsx: -------------------------------------------------------------------------------- 1 | var ReactDOM = require('react-dom'); 2 | var React = require('react'); 3 | const { default: T, MDText } = require('i18n-react'); 4 | 5 | const dictionary = { 6 | greeting: "###Hello, World!\n My name is **{myName}**! \n {{howAreYou}}", 7 | howAreYou: "_How do you do?_" 8 | }; 9 | 10 | T.setTexts(dictionary, { MDFlavor: 1 }) 11 | ReactDOM.render( 12 |
13 |

Singelton

14 | 15 |
, 16 | document.getElementById('content1') 17 | ); 18 | 19 | const Texts = new MDText(dictionary, { MDFlavor: 1 }); 20 | ReactDOM.render( 21 |
22 |

MDText object

23 | 24 |
, 25 | document.getElementById('content2') 26 | ); 27 | 28 | let MDTextContext = React.createContext(); 29 | 30 | ReactDOM.render( 31 |
32 |

MDText in React Context

33 | 34 | { (TT) => 35 | 36 | } 37 | 38 |
, 39 | document.getElementById('content3') 40 | ); 41 | 42 | -------------------------------------------------------------------------------- /karma.config.js: -------------------------------------------------------------------------------- 1 | // Karma configuration 2 | 3 | module.exports = function (config) { 4 | config.set({ 5 | // ... normal karma configuration 6 | basePath: '', 7 | frameworks: ['jasmine'], 8 | 9 | mime: { 10 | 'text/x-typescript': ['ts','tsx'] 11 | }, 12 | files: [ 13 | "https://cdnjs.cloudflare.com/ajax/libs/react/16.0.0/umd/react.development.js", 14 | "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.0.0/umd/react-dom-server.browser.development.js", 15 | // all files ending in "_test" 16 | 'tests/*_test.*', 17 | 'tests/**/*_test.*' 18 | // each file acts as entry point for the webpack configuration 19 | ], 20 | 21 | preprocessors: { 22 | // add webpack as preprocessor 23 | 'tests/*_test.*': ['webpack', 'sourcemap'], 24 | 'tests/**/*_test.*': ['webpack', 'sourcemap'] 25 | }, 26 | 27 | port: 8055, 28 | logLevel: config.LOG_INFO, 29 | colors: true, 30 | autoWatch: true, 31 | 32 | browsers: ['Chrome'], 33 | reporters: ['progress'], 34 | captureTimeout: 60000, 35 | singleRun: false, 36 | 37 | webpack: { 38 | cache: true, 39 | devtool: 'inline-source-map', 40 | stats: false, 41 | 42 | resolve: { 43 | extensions: ['.js', '.jsx', '.ts', '.tsx'] 44 | }, 45 | 46 | externals: { 47 | "react": "React", 48 | "react-dom": "ReactDOM", 49 | "react-dom-server": "ReactDOMServer", 50 | }, 51 | 52 | module: { 53 | loaders: [ 54 | { test: /\.tsx?$/, loader: 'ts-loader' }, 55 | { test: /\.jsx?$/, loader: 'jsx-loader?harmony' } 56 | ] 57 | }, 58 | }, 59 | }); 60 | }; 61 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "i18n-react", 3 | "version": "0.7.0", 4 | "description": "React JS text internationalization and externalizing", 5 | "main": "dist/i18n-react.js", 6 | "typings": "dist/i18n-react.d.ts", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/alexdrel/i18n-react" 10 | }, 11 | "scripts": { 12 | "start": "tsc -p src -d -watch", 13 | "prebuild": "tsc -p src -d", 14 | "build": "webpack --config webpack-umd.config.js && webpack -p --config webpack-umd.config.js --output-filename i18n-react.umd.min.js", 15 | "examples": "webpack-dev-server --config webpack-ex.config.js --port 1818 -d", 16 | "build:examples": "webpack --config webpack-ex.config.js -d --progress", 17 | "test": "karma start karma.config.js --browsers Firefox --single-run", 18 | "test:watch": "karma start karma.config.js" 19 | }, 20 | "keywords": [ 21 | "i18n", 22 | "react", 23 | "external", 24 | "text" 25 | ], 26 | "author": "Alex Drel", 27 | "license": "MIT", 28 | "engines": { 29 | "node": ">=4.0", 30 | "npm": ">=3.0" 31 | }, 32 | "dependencies": {}, 33 | "peerDependencies": { 34 | "react": ">=16.0.0" 35 | }, 36 | "devDependencies": { 37 | "@types/jasmine": "^2.6.0", 38 | "@types/react": "^16.0.10", 39 | "@types/react-dom": "^16.0.1", 40 | "jasmine-core": "^2.8.0", 41 | "json-loader": "^0.5.7", 42 | "jsx-loader": "^0.13.2", 43 | "karma": "^1.7.1", 44 | "karma-chrome-launcher": "^2.2.0", 45 | "karma-firefox-launcher": "^1.0.1", 46 | "karma-jasmine": "^1.1.0", 47 | "karma-sourcemap-loader": "^0.3.7", 48 | "karma-webpack": "^2.0.4", 49 | "node-libs-browser": "^2.0.0", 50 | "ts-loader": "^2.3.7", 51 | "typescript": "^3.4.5", 52 | "webpack": "^3.6.0", 53 | "webpack-dev-server": "^2.9.1", 54 | "yaml-loader": "^0.5.0" 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /dist/mdflavors.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | exports.__esModule = true; 3 | var R = { 4 | "`` ": [/^(.*?(?:(?!`).|^))(``+)\s(.*?)\s\2(?!`)(.*)$/, [1, 3, 4]], 5 | "``": [/^(.*?(?:(?!`).|^))(``+)(?!`)(.*?(?!`).)\2(?!`)(.*)$/, [1, 3, 4]], 6 | "*": /^(|.*?\W)\*(\S.*?)\*(|\W.*)$/, 7 | "**": /^(|.*?\W)\*\*(\S.*?)\*\*(|\W.*)$/, 8 | "_": /^(|.*?\W)_(\S.*?)_(|\W.*)$/, 9 | "__": /^(|.*?\W)__(\S.*?)__(|\W.*)$/, 10 | "~": /^(|.*?\W)~(\S.*?)~(|\W.*)$/, 11 | "~~": /^(|.*?\W)~~(\S.*?)~~(|\W.*)$/, 12 | "[]": /^(.*?)\[(.*?)\](.*)$/, 13 | "#": /^(|.*?(?=\n))\n*\s*#([^#].*?)#*\s*\n+([\S\s]*)$/, 14 | "##": /^(|.*?(?=\n))\n*\s*##([^#].*?)#*\s*\n+([\S\s]*)$/, 15 | "###": /^(|.*?(?=\n))\n*\s*###([^#].*?)#*\s*\n+([\S\s]*)$/, 16 | "####": /^(|.*?(?=\n))\n*\s*####([^#].*?)#*\s*\n+([\S\s]*)$/, 17 | "\n": /^(.*?)[^\S\n]*\n()[^\S\n]*([\s\S]*)$/, 18 | "{{}}": /^(.*?)\{\{(.*?)\}\}(.*)$/, 19 | "{}": /^(.*?)\{(.*?)\}(.*)$/ 20 | }; 21 | exports.mdFlavors = [ 22 | { 23 | maybe: /[\*_\{\[\n]/, 24 | tags: { 25 | strong: R["*"], 26 | em: R["_"], 27 | p: R["[]"], 28 | h1: R["#"], 29 | h2: R["##"], 30 | h3: R["###"], 31 | h4: R["####"], 32 | br: R["\n"], 33 | self: R["{{}}"], 34 | inter: R["{}"] 35 | } 36 | }, 37 | { 38 | maybe: /[`\*_~\{\[\n]/, 39 | tags: { 40 | literals: R["`` "], 41 | literal: R["``"], 42 | strong: R["**"], 43 | em: R["*"], 44 | b: R["__"], 45 | i: R["_"], 46 | strike: R["~~"], 47 | u: R["~"], 48 | p: R["[]"], 49 | h1: R["#"], 50 | h2: R["##"], 51 | h3: R["###"], 52 | h4: R["####"], 53 | br: R["\n"], 54 | self: R["{{}}"], 55 | inter: R["{}"] 56 | } 57 | } 58 | ]; 59 | function mdMatch(md, value) { 60 | if (!value.match(md.maybe)) 61 | return null; 62 | var tags = md.tags; 63 | var match = null; 64 | for (var ctag in tags) { 65 | if (!tags.hasOwnProperty(ctag)) 66 | continue; 67 | var rg = tags[ctag]; 68 | var _a = rg instanceof RegExp ? [rg, [1, 2, 3]] : rg, regex = _a[0], groups = _a[1]; 69 | var cmatch = regex.exec(value); 70 | if (cmatch) { 71 | if (match == null || cmatch[groups[0]].length < match.head.length) { 72 | match = { tag: ctag, head: cmatch[groups[0]], body: cmatch[groups[1]], tail: cmatch[groups[2]] }; 73 | } 74 | } 75 | } 76 | return match; 77 | } 78 | exports.mdMatch = mdMatch; 79 | -------------------------------------------------------------------------------- /src/mdflavors.ts: -------------------------------------------------------------------------------- 1 | type RegExpEx = RegExp | [RegExp, [number, number, number]]; 2 | export interface MDFlavor { 3 | maybe: RegExp; 4 | tags: { [type: string]: RegExpEx }; 5 | } 6 | 7 | const R: { [name: string]: RegExpEx } = { 8 | "`` ": [/^(.*?(?:(?!`).|^))(``+)\s(.*?)\s\2(?!`)(.*)$/, [1, 3, 4]], 9 | "``": [/^(.*?(?:(?!`).|^))(``+)(?!`)(.*?(?!`).)\2(?!`)(.*)$/, [1, 3, 4]], 10 | "*": /^(|.*?\W)\*(\S.*?)\*(|\W.*)$/, 11 | "**": /^(|.*?\W)\*\*(\S.*?)\*\*(|\W.*)$/, 12 | "_": /^(|.*?\W)_(\S.*?)_(|\W.*)$/, 13 | "__": /^(|.*?\W)__(\S.*?)__(|\W.*)$/, 14 | "~": /^(|.*?\W)~(\S.*?)~(|\W.*)$/, 15 | "~~": /^(|.*?\W)~~(\S.*?)~~(|\W.*)$/, 16 | "[]": /^(.*?)\[(.*?)\](.*)$/, 17 | "#": /^(|.*?(?=\n))\n*\s*#([^#].*?)#*\s*\n+([\S\s]*)$/, 18 | "##": /^(|.*?(?=\n))\n*\s*##([^#].*?)#*\s*\n+([\S\s]*)$/, 19 | "###": /^(|.*?(?=\n))\n*\s*###([^#].*?)#*\s*\n+([\S\s]*)$/, 20 | "####": /^(|.*?(?=\n))\n*\s*####([^#].*?)#*\s*\n+([\S\s]*)$/, 21 | "\n": /^(.*?)[^\S\n]*\n()[^\S\n]*([\s\S]*)$/, 22 | "{{}}": /^(.*?)\{\{(.*?)\}\}(.*)$/, 23 | "{}": /^(.*?)\{(.*?)\}(.*)$/, 24 | }; 25 | 26 | 27 | export const mdFlavors: MDFlavor[] = [ 28 | { // V0 29 | maybe: /[\*_\{\[\n]/, 30 | tags: { 31 | strong: R["*"], 32 | em: R["_"], 33 | p: R["[]"], 34 | h1: R["#"], 35 | h2: R["##"], 36 | h3: R["###"], 37 | h4: R["####"], 38 | br: R["\n"], 39 | self: R["{{}}"], 40 | inter: R["{}"], 41 | } 42 | }, 43 | { // V1 44 | maybe: /[`\*_~\{\[\n]/, 45 | tags: { 46 | literals: R["`` "], 47 | literal: R["``"], 48 | strong: R["**"], 49 | em: R["*"], 50 | b: R["__"], 51 | i: R["_"], 52 | strike: R["~~"], 53 | u: R["~"], 54 | p: R["[]"], 55 | h1: R["#"], 56 | h2: R["##"], 57 | h3: R["###"], 58 | h4: R["####"], 59 | br: R["\n"], 60 | self: R["{{}}"], 61 | inter: R["{}"], 62 | } 63 | } 64 | ]; 65 | 66 | type MDMatch = { tag: string, head: string, body: string, tail: string }; 67 | 68 | export function mdMatch(md: MDFlavor, value: string): MDMatch | null { 69 | if (!value.match(md.maybe)) 70 | return null; 71 | 72 | const tags = md.tags; 73 | let match: MDMatch | null = null; 74 | 75 | for (let ctag in tags) { 76 | if (!tags.hasOwnProperty(ctag)) continue; 77 | 78 | const rg = tags[ctag]; 79 | const [regex, groups] = rg instanceof RegExp ? [rg, [1, 2, 3]] : rg; 80 | 81 | const cmatch = regex.exec(value); 82 | if (cmatch) { 83 | if (match == null || cmatch[groups[0]].length < match.head.length) { 84 | match = { tag: ctag, head: cmatch[groups[0]], body: cmatch[groups[1]], tail: cmatch[groups[2]] }; 85 | } 86 | } 87 | } 88 | return match; 89 | } 90 | -------------------------------------------------------------------------------- /tests/syntaxv1_test.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import renderElement from './renderElement'; 3 | import { MDText } from '../src/i18n-react'; 4 | 5 | describe("i18n-react Flavor V1", () => { 6 | let T = new MDText({}, { MDFlavor: 1 }); 7 | function formatHTML(text: string, o?: any): string { 8 | var s = renderElement(React.createElement('super', null, T.format(text, o))); 9 | return s.replace(/<\/?super>/g, ''); 10 | } 11 | 12 | it("format renders or ", () => { 13 | expect(formatHTML("an *italic* style")).toBe("an italic style"); 14 | expect(formatHTML("an _italic_ style")).toBe("an italic style"); 15 | }); 16 | 17 | it("format renders or ", () => { 18 | expect(formatHTML("a **bold** move")).toBe("a bold move"); 19 | expect(formatHTML("a __bold__ move")).toBe("a bold move"); 20 | }); 21 | 22 | it("format renders or ", () => { 23 | expect(formatHTML("an ~underline~ word")).toBe("an underline word"); 24 | expect(formatHTML("a ~~strike~~ out")).toBe("a strike out"); 25 | }); 26 | 27 | it("format renders
", () => { 28 | expect(formatHTML("a\nb")).toBe("a
b"); 29 | expect(formatHTML("a\n b")).toBe("a
b"); 30 | expect(formatHTML("a \t \n\t b")).toBe("a
b"); 31 | expect(formatHTML("a\n\n\n b")).toBe("a


b"); 32 | }); 33 | 34 | it("format renders

", () => { 35 | expect(formatHTML("[a][b]")).toBe("

a

b

"); 36 | expect(formatHTML("[a] [b]")).toBe("

a

b

"); 37 | expect(formatHTML("c [a] [b] d")).toBe("c

a

b

d"); 38 | }); 39 | 40 | 41 | it("format renders ", () => { 42 | expect(formatHTML("#Head\nText")).toBe("

Head

Text"); 43 | expect(formatHTML("##Head\nText")).toBe("

Head

Text"); 44 | expect(formatHTML("###Head\nText")).toBe("

Head

Text"); 45 | expect(formatHTML("####Head\nText")).toBe("

Head

Text"); 46 | 47 | expect(formatHTML("#Head#\nText")).toBe("

Head

Text"); 48 | expect(formatHTML("##Head##\nText")).toBe("

Head

Text"); 49 | expect(formatHTML("###Head###\nText")).toBe("

Head

Text"); 50 | expect(formatHTML("####Head###\nText")).toBe("

Head

Text"); 51 | 52 | expect(formatHTML("p\n#Head#\nText")).toBe("p

Head

Text"); 53 | expect(formatHTML("p\n ##Head\nText")).toBe("p

Head

Text"); 54 | expect(formatHTML("p\n ###Head### \nText")).toBe("p

Head

Text"); 55 | expect(formatHTML("p\n#Head #\nText")).toBe("p

Head

Text"); 56 | expect(formatHTML("p\n#Head \nText")).toBe("p

Head

Text"); 57 | }); 58 | 59 | it("format renders multiple in a text block", () => { 60 | expect(formatHTML("# Lorem\nLorem ipsum dolor sit amet, consectetur adipiscing elit.\n## Quisque\nQuisque sit amet nisi quis eros cursus finibus quis sed nisl.\n")) 61 | .toContain('

'); 62 | }); 63 | 64 | it("format ignores midline #", () => { 65 | expect(formatHTML("a#\nText")).toBe("a#
Text"); 66 | expect(formatHTML("ttt##xxx\nText")).toBe("ttt##xxx
Text"); 67 | 68 | }); 69 | 70 | it("format renders React variables", () => { 71 | expect(formatHTML("z{R}z", { R: React.createElement('b', null, 'B') })).toBe("zBz"); 72 | }); 73 | 74 | }); 75 | 76 | -------------------------------------------------------------------------------- /tests/tags_test.tsx: -------------------------------------------------------------------------------- 1 | import React = require('react'); 2 | import renderElement from './renderElement'; 3 | import { MDText } from '../src/i18n-react'; 4 | 5 | describe("i18n-react", () => { 6 | 7 | it("renders ", () => { 8 | let T = new MDText({ x: "X", ll: "[l1][l2]", l2: "__b__[_v_]ddd" }, { MDFlavor: 1 }); 9 | 10 | expect(renderElement()).toBe("X"); 11 | expect(renderElement()).toBe("

l1

l2

"); 12 | expect(renderElement()).toBe("b

v

ddd"); 13 | }); 14 | 15 | it("renders ", () => { 16 | let T = new MDText({ x: "X", y: "Y" }); 17 | 18 | expect(renderElement()).toBe("X"); 19 | expect(renderElement()).toBe("X"); 20 | expect(renderElement()).toBe("

X

"); 21 | expect(renderElement()).toBe('X'); 22 | expect(renderElement()).toBe("
Y
"); 23 | expect(renderElement()).toBe(''); 24 | }); 25 | 26 | it("renders factory ", () => { 27 | let T = new MDText({ x: "X", y: "Y" }); 28 | var TStrong = T.factory('strong'); 29 | 30 | expect(renderElement()).toBe("X"); 31 | expect(renderElement()).toBe('Y'); 32 | }); 33 | 34 | it("renders tag type", () => { 35 | let T = new MDText({ x: "X", y: "Y" }); 36 | var TStrong = T.factory('strong'); 37 | 38 | expect(renderElement()).toBe("X"); 39 | expect(renderElement()).toBe("X"); 40 | expect(renderElement()).toBe('Y'); 41 | 42 | // Bound tag should not be replaced 43 | expect(renderElement()).toBe("X"); 44 | expect(renderElement()).toBe("

X

"); 45 | }); 46 | 47 | it("known props are not leaked into DOM", () => { 48 | let T = new MDText({ x: { a: "Xa", b: "Xb" }, y: "Y" }); 49 | // No react 15.2 errors should be caused 50 | 51 | expect(renderElement()).toBe("Xb"); 52 | expect(renderElement()).toBe("

Xb

"); 53 | 54 | expect(renderElement()).toBe("b"); 55 | }); 56 | 57 | // react 16 started to pass unknown attributes to DOM 58 | xit(" ignores custom attributes", () => { 59 | let T = new MDText({ x: "X", y: "Y" }); 60 | // supress react 15.2 warnings - Unknown prop `ZZ` on tag. 61 | let cerror = console.error; 62 | console.error = () => { }; 63 | try { 64 | expect(renderElement()).toBe("X"); 65 | expect(renderElement()).toBe('Y'); 66 | } catch (e) { } 67 | console.error = cerror; 68 | }); 69 | 70 | it(" renders data attributes", () => { 71 | let T = new MDText({ x: "X", y: "Y" }); 72 | 73 | expect(renderElement()).toBe('X'); 74 | expect(renderElement()).toBe('Y'); 75 | }); 76 | 77 | it(" handles missing text attribute in ", () => { 78 | let T = new MDText({ x: "X", y: "Y" }); 79 | expect(renderElement()).toBe(""); 80 | expect(renderElement()).toBe('

'); 81 | 82 | expect(renderElement()).toBe("

z

"); 83 | }); 84 | 85 | it(" handles notFound", () => { 86 | let T = new MDText({ x: "X", y: "Y" }); 87 | expect(renderElement()).toBe("

z

"); 88 | expect(renderElement()).toBe("

ZZ

"); 89 | expect(renderElement()).toBe("

ZZ

"); 90 | 91 | T.notFound = '_NA_'; 92 | expect(renderElement()).toBe("

NA

"); 93 | T = new MDText({ x: "X", y: "Y" }, { notFound: 'ZZ' }); 94 | expect(renderElement()).toBe("

ZZ

"); 95 | T.notFound = (key) => `_${key}_ not found`; 96 | expect(renderElement()).toBe("

z not found

"); 97 | }); 98 | }); 99 | 100 | -------------------------------------------------------------------------------- /tests/react_test.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { default as formatHTML, textHTML } from './formatHTML'; 3 | 4 | import T from '../src/i18n-react'; 5 | 6 | describe("i18n-react", () => { 7 | beforeEach(() => T.setOpts({ MDFlavor: 0 })); 8 | 9 | it("format renders ", () => { 10 | expect(formatHTML("*bold*")).toBe("bold"); 11 | expect(formatHTML("a *bold* move")).toBe("a bold move"); 12 | expect(formatHTML("a *bold* move *nice*")).toBe("a bold move nice"); 13 | }); 14 | 15 | it("format ignores * mid-word", () => { 16 | expect(formatHTML("2*3")).toBe("2*3"); 17 | expect(formatHTML("2*3*4")).toBe("2*3*4"); 18 | expect(formatHTML("2*3* 4")).toBe("2*3* 4"); 19 | }); 20 | 21 | 22 | it(" renders ", () => { 23 | T.setTexts({ bold: "*bold*", b2: "a *bold* move *nice*" }); 24 | expect(textHTML({ text: "bold" })).toBe("bold"); 25 | expect(textHTML({ text: "bold", tag: 'p' })).toBe("

bold

"); 26 | expect(textHTML({ text: "bold", tag: 'div' })).toBe("
bold
"); 27 | expect(textHTML({ text: "b2", tag: 'p' })).toBe("

a bold move nice

"); 28 | }); 29 | 30 | it("format renders ", () => { 31 | expect(formatHTML("_it_")).toBe("it"); 32 | expect(formatHTML("_it_ is")).toBe("it is"); 33 | expect(formatHTML("is _it_?")).toBe("is it?"); 34 | }); 35 | 36 | it("format renders
", () => { 37 | expect(formatHTML("a\nb")).toBe("a
b"); 38 | expect(formatHTML("a\n b")).toBe("a
b"); 39 | expect(formatHTML("a \t \n\t b")).toBe("a
b"); 40 | expect(formatHTML("a\n\n\n b")).toBe("a


b"); 41 | }); 42 | 43 | it("format renders

", () => { 44 | expect(formatHTML("[a][b]")).toBe("

a

b

"); 45 | expect(formatHTML("[a] [b]")).toBe("

a

b

"); 46 | expect(formatHTML("c [a] [b] d")).toBe("c

a

b

d"); 47 | }); 48 | 49 | it(" renders

", () => { 50 | T.setTexts({ p3: "[a][b][c]" }); 51 | expect(textHTML({ text: "p3" })).toBe("

a

b

c

");; 52 | }); 53 | 54 | it("format renders ", () => { 55 | expect(formatHTML("#Head\nText")).toBe("

Head

Text"); 56 | expect(formatHTML("##Head\nText")).toBe("

Head

Text"); 57 | expect(formatHTML("###Head\nText")).toBe("

Head

Text"); 58 | expect(formatHTML("####Head\nText")).toBe("

Head

Text"); 59 | 60 | expect(formatHTML("#Head#\nText")).toBe("

Head

Text"); 61 | expect(formatHTML("##Head##\nText")).toBe("

Head

Text"); 62 | expect(formatHTML("###Head###\nText")).toBe("

Head

Text"); 63 | expect(formatHTML("####Head###\nText")).toBe("

Head

Text"); 64 | 65 | expect(formatHTML("p\n#Head#\nText")).toBe("p

Head

Text"); 66 | expect(formatHTML("p\n ##Head\nText")).toBe("p

Head

Text"); 67 | expect(formatHTML("p\n ###Head### \nText")).toBe("p

Head

Text"); 68 | expect(formatHTML("p\n#Head #\nText")).toBe("p

Head

Text"); 69 | expect(formatHTML("p\n#Head \nText")).toBe("p

Head

Text"); 70 | }); 71 | 72 | it("format renders multiple in a text block", () => { 73 | expect(formatHTML("# Lorem\nLorem ipsum dolor sit amet, consectetur adipiscing elit.\n## Quisque\nQuisque sit amet nisi quis eros cursus finibus quis sed nisl.\n")) 74 | .toContain('

'); 75 | }); 76 | 77 | it("format ignores midline #", () => { 78 | expect(formatHTML("a#\nText")).toBe("a#
Text"); 79 | expect(formatHTML("ttt##xxx\nText")).toBe("ttt##xxx
Text"); 80 | 81 | }); 82 | 83 | it(" transfers html attributes", () => { 84 | T.setTexts({ a: "a", b: "{val}" }); 85 | expect(textHTML({ text: "a", tag: 'span', className: "cl" })).toBe("a"); 86 | expect(textHTML({ text: "a", tag: 'p', 'data-x': 'x' })).toBe("

a

"); 87 | expect(textHTML({ text: "a", tag: 'a', href: '#' })).toBe("a"); 88 | 89 | expect(textHTML({ text: { key: "b", val: 'B' }, tag: 'span', className: "cl" })).toBe("B"); 90 | }); 91 | 92 | it("format renders React variables", () => { 93 | expect(formatHTML("z{R}z", { R: React.createElement('b', null, 'B') })).toBe("zBz"); 94 | }); 95 | 96 | it("format handles literal", () => { 97 | T.setOpts({ MDFlavor: 1 }); 98 | expect(formatHTML("`` z[a]```[b]z ``")).toBe("z[a]```[b]z"); 99 | expect(formatHTML("``` z[a]``[b]z ```")).toBe("z[a]``[b]z"); 100 | }); 101 | 102 | }); 103 | -------------------------------------------------------------------------------- /dist/i18n-react.umd.min.js: -------------------------------------------------------------------------------- 1 | !function(t,n){"object"==typeof exports&&"object"==typeof module?module.exports=n(require("React")):"function"==typeof define&&define.amd?define(["React"],n):"object"==typeof exports?exports["i18n-react"]=n(require("React")):t["i18n-react"]=n(t.React)}(this,function(t){return function(t){function n(r){if(e[r])return e[r].exports;var o=e[r]={i:r,l:!1,exports:{}};return t[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}var e={};return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},n.p="",n(n.s=0)}([function(t,n,e){"use strict";function r(t){return"string"==typeof t||t instanceof String}function o(t){return"object"==typeof t}function i(t){return"function"==typeof t}function s(t,n){for(var e=n.split("."),r=0,i=e.length;r1?n:n.length?n[0]:null}function l(t,n){for(var e in t)if(t.hasOwnProperty(e)){var r=e.match(/^(-?\d+)\.\.(-?\d+)$/);if(r&&+r[1]<=n&&n<=+r[2])return t[e]}}function f(t,n,e,o){var i,a=e[n];return null!=a&&null!=o[a]&&null==(i=s(t,o[a].toString()))&&+o[a]===o[a]&&(i=l(t,+o[a])),null==i&&(i=t._),null==i&&(i=u(t)),null==i||r(i)?i:f(i,n+1,e,o)}function c(t,n){if(null==n)return f(t,0,[],null);if(o(n)){var e=[];if(t.__)e=t.__.split(".");else for(var r in n)n.hasOwnProperty(r)&&e.push(r);return f(t,0,e,n)}return f(t,0,["_"],{_:n})}var h=this&&this.__rest||function(t,n){var e={};for(var r in t)Object.prototype.hasOwnProperty.call(t,r)&&n.indexOf(r)<0&&(e[r]=t[r]);if(null!=t&&"function"==typeof Object.getOwnPropertySymbols)for(var o=0,r=Object.getOwnPropertySymbols(t);o { 4 | it("with context object", () => { 5 | var texts: any = { 6 | c: { 7 | __: "type.count", 8 | _: "{context.count} {context.type}(s)", 9 | star: { 10 | "0": "No stars", 11 | "1": "A single star", 12 | _: "{context.count} stars" 13 | }, 14 | planet: { 15 | "1": "A planet", 16 | _: "{context.count} planets" 17 | } 18 | } 19 | }; 20 | let T = new MDText(texts); 21 | 22 | expect(T.translate('c', { context: { type: 'star', count: 0 } })).toBe("No stars"); 23 | expect(T.translate('c', { context: { type: 'star', count: 1 } })).toBe("A single star"); 24 | expect(T.translate('c', { context: { type: 'star', count: 2 } })).toBe("2 stars"); 25 | expect(T.translate('c', { context: { type: 'star', count: 5 } })).toBe("5 stars"); 26 | 27 | expect(T.translate('c', { context: { type: 'planet', count: 0 } })).toBe("0 planets"); 28 | expect(T.translate('c', { context: { type: 'planet', count: 1 } })).toBe("A planet"); 29 | expect(T.translate('c', { context: { type: 'planet', count: 2 } })).toBe("2 planets"); 30 | 31 | expect(T.translate('c', { context: { type: 'ufo' } })).toBe(" ufo(s)"); 32 | expect(T.translate('c', { context: { count: 0 } })).toBe("0 (s)"); 33 | 34 | 35 | expect(T.translate('c', { context: { type: 'ufo', count: 0 } })).toBe("0 ufo(s)"); 36 | expect(T.translate('c', { context: { type: 'ufo', count: 1 } })).toBe("1 ufo(s)"); 37 | expect(T.translate('c', { context: { type: 'ufo', count: 2 } })).toBe("2 ufo(s)"); 38 | 39 | expect(T.translate('c', { context: { count: 1, type: 'star' } })).toBe("A single star"); 40 | delete texts.c.__; 41 | expect(T.translate('c', { context: { count: 1, type: 'star' } })).not.toBe("A single star"); 42 | }); 43 | 44 | it("finds default in context object", () => { 45 | let T = new MDText({ 46 | c: { 47 | __: "type.count", 48 | object: { 49 | "0": "No objects", 50 | "1": "A single object", 51 | _: "{context.count} objects" 52 | }, 53 | planet: { 54 | "1": "A planet", 55 | _: "{context.count} planets" 56 | } 57 | }, 58 | d: "{context.count} {context.type}(s)" 59 | }); 60 | 61 | expect(T.translate('c', { context: { type: 'ufo', count: 0 } })).toBe("No objects"); 62 | expect(T.translate('c', { context: { type: 'ufo', count: 1 } })).toBe("A single object"); 63 | expect(T.translate('c', { context: { type: 'ufo', count: 2 } })).toBe("2 objects"); 64 | 65 | expect(T.translate('d', { context: { type: 'ufo', count: 0 } })).toBe("0 ufo(s)"); 66 | expect(T.translate('d', { context: { type: 'ufo', count: 1 } })).toBe("1 ufo(s)"); 67 | expect(T.translate('d', { context: { type: 'ufo', count: 2 } })).toBe("2 ufo(s)"); 68 | }); 69 | 70 | it("supports context array", () => { 71 | let T = new MDText({ 72 | c: { 73 | A: { 74 | "0": "a0", 75 | "1": "a1", 76 | _: "ax" 77 | }, 78 | B: { 79 | "1": "b1", 80 | _: "bx" 81 | }, 82 | } 83 | }); 84 | 85 | expect(T.translate('c', { context: ['A', 0] })).toBe("a0"); 86 | expect(T.translate('c', { context: ['A', 1] })).toBe("a1"); 87 | expect(T.translate('c', { context: ['A', 2] })).toBe("ax"); 88 | 89 | expect(T.translate('c', { context: ['B', 1] })).toBe("b1"); 90 | expect(T.translate('c', { context: ['B', 2] })).toBe("bx"); 91 | 92 | expect(T.translate('c', { context: ['A'] })).toBe("ax"); 93 | expect(T.translate('c', { context: [] })).toBe("ax"); 94 | expect(T.translate('c', {})).toBe("ax"); 95 | 96 | expect(T.translate('c', { context: ['B'] })).toBe("bx"); 97 | }); 98 | 99 | it("range number context", () => { 100 | let T = new MDText({ 101 | c: { 102 | '0': 'none', 103 | '1': 'one', 104 | "2..3": 'a couple', 105 | "4..6": 'a few', 106 | "7..9": 'several', 107 | _: 'many' 108 | } 109 | }); 110 | 111 | expect(T.translate('c', { context: 0 })).toBe('none'); 112 | expect(T.translate('c', { context: 1 })).toBe('one'); 113 | expect(T.translate('c', { context: 2 })).toBe('a couple'); 114 | expect(T.translate('c', { context: 3 })).toBe('a couple'); 115 | expect(T.translate('c', { context: 4 })).toBe('a few'); 116 | expect(T.translate('c', { context: 5 })).toBe('a few'); 117 | expect(T.translate('c', { context: 6 })).toBe('a few'); 118 | expect(T.translate('c', { context: 7 })).toBe('several'); 119 | expect(T.translate('c', { context: 8 })).toBe('several'); 120 | expect(T.translate('c', { context: 9 })).toBe('several'); 121 | expect(T.translate('c', { context: 10 })).toBe('many'); 122 | expect(T.translate('c', { context: 11 })).toBe('many'); 123 | expect(T.translate('c', { context: 11 })).toBe('many'); 124 | }); 125 | 126 | it("functional definition ", () => { 127 | let T = new MDText({ 128 | c: (_key: string, ctx: number) => ctx ? `Number ${ctx}` : '', 129 | }); 130 | 131 | expect(T.translate('c', { context: 0 })).toBe(''); 132 | expect(T.translate('c', { context: 9 })).toBe('Number 9'); 133 | }); 134 | 135 | }); 136 | -------------------------------------------------------------------------------- /tests/basic_test.ts: -------------------------------------------------------------------------------- 1 | import { MDText } from '../src/i18n-react'; 2 | 3 | describe("i18n-react translate", () => { 4 | let T = new MDText({ 5 | a: "A", 6 | aa: { 7 | b: { 8 | c: "AABC" 9 | } 10 | }, 11 | b: "B", 12 | c: { 13 | a: "CA", 14 | b: "CB", 15 | _: "CX" 16 | }, 17 | d: { 18 | a: "DA", 19 | b: "DB", 20 | c: "DC{val}" 21 | }, 22 | plural: { 23 | "0": "No stars", 24 | "1": "A single star", 25 | _: "{context} stars" 26 | }, 27 | self: { 28 | aabc: "{{aa.b.c}}", 29 | d: "{{d}}", 30 | dc: "{{d.c}}" 31 | } 32 | }); 33 | 34 | it("empty values", () => { 35 | expect(T.translate(undefined)).toBe(undefined); 36 | expect(T.translate(null)).toBe(null); 37 | expect(T.translate("")).toBe(""); 38 | }); 39 | 40 | it("loads plain string", () => { 41 | expect(T.translate('a')).toBe('A'); 42 | expect(T.translate('aa.b.c')).toBe('AABC'); 43 | expect(T.translate('b')).toBe('B'); 44 | }); 45 | 46 | it("uses context (explicit default)", () => { 47 | expect(T.translate('c')).toBe('CX'); 48 | expect(T.translate('c', {})).toBe('CX'); 49 | 50 | expect(T.translate('c', { context: 'a' })).toBe('CA'); 51 | expect(T.translate('c', { context: 'b' })).toBe('CB'); 52 | expect(T.translate('c', { context: 'q' })).toBe('CX'); 53 | }); 54 | 55 | it("uses context (implicit - first as default)", () => { 56 | expect(T.translate('d')).toBe('DA'); 57 | expect(T.translate('d', { context: 'a' })).toBe('DA'); 58 | expect(T.translate('d', { context: 'b' })).toBe('DB'); 59 | expect(T.translate('d', { context: 'q' })).toBe('DA'); 60 | }); 61 | 62 | it("ignores missing context", () => { 63 | expect(T.translate('b', { context: 'a' })).toBe('B'); 64 | }); 65 | 66 | it("can do basic plurals", () => { 67 | expect(T.translate('plural', { context: 0 })).toBe("No stars"); 68 | expect(T.translate('plural', { context: 1 })).toBe("A single star"); 69 | expect(T.translate('plural', { context: 2 })).toBe("2 stars"); 70 | expect(T.translate('plural', { context: 5 })).toBe("5 stars"); 71 | }); 72 | 73 | it("can reference keys", () => { 74 | expect(T.translate('self.aabc')).toBe("AABC"); 75 | expect(T.translate('self.d', { context: 'b' })).toBe("DB"); 76 | }); 77 | 78 | it("can reference keys with params", () => { 79 | expect(T.translate('self.dc', { val: 'X' })).toBe("DCX"); 80 | }); 81 | 82 | it("handles missing keys", () => { 83 | expect(T.translate('na.na')).toBe("na.na"); 84 | expect(T.translate('na.na', { context: 'X' })).toBe("na.na"); 85 | expect(T.translate('na.na', { notFound: 'NA' })).toBe("NA"); 86 | T.notFound = 'NA'; 87 | expect(T.translate('na.na')).toBe("NA"); 88 | expect(T.translate('na.na', { notFound: 'NA' })).toBe("NA"); 89 | T.notFound = null; 90 | expect(T.translate('na.na')).toBeNull(); 91 | T.notFound = (key) => key + ' not found'; 92 | expect(T.translate('na.na')).toBe('na.na not found'); 93 | T.notFound = undefined; 94 | expect(T.translate('na.na')).toBe("na.na"); 95 | let T1 = new MDText({}, { notFound: 'NA' }); 96 | expect(T1.translate('na.na')).toBe("NA"); 97 | expect(T1.translate('na.na', { notFound: null })).toBe(null); 98 | 99 | T1 = new MDText({}, { notFound: null }); 100 | expect(T1.translate('na.na')).toBe(null); 101 | expect(T1.translate('na.na', { notFound: 'NA' })).toBe('NA'); 102 | 103 | T1 = new MDText({}, { notFound: undefined }); // leaves default 104 | expect(T1.translate('na.na')).toBe("na.na"); 105 | expect(T1.translate('na.na', { notFound: 'NA' })).toBe('NA'); 106 | expect(T1.translate('na.na', { notFound: null })).toBe(null); 107 | 108 | T1 = new MDText({}, { notFound: (key) => key + ' not found' }); 109 | expect(T1.translate('na.na')).toBe('na.na not found'); 110 | T1 = new MDText({}, { notFound: (key, ctx) => key + ' not found, a:' + ctx.a }); 111 | expect(T1.translate('na.na', { context: { a: 1 } })).toBe('na.na not found, a:1'); 112 | }); 113 | }); 114 | 115 | describe("i18n-react format", () => { 116 | let T = new MDText(null, { MDFlavor: 1 }); 117 | it("empty values", () => { 118 | expect(T.format(undefined)).toBe(undefined); 119 | expect(T.format(null)).toBe(null); 120 | expect(T.format("")).toBe(""); 121 | }); 122 | 123 | it("interpolates variable", () => { 124 | expect(T.format("{val}", { val: 'x' })).toBe('x'); 125 | expect(T.format("b{val}", { val: 'x' })).toBe('bx'); 126 | expect(T.format("{val}c", { val: 'x' })).toBe('xc'); 127 | expect(T.format("d{val}d", { val: 'x' })).toBe('dxd'); 128 | }); 129 | 130 | it("leaves literal", () => { 131 | expect(T.format("``{val}``", { val: 'x' })).toBe('{val}'); 132 | expect(T.format("`` [*b*] ``")).toBe(' [*b*] '); 133 | expect(T.format("``aa`` `` bb ``")).toBe('aa bb'); 134 | expect(T.format("`` ``` ``")).toBe(" ``` "); 135 | expect(T.format("```ab```")).toBe("ab"); 136 | expect(T.format("`` ```` ``")).toBe("````"); 137 | expect(T.format("``` `` ```")).toBe("``"); 138 | expect(T.format("``` ```` ```")).toBe("````"); 139 | expect(T.format("``` `````` `````` ```")).toBe("`````` ``````"); 140 | expect(T.format("```` `````` `````` ````")).toBe("`````` ``````"); 141 | expect(T.format("``[``a``]``")).toBe('[a]'); 142 | expect(T.format("``[*b*]``{val}``[*b*]``", { val: 'x' })).toBe('[*b*]x[*b*]'); 143 | expect(T.format("{val}``[*b*]``{val}", { val: 'x' })).toBe('x[*b*]x'); 144 | }); 145 | 146 | it("not a literal", () => { 147 | expect(T.format("`` a ```")).toBe("`` a ```"); 148 | expect(T.format("``` a ``")).toBe("``` a ``"); 149 | 150 | expect(T.format("``a```")).toBe("``a```"); 151 | expect(T.format("```a``")).toBe("```a``"); 152 | 153 | expect(T.format("`` ```")).toBe("`` ```"); 154 | expect(T.format("``` ``")).toBe("``` ``"); 155 | expect(T.format("``` ````")).toBe("``` ````"); 156 | expect(T.format("```` ```")).toBe("```` ```"); 157 | }); 158 | 159 | it("localizes numbers", () => { 160 | expect(T.format("{val,l}", { val: 10000 })).toMatch(/10[,']?000/); 161 | }); 162 | 163 | it("returns string type", () => { 164 | expect(T.format("{val}", { val: 0 })).toBe('0'); 165 | }); 166 | }); 167 | 168 | -------------------------------------------------------------------------------- /src/i18n-react.ts: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { mdFlavors, MDFlavor, mdMatch } from './mdflavors'; 3 | 4 | export type NotFound = string | ((key: string, context?: any) => string); 5 | 6 | function isString(s: any): s is string { 7 | return typeof s === 'string' || s instanceof String; 8 | } 9 | 10 | function isObject(o: any) { 11 | return typeof o === 'object'; 12 | } 13 | 14 | function isFunction(o: any) { 15 | return typeof o === 'function'; 16 | } 17 | 18 | function get(obj: any, path: string): any { 19 | var spath = path.split('.'); 20 | for (var i = 0, len = spath.length; i < len; i++) { 21 | if (!obj || !isObject(obj)) return undefined; 22 | obj = obj[spath[i]]; 23 | } 24 | return obj; 25 | } 26 | 27 | function first(o: any): any { 28 | for (var k in o) { 29 | if (k != '__') return o[k]; 30 | } 31 | } 32 | 33 | function flatten(l: (string | any)[]) { 34 | let r: any[] = []; 35 | let s = ''; 36 | let flush = () => s && (r.push(s), s = ''); 37 | 38 | for (let i of l) { 39 | if (i == null) continue; 40 | if (isString(i)) { 41 | s += i; 42 | } else { 43 | flush(); 44 | r.push(i); 45 | } 46 | } 47 | flush(); 48 | return r.length > 1 ? r : (r.length ? r[0] : null); 49 | } 50 | 51 | class matcher { 52 | constructor( 53 | public mdFlavor: MDFlavor, 54 | public inter: (exp: string) => any, 55 | public self: (exp: string) => any) { 56 | } 57 | 58 | M(value: string): React.ReactNode { 59 | if (!value) return null; 60 | 61 | const m = mdMatch(this.mdFlavor, value); 62 | if (!m) 63 | return value; 64 | 65 | let middle: any = null; 66 | switch (m.tag) { 67 | case "inter": 68 | middle = this.inter && this.inter(m.body); 69 | break; 70 | case "self": 71 | middle = this.self && this.self(m.body); 72 | break; 73 | case "literals": 74 | case "literal": 75 | middle = m.body; 76 | break; 77 | default: 78 | middle = React.createElement(m.tag, { key: m.tag + m.body }, this.M(m.body)); 79 | break; 80 | } 81 | return flatten([this.M(m.head), middle, this.M(m.tail)]); 82 | } 83 | } 84 | 85 | function rangeHit(node: any, val: number) { 86 | for (let t in node) { 87 | if (!node.hasOwnProperty(t)) continue; 88 | var range = t.match(/^(-?\d+)\.\.(-?\d+)$/); 89 | if (range && (+range[1] <= val && val <= +range[2])) { 90 | return node[t]; 91 | } 92 | } 93 | } 94 | 95 | function resolveContextPath(node: any, p: number, path: string[], context: any): string { 96 | const key = path[p]; 97 | let trans: any; 98 | 99 | if (key != null && context[key] != null) { 100 | trans = get(node, context[key].toString()); 101 | if (trans == null && (+context[key]) === context[key]) { 102 | trans = rangeHit(node, +context[key]); 103 | } 104 | } 105 | 106 | if (trans == null) 107 | trans = node._; 108 | if (trans == null) 109 | trans = first(node); 110 | 111 | if (trans != null && !isString(trans)) { 112 | return resolveContextPath(trans, p + 1, path, context); 113 | } 114 | return trans; 115 | } 116 | 117 | function resolveContext(node: any, context: any): string { 118 | if (context == null) { 119 | return resolveContextPath(node, 0, [], null); 120 | } else if (!isObject(context)) { 121 | return resolveContextPath(node, 0, ['_'], { _: context }); 122 | } else { 123 | let ctx_keys: string[] = []; 124 | if (node.__) { 125 | ctx_keys = node.__.split('.'); 126 | } else { 127 | for (var k in context) { 128 | if (!context.hasOwnProperty(k)) continue; 129 | ctx_keys.push(k); 130 | } 131 | } 132 | return resolveContextPath(node, 0, ctx_keys, context); 133 | } 134 | } 135 | 136 | export interface MDTextOpts { 137 | MDFlavor?: 0 | 1; 138 | notFound?: NotFound; 139 | } 140 | 141 | export class MDText { 142 | constructor(public texts: object, opt?: MDTextOpts) { 143 | this.setOpts(opt); 144 | } 145 | 146 | setTexts(texts: object, opt?: MDTextOpts) { 147 | this.texts = texts; 148 | this.setOpts(opt); 149 | } 150 | 151 | setOpts(opt: MDTextOpts) { 152 | if (!opt) return; 153 | if (opt.notFound !== undefined) this.notFound = opt.notFound; 154 | if (opt.MDFlavor !== undefined) this.MDFlavor = opt.MDFlavor; 155 | } 156 | 157 | private MDFlavor: 0 | 1 = 0; 158 | // public access is deprecated 159 | public notFound: NotFound = undefined; 160 | 161 | interpolate(exp: string, vars: object): any { 162 | const [vn, flags] = exp.split(','); 163 | const v = get(vars, vn); 164 | if (v == null) { 165 | return null; 166 | } else if (React.isValidElement<{ key: string }>(v)) { 167 | return React.cloneElement(v, { key: 'r' }); 168 | } 169 | let vs: string; 170 | if (flags && flags.match(/l/)) { 171 | vs = v.toLocaleString(); 172 | } else { 173 | vs = v.toString(); 174 | } 175 | return vs; 176 | } 177 | 178 | format(value: string, vars?: object): React.ReactNode { 179 | if (!value) return value; 180 | 181 | return new matcher( 182 | mdFlavors[this.MDFlavor], 183 | (exp: string) => this.interpolate(exp, vars), 184 | (exp: string) => this.translate(exp, vars) 185 | ).M(value); 186 | } 187 | 188 | translate(key: string, options?: any): React.ReactNode { 189 | if (!key) return key; 190 | 191 | var trans: string | any = get(this.texts, key); 192 | const context = options && options.context; 193 | 194 | if (trans != null && !(isString(trans) || isFunction(trans))) { 195 | trans = resolveContext(trans, context); 196 | } 197 | 198 | if (trans == null) { 199 | trans = (options && options.notFound !== undefined) ? options.notFound : 200 | this.notFound !== undefined ? this.notFound : 201 | key; 202 | } 203 | 204 | if (isFunction(trans)) { 205 | trans = trans(key, context); 206 | } 207 | 208 | return this.format(trans, options); 209 | } 210 | 211 | factory(tagF: string) { 212 | // name High Order Function for React Dev tools 213 | let MDText = (props: any) => { 214 | let { text, tag, ...restProps } = props; 215 | 216 | let key: string; 217 | let options: any; 218 | 219 | if (text == null || isString(text)) { 220 | key = text; 221 | options = props; 222 | let { notFound, context, ...rest2Props } = restProps; 223 | restProps = rest2Props; 224 | } else { 225 | key = text.key; 226 | options = text; 227 | } 228 | 229 | let aTag = tagF || tag; 230 | let translation = this.translate(key, options) 231 | return aTag ? 232 | React.createElement(aTag, restProps, translation) : 233 | translation; 234 | }; 235 | return MDText as React.StatelessComponent; 236 | } 237 | 238 | p = this.factory('p'); 239 | span = this.factory('span'); 240 | li = this.factory('li'); 241 | div = this.factory('div'); 242 | button = this.factory('button'); 243 | a = this.factory('a'); 244 | 245 | text = this.factory(null); 246 | } 247 | 248 | var singleton = new MDText(null); 249 | export default singleton; 250 | -------------------------------------------------------------------------------- /dist/i18n-react.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __rest = (this && this.__rest) || function (s, e) { 3 | var t = {}; 4 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 5 | t[p] = s[p]; 6 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 7 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) 8 | t[p[i]] = s[p[i]]; 9 | return t; 10 | }; 11 | exports.__esModule = true; 12 | var React = require("react"); 13 | var mdflavors_1 = require("./mdflavors"); 14 | function isString(s) { 15 | return typeof s === 'string' || s instanceof String; 16 | } 17 | function isObject(o) { 18 | return typeof o === 'object'; 19 | } 20 | function isFunction(o) { 21 | return typeof o === 'function'; 22 | } 23 | function get(obj, path) { 24 | var spath = path.split('.'); 25 | for (var i = 0, len = spath.length; i < len; i++) { 26 | if (!obj || !isObject(obj)) 27 | return undefined; 28 | obj = obj[spath[i]]; 29 | } 30 | return obj; 31 | } 32 | function first(o) { 33 | for (var k in o) { 34 | if (k != '__') 35 | return o[k]; 36 | } 37 | } 38 | function flatten(l) { 39 | var r = []; 40 | var s = ''; 41 | var flush = function () { return s && (r.push(s), s = ''); }; 42 | for (var _i = 0, l_1 = l; _i < l_1.length; _i++) { 43 | var i = l_1[_i]; 44 | if (i == null) 45 | continue; 46 | if (isString(i)) { 47 | s += i; 48 | } 49 | else { 50 | flush(); 51 | r.push(i); 52 | } 53 | } 54 | flush(); 55 | return r.length > 1 ? r : (r.length ? r[0] : null); 56 | } 57 | var matcher = /** @class */ (function () { 58 | function matcher(mdFlavor, inter, self) { 59 | this.mdFlavor = mdFlavor; 60 | this.inter = inter; 61 | this.self = self; 62 | } 63 | matcher.prototype.M = function (value) { 64 | if (!value) 65 | return null; 66 | var m = mdflavors_1.mdMatch(this.mdFlavor, value); 67 | if (!m) 68 | return value; 69 | var middle = null; 70 | switch (m.tag) { 71 | case "inter": 72 | middle = this.inter && this.inter(m.body); 73 | break; 74 | case "self": 75 | middle = this.self && this.self(m.body); 76 | break; 77 | case "literals": 78 | case "literal": 79 | middle = m.body; 80 | break; 81 | default: 82 | middle = React.createElement(m.tag, { key: m.tag + m.body }, this.M(m.body)); 83 | break; 84 | } 85 | return flatten([this.M(m.head), middle, this.M(m.tail)]); 86 | }; 87 | return matcher; 88 | }()); 89 | function rangeHit(node, val) { 90 | for (var t in node) { 91 | if (!node.hasOwnProperty(t)) 92 | continue; 93 | var range = t.match(/^(-?\d+)\.\.(-?\d+)$/); 94 | if (range && (+range[1] <= val && val <= +range[2])) { 95 | return node[t]; 96 | } 97 | } 98 | } 99 | function resolveContextPath(node, p, path, context) { 100 | var key = path[p]; 101 | var trans; 102 | if (key != null && context[key] != null) { 103 | trans = get(node, context[key].toString()); 104 | if (trans == null && (+context[key]) === context[key]) { 105 | trans = rangeHit(node, +context[key]); 106 | } 107 | } 108 | if (trans == null) 109 | trans = node._; 110 | if (trans == null) 111 | trans = first(node); 112 | if (trans != null && !isString(trans)) { 113 | return resolveContextPath(trans, p + 1, path, context); 114 | } 115 | return trans; 116 | } 117 | function resolveContext(node, context) { 118 | if (context == null) { 119 | return resolveContextPath(node, 0, [], null); 120 | } 121 | else if (!isObject(context)) { 122 | return resolveContextPath(node, 0, ['_'], { _: context }); 123 | } 124 | else { 125 | var ctx_keys = []; 126 | if (node.__) { 127 | ctx_keys = node.__.split('.'); 128 | } 129 | else { 130 | for (var k in context) { 131 | if (!context.hasOwnProperty(k)) 132 | continue; 133 | ctx_keys.push(k); 134 | } 135 | } 136 | return resolveContextPath(node, 0, ctx_keys, context); 137 | } 138 | } 139 | var MDText = /** @class */ (function () { 140 | function MDText(texts, opt) { 141 | this.texts = texts; 142 | this.MDFlavor = 0; 143 | // public access is deprecated 144 | this.notFound = undefined; 145 | this.p = this.factory('p'); 146 | this.span = this.factory('span'); 147 | this.li = this.factory('li'); 148 | this.div = this.factory('div'); 149 | this.button = this.factory('button'); 150 | this.a = this.factory('a'); 151 | this.text = this.factory(null); 152 | this.setOpts(opt); 153 | } 154 | MDText.prototype.setTexts = function (texts, opt) { 155 | this.texts = texts; 156 | this.setOpts(opt); 157 | }; 158 | MDText.prototype.setOpts = function (opt) { 159 | if (!opt) 160 | return; 161 | if (opt.notFound !== undefined) 162 | this.notFound = opt.notFound; 163 | if (opt.MDFlavor !== undefined) 164 | this.MDFlavor = opt.MDFlavor; 165 | }; 166 | MDText.prototype.interpolate = function (exp, vars) { 167 | var _a = exp.split(','), vn = _a[0], flags = _a[1]; 168 | var v = get(vars, vn); 169 | if (v == null) { 170 | return null; 171 | } 172 | else if (React.isValidElement(v)) { 173 | return React.cloneElement(v, { key: 'r' }); 174 | } 175 | var vs; 176 | if (flags && flags.match(/l/)) { 177 | vs = v.toLocaleString(); 178 | } 179 | else { 180 | vs = v.toString(); 181 | } 182 | return vs; 183 | }; 184 | MDText.prototype.format = function (value, vars) { 185 | var _this = this; 186 | if (!value) 187 | return value; 188 | return new matcher(mdflavors_1.mdFlavors[this.MDFlavor], function (exp) { return _this.interpolate(exp, vars); }, function (exp) { return _this.translate(exp, vars); }).M(value); 189 | }; 190 | MDText.prototype.translate = function (key, options) { 191 | if (!key) 192 | return key; 193 | var trans = get(this.texts, key); 194 | var context = options && options.context; 195 | if (trans != null && !(isString(trans) || isFunction(trans))) { 196 | trans = resolveContext(trans, context); 197 | } 198 | if (trans == null) { 199 | trans = (options && options.notFound !== undefined) ? options.notFound : 200 | this.notFound !== undefined ? this.notFound : 201 | key; 202 | } 203 | if (isFunction(trans)) { 204 | trans = trans(key, context); 205 | } 206 | return this.format(trans, options); 207 | }; 208 | MDText.prototype.factory = function (tagF) { 209 | var _this = this; 210 | // name High Order Function for React Dev tools 211 | var MDText = function (props) { 212 | var text = props.text, tag = props.tag, restProps = __rest(props, ["text", "tag"]); 213 | var key; 214 | var options; 215 | if (text == null || isString(text)) { 216 | key = text; 217 | options = props; 218 | var notFound = restProps.notFound, context = restProps.context, rest2Props = __rest(restProps, ["notFound", "context"]); 219 | restProps = rest2Props; 220 | } 221 | else { 222 | key = text.key; 223 | options = text; 224 | } 225 | var aTag = tagF || tag; 226 | var translation = _this.translate(key, options); 227 | return aTag ? 228 | React.createElement(aTag, restProps, translation) : 229 | translation; 230 | }; 231 | return MDText; 232 | }; 233 | return MDText; 234 | }()); 235 | exports.MDText = MDText; 236 | var singleton = new MDText(null); 237 | exports["default"] = singleton; 238 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/alexdrel/i18n-react.svg?branch=master)](https://travis-ci.org/alexdrel/i18n-react) 2 | 3 | i18n-react 4 | === 5 | React (JS) text internationalization and externalizing. 6 | Markdown-ish syntax with variables support (including of react element type). 7 | 8 | ### Quick example 9 | 10 | ```js 11 | var ReactDOM = require('react-dom'); 12 | var React = require('react'); 13 | const { MDText } = require('i18n-react'); 14 | 15 | const T = new MDText({ 16 | greeting: "#Hello, World!\n My name is **{myName}**! \n {{howAreYou}}", 17 | howAreYou: "_How do you do?_" 18 | }, { MDFlavor: 1 }); 19 | 20 | ReactDOM.render( 21 | , 22 | document.getElementById('content') 23 | ); 24 | ``` 25 | 26 | Unsurprisingly renders: 27 | ******** 28 | ### Hello, World! 29 | My name is **i18n-react**! 30 | 31 | _How do you do?_ 32 | 33 | ******** 34 | 35 | ### External yaml resource file 36 | Usually texts are retrived from an extrenal source (I would recommend YAML format) but 37 | loading of the external files is out of scope for the library. 38 | 39 | ```yaml 40 | greetings: 41 | hello: Hi, {who}! 42 | howdy: 43 | formal: How do you do? 44 | normal: How are you, {who}? 45 | informal: "What's up?" 46 | bye: Bye 47 | 48 | longTime: 49 | 0: Not a day no see 50 | 1: 1 day no see 51 | '2..4': A few days no see 52 | _: "[{context} days][Long time no see]" 53 | ``` 54 | 55 | Points of interest: 56 | * {who} - variable interpolation 57 | * formal/informal - context selectors 58 | * longTime - pluralization and range 59 | * [X days][...] - renders two paragraphs 60 | 61 | 62 | ## Usage 63 | Npm compatible packager (browserify/webpack) is recommended, but ```Dist``` folder also contains UMD versions 64 | (regular and minified) that can be used w/o commonJS packager. 65 | 66 | ### Global Singleton 67 | ```js 68 | /* ES6 & TS */ 69 | import T from 'i18n-react'; 70 | /* commonJS */ 71 | var T = require('i18n-react').default; 72 | /* when using UMD version w/o modules */ 73 | var T = window['i18n-react'].default; 74 | ``` 75 | 76 | 77 | Setup once - probably in an application entry point js: 78 | ```js 79 | T.setTexts({ 80 | greeting: "Hello, World! My name is *{myName}*! \n {{howAreYou}}", 81 | howAreYou: "_How do you do?_" 82 | }, { MDFlavor: 0 }); 83 | /* or if there is yaml/json loader */ 84 | var dictionary = require('../texts/texts-en.yml'); 85 | T.setTexts(dictionary); 86 | ``` 87 | 88 | Use it anywhere: 89 | ```xml 90 | 91 | 92 | 93 | X}}/> 94 |

{T.translate("path.to.string", { context: "context", val: 1})}

95 | ``` 96 | 97 | ### Creating new MDText object 98 | In case you want to control lifecycle of the dictionary object (instead of default singleton) 99 | it can be created with MDText constructor. 100 | ```js 101 | import { MDText } from 'i18n-react'; 102 | let T = new MDText({...}); 103 | let x = T.translate("path.to.string"); 104 | 105 | ``` 106 | ### Passing in the React Context 107 | MDText object can be passed in the react 16.3+ context. See examples/yaml for complete example. 108 | ```tsx 109 | import { MDText } from 'i18n-react'; 110 | let MDTextContext = React.createContext(); 111 | let Texts = new MDText({...}); 112 | 113 | 114 | { (T) => 115 | 116 | } 117 | 118 | ``` 119 | 120 | ### Difference between Keys and Context 121 | Text attribute is a key that should point to string or JSON object, it has to be present in the language resource. 122 | Then if needed the context is used to disambiguate betwen multiple texts according to the following rules: 123 | 1. Exact match for the context value. 124 | 1. For numeric context values - key with range, e.g. 2..4 that matches context value. 125 | 1. Explicit default - '_' key. 126 | 1. First key. 127 | 128 | ### Missing translations 129 | By default if translation for the specified key is not present the key itself is returned 130 | to help you find the missing translation. 131 | This behaviour can be augmented by passing custom ``notFound`` value to setText options or MDText contructor. 132 | 133 | This value can be either a string, or a function returning a string. 134 | If it is a string, then it will be returned as is any time a key is missing. 135 | If you provide a function, then the function will be run with the missing key 136 | and context as arguments. 137 | 138 | ```js 139 | // "Not Found!" will replace all missing translations 140 | T.setTexts(translations, { 141 | notFound: 'Not Found!' 142 | }) 143 | 144 | // "SomeKey <-- this guy" will appear instead 145 | T.setTexts(translations, { 146 | notFound: key => `${key} <-- this guy` 147 | }) 148 | 149 | // you can combine this solution with markdown! 150 | T.setTexts(translations, { 151 | notFound: key => `**${key}**` // will render SomeKey 152 | }) 153 | ``` 154 | 155 | ### Function in translation 156 | Translation dictionaries can be extended with functions (as in notFound). 157 | 158 | ```js 159 | T.setTexts({ 160 | a: 'A', 161 | n: (_key, ctx) => ctx ? `Number ${ctx}` : '', 162 | }); 163 | T.translate('a')) // 'A' 164 | T.translate('n', { context: 9 })) // 'Number 9' 165 | ``` 166 | 167 | ## Markdown syntax 168 | 169 | + ``*italic*`` *italic* - ```` **breaking change V1, ```` in V0** 170 | + ``_italic_`` _italic_ - ```` **breaking change V1, ```` in V0** 171 | + ``**bold**`` **bold** ```` *new - V1* 172 | + ``__bold__`` __bold__ ```` *new - V1* 173 | + ``~underlined~`` underlined ```` *new - V1* 174 | + ``~~strike~~`` ~~strike~~ ```` *new - V1* 175 | + ``\n`` New Line ``
`` 176 | + ``[Paragraph 1][Paragraph 2]`` Multiple paragraphs ``

`` 177 | + ``#``-``####`` Headers ``

-

`` 178 | + \`\` \*as\*\_[IS]\_ \`\` Literal *new - V1* 179 | 180 | ### Unit tests are half-loaf documentation 181 | You are welcomed to consult examples folder and unit tests for usage details and examples. 182 | 183 | ## Breaking changes 184 | ### 0.7 185 | ##### Literal \`\` changed to better match GitHub 186 | Allows matching number of backticks (with optional whitespace) to form a literal. This allows quoting of the backtick pairs: ```` ``` `` ``` ```` => ``` `` ``` . 187 | 188 | ### 0.6 189 | ##### Literal \`\` in V1 syntax 190 | New \`\` syntax \`\` (in V1 only) to disable MD processing. 191 | 192 | ### 0.5 193 | ##### React 16+ required 194 | As React now allows fragments and strings in render the default behavior of ```` changed not to wrap the output into ```` when ``tag`` property is not specified. 195 | 196 | ### 0.4 197 | ##### New MD syntax 198 | The new MD flavor (aligned with github's Markdown) is added : V1. Opt-in for this release, will become default in the next major release. 199 | V1 introduces strike and underline, and rehabilitates ```` and ```` tags. 200 | 201 | ```yaml 202 | em: "an *italic* style" 203 | i: "an _italic_ style" 204 | strong: "a **bold** move" 205 | b: "a __bold__ move" 206 | u: "an ~underlined~ word" 207 | strike: "a ~~strike~~ out" 208 | ``` 209 | To opt-in for the new syntax: 210 | ```js 211 | let T = new MDText(texts, { MDFlavor: 1 }); 212 | // or for the singelton 213 | T.setTexts(require('../texts/texts-en.yml'), { MDFlavor: 1, notFound: 'NA' }); 214 | ``` 215 | #### notFound Deprecation 216 | MDText notFound property is deprecated - please switch to constructor or serTexts options. 217 | 218 | ### 0.3 219 | ##### Unknown Prop Warning 220 | React 15.2 is preparing to stop filtering HTML properties (https://fb.me/react-unknown-prop) - the feature that i18n relied upon for 221 | preventing interpolation variables from leaking into the DOM. 222 | 223 | Thus new syntax for passing variables is introduced: 224 | ```xml 225 | 226 | /* replaces */ 227 | 228 | ``` 229 | All tags passing to T.* anything beside ```text```, ```tag``` and ```context``` properties have to be updated or React 15.2 will cry annoyingly. 230 | 231 | ##### typescript 2.0 / ts@next typings 232 | Updated package.json contains all the info for the new typescript to get typings automatically. 233 | 234 | ### 0.2 235 | * ES6 style export (use default export explicitly for commonJS/UMD) 236 | * Stateless react components (shouldComponentUpdate optimization removed) 237 | * Default export (T above) no longer can be used as a react component (use T.text or T.span instead) 238 | 239 | ## Development 240 | #### Commands 241 | * Watch commonJS build: ```$ npm start``` 242 | * Build commonJS/UMD version: ```$ npm run build``` 243 | * Start dev server for examples: ```$ npm run examples``` (http://localhost:1818/webpack-dev-server/examples/) 244 | * Build examples: ```$ npm run build:examples``` 245 | * Run tests (Firefox): ```$ npm test``` 246 | * Watch tests (Chrome): ```$ npm run test:watch``` 247 | 248 | -------------------------------------------------------------------------------- /dist/i18n-react.umd.js: -------------------------------------------------------------------------------- 1 | (function webpackUniversalModuleDefinition(root, factory) { 2 | if(typeof exports === 'object' && typeof module === 'object') 3 | module.exports = factory(require("React")); 4 | else if(typeof define === 'function' && define.amd) 5 | define(["React"], factory); 6 | else if(typeof exports === 'object') 7 | exports["i18n-react"] = factory(require("React")); 8 | else 9 | root["i18n-react"] = factory(root["React"]); 10 | })(this, function(__WEBPACK_EXTERNAL_MODULE_1__) { 11 | return /******/ (function(modules) { // webpackBootstrap 12 | /******/ // The module cache 13 | /******/ var installedModules = {}; 14 | /******/ 15 | /******/ // The require function 16 | /******/ function __webpack_require__(moduleId) { 17 | /******/ 18 | /******/ // Check if module is in cache 19 | /******/ if(installedModules[moduleId]) { 20 | /******/ return installedModules[moduleId].exports; 21 | /******/ } 22 | /******/ // Create a new module (and put it into the cache) 23 | /******/ var module = installedModules[moduleId] = { 24 | /******/ i: moduleId, 25 | /******/ l: false, 26 | /******/ exports: {} 27 | /******/ }; 28 | /******/ 29 | /******/ // Execute the module function 30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 31 | /******/ 32 | /******/ // Flag the module as loaded 33 | /******/ module.l = true; 34 | /******/ 35 | /******/ // Return the exports of the module 36 | /******/ return module.exports; 37 | /******/ } 38 | /******/ 39 | /******/ 40 | /******/ // expose the modules object (__webpack_modules__) 41 | /******/ __webpack_require__.m = modules; 42 | /******/ 43 | /******/ // expose the module cache 44 | /******/ __webpack_require__.c = installedModules; 45 | /******/ 46 | /******/ // define getter function for harmony exports 47 | /******/ __webpack_require__.d = function(exports, name, getter) { 48 | /******/ if(!__webpack_require__.o(exports, name)) { 49 | /******/ Object.defineProperty(exports, name, { 50 | /******/ configurable: false, 51 | /******/ enumerable: true, 52 | /******/ get: getter 53 | /******/ }); 54 | /******/ } 55 | /******/ }; 56 | /******/ 57 | /******/ // getDefaultExport function for compatibility with non-harmony modules 58 | /******/ __webpack_require__.n = function(module) { 59 | /******/ var getter = module && module.__esModule ? 60 | /******/ function getDefault() { return module['default']; } : 61 | /******/ function getModuleExports() { return module; }; 62 | /******/ __webpack_require__.d(getter, 'a', getter); 63 | /******/ return getter; 64 | /******/ }; 65 | /******/ 66 | /******/ // Object.prototype.hasOwnProperty.call 67 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 68 | /******/ 69 | /******/ // __webpack_public_path__ 70 | /******/ __webpack_require__.p = ""; 71 | /******/ 72 | /******/ // Load entry module and return exports 73 | /******/ return __webpack_require__(__webpack_require__.s = 0); 74 | /******/ }) 75 | /************************************************************************/ 76 | /******/ ([ 77 | /* 0 */ 78 | /***/ (function(module, exports, __webpack_require__) { 79 | 80 | "use strict"; 81 | 82 | var __rest = (this && this.__rest) || function (s, e) { 83 | var t = {}; 84 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) 85 | t[p] = s[p]; 86 | if (s != null && typeof Object.getOwnPropertySymbols === "function") 87 | for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) 88 | t[p[i]] = s[p[i]]; 89 | return t; 90 | }; 91 | exports.__esModule = true; 92 | var React = __webpack_require__(1); 93 | var mdflavors_1 = __webpack_require__(2); 94 | function isString(s) { 95 | return typeof s === 'string' || s instanceof String; 96 | } 97 | function isObject(o) { 98 | return typeof o === 'object'; 99 | } 100 | function isFunction(o) { 101 | return typeof o === 'function'; 102 | } 103 | function get(obj, path) { 104 | var spath = path.split('.'); 105 | for (var i = 0, len = spath.length; i < len; i++) { 106 | if (!obj || !isObject(obj)) 107 | return undefined; 108 | obj = obj[spath[i]]; 109 | } 110 | return obj; 111 | } 112 | function first(o) { 113 | for (var k in o) { 114 | if (k != '__') 115 | return o[k]; 116 | } 117 | } 118 | function flatten(l) { 119 | var r = []; 120 | var s = ''; 121 | var flush = function () { return s && (r.push(s), s = ''); }; 122 | for (var _i = 0, l_1 = l; _i < l_1.length; _i++) { 123 | var i = l_1[_i]; 124 | if (i == null) 125 | continue; 126 | if (isString(i)) { 127 | s += i; 128 | } 129 | else { 130 | flush(); 131 | r.push(i); 132 | } 133 | } 134 | flush(); 135 | return r.length > 1 ? r : (r.length ? r[0] : null); 136 | } 137 | var matcher = /** @class */ (function () { 138 | function matcher(mdFlavor, inter, self) { 139 | this.mdFlavor = mdFlavor; 140 | this.inter = inter; 141 | this.self = self; 142 | } 143 | matcher.prototype.M = function (value) { 144 | if (!value) 145 | return null; 146 | var m = mdflavors_1.mdMatch(this.mdFlavor, value); 147 | if (!m) 148 | return value; 149 | var middle = null; 150 | switch (m.tag) { 151 | case "inter": 152 | middle = this.inter && this.inter(m.body); 153 | break; 154 | case "self": 155 | middle = this.self && this.self(m.body); 156 | break; 157 | case "literals": 158 | case "literal": 159 | middle = m.body; 160 | break; 161 | default: 162 | middle = React.createElement(m.tag, { key: m.tag + m.body }, this.M(m.body)); 163 | break; 164 | } 165 | return flatten([this.M(m.head), middle, this.M(m.tail)]); 166 | }; 167 | return matcher; 168 | }()); 169 | function rangeHit(node, val) { 170 | for (var t in node) { 171 | if (!node.hasOwnProperty(t)) 172 | continue; 173 | var range = t.match(/^(-?\d+)\.\.(-?\d+)$/); 174 | if (range && (+range[1] <= val && val <= +range[2])) { 175 | return node[t]; 176 | } 177 | } 178 | } 179 | function resolveContextPath(node, p, path, context) { 180 | var key = path[p]; 181 | var trans; 182 | if (key != null && context[key] != null) { 183 | trans = get(node, context[key].toString()); 184 | if (trans == null && (+context[key]) === context[key]) { 185 | trans = rangeHit(node, +context[key]); 186 | } 187 | } 188 | if (trans == null) 189 | trans = node._; 190 | if (trans == null) 191 | trans = first(node); 192 | if (trans != null && !isString(trans)) { 193 | return resolveContextPath(trans, p + 1, path, context); 194 | } 195 | return trans; 196 | } 197 | function resolveContext(node, context) { 198 | if (context == null) { 199 | return resolveContextPath(node, 0, [], null); 200 | } 201 | else if (!isObject(context)) { 202 | return resolveContextPath(node, 0, ['_'], { _: context }); 203 | } 204 | else { 205 | var ctx_keys = []; 206 | if (node.__) { 207 | ctx_keys = node.__.split('.'); 208 | } 209 | else { 210 | for (var k in context) { 211 | if (!context.hasOwnProperty(k)) 212 | continue; 213 | ctx_keys.push(k); 214 | } 215 | } 216 | return resolveContextPath(node, 0, ctx_keys, context); 217 | } 218 | } 219 | var MDText = /** @class */ (function () { 220 | function MDText(texts, opt) { 221 | this.texts = texts; 222 | this.MDFlavor = 0; 223 | // public access is deprecated 224 | this.notFound = undefined; 225 | this.p = this.factory('p'); 226 | this.span = this.factory('span'); 227 | this.li = this.factory('li'); 228 | this.div = this.factory('div'); 229 | this.button = this.factory('button'); 230 | this.a = this.factory('a'); 231 | this.text = this.factory(null); 232 | this.setOpts(opt); 233 | } 234 | MDText.prototype.setTexts = function (texts, opt) { 235 | this.texts = texts; 236 | this.setOpts(opt); 237 | }; 238 | MDText.prototype.setOpts = function (opt) { 239 | if (!opt) 240 | return; 241 | if (opt.notFound !== undefined) 242 | this.notFound = opt.notFound; 243 | if (opt.MDFlavor !== undefined) 244 | this.MDFlavor = opt.MDFlavor; 245 | }; 246 | MDText.prototype.interpolate = function (exp, vars) { 247 | var _a = exp.split(','), vn = _a[0], flags = _a[1]; 248 | var v = get(vars, vn); 249 | if (v == null) { 250 | return null; 251 | } 252 | else if (React.isValidElement(v)) { 253 | return React.cloneElement(v, { key: 'r' }); 254 | } 255 | var vs; 256 | if (flags && flags.match(/l/)) { 257 | vs = v.toLocaleString(); 258 | } 259 | else { 260 | vs = v.toString(); 261 | } 262 | return vs; 263 | }; 264 | MDText.prototype.format = function (value, vars) { 265 | var _this = this; 266 | if (!value) 267 | return value; 268 | return new matcher(mdflavors_1.mdFlavors[this.MDFlavor], function (exp) { return _this.interpolate(exp, vars); }, function (exp) { return _this.translate(exp, vars); }).M(value); 269 | }; 270 | MDText.prototype.translate = function (key, options) { 271 | if (!key) 272 | return key; 273 | var trans = get(this.texts, key); 274 | var context = options && options.context; 275 | if (trans != null && !(isString(trans) || isFunction(trans))) { 276 | trans = resolveContext(trans, context); 277 | } 278 | if (trans == null) { 279 | trans = (options && options.notFound !== undefined) ? options.notFound : 280 | this.notFound !== undefined ? this.notFound : 281 | key; 282 | } 283 | if (isFunction(trans)) { 284 | trans = trans(key, context); 285 | } 286 | return this.format(trans, options); 287 | }; 288 | MDText.prototype.factory = function (tagF) { 289 | var _this = this; 290 | // name High Order Function for React Dev tools 291 | var MDText = function (props) { 292 | var text = props.text, tag = props.tag, restProps = __rest(props, ["text", "tag"]); 293 | var key; 294 | var options; 295 | if (text == null || isString(text)) { 296 | key = text; 297 | options = props; 298 | var notFound = restProps.notFound, context = restProps.context, rest2Props = __rest(restProps, ["notFound", "context"]); 299 | restProps = rest2Props; 300 | } 301 | else { 302 | key = text.key; 303 | options = text; 304 | } 305 | var aTag = tagF || tag; 306 | var translation = _this.translate(key, options); 307 | return aTag ? 308 | React.createElement(aTag, restProps, translation) : 309 | translation; 310 | }; 311 | return MDText; 312 | }; 313 | return MDText; 314 | }()); 315 | exports.MDText = MDText; 316 | var singleton = new MDText(null); 317 | exports["default"] = singleton; 318 | 319 | 320 | /***/ }), 321 | /* 1 */ 322 | /***/ (function(module, exports) { 323 | 324 | module.exports = __WEBPACK_EXTERNAL_MODULE_1__; 325 | 326 | /***/ }), 327 | /* 2 */ 328 | /***/ (function(module, exports, __webpack_require__) { 329 | 330 | "use strict"; 331 | 332 | exports.__esModule = true; 333 | var R = { 334 | "`` ": [/^(.*?(?:(?!`).|^))(``+)\s(.*?)\s\2(?!`)(.*)$/, [1, 3, 4]], 335 | "``": [/^(.*?(?:(?!`).|^))(``+)(?!`)(.*?(?!`).)\2(?!`)(.*)$/, [1, 3, 4]], 336 | "*": /^(|.*?\W)\*(\S.*?)\*(|\W.*)$/, 337 | "**": /^(|.*?\W)\*\*(\S.*?)\*\*(|\W.*)$/, 338 | "_": /^(|.*?\W)_(\S.*?)_(|\W.*)$/, 339 | "__": /^(|.*?\W)__(\S.*?)__(|\W.*)$/, 340 | "~": /^(|.*?\W)~(\S.*?)~(|\W.*)$/, 341 | "~~": /^(|.*?\W)~~(\S.*?)~~(|\W.*)$/, 342 | "[]": /^(.*?)\[(.*?)\](.*)$/, 343 | "#": /^(|.*?(?=\n))\n*\s*#([^#].*?)#*\s*\n+([\S\s]*)$/, 344 | "##": /^(|.*?(?=\n))\n*\s*##([^#].*?)#*\s*\n+([\S\s]*)$/, 345 | "###": /^(|.*?(?=\n))\n*\s*###([^#].*?)#*\s*\n+([\S\s]*)$/, 346 | "####": /^(|.*?(?=\n))\n*\s*####([^#].*?)#*\s*\n+([\S\s]*)$/, 347 | "\n": /^(.*?)[^\S\n]*\n()[^\S\n]*([\s\S]*)$/, 348 | "{{}}": /^(.*?)\{\{(.*?)\}\}(.*)$/, 349 | "{}": /^(.*?)\{(.*?)\}(.*)$/, 350 | }; 351 | exports.mdFlavors = [ 352 | { 353 | maybe: /[\*_\{\[\n]/, 354 | tags: { 355 | strong: R["*"], 356 | em: R["_"], 357 | p: R["[]"], 358 | h1: R["#"], 359 | h2: R["##"], 360 | h3: R["###"], 361 | h4: R["####"], 362 | br: R["\n"], 363 | self: R["{{}}"], 364 | inter: R["{}"], 365 | } 366 | }, 367 | { 368 | maybe: /[`\*_~\{\[\n]/, 369 | tags: { 370 | literals: R["`` "], 371 | literal: R["``"], 372 | strong: R["**"], 373 | em: R["*"], 374 | b: R["__"], 375 | i: R["_"], 376 | strike: R["~~"], 377 | u: R["~"], 378 | p: R["[]"], 379 | h1: R["#"], 380 | h2: R["##"], 381 | h3: R["###"], 382 | h4: R["####"], 383 | br: R["\n"], 384 | self: R["{{}}"], 385 | inter: R["{}"], 386 | } 387 | } 388 | ]; 389 | function mdMatch(md, value) { 390 | if (!value.match(md.maybe)) 391 | return null; 392 | var tags = md.tags; 393 | var match = null; 394 | for (var ctag in tags) { 395 | if (!tags.hasOwnProperty(ctag)) 396 | continue; 397 | var rg = tags[ctag]; 398 | var _a = rg instanceof RegExp ? [rg, [1, 2, 3]] : rg, regex = _a[0], groups = _a[1]; 399 | var cmatch = regex.exec(value); 400 | if (cmatch) { 401 | if (match == null || cmatch[groups[0]].length < match.head.length) { 402 | match = { tag: ctag, head: cmatch[groups[0]], body: cmatch[groups[1]], tail: cmatch[groups[2]] }; 403 | } 404 | } 405 | } 406 | return match; 407 | } 408 | exports.mdMatch = mdMatch; 409 | 410 | 411 | /***/ }) 412 | /******/ ]); 413 | }); 414 | //# sourceMappingURL=i18n-react.umd.js.map -------------------------------------------------------------------------------- /dist/i18n-react.umd.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///webpack/bootstrap 28526bce190001f41438","webpack:///./src/i18n-react.ts","webpack:///external \"React\"","webpack:///./src/mdflavors.ts"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD,O;ACVA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AC7DA;AACA;AACA;AACA;AACA;AACA;AACA,4DAA4D,cAAc;AAC1E;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,uCAAuC,SAAS;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,6BAA6B,iCAAiC;AAC9D,6BAA6B,iBAAiB;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qDAAqD,sBAAsB;AAC3E;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mDAAmD,aAAa;AAChE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,0CAA0C,WAAW;AACrD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iFAAiF,qCAAqC,EAAE,kBAAkB,mCAAmC,EAAE;AAC/K;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;;;;;;;AC5OA,+C;;;;;;;ACAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,YAAY,EAAE,OAAO,EAAE;AAChC,OAAO,YAAY,OAAO;AAC1B;AACA;AACA;AACA,sBAAsB;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB,wBAAwB;AACxB;AACA,KAAK;AACL;AACA,wBAAwB;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB,wBAAwB;AACxB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA;AACA;AACA;AACA","file":"i18n-react.umd.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"React\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"React\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"i18n-react\"] = factory(require(\"React\"));\n\telse\n\t\troot[\"i18n-react\"] = factory(root[\"React\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 28526bce190001f41438","\"use strict\";\nvar __rest = (this && this.__rest) || function (s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\n t[p[i]] = s[p[i]];\n return t;\n};\nexports.__esModule = true;\nvar React = require(\"react\");\nvar mdflavors_1 = require(\"./mdflavors\");\nfunction isString(s) {\n return typeof s === 'string' || s instanceof String;\n}\nfunction isObject(o) {\n return typeof o === 'object';\n}\nfunction isFunction(o) {\n return typeof o === 'function';\n}\nfunction get(obj, path) {\n var spath = path.split('.');\n for (var i = 0, len = spath.length; i < len; i++) {\n if (!obj || !isObject(obj))\n return undefined;\n obj = obj[spath[i]];\n }\n return obj;\n}\nfunction first(o) {\n for (var k in o) {\n if (k != '__')\n return o[k];\n }\n}\nfunction flatten(l) {\n var r = [];\n var s = '';\n var flush = function () { return s && (r.push(s), s = ''); };\n for (var _i = 0, l_1 = l; _i < l_1.length; _i++) {\n var i = l_1[_i];\n if (i == null)\n continue;\n if (isString(i)) {\n s += i;\n }\n else {\n flush();\n r.push(i);\n }\n }\n flush();\n return r.length > 1 ? r : (r.length ? r[0] : null);\n}\nvar matcher = /** @class */ (function () {\n function matcher(mdFlavor, inter, self) {\n this.mdFlavor = mdFlavor;\n this.inter = inter;\n this.self = self;\n }\n matcher.prototype.M = function (value) {\n if (!value)\n return null;\n var m = mdflavors_1.mdMatch(this.mdFlavor, value);\n if (!m)\n return value;\n var middle = null;\n switch (m.tag) {\n case \"inter\":\n middle = this.inter && this.inter(m.body);\n break;\n case \"self\":\n middle = this.self && this.self(m.body);\n break;\n case \"literals\":\n case \"literal\":\n middle = m.body;\n break;\n default:\n middle = React.createElement(m.tag, { key: m.tag + m.body }, this.M(m.body));\n break;\n }\n return flatten([this.M(m.head), middle, this.M(m.tail)]);\n };\n return matcher;\n}());\nfunction rangeHit(node, val) {\n for (var t in node) {\n if (!node.hasOwnProperty(t))\n continue;\n var range = t.match(/^(-?\\d+)\\.\\.(-?\\d+)$/);\n if (range && (+range[1] <= val && val <= +range[2])) {\n return node[t];\n }\n }\n}\nfunction resolveContextPath(node, p, path, context) {\n var key = path[p];\n var trans;\n if (key != null && context[key] != null) {\n trans = get(node, context[key].toString());\n if (trans == null && (+context[key]) === context[key]) {\n trans = rangeHit(node, +context[key]);\n }\n }\n if (trans == null)\n trans = node._;\n if (trans == null)\n trans = first(node);\n if (trans != null && !isString(trans)) {\n return resolveContextPath(trans, p + 1, path, context);\n }\n return trans;\n}\nfunction resolveContext(node, context) {\n if (context == null) {\n return resolveContextPath(node, 0, [], null);\n }\n else if (!isObject(context)) {\n return resolveContextPath(node, 0, ['_'], { _: context });\n }\n else {\n var ctx_keys = [];\n if (node.__) {\n ctx_keys = node.__.split('.');\n }\n else {\n for (var k in context) {\n if (!context.hasOwnProperty(k))\n continue;\n ctx_keys.push(k);\n }\n }\n return resolveContextPath(node, 0, ctx_keys, context);\n }\n}\nvar MDText = /** @class */ (function () {\n function MDText(texts, opt) {\n this.texts = texts;\n this.MDFlavor = 0;\n // public access is deprecated\n this.notFound = undefined;\n this.p = this.factory('p');\n this.span = this.factory('span');\n this.li = this.factory('li');\n this.div = this.factory('div');\n this.button = this.factory('button');\n this.a = this.factory('a');\n this.text = this.factory(null);\n this.setOpts(opt);\n }\n MDText.prototype.setTexts = function (texts, opt) {\n this.texts = texts;\n this.setOpts(opt);\n };\n MDText.prototype.setOpts = function (opt) {\n if (!opt)\n return;\n if (opt.notFound !== undefined)\n this.notFound = opt.notFound;\n if (opt.MDFlavor !== undefined)\n this.MDFlavor = opt.MDFlavor;\n };\n MDText.prototype.interpolate = function (exp, vars) {\n var _a = exp.split(','), vn = _a[0], flags = _a[1];\n var v = get(vars, vn);\n if (v == null) {\n return null;\n }\n else if (React.isValidElement(v)) {\n return React.cloneElement(v, { key: 'r' });\n }\n var vs;\n if (flags && flags.match(/l/)) {\n vs = v.toLocaleString();\n }\n else {\n vs = v.toString();\n }\n return vs;\n };\n MDText.prototype.format = function (value, vars) {\n var _this = this;\n if (!value)\n return value;\n return new matcher(mdflavors_1.mdFlavors[this.MDFlavor], function (exp) { return _this.interpolate(exp, vars); }, function (exp) { return _this.translate(exp, vars); }).M(value);\n };\n MDText.prototype.translate = function (key, options) {\n if (!key)\n return key;\n var trans = get(this.texts, key);\n var context = options && options.context;\n if (trans != null && !(isString(trans) || isFunction(trans))) {\n trans = resolveContext(trans, context);\n }\n if (trans == null) {\n trans = (options && options.notFound !== undefined) ? options.notFound :\n this.notFound !== undefined ? this.notFound :\n key;\n }\n if (isFunction(trans)) {\n trans = trans(key, context);\n }\n return this.format(trans, options);\n };\n MDText.prototype.factory = function (tagF) {\n var _this = this;\n // name High Order Function for React Dev tools\n var MDText = function (props) {\n var text = props.text, tag = props.tag, restProps = __rest(props, [\"text\", \"tag\"]);\n var key;\n var options;\n if (text == null || isString(text)) {\n key = text;\n options = props;\n var notFound = restProps.notFound, context = restProps.context, rest2Props = __rest(restProps, [\"notFound\", \"context\"]);\n restProps = rest2Props;\n }\n else {\n key = text.key;\n options = text;\n }\n var aTag = tagF || tag;\n var translation = _this.translate(key, options);\n return aTag ?\n React.createElement(aTag, restProps, translation) :\n translation;\n };\n return MDText;\n };\n return MDText;\n}());\nexports.MDText = MDText;\nvar singleton = new MDText(null);\nexports[\"default\"] = singleton;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/i18n-react.ts\n// module id = 0\n// module chunks = 0","module.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"React\"\n// module id = 1\n// module chunks = 0","\"use strict\";\nexports.__esModule = true;\nvar R = {\n \"`` \": [/^(.*?(?:(?!`).|^))(``+)\\s(.*?)\\s\\2(?!`)(.*)$/, [1, 3, 4]],\n \"``\": [/^(.*?(?:(?!`).|^))(``+)(?!`)(.*?(?!`).)\\2(?!`)(.*)$/, [1, 3, 4]],\n \"*\": /^(|.*?\\W)\\*(\\S.*?)\\*(|\\W.*)$/,\n \"**\": /^(|.*?\\W)\\*\\*(\\S.*?)\\*\\*(|\\W.*)$/,\n \"_\": /^(|.*?\\W)_(\\S.*?)_(|\\W.*)$/,\n \"__\": /^(|.*?\\W)__(\\S.*?)__(|\\W.*)$/,\n \"~\": /^(|.*?\\W)~(\\S.*?)~(|\\W.*)$/,\n \"~~\": /^(|.*?\\W)~~(\\S.*?)~~(|\\W.*)$/,\n \"[]\": /^(.*?)\\[(.*?)\\](.*)$/,\n \"#\": /^(|.*?(?=\\n))\\n*\\s*#([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"##\": /^(|.*?(?=\\n))\\n*\\s*##([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"###\": /^(|.*?(?=\\n))\\n*\\s*###([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"####\": /^(|.*?(?=\\n))\\n*\\s*####([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"\\n\": /^(.*?)[^\\S\\n]*\\n()[^\\S\\n]*([\\s\\S]*)$/,\n \"{{}}\": /^(.*?)\\{\\{(.*?)\\}\\}(.*)$/,\n \"{}\": /^(.*?)\\{(.*?)\\}(.*)$/,\n};\nexports.mdFlavors = [\n {\n maybe: /[\\*_\\{\\[\\n]/,\n tags: {\n strong: R[\"*\"],\n em: R[\"_\"],\n p: R[\"[]\"],\n h1: R[\"#\"],\n h2: R[\"##\"],\n h3: R[\"###\"],\n h4: R[\"####\"],\n br: R[\"\\n\"],\n self: R[\"{{}}\"],\n inter: R[\"{}\"],\n }\n },\n {\n maybe: /[`\\*_~\\{\\[\\n]/,\n tags: {\n literals: R[\"`` \"],\n literal: R[\"``\"],\n strong: R[\"**\"],\n em: R[\"*\"],\n b: R[\"__\"],\n i: R[\"_\"],\n strike: R[\"~~\"],\n u: R[\"~\"],\n p: R[\"[]\"],\n h1: R[\"#\"],\n h2: R[\"##\"],\n h3: R[\"###\"],\n h4: R[\"####\"],\n br: R[\"\\n\"],\n self: R[\"{{}}\"],\n inter: R[\"{}\"],\n }\n }\n];\nfunction mdMatch(md, value) {\n if (!value.match(md.maybe))\n return null;\n var tags = md.tags;\n var match = null;\n for (var ctag in tags) {\n if (!tags.hasOwnProperty(ctag))\n continue;\n var rg = tags[ctag];\n var _a = rg instanceof RegExp ? [rg, [1, 2, 3]] : rg, regex = _a[0], groups = _a[1];\n var cmatch = regex.exec(value);\n if (cmatch) {\n if (match == null || cmatch[groups[0]].length < match.head.length) {\n match = { tag: ctag, head: cmatch[groups[0]], body: cmatch[groups[1]], tail: cmatch[groups[2]] };\n }\n }\n }\n return match;\n}\nexports.mdMatch = mdMatch;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/mdflavors.ts\n// module id = 2\n// module chunks = 0"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/i18n-react.umd.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///i18n-react.umd.min.js","webpack:///webpack/bootstrap 38508bf759147b08282a","webpack:///./src/i18n-react.ts","webpack:///external \"React\"","webpack:///./src/mdflavors.ts"],"names":["root","factory","exports","module","require","define","amd","this","__WEBPACK_EXTERNAL_MODULE_1__","modules","__webpack_require__","moduleId","installedModules","i","l","call","m","c","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","isString","String","isObject","isFunction","obj","path","spath","split","len","length","first","k","flatten","r","flush","push","_i","l_1","rangeHit","node","val","t","range","match","resolveContextPath","context","trans","key","toString","_","resolveContext","ctx_keys","__","__rest","e","indexOf","getOwnPropertySymbols","React","mdflavors_1","matcher","mdFlavor","inter","self","M","value","mdMatch","middle","tag","body","createElement","head","tail","MDText","texts","opt","MDFlavor","notFound","undefined","span","li","div","button","a","text","setOpts","setTexts","interpolate","exp","vars","_a","vn","flags","v","isValidElement","cloneElement","toLocaleString","format","_this","mdFlavors","translate","options","tagF","props","restProps","aTag","translation","singleton","md","maybe","tags","ctag","rg","RegExp","regex","groups","cmatch","exec","R","`` ","``","*","**","~","~~","[]","#","##","###","####","\n","{{}}","{}","strong","em","h1","h2","h3","h4","br","literals","literal","b","strike","u"],"mappings":"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","file":"i18n-react.umd.min.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"React\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"React\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"i18n-react\"] = factory(require(\"React\"));\n\telse\n\t\troot[\"i18n-react\"] = factory(root[\"React\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory(require(\"React\"));\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([\"React\"], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"i18n-react\"] = factory(require(\"React\"));\n\telse\n\t\troot[\"i18n-react\"] = factory(root[\"React\"]);\n})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 0);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\nvar __rest = (this && this.__rest) || function (s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\n t[p[i]] = s[p[i]];\n return t;\n};\nexports.__esModule = true;\nvar React = __webpack_require__(1);\nvar mdflavors_1 = __webpack_require__(2);\nfunction isString(s) {\n return typeof s === 'string' || s instanceof String;\n}\nfunction isObject(o) {\n return typeof o === 'object';\n}\nfunction isFunction(o) {\n return typeof o === 'function';\n}\nfunction get(obj, path) {\n var spath = path.split('.');\n for (var i = 0, len = spath.length; i < len; i++) {\n if (!obj || !isObject(obj))\n return undefined;\n obj = obj[spath[i]];\n }\n return obj;\n}\nfunction first(o) {\n for (var k in o) {\n if (k != '__')\n return o[k];\n }\n}\nfunction flatten(l) {\n var r = [];\n var s = '';\n var flush = function () { return s && (r.push(s), s = ''); };\n for (var _i = 0, l_1 = l; _i < l_1.length; _i++) {\n var i = l_1[_i];\n if (i == null)\n continue;\n if (isString(i)) {\n s += i;\n }\n else {\n flush();\n r.push(i);\n }\n }\n flush();\n return r.length > 1 ? r : (r.length ? r[0] : null);\n}\nvar matcher = /** @class */ (function () {\n function matcher(mdFlavor, inter, self) {\n this.mdFlavor = mdFlavor;\n this.inter = inter;\n this.self = self;\n }\n matcher.prototype.M = function (value) {\n if (!value)\n return null;\n var m = mdflavors_1.mdMatch(this.mdFlavor, value);\n if (!m)\n return value;\n var middle = null;\n switch (m.tag) {\n case \"inter\":\n middle = this.inter && this.inter(m.body);\n break;\n case \"self\":\n middle = this.self && this.self(m.body);\n break;\n case \"literals\":\n case \"literal\":\n middle = m.body;\n break;\n default:\n middle = React.createElement(m.tag, { key: m.tag + m.body }, this.M(m.body));\n break;\n }\n return flatten([this.M(m.head), middle, this.M(m.tail)]);\n };\n return matcher;\n}());\nfunction rangeHit(node, val) {\n for (var t in node) {\n if (!node.hasOwnProperty(t))\n continue;\n var range = t.match(/^(-?\\d+)\\.\\.(-?\\d+)$/);\n if (range && (+range[1] <= val && val <= +range[2])) {\n return node[t];\n }\n }\n}\nfunction resolveContextPath(node, p, path, context) {\n var key = path[p];\n var trans;\n if (key != null && context[key] != null) {\n trans = get(node, context[key].toString());\n if (trans == null && (+context[key]) === context[key]) {\n trans = rangeHit(node, +context[key]);\n }\n }\n if (trans == null)\n trans = node._;\n if (trans == null)\n trans = first(node);\n if (trans != null && !isString(trans)) {\n return resolveContextPath(trans, p + 1, path, context);\n }\n return trans;\n}\nfunction resolveContext(node, context) {\n if (context == null) {\n return resolveContextPath(node, 0, [], null);\n }\n else if (!isObject(context)) {\n return resolveContextPath(node, 0, ['_'], { _: context });\n }\n else {\n var ctx_keys = [];\n if (node.__) {\n ctx_keys = node.__.split('.');\n }\n else {\n for (var k in context) {\n if (!context.hasOwnProperty(k))\n continue;\n ctx_keys.push(k);\n }\n }\n return resolveContextPath(node, 0, ctx_keys, context);\n }\n}\nvar MDText = /** @class */ (function () {\n function MDText(texts, opt) {\n this.texts = texts;\n this.MDFlavor = 0;\n // public access is deprecated\n this.notFound = undefined;\n this.p = this.factory('p');\n this.span = this.factory('span');\n this.li = this.factory('li');\n this.div = this.factory('div');\n this.button = this.factory('button');\n this.a = this.factory('a');\n this.text = this.factory(null);\n this.setOpts(opt);\n }\n MDText.prototype.setTexts = function (texts, opt) {\n this.texts = texts;\n this.setOpts(opt);\n };\n MDText.prototype.setOpts = function (opt) {\n if (!opt)\n return;\n if (opt.notFound !== undefined)\n this.notFound = opt.notFound;\n if (opt.MDFlavor !== undefined)\n this.MDFlavor = opt.MDFlavor;\n };\n MDText.prototype.interpolate = function (exp, vars) {\n var _a = exp.split(','), vn = _a[0], flags = _a[1];\n var v = get(vars, vn);\n if (v == null) {\n return null;\n }\n else if (React.isValidElement(v)) {\n return React.cloneElement(v, { key: 'r' });\n }\n var vs;\n if (flags && flags.match(/l/)) {\n vs = v.toLocaleString();\n }\n else {\n vs = v.toString();\n }\n return vs;\n };\n MDText.prototype.format = function (value, vars) {\n var _this = this;\n if (!value)\n return value;\n return new matcher(mdflavors_1.mdFlavors[this.MDFlavor], function (exp) { return _this.interpolate(exp, vars); }, function (exp) { return _this.translate(exp, vars); }).M(value);\n };\n MDText.prototype.translate = function (key, options) {\n if (!key)\n return key;\n var trans = get(this.texts, key);\n var context = options && options.context;\n if (trans != null && !(isString(trans) || isFunction(trans))) {\n trans = resolveContext(trans, context);\n }\n if (trans == null) {\n trans = (options && options.notFound !== undefined) ? options.notFound :\n this.notFound !== undefined ? this.notFound :\n key;\n }\n if (isFunction(trans)) {\n trans = trans(key, context);\n }\n return this.format(trans, options);\n };\n MDText.prototype.factory = function (tagF) {\n var _this = this;\n // name High Order Function for React Dev tools\n var MDText = function (props) {\n var text = props.text, tag = props.tag, restProps = __rest(props, [\"text\", \"tag\"]);\n var key;\n var options;\n if (text == null || isString(text)) {\n key = text;\n options = props;\n var notFound = restProps.notFound, context = restProps.context, rest2Props = __rest(restProps, [\"notFound\", \"context\"]);\n restProps = rest2Props;\n }\n else {\n key = text.key;\n options = text;\n }\n var aTag = tagF || tag;\n var translation = _this.translate(key, options);\n return aTag ?\n React.createElement(aTag, restProps, translation) :\n translation;\n };\n return MDText;\n };\n return MDText;\n}());\nexports.MDText = MDText;\nvar singleton = new MDText(null);\nexports[\"default\"] = singleton;\n\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports) {\n\nmodule.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\nexports.__esModule = true;\nvar R = {\n \"`` \": [/^(.*?(?:(?!`).|^))(``+)\\s(.*?)\\s\\2(?!`)(.*)$/, [1, 3, 4]],\n \"``\": [/^(.*?(?:(?!`).|^))(``+)(?!`)(.*?(?!`).)\\2(?!`)(.*)$/, [1, 3, 4]],\n \"*\": /^(|.*?\\W)\\*(\\S.*?)\\*(|\\W.*)$/,\n \"**\": /^(|.*?\\W)\\*\\*(\\S.*?)\\*\\*(|\\W.*)$/,\n \"_\": /^(|.*?\\W)_(\\S.*?)_(|\\W.*)$/,\n \"__\": /^(|.*?\\W)__(\\S.*?)__(|\\W.*)$/,\n \"~\": /^(|.*?\\W)~(\\S.*?)~(|\\W.*)$/,\n \"~~\": /^(|.*?\\W)~~(\\S.*?)~~(|\\W.*)$/,\n \"[]\": /^(.*?)\\[(.*?)\\](.*)$/,\n \"#\": /^(|.*?(?=\\n))\\n*\\s*#([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"##\": /^(|.*?(?=\\n))\\n*\\s*##([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"###\": /^(|.*?(?=\\n))\\n*\\s*###([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"####\": /^(|.*?(?=\\n))\\n*\\s*####([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"\\n\": /^(.*?)[^\\S\\n]*\\n()[^\\S\\n]*([\\s\\S]*)$/,\n \"{{}}\": /^(.*?)\\{\\{(.*?)\\}\\}(.*)$/,\n \"{}\": /^(.*?)\\{(.*?)\\}(.*)$/,\n};\nexports.mdFlavors = [\n {\n maybe: /[\\*_\\{\\[\\n]/,\n tags: {\n strong: R[\"*\"],\n em: R[\"_\"],\n p: R[\"[]\"],\n h1: R[\"#\"],\n h2: R[\"##\"],\n h3: R[\"###\"],\n h4: R[\"####\"],\n br: R[\"\\n\"],\n self: R[\"{{}}\"],\n inter: R[\"{}\"],\n }\n },\n {\n maybe: /[`\\*_~\\{\\[\\n]/,\n tags: {\n literals: R[\"`` \"],\n literal: R[\"``\"],\n strong: R[\"**\"],\n em: R[\"*\"],\n b: R[\"__\"],\n i: R[\"_\"],\n strike: R[\"~~\"],\n u: R[\"~\"],\n p: R[\"[]\"],\n h1: R[\"#\"],\n h2: R[\"##\"],\n h3: R[\"###\"],\n h4: R[\"####\"],\n br: R[\"\\n\"],\n self: R[\"{{}}\"],\n inter: R[\"{}\"],\n }\n }\n];\nfunction mdMatch(md, value) {\n if (!value.match(md.maybe))\n return null;\n var tags = md.tags;\n var match = null;\n for (var ctag in tags) {\n if (!tags.hasOwnProperty(ctag))\n continue;\n var rg = tags[ctag];\n var _a = rg instanceof RegExp ? [rg, [1, 2, 3]] : rg, regex = _a[0], groups = _a[1];\n var cmatch = regex.exec(value);\n if (cmatch) {\n if (match == null || cmatch[groups[0]].length < match.head.length) {\n match = { tag: ctag, head: cmatch[groups[0]], body: cmatch[groups[1]], tail: cmatch[groups[2]] };\n }\n }\n }\n return match;\n}\nexports.mdMatch = mdMatch;\n\n\n/***/ })\n/******/ ]);\n});\n\n\n// WEBPACK FOOTER //\n// i18n-react.umd.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 38508bf759147b08282a","\"use strict\";\nvar __rest = (this && this.__rest) || function (s, e) {\n var t = {};\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\n t[p] = s[p];\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)\n t[p[i]] = s[p[i]];\n return t;\n};\nexports.__esModule = true;\nvar React = require(\"react\");\nvar mdflavors_1 = require(\"./mdflavors\");\nfunction isString(s) {\n return typeof s === 'string' || s instanceof String;\n}\nfunction isObject(o) {\n return typeof o === 'object';\n}\nfunction isFunction(o) {\n return typeof o === 'function';\n}\nfunction get(obj, path) {\n var spath = path.split('.');\n for (var i = 0, len = spath.length; i < len; i++) {\n if (!obj || !isObject(obj))\n return undefined;\n obj = obj[spath[i]];\n }\n return obj;\n}\nfunction first(o) {\n for (var k in o) {\n if (k != '__')\n return o[k];\n }\n}\nfunction flatten(l) {\n var r = [];\n var s = '';\n var flush = function () { return s && (r.push(s), s = ''); };\n for (var _i = 0, l_1 = l; _i < l_1.length; _i++) {\n var i = l_1[_i];\n if (i == null)\n continue;\n if (isString(i)) {\n s += i;\n }\n else {\n flush();\n r.push(i);\n }\n }\n flush();\n return r.length > 1 ? r : (r.length ? r[0] : null);\n}\nvar matcher = /** @class */ (function () {\n function matcher(mdFlavor, inter, self) {\n this.mdFlavor = mdFlavor;\n this.inter = inter;\n this.self = self;\n }\n matcher.prototype.M = function (value) {\n if (!value)\n return null;\n var m = mdflavors_1.mdMatch(this.mdFlavor, value);\n if (!m)\n return value;\n var middle = null;\n switch (m.tag) {\n case \"inter\":\n middle = this.inter && this.inter(m.body);\n break;\n case \"self\":\n middle = this.self && this.self(m.body);\n break;\n case \"literals\":\n case \"literal\":\n middle = m.body;\n break;\n default:\n middle = React.createElement(m.tag, { key: m.tag + m.body }, this.M(m.body));\n break;\n }\n return flatten([this.M(m.head), middle, this.M(m.tail)]);\n };\n return matcher;\n}());\nfunction rangeHit(node, val) {\n for (var t in node) {\n if (!node.hasOwnProperty(t))\n continue;\n var range = t.match(/^(-?\\d+)\\.\\.(-?\\d+)$/);\n if (range && (+range[1] <= val && val <= +range[2])) {\n return node[t];\n }\n }\n}\nfunction resolveContextPath(node, p, path, context) {\n var key = path[p];\n var trans;\n if (key != null && context[key] != null) {\n trans = get(node, context[key].toString());\n if (trans == null && (+context[key]) === context[key]) {\n trans = rangeHit(node, +context[key]);\n }\n }\n if (trans == null)\n trans = node._;\n if (trans == null)\n trans = first(node);\n if (trans != null && !isString(trans)) {\n return resolveContextPath(trans, p + 1, path, context);\n }\n return trans;\n}\nfunction resolveContext(node, context) {\n if (context == null) {\n return resolveContextPath(node, 0, [], null);\n }\n else if (!isObject(context)) {\n return resolveContextPath(node, 0, ['_'], { _: context });\n }\n else {\n var ctx_keys = [];\n if (node.__) {\n ctx_keys = node.__.split('.');\n }\n else {\n for (var k in context) {\n if (!context.hasOwnProperty(k))\n continue;\n ctx_keys.push(k);\n }\n }\n return resolveContextPath(node, 0, ctx_keys, context);\n }\n}\nvar MDText = /** @class */ (function () {\n function MDText(texts, opt) {\n this.texts = texts;\n this.MDFlavor = 0;\n // public access is deprecated\n this.notFound = undefined;\n this.p = this.factory('p');\n this.span = this.factory('span');\n this.li = this.factory('li');\n this.div = this.factory('div');\n this.button = this.factory('button');\n this.a = this.factory('a');\n this.text = this.factory(null);\n this.setOpts(opt);\n }\n MDText.prototype.setTexts = function (texts, opt) {\n this.texts = texts;\n this.setOpts(opt);\n };\n MDText.prototype.setOpts = function (opt) {\n if (!opt)\n return;\n if (opt.notFound !== undefined)\n this.notFound = opt.notFound;\n if (opt.MDFlavor !== undefined)\n this.MDFlavor = opt.MDFlavor;\n };\n MDText.prototype.interpolate = function (exp, vars) {\n var _a = exp.split(','), vn = _a[0], flags = _a[1];\n var v = get(vars, vn);\n if (v == null) {\n return null;\n }\n else if (React.isValidElement(v)) {\n return React.cloneElement(v, { key: 'r' });\n }\n var vs;\n if (flags && flags.match(/l/)) {\n vs = v.toLocaleString();\n }\n else {\n vs = v.toString();\n }\n return vs;\n };\n MDText.prototype.format = function (value, vars) {\n var _this = this;\n if (!value)\n return value;\n return new matcher(mdflavors_1.mdFlavors[this.MDFlavor], function (exp) { return _this.interpolate(exp, vars); }, function (exp) { return _this.translate(exp, vars); }).M(value);\n };\n MDText.prototype.translate = function (key, options) {\n if (!key)\n return key;\n var trans = get(this.texts, key);\n var context = options && options.context;\n if (trans != null && !(isString(trans) || isFunction(trans))) {\n trans = resolveContext(trans, context);\n }\n if (trans == null) {\n trans = (options && options.notFound !== undefined) ? options.notFound :\n this.notFound !== undefined ? this.notFound :\n key;\n }\n if (isFunction(trans)) {\n trans = trans(key, context);\n }\n return this.format(trans, options);\n };\n MDText.prototype.factory = function (tagF) {\n var _this = this;\n // name High Order Function for React Dev tools\n var MDText = function (props) {\n var text = props.text, tag = props.tag, restProps = __rest(props, [\"text\", \"tag\"]);\n var key;\n var options;\n if (text == null || isString(text)) {\n key = text;\n options = props;\n var notFound = restProps.notFound, context = restProps.context, rest2Props = __rest(restProps, [\"notFound\", \"context\"]);\n restProps = rest2Props;\n }\n else {\n key = text.key;\n options = text;\n }\n var aTag = tagF || tag;\n var translation = _this.translate(key, options);\n return aTag ?\n React.createElement(aTag, restProps, translation) :\n translation;\n };\n return MDText;\n };\n return MDText;\n}());\nexports.MDText = MDText;\nvar singleton = new MDText(null);\nexports[\"default\"] = singleton;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/i18n-react.ts\n// module id = 0\n// module chunks = 0","module.exports = __WEBPACK_EXTERNAL_MODULE_1__;\n\n\n//////////////////\n// WEBPACK FOOTER\n// external \"React\"\n// module id = 1\n// module chunks = 0","\"use strict\";\nexports.__esModule = true;\nvar R = {\n \"`` \": [/^(.*?(?:(?!`).|^))(``+)\\s(.*?)\\s\\2(?!`)(.*)$/, [1, 3, 4]],\n \"``\": [/^(.*?(?:(?!`).|^))(``+)(?!`)(.*?(?!`).)\\2(?!`)(.*)$/, [1, 3, 4]],\n \"*\": /^(|.*?\\W)\\*(\\S.*?)\\*(|\\W.*)$/,\n \"**\": /^(|.*?\\W)\\*\\*(\\S.*?)\\*\\*(|\\W.*)$/,\n \"_\": /^(|.*?\\W)_(\\S.*?)_(|\\W.*)$/,\n \"__\": /^(|.*?\\W)__(\\S.*?)__(|\\W.*)$/,\n \"~\": /^(|.*?\\W)~(\\S.*?)~(|\\W.*)$/,\n \"~~\": /^(|.*?\\W)~~(\\S.*?)~~(|\\W.*)$/,\n \"[]\": /^(.*?)\\[(.*?)\\](.*)$/,\n \"#\": /^(|.*?(?=\\n))\\n*\\s*#([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"##\": /^(|.*?(?=\\n))\\n*\\s*##([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"###\": /^(|.*?(?=\\n))\\n*\\s*###([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"####\": /^(|.*?(?=\\n))\\n*\\s*####([^#].*?)#*\\s*\\n+([\\S\\s]*)$/,\n \"\\n\": /^(.*?)[^\\S\\n]*\\n()[^\\S\\n]*([\\s\\S]*)$/,\n \"{{}}\": /^(.*?)\\{\\{(.*?)\\}\\}(.*)$/,\n \"{}\": /^(.*?)\\{(.*?)\\}(.*)$/,\n};\nexports.mdFlavors = [\n {\n maybe: /[\\*_\\{\\[\\n]/,\n tags: {\n strong: R[\"*\"],\n em: R[\"_\"],\n p: R[\"[]\"],\n h1: R[\"#\"],\n h2: R[\"##\"],\n h3: R[\"###\"],\n h4: R[\"####\"],\n br: R[\"\\n\"],\n self: R[\"{{}}\"],\n inter: R[\"{}\"],\n }\n },\n {\n maybe: /[`\\*_~\\{\\[\\n]/,\n tags: {\n literals: R[\"`` \"],\n literal: R[\"``\"],\n strong: R[\"**\"],\n em: R[\"*\"],\n b: R[\"__\"],\n i: R[\"_\"],\n strike: R[\"~~\"],\n u: R[\"~\"],\n p: R[\"[]\"],\n h1: R[\"#\"],\n h2: R[\"##\"],\n h3: R[\"###\"],\n h4: R[\"####\"],\n br: R[\"\\n\"],\n self: R[\"{{}}\"],\n inter: R[\"{}\"],\n }\n }\n];\nfunction mdMatch(md, value) {\n if (!value.match(md.maybe))\n return null;\n var tags = md.tags;\n var match = null;\n for (var ctag in tags) {\n if (!tags.hasOwnProperty(ctag))\n continue;\n var rg = tags[ctag];\n var _a = rg instanceof RegExp ? [rg, [1, 2, 3]] : rg, regex = _a[0], groups = _a[1];\n var cmatch = regex.exec(value);\n if (cmatch) {\n if (match == null || cmatch[groups[0]].length < match.head.length) {\n match = { tag: ctag, head: cmatch[groups[0]], body: cmatch[groups[1]], tail: cmatch[groups[2]] };\n }\n }\n }\n return match;\n}\nexports.mdMatch = mdMatch;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/mdflavors.ts\n// module id = 2\n// module chunks = 0"],"sourceRoot":""} --------------------------------------------------------------------------------