{"action":"created","comment":{"url":"https://api.github.com/repos/optimizely/marketing-website/pulls/comments/23699095","id":23699095,"diff_hunk":"@@ -0,0 +1,37 @@\n+/*\n+  Helper function to mark messages that should be localized.\n+  Later it may be changed to retrieve actual translations from somewhere.\n+  It allows to substitute messages - for example tr(\"Hi {0}, this is {1}\", \"Bob\", \"Jerry\"); will return \"Hi Bob, this is Jerry\"\n+ */\n+/**\n+ * Returns localized version of a string with parameters substituted.\n+ * Everything after first argument is considered as substitutions.\n+ * @param {String} str -  String to localize\n+ * @param {...*} substitutions - Substitution parameters\n+ * @returns {String} Localized string\n+ */\n+module.exports = function(str) {","path":"website-guts/assets/js/globals/translation.js","position":13,"original_position":13,"commit_id":"0e17a62890c726a3dfbe020b745527d44b67c3e3","original_commit_id":"0e17a62890c726a3dfbe020b745527d44b67c3e3","user":{"login":"dtothefp","id":4656726,"avatar_url":"https://avatars.githubusercontent.com/u/4656726?v=3","gravatar_id":"","url":"https://api.github.com/users/dtothefp","html_url":"https://github.com/dtothefp","followers_url":"https://api.github.com/users/dtothefp/followers","following_url":"https://api.github.com/users/dtothefp/following{/other_user}","gists_url":"https://api.github.com/users/dtothefp/gists{/gist_id}","starred_url":"https://api.github.com/users/dtothefp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dtothefp/subscriptions","organizations_url":"https://api.github.com/users/dtothefp/orgs","repos_url":"https://api.github.com/users/dtothefp/repos","events_url":"https://api.github.com/users/dtothefp/events{/privacy}","received_events_url":"https://api.github.com/users/dtothefp/received_events","type":"User","site_admin":false},"body":"@4vanger `tr` is no longer attached to the window and can be `require`d on server and client side","created_at":"2015-01-28T16:25:27Z","updated_at":"2015-01-28T16:25:27Z","html_url":"https://github.com/optimizely/marketing-website/pull/779#discussion_r23699095","pull_request_url":"https://api.github.com/repos/optimizely/marketing-website/pulls/779","_links":{"self":{"href":"https://api.github.com/repos/optimizely/marketing-website/pulls/comments/23699095"},"html":{"href":"https://github.com/optimizely/marketing-website/pull/779#discussion_r23699095"},"pull_request":{"href":"https://api.github.com/repos/optimizely/marketing-website/pulls/779"}}},"pull_request":{"url":"https://api.github.com/repos/optimizely/marketing-website/pulls/779","id":27167161,"html_url":"https://github.com/optimizely/marketing-website/pull/779","diff_url":"https://github.com/optimizely/marketing-website/pull/779.diff","patch_url":"https://github.com/optimizely/marketing-website/pull/779.patch","issue_url":"https://api.github.com/repos/optimizely/marketing-website/issues/779","number":779,"state":"open","locked":false,"title":"add webpack","user":{"login":"dtothefp","id":4656726,"avatar_url":"https://avatars.githubusercontent.com/u/4656726?v=3","gravatar_id":"","url":"https://api.github.com/users/dtothefp","html_url":"https://github.com/dtothefp","followers_url":"https://api.github.com/users/dtothefp/followers","following_url":"https://api.github.com/users/dtothefp/following{/other_user}","gists_url":"https://api.github.com/users/dtothefp/gists{/gist_id}","starred_url":"https://api.github.com/users/dtothefp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dtothefp/subscriptions","organizations_url":"https://api.github.com/users/dtothefp/orgs","repos_url":"https://api.github.com/users/dtothefp/repos","events_url":"https://api.github.com/users/dtothefp/events{/privacy}","received_events_url":"https://api.github.com/users/dtothefp/received_events","type":"User","site_admin":false},"body":"This PR addresses adding webpack module loader into the marketing repo.  I know this implementation isn't a very \"webpack\" way, but I'm first trying to mimic our build behavior that was happening with the `concat` task to get everything working, and then go back and refactor. \r\n\r\nIssues:\r\n- [x] ~~How to invoke sourcemaps in `grunt-webpack`~~ Addressed by adding `devtools: source-maps` in grunt config options for webpack task.  Forked `grunt-webpack` plugin and delete this option in everything except `dev` config.\r\n- [x]~~How to create a `production` flag in `grunt-webpack` in order to specify files to be uglified by webpack.~~ Forked `grunt-webpack` allowing to pass templated grunt config.\r\n- [x]~~Bundling vendor files into one file and making their globals available outside of the bundle.  Currently, I'm accomplishing this through the `script-loader`, which seems to concat all files into a string and call `eval` on it.~~ Libraries are required directly from Bower in `global.js` and bundles with all other global files.\r\n- [x] ~~Mimicking `concat` behavior for the `namespacePages` target https://github.com/optimizely/marketing-website/blob/master/grunt/concat.js. i.e. separate bundles will be created for `page` and `layout` level JS and they will be output to `dist/assets/js` directory in the appropriate directory structure `layout/*.js` or `page/*.js`.  I think this can be accomplished by something similar to http://stackoverflow.com/questions/22078420/grunt-webpack-wildcard-on-entry/22715972#22715972, in combination with some sort of function that parses whether it is a page or layout and appends the correct directory structure.~~ (this could be improved by having one task for pages and layouts, currently it is split in two tasks due to output path)\r\n- [x] ~~Currently `concat` is creating a banner and footer around JS bundles for catching errors in staging/production and creating a closure with the `window.optly.mrkt` global defined. May need to build a webpack loader that implements this functionality, or just continue to use concat.~~ Modified webpack BannerPlugin and required it in package.json from dtothefp github.\r\n- [ ] Handlebars is being bundled more than once.  Once in global.js and additional times in page/layout js. Find a way to have handlebars only bundles once, or bundled globally and not included in the hbs-loader requires ( not merge blocking )\r\n- [x] ~~Move JSHint into webpack.~~ All JSHint is happening through webpack except for the linting the test files. JSHint config for all tasks is still necessary as it is `require`d in the `webpack` grunt task.\r\n\r\n\r\n### To Test\r\n\r\nmake sure to `rm -rf node_modules && npm cache clear && npm i`\r\n`rm -rf bower_components && bower i`\r\nrun `grunt server`\r\n- watch the build, that webpack compiles correctly. It will be halted on any JSHint errors.\r\n- inspect your console to make sure there are no JS errors\r\n- inspect the dist directory and see that all of the JS files have an associate source map file and that individual modules are wrapped in the closure transforming window and document to w and d, respectively.\r\n- test a page like `/events` that uses a client side handlebars template. These are now being compiled with the webpack handlebars loader.\r\n- in the `webpack` grunt config file fine the `sharedPreLoaders` array.  Append a `console.log(targetName)` to the end of the query string \r\n```js\r\nloader: 'inject-filename-loader?inject=' + encodeURIComponent('var targetName = __filename.replace(\"website-guts/assets/js/\", \"\");\\n\\nconsole.log(targetName)')\r\n```\r\nrun the `grunt server` task again.  You will see all individual JS module file names logged.  This is what is used in error reporting to GA and debugging in production.\r\n- look in `website-guts/assets/js/global.js` and see how the `require` functions bootstrap the JS in a particular order.  This order is important for internal dependencies\r\n- play around with some es6 if you want\r\n- throw an error in the JS and check that it maps back to the appropriate source file through the source map http://cl.ly/27173s2T3p00\r\n- run grunt build and inspect that source map files no longer exist in the `dist` directory and that JS has been uglified\r\n- check it out in staging and see that there are no errors in the console.  Also, inspect that the source has been uglified.\r\n\r\n### Enhancements\r\n- we can now write es6\r\n- source maps for local JS debugging\r\n- JSHint inside webpack\r\n- elimination of handlebars and uglify task\r\n- drastic reduction of code in concat and JSHint task\r\n- Handlebars is no longer required in the vendor dependencies\r\n- future elimination of globals substituted by `require`s\r\n- JS files are watched by webpack which applies a cache. First build is slowish, but subsequent live changes with server running are fast.\r\n- probably lots of other stuff I'm not thinking of\r\n\r\n### Additional\r\n- removed `yepnope` from `bower.json`. We deprecated this a long time ago","created_at":"2015-01-11T19:48:36Z","updated_at":"2015-01-28T16:25:27Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b3d87007434c4b5fec5fcb76f7eb52d8f34892f9","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/optimizely/marketing-website/pulls/779/commits","review_comments_url":"https://api.github.com/repos/optimizely/marketing-website/pulls/779/comments","review_comment_url":"https://api.github.com/repos/optimizely/marketing-website/pulls/comments/{number}","comments_url":"https://api.github.com/repos/optimizely/marketing-website/issues/779/comments","statuses_url":"https://api.github.com/repos/optimizely/marketing-website/statuses/0e17a62890c726a3dfbe020b745527d44b67c3e3","head":{"label":"optimizely:dfoxpowell/webpack","ref":"dfoxpowell/webpack","sha":"0e17a62890c726a3dfbe020b745527d44b67c3e3","user":{"login":"optimizely","id":1274132,"avatar_url":"https://avatars.githubusercontent.com/u/1274132?v=3","gravatar_id":"","url":"https://api.github.com/users/optimizely","html_url":"https://github.com/optimizely","followers_url":"https://api.github.com/users/optimizely/followers","following_url":"https://api.github.com/users/optimizely/following{/other_user}","gists_url":"https://api.github.com/users/optimizely/gists{/gist_id}","starred_url":"https://api.github.com/users/optimizely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/optimizely/subscriptions","organizations_url":"https://api.github.com/users/optimizely/orgs","repos_url":"https://api.github.com/users/optimizely/repos","events_url":"https://api.github.com/users/optimizely/events{/privacy}","received_events_url":"https://api.github.com/users/optimizely/received_events","type":"Organization","site_admin":false},"repo":{"id":16794397,"name":"marketing-website","full_name":"optimizely/marketing-website","owner":{"login":"optimizely","id":1274132,"avatar_url":"https://avatars.githubusercontent.com/u/1274132?v=3","gravatar_id":"","url":"https://api.github.com/users/optimizely","html_url":"https://github.com/optimizely","followers_url":"https://api.github.com/users/optimizely/followers","following_url":"https://api.github.com/users/optimizely/following{/other_user}","gists_url":"https://api.github.com/users/optimizely/gists{/gist_id}","starred_url":"https://api.github.com/users/optimizely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/optimizely/subscriptions","organizations_url":"https://api.github.com/users/optimizely/orgs","repos_url":"https://api.github.com/users/optimizely/repos","events_url":"https://api.github.com/users/optimizely/events{/privacy}","received_events_url":"https://api.github.com/users/optimizely/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/optimizely/marketing-website","description":"Optimizely's marketing website--in progress.","fork":false,"url":"https://api.github.com/repos/optimizely/marketing-website","forks_url":"https://api.github.com/repos/optimizely/marketing-website/forks","keys_url":"https://api.github.com/repos/optimizely/marketing-website/keys{/key_id}","collaborators_url":"https://api.github.com/repos/optimizely/marketing-website/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/optimizely/marketing-website/teams","hooks_url":"https://api.github.com/repos/optimizely/marketing-website/hooks","issue_events_url":"https://api.github.com/repos/optimizely/marketing-website/issues/events{/number}","events_url":"https://api.github.com/repos/optimizely/marketing-website/events","assignees_url":"https://api.github.com/repos/optimizely/marketing-website/assignees{/user}","branches_url":"https://api.github.com/repos/optimizely/marketing-website/branches{/branch}","tags_url":"https://api.github.com/repos/optimizely/marketing-website/tags","blobs_url":"https://api.github.com/repos/optimizely/marketing-website/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/optimizely/marketing-website/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/optimizely/marketing-website/git/refs{/sha}","trees_url":"https://api.github.com/repos/optimizely/marketing-website/git/trees{/sha}","statuses_url":"https://api.github.com/repos/optimizely/marketing-website/statuses/{sha}","languages_url":"https://api.github.com/repos/optimizely/marketing-website/languages","stargazers_url":"https://api.github.com/repos/optimizely/marketing-website/stargazers","contributors_url":"https://api.github.com/repos/optimizely/marketing-website/contributors","subscribers_url":"https://api.github.com/repos/optimizely/marketing-website/subscribers","subscription_url":"https://api.github.com/repos/optimizely/marketing-website/subscription","commits_url":"https://api.github.com/repos/optimizely/marketing-website/commits{/sha}","git_commits_url":"https://api.github.com/repos/optimizely/marketing-website/git/commits{/sha}","comments_url":"https://api.github.com/repos/optimizely/marketing-website/comments{/number}","issue_comment_url":"https://api.github.com/repos/optimizely/marketing-website/issues/comments/{number}","contents_url":"https://api.github.com/repos/optimizely/marketing-website/contents/{+path}","compare_url":"https://api.github.com/repos/optimizely/marketing-website/compare/{base}...{head}","merges_url":"https://api.github.com/repos/optimizely/marketing-website/merges","archive_url":"https://api.github.com/repos/optimizely/marketing-website/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/optimizely/marketing-website/downloads","issues_url":"https://api.github.com/repos/optimizely/marketing-website/issues{/number}","pulls_url":"https://api.github.com/repos/optimizely/marketing-website/pulls{/number}","milestones_url":"https://api.github.com/repos/optimizely/marketing-website/milestones{/number}","notifications_url":"https://api.github.com/repos/optimizely/marketing-website/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/optimizely/marketing-website/labels{/name}","releases_url":"https://api.github.com/repos/optimizely/marketing-website/releases{/id}","created_at":"2014-02-13T06:45:06Z","updated_at":"2015-01-28T15:01:58Z","pushed_at":"2015-01-28T16:24:13Z","git_url":"git://github.com/optimizely/marketing-website.git","ssh_url":"git@github.com:optimizely/marketing-website.git","clone_url":"https://github.com/optimizely/marketing-website.git","svn_url":"https://github.com/optimizely/marketing-website","homepage":"https://www.optimizely.com","size":383203,"stargazers_count":13,"watchers_count":13,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":13,"mirror_url":null,"open_issues_count":25,"forks":13,"open_issues":25,"watchers":13,"default_branch":"master"}},"base":{"label":"optimizely:master","ref":"master","sha":"9a31e0b8c05a018385bc10d7b7caf7b86139eb35","user":{"login":"optimizely","id":1274132,"avatar_url":"https://avatars.githubusercontent.com/u/1274132?v=3","gravatar_id":"","url":"https://api.github.com/users/optimizely","html_url":"https://github.com/optimizely","followers_url":"https://api.github.com/users/optimizely/followers","following_url":"https://api.github.com/users/optimizely/following{/other_user}","gists_url":"https://api.github.com/users/optimizely/gists{/gist_id}","starred_url":"https://api.github.com/users/optimizely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/optimizely/subscriptions","organizations_url":"https://api.github.com/users/optimizely/orgs","repos_url":"https://api.github.com/users/optimizely/repos","events_url":"https://api.github.com/users/optimizely/events{/privacy}","received_events_url":"https://api.github.com/users/optimizely/received_events","type":"Organization","site_admin":false},"repo":{"id":16794397,"name":"marketing-website","full_name":"optimizely/marketing-website","owner":{"login":"optimizely","id":1274132,"avatar_url":"https://avatars.githubusercontent.com/u/1274132?v=3","gravatar_id":"","url":"https://api.github.com/users/optimizely","html_url":"https://github.com/optimizely","followers_url":"https://api.github.com/users/optimizely/followers","following_url":"https://api.github.com/users/optimizely/following{/other_user}","gists_url":"https://api.github.com/users/optimizely/gists{/gist_id}","starred_url":"https://api.github.com/users/optimizely/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/optimizely/subscriptions","organizations_url":"https://api.github.com/users/optimizely/orgs","repos_url":"https://api.github.com/users/optimizely/repos","events_url":"https://api.github.com/users/optimizely/events{/privacy}","received_events_url":"https://api.github.com/users/optimizely/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/optimizely/marketing-website","description":"Optimizely's marketing website--in progress.","fork":false,"url":"https://api.github.com/repos/optimizely/marketing-website","forks_url":"https://api.github.com/repos/optimizely/marketing-website/forks","keys_url":"https://api.github.com/repos/optimizely/marketing-website/keys{/key_id}","collaborators_url":"https://api.github.com/repos/optimizely/marketing-website/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/optimizely/marketing-website/teams","hooks_url":"https://api.github.com/repos/optimizely/marketing-website/hooks","issue_events_url":"https://api.github.com/repos/optimizely/marketing-website/issues/events{/number}","events_url":"https://api.github.com/repos/optimizely/marketing-website/events","assignees_url":"https://api.github.com/repos/optimizely/marketing-website/assignees{/user}","branches_url":"https://api.github.com/repos/optimizely/marketing-website/branches{/branch}","tags_url":"https://api.github.com/repos/optimizely/marketing-website/tags","blobs_url":"https://api.github.com/repos/optimizely/marketing-website/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/optimizely/marketing-website/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/optimizely/marketing-website/git/refs{/sha}","trees_url":"https://api.github.com/repos/optimizely/marketing-website/git/trees{/sha}","statuses_url":"https://api.github.com/repos/optimizely/marketing-website/statuses/{sha}","languages_url":"https://api.github.com/repos/optimizely/marketing-website/languages","stargazers_url":"https://api.github.com/repos/optimizely/marketing-website/stargazers","contributors_url":"https://api.github.com/repos/optimizely/marketing-website/contributors","subscribers_url":"https://api.github.com/repos/optimizely/marketing-website/subscribers","subscription_url":"https://api.github.com/repos/optimizely/marketing-website/subscription","commits_url":"https://api.github.com/repos/optimizely/marketing-website/commits{/sha}","git_commits_url":"https://api.github.com/repos/optimizely/marketing-website/git/commits{/sha}","comments_url":"https://api.github.com/repos/optimizely/marketing-website/comments{/number}","issue_comment_url":"https://api.github.com/repos/optimizely/marketing-website/issues/comments/{number}","contents_url":"https://api.github.com/repos/optimizely/marketing-website/contents/{+path}","compare_url":"https://api.github.com/repos/optimizely/marketing-website/compare/{base}...{head}","merges_url":"https://api.github.com/repos/optimizely/marketing-website/merges","archive_url":"https://api.github.com/repos/optimizely/marketing-website/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/optimizely/marketing-website/downloads","issues_url":"https://api.github.com/repos/optimizely/marketing-website/issues{/number}","pulls_url":"https://api.github.com/repos/optimizely/marketing-website/pulls{/number}","milestones_url":"https://api.github.com/repos/optimizely/marketing-website/milestones{/number}","notifications_url":"https://api.github.com/repos/optimizely/marketing-website/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/optimizely/marketing-website/labels{/name}","releases_url":"https://api.github.com/repos/optimizely/marketing-website/releases{/id}","created_at":"2014-02-13T06:45:06Z","updated_at":"2015-01-28T15:01:58Z","pushed_at":"2015-01-28T16:24:13Z","git_url":"git://github.com/optimizely/marketing-website.git","ssh_url":"git@github.com:optimizely/marketing-website.git","clone_url":"https://github.com/optimizely/marketing-website.git","svn_url":"https://github.com/optimizely/marketing-website","homepage":"https://www.optimizely.com","size":383203,"stargazers_count":13,"watchers_count":13,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":13,"mirror_url":null,"open_issues_count":25,"forks":13,"open_issues":25,"watchers":13,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/optimizely/marketing-website/pulls/779"},"html":{"href":"https://github.com/optimizely/marketing-website/pull/779"},"issue":{"href":"https://api.github.com/repos/optimizely/marketing-website/issues/779"},"comments":{"href":"https://api.github.com/repos/optimizely/marketing-website/issues/779/comments"},"review_comments":{"href":"https://api.github.com/repos/optimizely/marketing-website/pulls/779/comments"},"review_comment":{"href":"https://api.github.com/repos/optimizely/marketing-website/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/optimizely/marketing-website/pulls/779/commits"},"statuses":{"href":"https://api.github.com/repos/optimizely/marketing-website/statuses/0e17a62890c726a3dfbe020b745527d44b67c3e3"}}}}