From 9eb942b8aead5a07df741ff3e3e3c60eb400c024 Mon Sep 17 00:00:00 2001 From: Heidi Kasemir Date: Mon, 19 Nov 2018 16:20:34 -0800 Subject: [PATCH 1/5] initial file restructure --- lerna.json | 6 ++ package.json | 1 + packages/components/examples/components.jsx | 16 ++++ .../components/examples/project-file-loc.jsx | 27 +++++++ .../examples/project-file-localized.jsx | 29 +++++++ .../components/examples/project-file-t.jsx | 26 ++++++ packages/components/package.json | 69 ++++++++++++++++ .../components/src}/Loc.js | 0 .../components/src}/index.js | 0 .../src}/make-localized-element.jsx | 0 .../components/src}/pseudolocalize.js | 0 .../components/test}/Loc.test.js | 0 .../test}/make-localized-element.test.js | 0 .../components/test}/pseudolocalize.test.js | 0 packages/extraction/examples/components.jsx | 16 ++++ .../extraction/examples/project-file-loc.jsx | 27 +++++++ .../examples/project-file-localized.jsx | 29 +++++++ .../extraction/examples/project-file-t.jsx | 26 ++++++ packages/extraction/package.json | 79 +++++++++++++++++++ .../extraction/src}/ast-helper.js | 0 {src => packages/extraction/src}/cli.js | 0 .../extraction/src}/constants.js | 0 .../extraction/src}/defaults.js | 0 .../extraction/src}/extraction.js | 0 .../extraction/src}/format-helper.js | 0 .../extraction/src}/index.js | 0 .../extraction/test}/extraction.test.js | 0 src/index.js | 5 -- test/index.js | 17 ---- 29 files changed, 351 insertions(+), 22 deletions(-) create mode 100644 lerna.json create mode 100644 packages/components/examples/components.jsx create mode 100644 packages/components/examples/project-file-loc.jsx create mode 100644 packages/components/examples/project-file-localized.jsx create mode 100644 packages/components/examples/project-file-t.jsx create mode 100644 packages/components/package.json rename {src/components => packages/components/src}/Loc.js (100%) rename {src/components => packages/components/src}/index.js (100%) rename {src/components => packages/components/src}/make-localized-element.jsx (100%) rename {src/components => packages/components/src}/pseudolocalize.js (100%) rename {test/components => packages/components/test}/Loc.test.js (100%) rename {test/components => packages/components/test}/make-localized-element.test.js (100%) rename {test/components => packages/components/test}/pseudolocalize.test.js (100%) create mode 100644 packages/extraction/examples/components.jsx create mode 100644 packages/extraction/examples/project-file-loc.jsx create mode 100644 packages/extraction/examples/project-file-localized.jsx create mode 100644 packages/extraction/examples/project-file-t.jsx create mode 100644 packages/extraction/package.json rename {src/extraction => packages/extraction/src}/ast-helper.js (100%) rename {src => packages/extraction/src}/cli.js (100%) rename {src/extraction => packages/extraction/src}/constants.js (100%) rename {src/extraction => packages/extraction/src}/defaults.js (100%) rename {src/extraction => packages/extraction/src}/extraction.js (100%) rename {src/extraction => packages/extraction/src}/format-helper.js (100%) rename {src/extraction => packages/extraction/src}/index.js (100%) rename {test/extraction => packages/extraction/test}/extraction.test.js (100%) delete mode 100644 src/index.js delete mode 100644 test/index.js diff --git a/lerna.json b/lerna.json new file mode 100644 index 0000000..89763cc --- /dev/null +++ b/lerna.json @@ -0,0 +1,6 @@ +{ + "packages": [ + "packages/*" + ], + "version": "0.1.0" +} diff --git a/package.json b/package.json index 7be21a4..df65b0a 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "eslint-plugin-react": "^7.4.0", "fluent-react": "^0.8.1", "istanbul": "^1.0.0-alpha", + "lerna": "^3.4.3", "mocha": "^5.0.0", "prop-types": "^15.6.2", "react": "^16.5.2", diff --git a/packages/components/examples/components.jsx b/packages/components/examples/components.jsx new file mode 100644 index 0000000..28bbdac --- /dev/null +++ b/packages/components/examples/components.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export function MyComponent(props) { + return ( +
+

Widget for {props.label}

+ {props.label} +
+ ); +} + +MyComponent.propTypes = { + label: PropTypes.string.isRequired, + imageSrc: PropTypes.string.isRequired +}; diff --git a/packages/components/examples/project-file-loc.jsx b/packages/components/examples/project-file-loc.jsx new file mode 100644 index 0000000..dc88ab8 --- /dev/null +++ b/packages/components/examples/project-file-loc.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Link } from 'react-router'; +import { signOut } from 'utils'; +import warningImg from 'assets/images'; +import { Loc } from '../src'; + +export function NotAuthorized() { + return ( +
+ + {/* here is a comment */} + Oops! looks like you are not authorized to use this app. + + + , + a: , + button: '} + +
+ ); +} diff --git a/packages/components/examples/project-file-localized.jsx b/packages/components/examples/project-file-localized.jsx new file mode 100644 index 0000000..cb332ea --- /dev/null +++ b/packages/components/examples/project-file-localized.jsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Localized } from 'fluent-react/compat'; +import { Link } from 'react-router'; +import { signOut } from 'utils'; +import warningImg from 'assets/images'; + +export function NotAuthorized() { + return ( +
+ +

+ {/* here is a comment */} + Oops! looks like you are not authorized to use this app. +

+
+ + warning sign + + } + a={} + button={'}

+
+
+ ); +} diff --git a/packages/components/examples/project-file-t.jsx b/packages/components/examples/project-file-t.jsx new file mode 100644 index 0000000..279f581 --- /dev/null +++ b/packages/components/examples/project-file-t.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Link } from 'react-router'; +import { signOut, T } from 'utils'; +import warningImg from 'assets/images'; + +export function NotAuthorized() { + return ( +
+ + {/* here is a comment */} + Oops! looks like you are not authorized to use this app. + + + , + a: , + button: '} + +
+ ); +} diff --git a/packages/components/package.json b/packages/components/package.json new file mode 100644 index 0000000..4fb6b28 --- /dev/null +++ b/packages/components/package.json @@ -0,0 +1,69 @@ +{ + "name": "fluent-react-components", + "version": "0.1.0", + "description": "Utility components for fluent-react", + "main": "./lib/index.js", + "scripts": { + "clean": "rimraf lib", + "test": "npm run lint && npm run cover", + "test:prod": "cross-env BABEL_ENV=production npm run test", + "test:only": "mocha --require babel-core/register --require babel-polyfill --recursive", + "cover": "istanbul cover _mocha -- --require babel-core/register --require babel-polyfill --recursive", + "lint": "eslint src test", + "build": "cross-env BABEL_ENV=production babel src --out-dir lib", + "prepublish": "npm run clean && npm run test && npm run build" + }, + "keywords": [ + "udacity", + "fluent", + "localization", + "l10n", + "ftl", + "translate", + "translation", + "fluent-react", + "internationalization", + "i18n", + "components", + "react" + ], + "repository": { + "type": "git", + "url": "https://github.com/udacity/fluent-react-utils" + }, + "files": [ + "lib", + "src" + ], + "license": "Apache-2.0", + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-eslint": "^8.2.1", + "babel-plugin-add-module-exports": "^0.2.1", + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-preset-env": "^1.7.0", + "babel-preset-es2015": "^6.24.1", + "babel-preset-minify": "^0.3.0", + "babel-preset-react": "^6.24.1", + "chai": "^4.1.2", + "cross-env": "^5.1.3", + "enzyme": "^3.6.0", + "enzyme-adapter-react-16": "^1.5.0", + "eslint": "^4.16.0", + "eslint-config-airbnb": "^16.1.0", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-jsx-a11y": "^6.0.2", + "eslint-plugin-react": "^7.4.0", + "fluent-react": "^0.8.1", + "istanbul": "^1.0.0-alpha", + "lerna": "^3.4.3", + "mocha": "^5.0.0", + "prop-types": "^15.6.2", + "react": "^16.5.2", + "react-dom": "^16.5.2", + "rimraf": "^2.6.2" + }, + "dependencies": { + } +} diff --git a/src/components/Loc.js b/packages/components/src/Loc.js similarity index 100% rename from src/components/Loc.js rename to packages/components/src/Loc.js diff --git a/src/components/index.js b/packages/components/src/index.js similarity index 100% rename from src/components/index.js rename to packages/components/src/index.js diff --git a/src/components/make-localized-element.jsx b/packages/components/src/make-localized-element.jsx similarity index 100% rename from src/components/make-localized-element.jsx rename to packages/components/src/make-localized-element.jsx diff --git a/src/components/pseudolocalize.js b/packages/components/src/pseudolocalize.js similarity index 100% rename from src/components/pseudolocalize.js rename to packages/components/src/pseudolocalize.js diff --git a/test/components/Loc.test.js b/packages/components/test/Loc.test.js similarity index 100% rename from test/components/Loc.test.js rename to packages/components/test/Loc.test.js diff --git a/test/components/make-localized-element.test.js b/packages/components/test/make-localized-element.test.js similarity index 100% rename from test/components/make-localized-element.test.js rename to packages/components/test/make-localized-element.test.js diff --git a/test/components/pseudolocalize.test.js b/packages/components/test/pseudolocalize.test.js similarity index 100% rename from test/components/pseudolocalize.test.js rename to packages/components/test/pseudolocalize.test.js diff --git a/packages/extraction/examples/components.jsx b/packages/extraction/examples/components.jsx new file mode 100644 index 0000000..28bbdac --- /dev/null +++ b/packages/extraction/examples/components.jsx @@ -0,0 +1,16 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export function MyComponent(props) { + return ( +
+

Widget for {props.label}

+ {props.label} +
+ ); +} + +MyComponent.propTypes = { + label: PropTypes.string.isRequired, + imageSrc: PropTypes.string.isRequired +}; diff --git a/packages/extraction/examples/project-file-loc.jsx b/packages/extraction/examples/project-file-loc.jsx new file mode 100644 index 0000000..dc88ab8 --- /dev/null +++ b/packages/extraction/examples/project-file-loc.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Link } from 'react-router'; +import { signOut } from 'utils'; +import warningImg from 'assets/images'; +import { Loc } from '../src'; + +export function NotAuthorized() { + return ( +
+ + {/* here is a comment */} + Oops! looks like you are not authorized to use this app. + + + , + a: , + button: '} + +
+ ); +} diff --git a/packages/extraction/examples/project-file-localized.jsx b/packages/extraction/examples/project-file-localized.jsx new file mode 100644 index 0000000..cb332ea --- /dev/null +++ b/packages/extraction/examples/project-file-localized.jsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { Localized } from 'fluent-react/compat'; +import { Link } from 'react-router'; +import { signOut } from 'utils'; +import warningImg from 'assets/images'; + +export function NotAuthorized() { + return ( +
+ +

+ {/* here is a comment */} + Oops! looks like you are not authorized to use this app. +

+
+ + warning sign + + } + a={} + button={'}

+
+
+ ); +} diff --git a/packages/extraction/examples/project-file-t.jsx b/packages/extraction/examples/project-file-t.jsx new file mode 100644 index 0000000..279f581 --- /dev/null +++ b/packages/extraction/examples/project-file-t.jsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Link } from 'react-router'; +import { signOut, T } from 'utils'; +import warningImg from 'assets/images'; + +export function NotAuthorized() { + return ( +
+ + {/* here is a comment */} + Oops! looks like you are not authorized to use this app. + + + , + a: , + button: '} + +
+ ); +} diff --git a/packages/extraction/package.json b/packages/extraction/package.json new file mode 100644 index 0000000..c2a163e --- /dev/null +++ b/packages/extraction/package.json @@ -0,0 +1,79 @@ +{ + "name": "fluent-react-extract", + "version": "0.1.0", + "description": "String extraction CLI for fluent-react", + "main": "./lib/index.js", + "scripts": { + "clean": "rimraf lib", + "test": "npm run lint && npm run cover", + "test:prod": "cross-env BABEL_ENV=production npm run test", + "test:only": "mocha --require babel-core/register --require babel-polyfill --recursive", + "cover": "istanbul cover _mocha -- --require babel-core/register --require babel-polyfill --recursive", + "lint": "eslint src test", + "build": "cross-env BABEL_ENV=production babel src --out-dir lib", + "prepublish": "npm run clean && npm run test && npm run build" + }, + "keywords": [ + "udacity", + "fluent", + "localization", + "l10n", + "ftl", + "translate", + "translation", + "fluent-react", + "internationalization", + "i18n", + "components", + "react" + ], + "repository": { + "type": "git", + "url": "https://github.com/udacity/fluent-react-utils" + }, + "bin": { + "l10n": "lib/cli.js" + }, + "files": [ + "lib", + "src" + ], + "license": "Apache-2.0", + "devDependencies": { + "babel-cli": "^6.26.0", + "babel-eslint": "^8.2.1", + "babel-plugin-add-module-exports": "^0.2.1", + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-polyfill": "^6.26.0", + "babel-preset-env": "^1.7.0", + "babel-preset-es2015": "^6.24.1", + "babel-preset-minify": "^0.3.0", + "babel-preset-react": "^6.24.1", + "chai": "^4.1.2", + "cross-env": "^5.1.3", + "enzyme": "^3.6.0", + "enzyme-adapter-react-16": "^1.5.0", + "eslint": "^4.16.0", + "eslint-config-airbnb": "^16.1.0", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-jsx-a11y": "^6.0.2", + "eslint-plugin-react": "^7.4.0", + "fluent-react": "^0.8.1", + "istanbul": "^1.0.0-alpha", + "lerna": "^3.4.3", + "mocha": "^5.0.0", + "prop-types": "^15.6.2", + "react": "^16.5.2", + "react-dom": "^16.5.2", + "rimraf": "^2.6.2" + }, + "dependencies": { + "@babel/parser": "^7.1.0", + "babylon-walk": "^1.0.2", + "fluent-syntax": "^0.8.1", + "glob": "^7.1.3", + "jsx-ast-utils": "^2.0.1", + "mkdirp": "^0.5.1", + "yargs": "^12.0.2" + } +} diff --git a/src/extraction/ast-helper.js b/packages/extraction/src/ast-helper.js similarity index 100% rename from src/extraction/ast-helper.js rename to packages/extraction/src/ast-helper.js diff --git a/src/cli.js b/packages/extraction/src/cli.js similarity index 100% rename from src/cli.js rename to packages/extraction/src/cli.js diff --git a/src/extraction/constants.js b/packages/extraction/src/constants.js similarity index 100% rename from src/extraction/constants.js rename to packages/extraction/src/constants.js diff --git a/src/extraction/defaults.js b/packages/extraction/src/defaults.js similarity index 100% rename from src/extraction/defaults.js rename to packages/extraction/src/defaults.js diff --git a/src/extraction/extraction.js b/packages/extraction/src/extraction.js similarity index 100% rename from src/extraction/extraction.js rename to packages/extraction/src/extraction.js diff --git a/src/extraction/format-helper.js b/packages/extraction/src/format-helper.js similarity index 100% rename from src/extraction/format-helper.js rename to packages/extraction/src/format-helper.js diff --git a/src/extraction/index.js b/packages/extraction/src/index.js similarity index 100% rename from src/extraction/index.js rename to packages/extraction/src/index.js diff --git a/test/extraction/extraction.test.js b/packages/extraction/test/extraction.test.js similarity index 100% rename from test/extraction/extraction.test.js rename to packages/extraction/test/extraction.test.js diff --git a/src/index.js b/src/index.js deleted file mode 100644 index 90ec4e5..0000000 --- a/src/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import { Loc, makeLocalizedElement, augmentLoc, pseudolocalize } from './components'; - -export default { - Loc, makeLocalizedElement, augmentLoc, pseudolocalize -}; diff --git a/test/index.js b/test/index.js deleted file mode 100644 index 33e5d11..0000000 --- a/test/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import { assert } from 'chai'; -import fluentReactUtils from '../src'; - -describe('fluentReactUtils', () => { - it('has Loc export', () => { - assert(fluentReactUtils.Loc !== undefined); - }); - it('has pseudolocalize export', () => { - assert(fluentReactUtils.pseudolocalize !== undefined); - }); - it('has makeLocalizedElement export', () => { - assert(fluentReactUtils.makeLocalizedElement !== undefined); - }); - it('has augmentLoc export', () => { - assert(fluentReactUtils.augmentLoc !== undefined); - }); -}); From 43e24127dcd94fa7205907b632887b1e9242a775 Mon Sep 17 00:00:00 2001 From: Heidi Kasemir Date: Mon, 19 Nov 2018 16:44:59 -0800 Subject: [PATCH 2/5] update broken file paths to successfully bootstrap and test fix bad import path --- .travis.yml | 10 ------- examples/components.jsx | 16 ---------- examples/project-file-loc.jsx | 27 ----------------- examples/project-file-localized.jsx | 29 ------------------- examples/project-file-t.jsx | 26 ----------------- package.json | 4 --- .babelrc => packages/components/.babelrc | 0 .eslintrc => packages/components/.eslintrc | 0 packages/components/package.json | 3 +- packages/components/src/Loc.js | 2 +- packages/components/test/Loc.test.js | 6 ++-- .../test/make-localized-element.test.js | 2 +- .../components/test/pseudolocalize.test.js | 2 +- packages/extraction/.babelrc | 18 ++++++++++++ packages/extraction/.eslintrc | 21 ++++++++++++++ packages/extraction/src/ast-helper.js | 2 +- packages/extraction/src/cli.js | 2 +- packages/extraction/src/index.js | 1 - packages/extraction/test/extraction.test.js | 2 +- .../extraction/src => shared}/constants.js | 12 ++++++-- 20 files changed, 58 insertions(+), 127 deletions(-) delete mode 100644 .travis.yml delete mode 100644 examples/components.jsx delete mode 100644 examples/project-file-loc.jsx delete mode 100644 examples/project-file-localized.jsx delete mode 100644 examples/project-file-t.jsx rename .babelrc => packages/components/.babelrc (100%) rename .eslintrc => packages/components/.eslintrc (100%) create mode 100644 packages/extraction/.babelrc create mode 100644 packages/extraction/.eslintrc rename {packages/extraction/src => shared}/constants.js (88%) diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 24b8730..0000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: node_js -node_js: - - '8' - - '6' -script: - - npm run test - - npm run build -branches: - only: - - master diff --git a/examples/components.jsx b/examples/components.jsx deleted file mode 100644 index 28bbdac..0000000 --- a/examples/components.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -export function MyComponent(props) { - return ( -
-

Widget for {props.label}

- {props.label} -
- ); -} - -MyComponent.propTypes = { - label: PropTypes.string.isRequired, - imageSrc: PropTypes.string.isRequired -}; diff --git a/examples/project-file-loc.jsx b/examples/project-file-loc.jsx deleted file mode 100644 index dc88ab8..0000000 --- a/examples/project-file-loc.jsx +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -import { Link } from 'react-router'; -import { signOut } from 'utils'; -import warningImg from 'assets/images'; -import { Loc } from '../src'; - -export function NotAuthorized() { - return ( -
- - {/* here is a comment */} - Oops! looks like you are not authorized to use this app. - - - , - a: , - button: '} - -
- ); -} diff --git a/examples/project-file-localized.jsx b/examples/project-file-localized.jsx deleted file mode 100644 index cb332ea..0000000 --- a/examples/project-file-localized.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react'; -import { Localized } from 'fluent-react/compat'; -import { Link } from 'react-router'; -import { signOut } from 'utils'; -import warningImg from 'assets/images'; - -export function NotAuthorized() { - return ( -
- -

- {/* here is a comment */} - Oops! looks like you are not authorized to use this app. -

-
- - warning sign - - } - a={} - button={'}

-
-
- ); -} diff --git a/examples/project-file-t.jsx b/examples/project-file-t.jsx deleted file mode 100644 index 279f581..0000000 --- a/examples/project-file-t.jsx +++ /dev/null @@ -1,26 +0,0 @@ -import React from 'react'; -import { Link } from 'react-router'; -import { signOut, T } from 'utils'; -import warningImg from 'assets/images'; - -export function NotAuthorized() { - return ( -
- - {/* here is a comment */} - Oops! looks like you are not authorized to use this app. - - - , - a: , - button: '} - -
- ); -} diff --git a/package.json b/package.json index df65b0a..a721a86 100644 --- a/package.json +++ b/package.json @@ -58,13 +58,9 @@ "eslint-plugin-import": "^2.7.0", "eslint-plugin-jsx-a11y": "^6.0.2", "eslint-plugin-react": "^7.4.0", - "fluent-react": "^0.8.1", "istanbul": "^1.0.0-alpha", "lerna": "^3.4.3", "mocha": "^5.0.0", - "prop-types": "^15.6.2", - "react": "^16.5.2", - "react-dom": "^16.5.2", "rimraf": "^2.6.2" }, "dependencies": { diff --git a/.babelrc b/packages/components/.babelrc similarity index 100% rename from .babelrc rename to packages/components/.babelrc diff --git a/.eslintrc b/packages/components/.eslintrc similarity index 100% rename from .eslintrc rename to packages/components/.eslintrc diff --git a/packages/components/package.json b/packages/components/package.json index 4fb6b28..af50a4f 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -64,6 +64,5 @@ "react-dom": "^16.5.2", "rimraf": "^2.6.2" }, - "dependencies": { - } + "dependencies": {} } diff --git a/packages/components/src/Loc.js b/packages/components/src/Loc.js index ea55e3c..d7a6472 100644 --- a/packages/components/src/Loc.js +++ b/packages/components/src/Loc.js @@ -1,5 +1,5 @@ import { makeLocalizedElement } from './make-localized-element'; -import { STANDARD_ELEMENT_TYPES } from '../extraction/constants'; +import { STANDARD_ELEMENT_TYPES } from '../../../shared/constants'; export const Loc = { A: makeLocalizedElement('a'), diff --git a/packages/components/test/Loc.test.js b/packages/components/test/Loc.test.js index 2aa4c5d..b6631e8 100644 --- a/packages/components/test/Loc.test.js +++ b/packages/components/test/Loc.test.js @@ -1,7 +1,7 @@ import { assert, expect } from 'chai'; -import { MyComponent } from '../../examples/components'; -import { augmentLoc, Loc } from '../../src/components/Loc'; -import { makeLocalizedElement } from '../../lib/components/make-localized-element'; +import { MyComponent } from '../examples/components'; +import { augmentLoc, Loc } from '../src/Loc'; +import { makeLocalizedElement } from '../src/make-localized-element'; describe('augmentLoc', () => { it('Augments the Loc object with a custom element', () => { diff --git a/packages/components/test/make-localized-element.test.js b/packages/components/test/make-localized-element.test.js index ea907f1..060288f 100644 --- a/packages/components/test/make-localized-element.test.js +++ b/packages/components/test/make-localized-element.test.js @@ -3,7 +3,7 @@ import { Localized } from 'fluent-react/compat'; import { assert, expect } from 'chai'; import Enzyme, { shallow } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; -import { formatVars, makeLocalizedElement } from '../../src/components/make-localized-element'; +import { formatVars, makeLocalizedElement } from '../src/make-localized-element'; Enzyme.configure({ adapter: new Adapter() }); diff --git a/packages/components/test/pseudolocalize.test.js b/packages/components/test/pseudolocalize.test.js index ce540e3..6f56242 100644 --- a/packages/components/test/pseudolocalize.test.js +++ b/packages/components/test/pseudolocalize.test.js @@ -1,5 +1,5 @@ import { assert } from 'chai'; -import { pseudolocalize } from '../../src'; +import { pseudolocalize } from '../src'; describe('pseudolocalize', () => { it('should transform a message', () => { diff --git a/packages/extraction/.babelrc b/packages/extraction/.babelrc new file mode 100644 index 0000000..b9a56e2 --- /dev/null +++ b/packages/extraction/.babelrc @@ -0,0 +1,18 @@ +{ + "env": { + "development": { + "presets": ["env", "react", "es2015"], + "plugins": [ + "add-module-exports", + "transform-object-rest-spread" + ] + }, + "production": { + "presets": ["env", "react", "es2015", "minify"], + "plugins": [ + "add-module-exports", + "transform-object-rest-spread" + ] + } + } +} diff --git a/packages/extraction/.eslintrc b/packages/extraction/.eslintrc new file mode 100644 index 0000000..4ccec45 --- /dev/null +++ b/packages/extraction/.eslintrc @@ -0,0 +1,21 @@ +{ + "parser": "babel-eslint", + "extends": "airbnb", + "env": { + "mocha": true + }, + "rules": { + "comma-dangle": ["error", "only-multiline"], + "consistent-return": "off", + "import/prefer-default-export": "off", + "import/no-extraneous-dependencies": "off", + "import/no-unresolved": "off", + "import/extensions": "off", + "jsx-a11y/alt-text": "off", + "jsx-a11y/anchor-has-content": "off", + "jsx-a11y/anchor-is-valid": "off", + "jsx-a11y/heading-has-content": "off", + "no-console": "off", + "react/jsx-filename-extension": "off" + } +} diff --git a/packages/extraction/src/ast-helper.js b/packages/extraction/src/ast-helper.js index 3cfd191..97d4715 100644 --- a/packages/extraction/src/ast-helper.js +++ b/packages/extraction/src/ast-helper.js @@ -1,5 +1,5 @@ import { getProp, elementType as _elementType, hasProp } from 'jsx-ast-utils'; -import { AST_NODE_TYPES, FLUENT_ATTRS, STANDARD_ELEMENT_TYPES } from './constants'; +import { AST_NODE_TYPES, FLUENT_ATTRS, STANDARD_ELEMENT_TYPES } from '../../../shared/constants'; import { defaultShorthandName } from './defaults'; import { formatRule, pullLocalizedDOMAttributes, formatMessage } from './format-helper'; diff --git a/packages/extraction/src/cli.js b/packages/extraction/src/cli.js index 7d3be2b..578724a 100755 --- a/packages/extraction/src/cli.js +++ b/packages/extraction/src/cli.js @@ -8,7 +8,7 @@ import { defaultFilePattern, defaultShorthandName, getSourceStrings -} from './extraction'; +} from './'; const DOCSTRING = 'Fluent React Utils'; diff --git a/packages/extraction/src/index.js b/packages/extraction/src/index.js index 4012a11..84b7a26 100644 --- a/packages/extraction/src/index.js +++ b/packages/extraction/src/index.js @@ -1,5 +1,4 @@ export * from './ast-helper'; -export * from './constants'; export * from './defaults'; export * from './extraction'; export * from './format-helper'; diff --git a/packages/extraction/test/extraction.test.js b/packages/extraction/test/extraction.test.js index 4338e78..1fec5fb 100644 --- a/packages/extraction/test/extraction.test.js +++ b/packages/extraction/test/extraction.test.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { getSourceStrings } from '../../src/extraction'; +import { getSourceStrings } from '../src/extraction'; const expectedOutput = `# here is a comment NotAuthorized_oopsMessage = Oops! looks like you are not authorized to use this app. diff --git a/packages/extraction/src/constants.js b/shared/constants.js similarity index 88% rename from packages/extraction/src/constants.js rename to shared/constants.js index 8b5035a..e6d33c7 100644 --- a/packages/extraction/src/constants.js +++ b/shared/constants.js @@ -1,4 +1,4 @@ -export const AST_NODE_TYPES = { +const AST_NODE_TYPES = { JSXElement: 'JSXElement', JSXText: 'JSXText', JSXExpressionContainer: 'JSXExpressionContainer', @@ -6,14 +6,14 @@ export const AST_NODE_TYPES = { StringLiteral: 'StringLiteral' }; -export const FLUENT_ATTRS = { +const FLUENT_ATTRS = { attrs: 'attrs', l10nId: 'l10nId', l10nVars: 'l10nVars', l10nJSX: 'l10nJSX' }; -export const STANDARD_ELEMENT_TYPES = { +const STANDARD_ELEMENT_TYPES = { A: {}, Abbr: {}, Address: {}, @@ -89,3 +89,9 @@ export const STANDARD_ELEMENT_TYPES = { Var: {}, Video: {} }; + +module.exports = { + STANDARD_ELEMENT_TYPES, + FLUENT_ATTRS, + AST_NODE_TYPES +} \ No newline at end of file From 4539f79330598cff9838d166bec103e8158e3afa Mon Sep 17 00:00:00 2001 From: Heidi Kasemir Date: Tue, 20 Nov 2018 12:32:31 -0800 Subject: [PATCH 3/5] update readmes --- README.md | 331 +--------------------------------- packages/components/README.md | 167 +++++++++++++++++ packages/extraction/README.md | 166 +++++++++++++++++ 3 files changed, 341 insertions(+), 323 deletions(-) create mode 100644 packages/components/README.md create mode 100644 packages/extraction/README.md diff --git a/README.md b/README.md index 80adafd..535dc7f 100644 --- a/README.md +++ b/README.md @@ -1,334 +1,19 @@ # fluent-react-utils String extraction and helper components for using [fluent-react](https://github.com/projectfluent/fluent.js/tree/master/fluent-react) in your projects. -## Helper Components -Basic fluent-react makes use of `Localized` components to wrap jsx components, like this: -```jsx -export function NotAuthorized() { - return ( -
- -

- {/* here is a comment for the localizer */} - Oops! looks like you're not authorized to use this app. -

-
- - warning sign - - } - a={} - button={' - } -

-
-
- ); -} -``` - -This makes for a lot of `Localized` components on the page, and can make it hard -to visually scan for specific HTML elements. This package comes with standard HTML -elements already wrapped in `Localized` with their typical `attrs` enabled in the -`Loc` component. This turns the above into: - -```jsx -import {Loc} from 'fluent-react-utils'; - -export function NotAuthorized() { - return ( -
- - {/* here is a comment for the localizer */} - Oops! looks like you're not authorized to use this app. - - - , - a: , - button: ' - } - -
- ); -} -``` - -#### Props -In the `Loc` components you have access to three `l10n` props to describe how -this message needs to be translated. - -##### l10nId (Required) -The localization key for that message - -##### l10nVars -This is a plain object with the message variables as keys. It's only used if the message has a variable to substitute. - -```jsx - - {'Welcome, { $name }'} - -``` - -##### l10nJsx -A plain object with the element alias as the key and a JSX component as the value. -This is used for any components that are included inline in the message, with the -alias used in HTML-like syntax to wrap the translated message. - -```jsx - - }} -> - { - 'Go home' - } - -``` - -### Custom Loc Components -Your project may have components that would be great to include in the `Loc` -object, but which are not standard HTML. Say you have a styled `MyButton` -component, for example. - -```jsx - - - -``` - -You can make use of two helpers from fluent-react-utils to quickly wrap a -component in `Localized` and / or add it to the `Loc` object. - -#### `makeLocalizedElement(Element[, attrs])` - -```js -const MyLocalizedButton = makeLocalizedElement(MyButton, {label: true}) -``` - -`MyLocalizedButton` will now have access to the `l10nId`, `l10nVars`, and -`l10nJsx` props. - - -#### `augmentLoc(customElements)` -In order for your custom elements to be recognized by the string extraction tool, -they need to be prefixed by `Loc.` (or a custom name of your choice - -see information about the `.l10nrc` file). +This is a mono-repo containing two packages: +## [fluent-react-components](./packages/components) +Helper components to write cleaner jsx with fluent-react. -```js -// my-utils -import {augmentLoc} from 'fluent-react-utils'; +## [fluent-react-extract](./packages/extraction) +CLI for extracting strings for localization into ftl files. -const customElements = { - MyButton: MyLocalizedButton -}; -export const Loc = augmentLoc(customElements); +# Contributing -// elsewhere +To get started developing locally, install dependencies and build the packages using -import {Loc} from 'my-utils'; - -... - - Look, a button! - - ``` - -## String Extraction -Get default messages from your source code so that you don't have to switch -context to manage translatable messages - -Uses the [fluent-syntax](https://github.com/projectfluent/fluent.js/tree/master/fluent-syntax) serializer -and [Babel parser](https://github.com/babel/babel/tree/master/packages/babel-parser) to -create an AST for your React code to pull out default messages and format them in -FTL. - -### How to Use -```sh -l10n extract [--pattern '...'] [--outputDir '...'] -``` -This will run through all files matching the file pattern, parse the code into an -AST, locate all the `Localized` or `Loc.X` (`Loc.` is the default, but this can -be customized, see `.l10nrc` information below) helper components and pull the id, -messages, and comments for that component into a fresh `data.ftl` file located -in the specified output directory. - -#### Example -```jsx -// imports - -export function NotAuthorized() { - return ( -
- - {/* here is a comment for the localizer */} - Oops! looks like you're not authorized to use this app. - - - , - a: , - button: ' - } - -
- ); -} +$ lerna bootstrap ``` - -Running the localization script on this file would result in the `data.ftl` below: -``` -# here is a comment for the localizer -NotAuthorized_oopsMessage = Oops! looks like you're not authorized to use this app. -NotAuthorized_warningImg = - .alt = warning sign -NotAuthorized_possibleActions = Try again, go Home or -``` - -*NOTE*: adding comments along with the children of a component will extract this -out as a comment to the localizer. This can be helpful for leaving tips about -context of the message to make translation easier. - -### .l10nrc File -In order to run the extraction based on your project's custom needs, a `.l10nrc` -file is supported. Possible values of this file: - -#### `customElementsPath` -If you use the custom elements as described above, if they include any attributes -(i.e. `label` on the `MyButton` component), they need to be included to tell the -extraction scripts which attributes to look for. The format for this is a json object -with the component names as keys, and an object of their allowed (or explicitly -disallowed) attributes. For example: - -```json -// custom-elements.json -{ - "MyButton": {"label": true} -} -``` -It is recommended that this record of custom element attributes is held in a json -file that is pulled into any file defining the `attrs` of that element in the React -code. -```js -import {augmentLoc, makeLocalizedElement} from 'fluent-react-utils'; -import customAttrs from './custom-elements.json'; - -const customElements = { - MyButton: makeLocalizedElement(MyButton, customAttrs.MyButton) -}; - -export const Loc = augmentLoc(customElements); -``` - -The value for `customElementsPath` is the path to the `custom-elements.json` file -from the project root. - -For example: -```json -{ - "customElementsPath": "./src/app/utils/custom-elements.json", -} -``` - -#### `shorthandName` -By default, this is `Loc`, but if your project prefers not to use the same name -as this library's `Loc` utility, you can update this in the `.l10nrc` file. - -```js -// my-utils -import {augmentLoc, makeLocalizedElement} from 'fluent-react-utils'; -import customAttrs from './custom-elements.json'; - -const customElements = { - MyButton: makeLocalizedElement(MyButton, customAttrs.MyButton) -}; - -export const L = augmentLoc(customElements); - -// elsewhere - -import {L} from 'my-utils'; - -... - - Look, a button! - - -``` - -```json -{ - "shorthandName": "L", -} -``` - -#### `filePattern` -In case your project always extracts the same file pattern, this can be defined -in `.l10nrc` as opposed to passing it into the cli every time. -```json -{ - "filePattern": "./src/app/**/*.{js,jsx}", -} -``` - -#### `outputDir` -The location you want the string extraction script to write its results. -```json -{ - "outputDir": "./public/locales/new-strings/", -} -``` - -## future work: -- message deduplication with interface - - decide which message to keep, or to create a new l10nId and write back to file -- compare string extraction output with production files - - provide no reference warnings (may indicate obsolete string) diff --git a/packages/components/README.md b/packages/components/README.md new file mode 100644 index 0000000..a2ac457 --- /dev/null +++ b/packages/components/README.md @@ -0,0 +1,167 @@ +# Fluent React Components + +Basic fluent-react makes use of `Localized` components to wrap jsx components, like this: + +```jsx +export function NotAuthorized() { + return ( +
+ +

+ {/* here is a comment for the localizer */} + Oops! looks like you're not authorized to use this app. +

+
+ + warning sign + + } + a={} + button={' + } +

+
+
+ ); +} +``` + +This makes for a lot of `Localized` components on the page, and can make it hard +to visually scan for specific HTML elements. This package comes with standard HTML +elements already wrapped in `Localized` with their typical `attrs` enabled in the +`Loc` component. This turns the above into: + +```jsx +import {Loc} from 'fluent-react-utils'; + +export function NotAuthorized() { + return ( +
+ + {/* here is a comment for the localizer */} + Oops! looks like you're not authorized to use this app. + + + , + a: , + button: ' + } + +
+ ); +} +``` + +### Props +In the `Loc` components you have access to three `l10n` props to describe how +this message needs to be translated. + +#### l10nId (Required) +The localization key for that message + +#### l10nVars +This is a plain object with the message variables as keys. It's only used if the message has a variable to substitute. + +```jsx + + {'Welcome, { $name }'} + +``` + +#### l10nJsx +A plain object with the element alias as the key and a JSX component as the value. +This is used for any components that are included inline in the message, with the +alias used in HTML-like syntax to wrap the translated message. + +```jsx + + }} +> + { + 'Go home' + } + +``` + +## Custom Loc Components +Your project may have components that would be great to include in the `Loc` +object, but which are not standard HTML. Say you have a styled `MyButton` +component, for example. + +```jsx + + + +``` + +You can make use of two helpers from fluent-react-utils to quickly wrap a +component in `Localized` and / or add it to the `Loc` object. + +### `makeLocalizedElement(Element[, attrs])` + +```js +const MyLocalizedButton = makeLocalizedElement(MyButton, {label: true}) +``` + +`MyLocalizedButton` will now have access to the `l10nId`, `l10nVars`, and +`l10nJsx` props. + + +### `augmentLoc(customElements)` +In order for your custom elements to be recognized by the string extraction tool, +they need to be prefixed by `Loc.` (or a custom name of your choice - +see information about the `.l10nrc` file). + +```js +// my-utils +import {augmentLoc} from 'fluent-react-utils'; + +const customElements = { + MyButton: MyLocalizedButton +}; + +export const Loc = augmentLoc(customElements); + +// elsewhere + +import {Loc} from 'my-utils'; + +... + + Look, a button! + + +``` \ No newline at end of file diff --git a/packages/extraction/README.md b/packages/extraction/README.md new file mode 100644 index 0000000..755f0e0 --- /dev/null +++ b/packages/extraction/README.md @@ -0,0 +1,166 @@ + +# Fluent React Extract + +Get default messages from your source code so that you don't have to switch +context to manage translatable messages + +Uses the [fluent-syntax](https://github.com/projectfluent/fluent.js/tree/master/fluent-syntax) serializer +and [Babel parser](https://github.com/babel/babel/tree/master/packages/babel-parser) to +create an AST for your React code to pull out default messages and format them in +FTL. + +### How to Use +```sh +l10n extract [--pattern '...'] [--outputDir '...'] +``` +This will run through all files matching the file pattern, parse the code into an +AST, locate all the `Localized` or `Loc.X` (`Loc.` is the default, but this can +be customized, see `.l10nrc` information below) helper components and pull the id, +messages, and comments for that component into a fresh `data.ftl` file located +in the specified output directory. + +### Example +```jsx +// imports + +export function NotAuthorized() { + return ( +
+ + {/* here is a comment for the localizer */} + Oops! looks like you're not authorized to use this app. + + + , + a: , + button: ' + } + +
+ ); +} +``` + +Running the localization script on this file would result in the `data.ftl` below: +``` +# here is a comment for the localizer +NotAuthorized_oopsMessage = Oops! looks like you're not authorized to use this app. +NotAuthorized_warningImg = + .alt = warning sign +NotAuthorized_possibleActions = Try again, go Home or +``` + +*NOTE*: adding comments along with the children of a component will extract this +out as a comment to the localizer. This can be helpful for leaving tips about +context of the message to make translation easier. + +## .l10nrc File +In order to run the extraction based on your project's custom needs, a `.l10nrc` +file is supported. Possible values of this file: + +### `customElementsPath` +If you use the custom elements as described above, if they include any attributes +(i.e. `label` on the `MyButton` component), they need to be included to tell the +extraction scripts which attributes to look for. The format for this is a json object +with the component names as keys, and an object of their allowed (or explicitly +disallowed) attributes. For example: + +```json +// custom-elements.json +{ + "MyButton": {"label": true} +} +``` +It is recommended that this record of custom element attributes is held in a json +file that is pulled into any file defining the `attrs` of that element in the React +code. +```js +import {augmentLoc, makeLocalizedElement} from 'fluent-react-utils'; +import customAttrs from './custom-elements.json'; + +const customElements = { + MyButton: makeLocalizedElement(MyButton, customAttrs.MyButton) +}; + +export const Loc = augmentLoc(customElements); +``` + +The value for `customElementsPath` is the path to the `custom-elements.json` file +from the project root. + +For example: +```json +{ + "customElementsPath": "./src/app/utils/custom-elements.json", +} +``` + +### `shorthandName` +By default, this is `Loc`, but if your project prefers not to use the same name +as this library's `Loc` utility, you can update this in the `.l10nrc` file. + +```js +// my-utils +import {augmentLoc, makeLocalizedElement} from 'fluent-react-utils'; +import customAttrs from './custom-elements.json'; + +const customElements = { + MyButton: makeLocalizedElement(MyButton, customAttrs.MyButton) +}; + +export const L = augmentLoc(customElements); + +// elsewhere + +import {L} from 'my-utils'; + +... + + Look, a button! + + +``` + +```json +{ + "shorthandName": "L", +} +``` + +### `filePattern` +In case your project always extracts the same file pattern, this can be defined +in `.l10nrc` as opposed to passing it into the cli every time. +```json +{ + "filePattern": "./src/app/**/*.{js,jsx}", +} +``` + +### `outputDir` +The location you want the string extraction script to write its results. +```json +{ + "outputDir": "./public/locales/new-strings/", +} +``` + +# Future Work: +- Message deduplication with interface + - decide which message to keep, or to create a new l10nId and write back to file +- Compare string extraction output with production files + - provide no reference warnings (may indicate obsolete string) From 60722f14b90bb01cff6119312282363c893fed25 Mon Sep 17 00:00:00 2001 From: Heidi Kasemir Date: Tue, 20 Nov 2018 12:36:54 -0800 Subject: [PATCH 4/5] add codeowners file --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) create mode 100644 CODEOWNERS diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..b0e6d1e --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @hkasemir \ No newline at end of file From f9af06b958f4839ce0c954c7e97b03a8944981a6 Mon Sep 17 00:00:00 2001 From: Heidi Kasemir Date: Tue, 20 Nov 2018 12:46:03 -0800 Subject: [PATCH 5/5] clean out package.json in root --- package.json | 51 ++------------------------------------------------- 1 file changed, 2 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index a721a86..71c7fc8 100644 --- a/package.json +++ b/package.json @@ -2,16 +2,8 @@ "name": "fluent-react-utils", "version": "0.1.0", "description": "Utilities for fluent-react", - "main": "./lib/index.js", "scripts": { - "clean": "rimraf lib", - "test": "npm run lint && npm run cover", - "test:prod": "cross-env BABEL_ENV=production npm run test", - "test:only": "mocha --require babel-core/register --require babel-polyfill --recursive", - "cover": "istanbul cover _mocha -- --require babel-core/register --require babel-polyfill --recursive", - "lint": "eslint src test", - "build": "cross-env BABEL_ENV=production babel src --out-dir lib", - "prepublish": "npm run clean && npm run test && npm run build" + "build": "lerna bootstrap" }, "keywords": [ "udacity", @@ -31,45 +23,6 @@ "type": "git", "url": "https://github.com/udacity/fluent-react-utils" }, - "bin": { - "l10n": "lib/cli.js" - }, - "files": [ - "lib", - "src" - ], "license": "Apache-2.0", - "devDependencies": { - "babel-cli": "^6.26.0", - "babel-eslint": "^8.2.1", - "babel-plugin-add-module-exports": "^0.2.1", - "babel-plugin-transform-object-rest-spread": "^6.26.0", - "babel-polyfill": "^6.26.0", - "babel-preset-env": "^1.7.0", - "babel-preset-es2015": "^6.24.1", - "babel-preset-minify": "^0.3.0", - "babel-preset-react": "^6.24.1", - "chai": "^4.1.2", - "cross-env": "^5.1.3", - "enzyme": "^3.6.0", - "enzyme-adapter-react-16": "^1.5.0", - "eslint": "^4.16.0", - "eslint-config-airbnb": "^16.1.0", - "eslint-plugin-import": "^2.7.0", - "eslint-plugin-jsx-a11y": "^6.0.2", - "eslint-plugin-react": "^7.4.0", - "istanbul": "^1.0.0-alpha", - "lerna": "^3.4.3", - "mocha": "^5.0.0", - "rimraf": "^2.6.2" - }, - "dependencies": { - "@babel/parser": "^7.1.0", - "babylon-walk": "^1.0.2", - "fluent-syntax": "^0.8.1", - "glob": "^7.1.3", - "jsx-ast-utils": "^2.0.1", - "mkdirp": "^0.5.1", - "yargs": "^12.0.2" - } + "dependencies": {} }