├── .npmignore ├── .npmrc ├── logo.png ├── renovate.json ├── .babelrc ├── .gitignore ├── examples ├── src │ ├── styles.css │ ├── index.js │ ├── HOCExample.js │ ├── localized-strings-en.json │ ├── Banner.js │ └── App.js ├── package.json ├── README.md └── public │ └── index.html ├── test ├── setupTests.js ├── __snapshots__ │ ├── TextProviderHOC.test.js.snap │ └── TextProvider.test.js.snap ├── FormattedMessage.test.js ├── TextProvider.test.js └── TextProviderHOC.test.js ├── .editorconfig ├── src ├── index.js ├── TextProvider.jsx ├── TextProviderHOC.jsx └── FormattedMessage.jsx ├── prettier.config.js ├── .github ├── CONTRIBUTING.md └── PULL_REQUEST_TEMPLATE.md ├── commitlint.config.js ├── jest.config.json ├── .eslintrc.json ├── .releaserc ├── .circleci └── config.yml ├── LICENSE ├── package.json ├── webpack.config.js ├── README.md └── CHANGELOG.md /.npmignore: -------------------------------------------------------------------------------- 1 | .circleci/ 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org 2 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/intuit/text-provider/HEAD/logo.png -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "config:base" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | reports/ 4 | yarn-error.log 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /examples/src/styles.css: -------------------------------------------------------------------------------- 1 | .App { 2 | font-family: sans-serif; 3 | text-align: center; 4 | } 5 | -------------------------------------------------------------------------------- /test/setupTests.js: -------------------------------------------------------------------------------- 1 | import Enzyme from 'enzyme'; 2 | import Adapter from 'enzyme-adapter-react-16'; 3 | // React 16 Enzyme adapter 4 | Enzyme.configure({ adapter: new Adapter() }); 5 | -------------------------------------------------------------------------------- /test/__snapshots__/TextProviderHOC.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[` rendering should render TextProviderHOC correctly 1`] = ` 4 |
5 | id 6 |
7 | `; 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Tab indentation (no size specified) 2 | [*.yml] 3 | indent_style = space 4 | indent_size = 2 5 | 6 | [*.js] 7 | indent_style = space 8 | indent_size = 2 9 | 10 | [*.md] 11 | indent_style = space 12 | indent_size = 4 13 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import FormattedMessage from './FormattedMessage'; 2 | import TextProvider from './TextProvider'; 3 | import withTextProvider from './TextProviderHOC'; 4 | 5 | export { 6 | FormattedMessage, 7 | TextProvider, 8 | withTextProvider, 9 | }; 10 | -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Prettier will read RC files, you can set your prettier rules here 3 | */ 4 | 5 | module.exports = { 6 | singleQuote: true, 7 | trailingComma: 'all', 8 | arrowParens: 'always', 9 | printWidth: 100, 10 | proseWrap: 'always', 11 | }; 12 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute ? 2 | 3 | 👍🎉 First off, thanks for taking the time to contribute! 🎉👍 4 | 5 | - Fork the repo. Submit a pull request. 6 | - Code coverage has to be 100%. 7 | - No code coverage for presentational components. 8 | - All code should be documented. 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | PR checklist: 2 | 3 | - [ ] Github Issue associated with branch. 4 | - [ ] Code passes eslint analysis. 5 | - [ ] Code passes cross browser testing. 6 | - [ ] Test code coverage is 85% or greater. 7 | - [ ] PR branch is up-to-date with latest master branch. 8 | -------------------------------------------------------------------------------- /examples/src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | 4 | import App from "./App"; 5 | 6 | const rootElement = document.getElementById("root"); 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | rootElement 12 | ); 13 | -------------------------------------------------------------------------------- /examples/src/HOCExample.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { withTextProvider } from "text-provider"; 3 | 4 | class HOCExample extends React.Component { 5 | render() { 6 | return this.props.getTextForKey("hocExample"); 7 | } 8 | } 9 | 10 | export default withTextProvider(HOCExample); 11 | -------------------------------------------------------------------------------- /examples/src/localized-strings-en.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Hello Codesandbox", 3 | "subTitle": "Start editing to see some magic happen!", 4 | "note": "Hello {name}, this string uses variable injection for the name.", 5 | "hocExample": "This string is rendered using the higher-order component" 6 | } 7 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * DISCLAIMER: 3 | * This file helps enforce semantic commits. This is NECESSARY to allow for automated releases 4 | * of a plugin. Removing or disabling it will break the release process, and is not recommended. 5 | */ 6 | 7 | module.exports = { 8 | extends: ['@commitlint/config-conventional'], 9 | }; 10 | -------------------------------------------------------------------------------- /test/FormattedMessage.test.js: -------------------------------------------------------------------------------- 1 | import FormattedMessage from '../src/FormattedMessage'; 2 | 3 | describe(' rendering', () => { 4 | it('should have default value and alt props', () => { 5 | expect(FormattedMessage.defaultProps.values).toBeDefined(); 6 | expect(FormattedMessage.defaultProps.alt).toBeDefined(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /test/__snapshots__/TextProvider.test.js.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[` rendering should render correctly 1`] = ` 4 | 16 | `; 17 | -------------------------------------------------------------------------------- /jest.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "setupFiles": ["/test/setupTests.js"], 3 | "testRegex": "/*.test.js$", 4 | "collectCoverage": true, 5 | "coverageReporters": ["lcov"], 6 | "coverageDirectory": "reports/jest", 7 | "coverageThreshold": { 8 | "global": { 9 | "branches": 0, 10 | "functions": 0, 11 | "lines": 0, 12 | "statements": 0 13 | } 14 | }, 15 | "moduleDirectories": ["node_modules", "src"] 16 | } 17 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "babel-eslint", 4 | "extends": ["eslint:recommended", "plugin:react/recommended", "airbnb"], 5 | "settings": { 6 | "import/extensions": [".js", ".jsx", ".ts", ".tsx"] 7 | }, 8 | "rules": { 9 | "import/extensions": "off", 10 | "import/no-unresolved": "off", 11 | "react/jsx-props-no-spreading": "off", 12 | "max-len": "off", 13 | "object-curly-newline": "off" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/TextProvider.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | export const TextContext = React.createContext({}); 5 | 6 | const TextProvider = (props) => { 7 | const { globalText, children } = props; 8 | return {children}; 9 | }; 10 | 11 | TextProvider.propTypes = { 12 | globalText: PropTypes.objectOf(PropTypes.string), 13 | children: PropTypes.node.isRequired, 14 | }; 15 | 16 | TextProvider.defaultProps = { 17 | globalText: {}, 18 | }; 19 | 20 | export { TextProvider as default }; 21 | -------------------------------------------------------------------------------- /examples/src/Banner.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { FormattedMessage } from "text-provider"; 3 | 4 | /** 5 | * Component to display the banner. 6 | */ 7 | export default class Banner extends React.Component { 8 | 9 | /** 10 | * The FormattedMessage component reads the string 11 | * against the id provided from the TextProvider component 12 | * defined in this components ancestory. The matching string 13 | * is then rendered. 14 | */ 15 | render() { 16 | return ( 17 |
18 |

19 | 20 |

21 |

22 | 23 |

24 |
25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /.releaserc: -------------------------------------------------------------------------------- 1 | { 2 | "branch": "master", 3 | "plugins": [ 4 | "@semantic-release/commit-analyzer", 5 | "@semantic-release/release-notes-generator", 6 | [ 7 | "@semantic-release/changelog", 8 | { 9 | "changelogFile": "CHANGELOG.md", 10 | "changelogTitle": "# Semantic Versioning Changelog" 11 | } 12 | ], 13 | "@semantic-release/npm", 14 | [ 15 | "@semantic-release/git", 16 | { 17 | "assets": [ 18 | "CHANGELOG.md", "package.json" 19 | ], 20 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 21 | } 22 | ], 23 | "@semantic-release/github" 24 | ] 25 | } -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | # trigger build 2 | version: 2 3 | debug: true 4 | jobs: 5 | build: 6 | docker: 7 | - image: circleci/node:12.18.4 8 | steps: 9 | - checkout 10 | - run: yarn install 11 | - run: yarn run build 12 | - run: yarn run lint 13 | - run: yarn run test 14 | - persist_to_workspace: 15 | root: . 16 | paths: 17 | - . 18 | publish: 19 | docker: 20 | - image: circleci/node:12.18.4 21 | steps: 22 | - attach_workspace: 23 | at: . 24 | - run: npx semantic-release 25 | workflows: 26 | version: 2 27 | build: 28 | jobs: 29 | - build 30 | - publish: 31 | requires: 32 | - build 33 | filters: 34 | branches: 35 | only: 36 | - master 37 | -------------------------------------------------------------------------------- /examples/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "text-provider-sample", 3 | "version": "1.0.0", 4 | "description": "Sample project to demo text-provider usage", 5 | "keywords": [ 6 | "react", 7 | "text-provider" 8 | ], 9 | "author": { 10 | "name": "Niti Singhal", 11 | "url": "https://nitisinghal.com", 12 | "github": "nsinghal12" 13 | }, 14 | "main": "src/index.js", 15 | "dependencies": { 16 | "react": "16.13.1", 17 | "react-dom": "16.13.1", 18 | "react-scripts": "3.4.3", 19 | "text-provider": "0.0.37" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test --env=jsdom", 25 | "eject": "react-scripts eject" 26 | }, 27 | "browserslist": [ 28 | ">0.2%", 29 | "not dead", 30 | "not ie <= 11", 31 | "not op_mini all" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # `text-provider` example 2 | 3 | This folder contains a very basic example on how to 4 | use the `text-provider` library in your own React project. 5 | This sample is based on the [Create React App](https://github.com/facebook/create-react-app) sample application. 6 | 7 | ## Running the sample 8 | 9 | To run the sample on your local machine, clone this 10 | repository and then follow the below instructions: 11 | 12 | ```sh 13 | # clone this repo 14 | $ git clone git@github.com:intuit/text-provider.git 15 | 16 | # move to examples folder 17 | $ cd examples 18 | 19 | # install the dependencies 20 | $ npm install 21 | 22 | # Start the sample project 23 | $ npm run start 24 | ``` 25 | 26 | If you wish to use `yarn` instead of `npm` replace the last 27 | 2 commands with the ones below: 28 | 29 | ```sh 30 | # install the dependencies 31 | $ yarn 32 | 33 | # Start the sample project 34 | $ yarn run start 35 | ``` 36 | 37 | Happy Hacking! 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 Intuit 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 14 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 15 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 16 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 17 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 18 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 19 | OR OTHER DEALINGS IN THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /src/TextProviderHOC.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TextContext } from './TextProvider'; 3 | 4 | const withTextProvider = (SomeComponent) => { 5 | /* eslint-disable-line no-unused-vars */ 6 | class TextProviderHOC extends React.Component { 7 | constructor(props) { 8 | super(props); 9 | this.getTextForKey = this.getTextForKey.bind(this); 10 | } 11 | 12 | getTextForKey(id, values = {}) { 13 | const globalText = this.context; 14 | let messageString = Object.prototype.hasOwnProperty.call(globalText, id) 15 | ? globalText[id] 16 | : ''; 17 | /** 18 | * Iterate through all the keys given as the prop and replace with corresponding values. 19 | */ 20 | Object.keys(values).forEach((key) => { 21 | messageString = messageString.replace(`{${key}}`, values[key]); 22 | }); 23 | return messageString; 24 | } 25 | 26 | render() { 27 | return ( 28 | 32 | ); 33 | } 34 | } 35 | 36 | TextProviderHOC.contextType = TextContext; 37 | 38 | return TextProviderHOC; 39 | }; 40 | 41 | export { withTextProvider as default }; 42 | -------------------------------------------------------------------------------- /test/TextProvider.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | import TextProvider from '../src/TextProvider'; 4 | import FormattedMessage from '../src/FormattedMessage'; 5 | 6 | describe(' rendering', () => { 7 | const randomId = 'Random Id'; 8 | const values = { 9 | valueToBeInjected: 'Random Value', 10 | }; 11 | const sampleText = { 12 | 'Random Id': '{valueToBeInjected}', 13 | }; 14 | 15 | it('should have default globalText prop', () => { 16 | expect(TextProvider.defaultProps.globalText).toBeDefined(); 17 | }); 18 | 19 | it('should render correctly', () => { 20 | let wrapper = renderer.create( 21 | } 24 | />, 25 | ); 26 | expect(wrapper.toJSON()).toMatchSnapshot(); 27 | }); 28 | 29 | it('should replace the id with value in the context message', () => { 30 | let wrapper = renderer.create( 31 | } 34 | />, 35 | ); 36 | expect(wrapper.toJSON().props.style.fontSize).toBe('inherit'); 37 | expect(wrapper.toJSON().props.dangerouslySetInnerHTML.__html).toBe(values['valueToBeInjected']); 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /examples/src/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { TextProvider, FormattedMessage } from "text-provider"; 3 | import Banner from "./Banner"; 4 | import HOCExample from "./HOCExample"; 5 | 6 | import "./styles.css"; 7 | 8 | /** 9 | * The following imports a JSON file containing the localized 10 | * strings against each key. The key is used inside 11 | * the React code to display the string, 12 | */ 13 | import localizedStrings from "./localized-strings-en.json"; 14 | 15 | const stringVariables = { 16 | name: "Niti Singhal" 17 | }; 18 | 19 | /** 20 | * Default React component being loaded via index.js 21 | */ 22 | export default class App extends React.Component { 23 | /** 24 | * The TextProvider is the provider component to enable 25 | * the child heirarchy to read string defined inside the 26 | * globalText object. 27 | */ 28 | render() { 29 | return ( 30 | 31 | 32 | {/* The banner component uses the TextProvider component 33 | in ancestory to find all loaded strings. */} 34 | 35 |

36 | 37 |

38 | 39 |

40 | 41 |

42 |
43 |
44 | ); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/FormattedMessage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { TextContext } from './TextProvider'; 4 | 5 | const FormattedMessage = (props) => ( 6 | 7 | {(context) => { 8 | /** 9 | * We get the text to be injected from react's context. Here its TextContext 10 | */ 11 | const { id, values, alt, ...restProps } = props; 12 | /* eslint-disable-next-line react/destructuring-assignment */ 13 | let messageString = Object.prototype.hasOwnProperty.call(context, id) ? context[id] : alt; 14 | /** 15 | * Iterate through all the keys given as the prop and replace with corresponding values. 16 | */ 17 | Object.keys(values).forEach((key) => { 18 | messageString = messageString.replace(`{${key}}`, values[key]); 19 | }); 20 | /* Do not frown over this, many a times you need to do this, like : 21 | * https://github.com/yahoo/react-intl/blob/master/src/components/html-message.js#L86 22 | */ 23 | const style = { 24 | fontSize: 'inherit', 25 | }; 26 | /* eslint-disable react/no-danger */ 27 | return ( 28 | 29 | ); 30 | }} 31 | 32 | ); 33 | 34 | FormattedMessage.propTypes = { 35 | id: PropTypes.string.isRequired, 36 | values: PropTypes.objectOf(PropTypes.string), 37 | alt: PropTypes.string, 38 | }; 39 | 40 | FormattedMessage.defaultProps = { 41 | values: {}, 42 | alt: '', 43 | }; 44 | 45 | export { FormattedMessage as default }; 46 | -------------------------------------------------------------------------------- /examples/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 23 | Text Provider Sample 24 | 25 | 26 | 27 | 30 |
31 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /test/TextProviderHOC.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import renderer from 'react-test-renderer'; 3 | import TextProvider from '../src/TextProvider'; 4 | import withTextProvider from '../src/TextProviderHOC'; 5 | 6 | describe(' rendering', () => { 7 | class SomeComponent extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | } 11 | 12 | render() { 13 | return
{this.props.id ? this.props.id : 'id'}
; 14 | } 15 | } 16 | 17 | it('should render TextProviderHOC correctly', () => { 18 | const MockWithHOC = withTextProvider(SomeComponent); 19 | 20 | const wrapper = renderer.create(); 21 | expect(wrapper.toJSON()).toMatchSnapshot(); 22 | }); 23 | 24 | it('should add getTextForKey as prop for component', () => { 25 | const MockWithHOC = withTextProvider(SomeComponent); 26 | 27 | const wrapper = renderer.create().root; 28 | expect(wrapper.findByType(SomeComponent).props.getTextForKey).toBeDefined(); 29 | 30 | // TextProviderHOC uses {} as default context 31 | expect(wrapper.findByType(SomeComponent).props.getTextForKey('test')).toEqual(''); 32 | }); 33 | 34 | it('should render the component provided along with props', () => { 35 | const MockWithHOC = withTextProvider(SomeComponent); 36 | const wrapper = renderer.create().root; 37 | expect(wrapper.findByType(SomeComponent).props.id).toEqual('id'); 38 | }); 39 | 40 | it('test getTextForKey with context', () => { 41 | let context = { id: 'test id' }; 42 | const MockWithHOC = withTextProvider(SomeComponent); 43 | let wrapper = renderer.create(} />) 44 | .root; 45 | expect(wrapper.findByType(SomeComponent).props.getTextForKey('id')).toEqual(context.id); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "text-provider", 3 | "version": "1.1.3", 4 | "description": "A component which provides all the string constants using provider pattern.", 5 | "license": "MIT", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/intuit/text-provider" 9 | }, 10 | "main": "build/index.js", 11 | "scripts": { 12 | "lint:fix": "eslint --fix src/*.jsx src/*.js", 13 | "lint": "eslint src/*.jsx src/*.js", 14 | "build": "webpack --config webpack.config.js", 15 | "start": "webpack-dev-server --mode development", 16 | "test": "jest --coverage" 17 | }, 18 | "husky": { 19 | "hooks": { 20 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", 21 | "pre-commit": "npx eslint --ext .jsx --ext .js src/** --fix --no-error-on-unmatched-pattern && pretty-quick --staged", 22 | "pre-push": "npx eslint --ext .jsx --ext .js src/** && npm run build" 23 | } 24 | }, 25 | "author": { 26 | "name": "Rohith R", 27 | "email": "rohithr31@gmail.com" 28 | }, 29 | "devDependencies": { 30 | "@babel/core": "7.11.6", 31 | "@babel/preset-env": "7.11.5", 32 | "@babel/preset-react": "7.10.4", 33 | "@commitlint/cli": "8.3.5", 34 | "@commitlint/config-conventional": "8.3.4", 35 | "@semantic-release/changelog": "^5.0.1", 36 | "@semantic-release/commit-analyzer": "^8.0.1", 37 | "@semantic-release/git": "^9.0.0", 38 | "@semantic-release/github": "^7.1.1", 39 | "@semantic-release/npm": "^7.0.6", 40 | "@semantic-release/release-notes-generator": "^9.0.1", 41 | "babel-eslint": "10.1.0", 42 | "babel-loader": "8.1.0", 43 | "css-loader": "3.6.0", 44 | "enzyme": "^3.11.0", 45 | "enzyme-adapter-react-16": "^1.15.5", 46 | "eslint": "7.5.0", 47 | "eslint-config-airbnb": "18.2.0", 48 | "eslint-loader": "4.0.2", 49 | "eslint-plugin-import": "2.22.1", 50 | "eslint-plugin-jsx-a11y": "6.3.1", 51 | "eslint-plugin-react": "7.20.3", 52 | "file-loader": "6.1.0", 53 | "html-loader": "1.1.0", 54 | "husky": "4.2.5", 55 | "jest": "^26.4.2", 56 | "prettier": "2.1.2", 57 | "pretty-quick": "2.0.1", 58 | "semantic-release": "^17.1.2", 59 | "react-test-renderer": "17.0.2", 60 | "webpack": "4.44.1", 61 | "webpack-cli": "3.3.12", 62 | "webpack-dev-server": "3.11.0" 63 | }, 64 | "dependencies": { 65 | "prop-types": "^15.7.2", 66 | "react": "^16.13.1", 67 | "react-dom": "^16.13.1" 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * This contains the configuration for our module. 3 | * We use this configuration to figure out our start points, logical structure and other optimizations possible. 4 | * These may (in the future) include : 5 | * - Splitting tthe code based on entry points 6 | * - Adding multiple outputs using the same config 7 | */ 8 | const path = require('path'); 9 | 10 | module.exports = { 11 | mode: 'production', 12 | entry: ['src/index.js'], 13 | output: { 14 | path: path.resolve(__dirname, 'build'), 15 | filename: 'index.js', 16 | libraryTarget: 'commonjs2' 17 | }, 18 | resolve: { 19 | extensions: ['.js', '.jsx'] 20 | }, 21 | externals: { 22 | react: { 23 | root: 'React', 24 | commonjs2: 'react', 25 | commonjs: 'react', 26 | amd: 'react' 27 | }, 28 | 'react-dom': { 29 | root: 'ReactDOM', 30 | commonjs2: 'react-dom', 31 | commonjs: 'react-dom', 32 | amd: 'react-dom' 33 | } 34 | }, 35 | module : { 36 | rules: [ 37 | { 38 | test: /\.txt$/, 39 | use: 'raw-loader' 40 | }, 41 | { 42 | enforce: 'pre', 43 | test: /\.jsx?$/, 44 | exclude: /node_modules/, 45 | loader: 'eslint-loader', 46 | options: { 47 | emitError: true, 48 | failOnError: true, 49 | emitWarning: true, 50 | failOnWarning: false, 51 | }, 52 | resolve: { 53 | extensions: ['.js', '.jsx'] 54 | } 55 | }, 56 | { 57 | test: /\.jsx?$/, 58 | use: { 59 | loader: 'babel-loader', 60 | query: { 61 | presets: ['@babel/preset-env', '@babel/preset-react'] 62 | } 63 | }, 64 | resolve: { 65 | extensions: ['.js', '.jsx'] 66 | }, 67 | exclude: /node_modules/ 68 | }, 69 | { 70 | test: /\.(html)$/, 71 | use: { 72 | loader: 'html-loader', 73 | options: { 74 | attrs: [':data-src'] 75 | } 76 | } 77 | }, 78 | { 79 | test: /\.(woff|woff2|eot|ttf)$/, 80 | loader: 'url-loader?limit=100000' 81 | }, 82 | { 83 | test: /\.(jpe?g|png|gif|svg)$/i, 84 | loader: 'file-loader' 85 | } 86 | ] 87 | }, 88 | resolve: { 89 | modules: [ 90 | path.resolve(__dirname, './'), 91 | './node_modules' 92 | ] 93 | }, 94 | devServer: { 95 | port: 3001 96 | }, 97 | }; 98 | 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 6 |

text-provider

7 |

8 | A component which provides all the string constants using provider pattern 9 |

10 |
11 | 12 | 38 | 39 | Text provider is a library to place all the string constants of an application in a single place and use them inside the components in a memory friendly way. 40 | 41 | It provides two components: 42 | 43 | 1. [TextProvider](src/TextProvider.jsx) 44 | 2. [FormattedMessage](src/FormattedMessage.jsx) 45 | 46 | ## Install 47 | 48 | ```bash 49 | npm i text-provider 50 | ``` 51 | 52 | ## Usage 53 | 54 | 1. Import the string constants required for the particular presentational component: 55 | 56 | ```javascript 57 | const sampleText = require("src/nls/sample-text.json"); 58 | ``` 59 | 60 | 2. Use the [TextProvider](src/TextProvider.jsx) to make it available for all the components: 61 | 62 | ```jsx 63 | 64 | 65 | 66 | ``` 67 | 68 | 3. Use it inside the presentational component: 69 | 70 | ```jsx 71 | 72 | ``` 73 | 74 | ```jsx 75 | const randomId = "Random Id"; 76 | const values = { 77 | "valueToBeInjected": "Random Value" 78 | }; 79 | 80 | 81 | ``` 82 | 83 | Works like a format string also. Example JSON: 84 | 85 | ```json 86 | { 87 | "Random Id": "Random Text Returns {valueToBeInjected} for each text)" 88 | } 89 | ``` 90 | 91 | Then ``${valueToBeInjected}`` gets replaced with the value specified in `values`. 92 | 93 | Make sure that a string by the same `id` exists in the JSON file. 94 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Semantic Versioning Changelog 2 | 3 | ## [1.1.3](https://github.com/intuit/text-provider/compare/v1.1.2...v1.1.3) (2021-01-29) 4 | 5 | 6 | ### Bug Fixes 7 | 8 | * propagating props which come from parent component ([0811186](https://github.com/intuit/text-provider/commit/08111864e7b9a817c5cc5e0a7704129bacdd3235)) 9 | * propagating props which come from parent component ([b571605](https://github.com/intuit/text-provider/commit/b5716059802147d0d31bc06bcd7b32c5a1474338)) 10 | * propagating props which come from parent component ([138e059](https://github.com/intuit/text-provider/commit/138e05942e90decfc5250e14d6b2998f71e86ce1)) 11 | 12 | ## [1.1.2](https://github.com/intuit/text-provider/compare/v1.1.1...v1.1.2) (2021-01-28) 13 | 14 | 15 | ### Bug Fixes 16 | 17 | * adding the tests in CI ([74f1d24](https://github.com/intuit/text-provider/commit/74f1d245dc0ca2eca70dfb740832d3d42081e7a4)) 18 | * adding the tests in CI ([17fde0c](https://github.com/intuit/text-provider/commit/17fde0ce6ed438a0dd3b75c927368d0dd12c32df)) 19 | 20 | ## [1.1.1](https://github.com/intuit/text-provider/compare/v1.1.0...v1.1.1) (2021-01-28) 21 | 22 | 23 | ### Bug Fixes 24 | 25 | * adding lint fixes ([d8ef3f1](https://github.com/intuit/text-provider/commit/d8ef3f1e159a5104f424206213e2ce3172b96bfa)) 26 | * adding the values to the HOC ([433e08f](https://github.com/intuit/text-provider/commit/433e08f5640419cae61f8ca12d07ba53f46658de)) 27 | * adding the values to the HOC ([19aac7b](https://github.com/intuit/text-provider/commit/19aac7bc5c7157afd78b35cd93139500ae0e1dde)) 28 | 29 | # [1.1.0](https://github.com/intuit/text-provider/compare/v1.0.0...v1.1.0) (2020-10-31) 30 | 31 | 32 | ### Features 33 | 34 | * updating config to include package.json to be auto-updated with latest version ([6efe56f](https://github.com/intuit/text-provider/commit/6efe56fc884acc4c05854853ffb0248ed55f5f22)) 35 | 36 | # 1.0.0 (2020-10-31) 37 | 38 | 39 | ### Bug Fixes 40 | 41 | * bug in formatted message ([bcc69ae](https://github.com/intuit/text-provider/commit/bcc69aec04f63e692d881ba090f9030ee0d06ad4)) 42 | * bug in formatted message ([57754b8](https://github.com/intuit/text-provider/commit/57754b836f4c1c0c30f905ab36ed351944f65634)) 43 | * bumping package version ([a7a202e](https://github.com/intuit/text-provider/commit/a7a202e641a3fe91eb75b796a6b899650101c277)) 44 | * inheriting the font-size from parent ([b94f145](https://github.com/intuit/text-provider/commit/b94f14516f520dcac7639e71dc6dec94ba61f9d4)) 45 | * node version ([a3a4d83](https://github.com/intuit/text-provider/commit/a3a4d83e38f93274ab4120ad08819c23425cbf2b)) 46 | * removing tests ([b9d495b](https://github.com/intuit/text-provider/commit/b9d495b76b0aa04476e3fd67d45a08348255c1c6)) 47 | * trying to get the props through the HOC ([fd1d068](https://github.com/intuit/text-provider/commit/fd1d068149a8e61b8e247cd7a05db261c9977073)) 48 | * using the consumer api ([646afcd](https://github.com/intuit/text-provider/commit/646afcd5648c2b3ae52c6587f62d3d74ac5cb634)) 49 | * using the consumer api ([4974b82](https://github.com/intuit/text-provider/commit/4974b82b298d6c8a58a6674329c88a77bc149427)) 50 | 51 | 52 | ### Features 53 | 54 | * adding an alt prop for cases when text is not found ([63770de](https://github.com/intuit/text-provider/commit/63770dec802037273838ed714ce60796c61b814c)) 55 | * adding commitlint ([6f7e84f](https://github.com/intuit/text-provider/commit/6f7e84f58f8e0fe10052c2b21d6ff62286b195e1)) 56 | * adding husky and prettier ([93454b4](https://github.com/intuit/text-provider/commit/93454b47e858eee6cb4d7736d1cdaebe672e159e)) 57 | * adding semantic release ([f8de12a](https://github.com/intuit/text-provider/commit/f8de12a60d155faad5e2c10c98e386d9dc0e6642)) 58 | * integration with semantic release ([4ea31f8](https://github.com/intuit/text-provider/commit/4ea31f8f8d17c1be3708366d3cdfc3b53939156a)) 59 | * upgrading to the latest build system ([b30120c](https://github.com/intuit/text-provider/commit/b30120cc47cbf2c57092ae536cf19a83f7e72c06)) 60 | * upgrading to the latest build system ([d8d202c](https://github.com/intuit/text-provider/commit/d8d202ca12379020b5c6e933bccfd4eb49973858)) 61 | --------------------------------------------------------------------------------