Skip to content

Commit

Permalink
chore: Add prettier
Browse files Browse the repository at this point in the history
  • Loading branch information
tricoder42 committed Nov 24, 2017
1 parent 8f5f6c5 commit 510c661
Show file tree
Hide file tree
Showing 101 changed files with 2,479 additions and 1,929 deletions.
10 changes: 4 additions & 6 deletions .eslintrc
Expand Up @@ -9,23 +9,21 @@
}
},
"extends": [
"standard",
"plugin:flowtype/recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:react/recommended",
"plugin:jest/recommended"
],
"plugins": [
"standard",
"promise",
"flowtype",
"import",
"react",
"jest"
"jest",
"prettier"
],
"rules": {
"no-duplicate-imports": "off",
"react/display-name": "off"
"react/display-name": "off",
"prettier/prettier": "error"
}
}
4 changes: 4 additions & 0 deletions .prettierignore
@@ -0,0 +1,4 @@
**/dist/*
**/test/**/actual.js
**/test/**/expected.js
**/locale/*
4 changes: 4 additions & 0 deletions .prettierrc
@@ -0,0 +1,4 @@
{
"semi": false,
"parser": "flow"
}
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -44,14 +44,13 @@
"enzyme-adapter-react-16": "^1.1.0",
"enzyme-to-json": "^3.2.2",
"eslint": "^4.11.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-flowtype": "^2.39.1",
"eslint-plugin-import": "^2.8.0",
"eslint-plugin-jest": "^21.3.2",
"eslint-plugin-node": "^5.2.1",
"eslint-plugin-prettier": "^2.3.1",
"eslint-plugin-promise": "^3.6.0",
"eslint-plugin-react": "^7.5.1",
"eslint-plugin-standard": "^3.0.1",
"flow-bin": "^0.59.0",
"flow-typed": "^2.2.3",
"glob": "^7.1.2",
Expand All @@ -62,6 +61,7 @@
"mock-fs": "^4.4.2",
"nixt": "^0.5.0",
"node-emoji": "^1.6.1",
"prettier": "^1.8.2",
"react": "16.1.1",
"react-dom": "16.1.1",
"react-test-renderer": "16.1.1",
Expand Down
106 changes: 60 additions & 46 deletions packages/babel-plugin-lingui-extract-messages/src/index.js
@@ -1,55 +1,60 @@
import fs from 'fs'
import fsPath from 'path'
import mkdirp from 'mkdirp'
import generate from 'babel-generator'
import getConfig from 'lingui-conf'
import fs from "fs"
import fsPath from "path"
import mkdirp from "mkdirp"
import generate from "babel-generator"
import getConfig from "lingui-conf"

// Map of messages
const MESSAGES = Symbol('I18nMessages')
const MESSAGES = Symbol("I18nMessages")

// We need to remember all processed nodes. When JSX expressions are
// replaced with CallExpressions, all children are traversed for each CallExpression.
// Then, i18n._ methods are visited multiple times for each parent CallExpression.
const VISITED = Symbol('I18nVisited')
const VISITED = Symbol("I18nVisited")

function addMessage (path, messages, { id, defaults, origin }) {
function addMessage(path, messages, { id, defaults, origin }) {
if (messages.has(id)) {
const message = messages.get(id)

// only set/check default language when it's defined.
if (message.defaults && defaults && message.defaults !== defaults) {
throw path.buildCodeFrameError('Different defaults for the same message ID.')
throw path.buildCodeFrameError(
"Different defaults for the same message ID."
)
} else {
if (defaults) {
message.defaults = defaults
}

[].push.apply(message.origin, origin)
;[].push.apply(message.origin, origin)
}
} else {
messages.set(id, { defaults, origin })
}
}

export default function ({ types: t }) {
export default function({ types: t }) {
let localTransComponentName

const opts = getConfig()
const optsBaseDir = opts.rootDir

function isTransComponent (node) {
return t.isJSXElement(node) && t.isJSXIdentifier(node.openingElement.name, {
name: localTransComponentName
})
function isTransComponent(node) {
return (
t.isJSXElement(node) &&
t.isJSXIdentifier(node.openingElement.name, {
name: localTransComponentName
})
)
}

const isNoopMethod = node => t.isIdentifier(node, { name: 'i18nMark' })
const isNoopMethod = node => t.isIdentifier(node, { name: "i18nMark" })
const isI18nMethod = node =>
t.isMemberExpression(node) &&
t.isIdentifier(node.object, { name: 'i18n' }) &&
t.isIdentifier(node.property, { name: '_' })
t.isIdentifier(node.object, { name: "i18n" }) &&
t.isIdentifier(node.property, { name: "_" })

function collectMessage (path, file, props) {
function collectMessage(path, file, props) {
const messages = file.get(MESSAGES)

const filename = fsPath.relative(optsBaseDir, file.opts.filename)
Expand All @@ -64,24 +69,24 @@ export default function ({ types: t }) {
// Get the local name of Trans component. Usually it's just `Trans`, but
// it might be different when the import is aliased:
// import { Trans as T } from 'lingui-react';
ImportDeclaration (path) {
ImportDeclaration(path) {
const { node } = path

const moduleName = node.source.value.split('/').slice(-1)[0]
if (!Array.includes(['lingui-react', 'lingui-i18n'], moduleName)) return
const moduleName = node.source.value.split("/").slice(-1)[0]
if (!Array.includes(["lingui-react", "lingui-i18n"], moduleName)) return

const importDeclarations = {}
if (moduleName === 'lingui-react') {
if (moduleName === "lingui-react") {
node.specifiers.forEach(specifier => {
importDeclarations[specifier.imported.name] = specifier.local.name
})

localTransComponentName = importDeclarations['Trans']
localTransComponentName = importDeclarations["Trans"]
}

// Remove imports of i18nMark identity
node.specifiers = node.specifiers.filter(specifier =>
specifier.imported.name !== 'i18nMark'
node.specifiers = node.specifiers.filter(
specifier => specifier.imported.name !== "i18nMark"
)

if (!node.specifiers.length) {
Expand All @@ -90,23 +95,23 @@ export default function ({ types: t }) {
},

// Extract translation from <Trans /> component.
JSXElement (path, { file }) {
JSXElement(path, { file }) {
const { node } = path
if (!localTransComponentName || !isTransComponent(node)) return

const attrs = node.openingElement.attributes || []

const props = attrs.reduce((acc, item) => {
const key = item.name.name
if (key === 'id' || key === 'defaults') acc[key] = item.value.value
if (key === "id" || key === "defaults") acc[key] = item.value.value
return acc
}, {})

if (!props.id) {
// <Trans id={message} /> is valid, don't raise warning
const idProp = attrs.filter(item => item.name.name === 'id')[0]
const idProp = attrs.filter(item => item.name.name === "id")[0]
if (idProp === undefined || t.isLiteral(props.id)) {
console.warn('Missing message ID, skipping.')
console.warn("Missing message ID, skipping.")
console.warn(generate(node).code)
}
return
Expand All @@ -116,7 +121,7 @@ export default function ({ types: t }) {
},

// Extract translation from i18n._ call
CallExpression (path, { file }) {
CallExpression(path, { file }) {
const { node } = path
const visited = file.get(VISITED)

Expand All @@ -131,32 +136,39 @@ export default function ({ types: t }) {

visited.add(node.callee)

if (isNoopMethod(node.callee) && !t.isStringLiteral(node.arguments[0])) {
console.warn('Only string literals are allowed in i18nMark.')
if (
isNoopMethod(node.callee) &&
!t.isStringLiteral(node.arguments[0])
) {
console.warn("Only string literals are allowed in i18nMark.")
return
}

const attrs = node.arguments[1] && node.arguments[1].properties
? node.arguments[1].properties
: []
const attrs =
node.arguments[1] && node.arguments[1].properties
? node.arguments[1].properties
: []

const idArg = node.arguments[0]
const id = idArg && idArg.value
if (!id) {
// i18n._(message) is valid, don't raise warning
if (idArg === undefined || t.isLiteral(idArg)) {
console.warn('Missing message ID, skipping.')
console.warn("Missing message ID, skipping.")
console.warn(generate(node).code)
}

return
}

const props = attrs.reduce((acc, item) => {
const key = item.key.name
if (key === 'defaults') acc[key] = item.value.value
return acc
}, { id })
const props = attrs.reduce(
(acc, item) => {
const key = item.key.name
if (key === "defaults") acc[key] = item.value.value
return acc
},
{ id }
)

collectMessage(path, file, props)

Expand All @@ -167,7 +179,7 @@ export default function ({ types: t }) {
}
},

pre (file) {
pre(file) {
localTransComponentName = null

// Ignore else path for now. Collision is possible if other plugin is
Expand All @@ -180,23 +192,25 @@ export default function ({ types: t }) {
file.set(VISITED, new WeakSet())
},

post (file) {
post(file) {
/* Write catalog to directory `localeDir`/_build/`path.to.file`/`filename`.json
* e.g: if file is src/components/App.js (relative to package.json), then
* catalog will be in locale/_build/src/components/App.json
*/
const localeDir = this.opts.localeDir || opts.localeDir
const { filename, basename } = file.opts
const baseDir = fsPath.dirname(fsPath.relative(optsBaseDir, filename))
const targetDir = fsPath.join(localeDir, '_build', baseDir)
const targetDir = fsPath.join(localeDir, "_build", baseDir)

const messages = file.get(MESSAGES)
const catalog = {}

// no messages, skip file
if (!messages.size) return

messages.forEach((value, key) => { catalog[key] = value })
messages.forEach((value, key) => {
catalog[key] = value
})

mkdirp.sync(targetDir)
fs.writeFileSync(
Expand Down
Expand Up @@ -6,7 +6,7 @@ Object {
"origin": Array [
Array [
"packages/babel-plugin-lingui-extract-messages/test/fixtures/jsx/with-react.js",
4,
3,
],
],
},
Expand Down Expand Up @@ -95,27 +95,27 @@ Object {
],
Array [
"packages/babel-plugin-lingui-extract-messages/test/fixtures/jsx/integration.js",
11,
13,
],
Array [
"packages/babel-plugin-lingui-extract-messages/test/fixtures/jsx/integration.js",
12,
14,
],
],
},
"{count, plural, one {# book} other {# books}}": Object {
"origin": Array [
Array [
"packages/babel-plugin-lingui-extract-messages/test/fixtures/jsx/integration.js",
5,
6,
],
Array [
"packages/babel-plugin-lingui-extract-messages/test/fixtures/jsx/integration.js",
14,
16,
],
Array [
"packages/babel-plugin-lingui-extract-messages/test/fixtures/jsx/integration.js",
19,
21,
],
],
},
Expand Down
@@ -1,6 +1,6 @@
_("ignore")

i18n._() // this should be ignored
i18n._() // this should be ignored
i18n._("msg.hello")
i18n._("msg.default", { defaults: "Hello World" })
i18n._("msg.default", { defaults: "Hello World" })
Expand Down
@@ -1,15 +1,15 @@
import { Trans } from 'lingui-react';
import { Trans } from "lingui-react"

<span id="ignore" />;
<Trans />; // this should be ignored
<Trans defaults="Missing ID"/>; // this should be ignored
<Trans id="msg.hello" />;
<Trans id="msg.default" defaults="Hello World" />;
<Trans id="msg.default" defaults="Hello World" />;
<Trans id="Hi, my name is <0>{name}</0>" values={{ count }} />;
;<span id="ignore" />
;<Trans /> // this should be ignored
;<Trans defaults="Missing ID" /> // this should be ignored
;<Trans id="msg.hello" />
;<Trans id="msg.default" defaults="Hello World" />
;<Trans id="msg.default" defaults="Hello World" />
;<Trans id="Hi, my name is <0>{name}</0>" values={{ count }} />
i18n._("{count, plural, one {# book} other {# books}}", {
values: {
count: count
}
});
<Trans id={message} />;
})
;<Trans id={message} />
@@ -1,7 +1,7 @@
import { Trans } from 'lingui-react';
import { Trans } from "lingui-react"

<span id="ignore" />;
<Trans id="msg.hello" />;
<Trans id="msg.default" defaults="Hello World" />;
<Trans id="msg.default" defaults="Hello World" />;
<Trans id="Hi, my name is <0>{name}</0>" />;
;<span id="ignore" />
;<Trans id="msg.hello" />
;<Trans id="msg.default" defaults="Hello World" />
;<Trans id="msg.default" defaults="Hello World" />
;<Trans id="Hi, my name is <0>{name}</0>" />

0 comments on commit 510c661

Please sign in to comment.