Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate ID's for <FormattedMessage> components #31

Merged
merged 2 commits into from Feb 13, 2018

Conversation

bradbarrow
Copy link
Contributor

@bradbarrow bradbarrow commented Feb 6, 2018

What:

Closes #27

babel-plugin-react-intl-auto will generate a globally unique ID for <FormattedMessage> components that don't specify one themselves.

Why:

react-intl provides two primary interfaces for defining and rendering formatted strings: the defineMessages function and <FormattedMessage> React component.

Currently, this plugin only supports generating an ID for messages defined via defineMessages.

We would like to be able to use the React component but still don't want to have to deal with unique IDs.

How:

This plugin (essentially) creates ID's for defineMessages by combining the key passed to defineMessages with the path to the current file.

With <FormattedMessage> we don't have any key at all, just the message (descriptions are optional).

So this PR proposes a way of creating ID's for React components by combining the path to the current file with a hash of the provided defaultMessage.

This ensures that per file, all occurrences of a given defaultMessage will have the same unique ID. You will never get two matching ID's with different messages.

Note We considered including per file instance variance in the ID (line number of the component for e.g) but decided this could cause a lot of churn in the ID as components are moved in a file.

Checklist:

  • Documentation
  • Tests
  • Ready to be merged
  • Added myself to contributors table

@bradbarrow bradbarrow changed the title WIP Generate ID's for FormattedMessages Feb 6, 2018
@akameco akameco self-requested a review February 6, 2018 15:28
@bradbarrow
Copy link
Contributor Author

Sorry, we PR'd this early by mistake. Still a WIP but we intend to propose the change.

@bradbarrow bradbarrow force-pushed the generate-id-for-formatted-message branch 3 times, most recently from 5295977 to f96f4cb Compare February 8, 2018 13:13
@bradbarrow bradbarrow changed the title Generate ID's for FormattedMessages Generate ID's for <FormattedMessage> components Feb 8, 2018
@bradbarrow bradbarrow force-pushed the generate-id-for-formatted-message branch from f96f4cb to 8f9e880 Compare February 8, 2018 13:29
@bradbarrow
Copy link
Contributor Author

Hi, we think this is ready to go - would love to hear what you think :)

@akameco
Copy link
Owner

akameco commented Feb 8, 2018

@bradbarrow Great work🎉
I'll merge it after review 👍

title: '',
plugin,
snapshot: true,
babelOptions: { filename, babelrc: true },
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use babelOptions: { filename, parserOpts: { plugins: ['jsx'] } },
remove babelrc: true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh cool... I understand the dependency removal now too thanks. What does it use to parse jsx under the hood?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -1,10 +1,15 @@
// @flow
import p from 'path'
import * as t from 'babel-types'
import murmur from 'murmurhash3js'
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this library?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What: an efficient hashing library to create unique but short hashes

Why: wanted to use the defaultMessage as part of the ID but they are difficult to sanitize and might be quite long. This is the same hash used in the Babel react intl hash plugin

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@@ -16,7 +21,7 @@ const isImportLocalName = (name: string, { file }: State) => {
for (const specifier of path.get('specifiers')) {
if (
specifier.isImportSpecifier() &&
specifier.node.imported.name === 'defineMessages'
allowedNames.includes(specifier.node.imported.name)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

package.json Outdated
@@ -64,6 +65,7 @@
"babel-plugin-tester": "^5.0.0",
"babel-preset-env": "^1.6.1",
"babel-preset-flow": "^6.23.0",
"babel-preset-react": "^6.24.1",
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found that without this, jest was unable to run my component fixtures. It throws errors when it finds the JSX nodes

code: `
import { FormattedMessage } from 'react-intl'

console.log(<FormattedMessage defaultMessage="hello" />);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why need console.log ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't. I wanted to use the smallest possible valid code sample.i could just have the component by itself...It just felt like it would be floating...And not a typical use case 😄 happy to remove since I suppose Babel doesn't care

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to remove this, and in fact it does throw an error when <FormattedMessage> is just in line on it's own. So, I've left the log to give it some structure.

Open to other ideas like a function:

const Component = () => <FormattedMessage />

or something?

src/index.js Outdated
// Evaluate the message expression to see if it yields a string
const evaluated = messageValuePath.get('expression').evaluate()

//if (evaluated.confident && t.isStringLiteral(evaluated)) {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops sorry :)

code: `
import { FormattedMessage } from 'react-intl'

console.log(<FormattedMessage defaultMessage={\`hello world ${1}\`} />);
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clear intention 11 + 1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi I'll change that here and in the other test too

@akameco
Copy link
Owner

akameco commented Feb 8, 2018

And please explain the description to the readme :)

@bradbarrow
Copy link
Contributor Author

Hi I'll sort out those changes today :)

I'm not sure what you'd like me to explain about the Readme?

I tried to add a few examples and additions to show how this component based approach would look and what the result is.

I added some minor formatting changes to make the section about extracting a little clearer ... I hope.

@bradbarrow bradbarrow force-pushed the generate-id-for-formatted-message branch from 8f9e880 to 504c729 Compare February 8, 2018 22:55
@bradbarrow
Copy link
Contributor Author

Ok feedback addressed. I have left the console logs as it doesn't work without some kind of wrapper for context.

@bradbarrow bradbarrow force-pushed the generate-id-for-formatted-message branch from 504c729 to f6416cc Compare February 9, 2018 12:27
@bradbarrow
Copy link
Contributor Author

That worked, changes pushed @akameco thank you :)

Generates and inserts globally unique id props for react-intl
React components FormattedMessage and FormattedHTMLMessage
@bradbarrow bradbarrow force-pushed the generate-id-for-formatted-message branch from f6416cc to 6a25249 Compare February 9, 2018 12:29
@@ -74,7 +74,7 @@ const tests = [
import { defineMessages } from 'react-intl'

defineMessages({
hello: \`hello world \${1}\`,
hello: \`hello world \${1+1}\`,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not change. Because no need to evaluate here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

@akameco
Copy link
Owner

akameco commented Feb 12, 2018

Do not rebase😱 I'd like to see diff because of the cost of reviews.

@bradbarrow
Copy link
Contributor Author

Fixed up the test :) Sorry, rebasing is my default workflow. Have added the latest fix as a new commit

@bradbarrow bradbarrow force-pushed the generate-id-for-formatted-message branch from 4c5f4f4 to 248a9e5 Compare February 12, 2018 01:00
@bradbarrow bradbarrow force-pushed the generate-id-for-formatted-message branch from 248a9e5 to 37b553b Compare February 12, 2018 01:01
@akameco akameco self-requested a review February 12, 2018 02:21
@bradbarrow
Copy link
Contributor Author

Thanks for the review @akameco :) We're looking forward to the publish so we can start using this in production - we'll be sure to raise any improvements once we've used it for a while :)

Thanks for being available 👍

@bradbarrow
Copy link
Contributor Author

Hi @akameco, just wondering if you have an ETA on this release? We're relying on it for a piece of work and we'd love to deliver it this week :)

Thank you 🙏

@akameco akameco merged commit df2fdcc into akameco:master Feb 13, 2018
@akameco
Copy link
Owner

akameco commented Feb 13, 2018

@bradbarrow I released 1.1.0 🎉 Great work 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support React Components
2 participants