{"action":"created","comment":{"url":"https://api.github.com/repos/yabwe/medium-editor/pulls/comments/31625621","id":31625621,"diff_hunk":"@@ -370,81 +373,41 @@ function MediumEditor(elements, options) {\n         }\n     }\n \n-    function initPlaceholder(options) {\n-        return new MediumEditor.extensions.placeholder(\n-            Util.extend({}, options)\n-        );\n-    }\n-\n-    function initAnchorPreview(options) {\n-        return new MediumEditor.extensions.anchorPreview(\n-            Util.extend({}, options)\n-        );\n-    }\n-\n-    function initAnchorForm(options) {\n-        return new MediumEditor.extensions.anchor(\n-            Util.extend({}, options)\n-        );\n-    }\n+    function initExtensions() {\n \n-    function initPasteHandler(options) {\n-        return new MediumEditor.extensions.paste(\n-            Util.extend({}, options)\n-        );\n-    }\n+        this.extensions = [];\n \n-    function initCommands() {\n-        var buttons = this.options.buttons,\n-            extensions = this.options.extensions,\n-            ext,\n-            name;\n-        this.commands = [];\n-\n-        buttons.forEach(function (buttonName) {\n-            if (extensions[buttonName]) {\n-                ext = initExtension(extensions[buttonName], buttonName, this);\n-                this.commands.push(ext);\n-            } else if (buttonName === 'anchor') {\n-                ext = initExtension(initAnchorForm.call(this, this.options.anchor), 'anchor', this);\n-                this.commands.push(ext);\n-            } else if (buttonName === 'fontsize') {\n-                ext = initExtension(new MediumEditor.extensions.fontSize(), buttonName, this);\n-                this.commands.push(ext);\n-            } else if (ButtonsData.hasOwnProperty(buttonName)) {\n-                ext = initExtension(new MediumEditor.extensions.button(ButtonsData[buttonName]), buttonName, this);\n-                this.commands.push(ext);\n+        // Passed in extensions\n+        Object.keys(this.options.extensions).forEach(function (name) {\n+            // Always save the toolbar extension for last\n+            if (name !== 'toolbar' && this.options.extensions[name]) {\n+                this.extensions.push(initExtension(this.options.extensions[name], name, this));\n             }\n         }, this);\n \n-        for (name in extensions) {\n-            if (extensions.hasOwnProperty(name) && buttons.indexOf(name) === -1) {\n-                ext = initExtension(extensions[name], name, this);\n-                this.commands.push(ext);\n+        // Built-in extensions\n+        var builtIns = {\n+            paste: true,\n+            anchorPreview: isAnchorPreviewEnabled.call(this),\n+            autoLink: isAutoLinkEnabled.call(this),\n+            imageDragging: isImageDraggingEnabled.call(this),\n+            keyboardCommands: isKeyboardCommandsEnabled.call(this),\n+            placeholder: isPlaceholderEnabled.call(this)\n+        };\n+        Object.keys(builtIns).forEach(function (name) {\n+            if (builtIns[name]) {\n+                this.addBuiltInExtension(name);\n             }\n-        }\n-\n-        // Only add default paste extension if it wasn't overriden\n-        if (!extensions['paste']) {\n-            this.commands.push(initExtension(initPasteHandler.call(this, this.options.paste), 'paste', this));\n-        }\n-\n-        // Add AnchorPreview as extension if needed\n-        if (shouldAddDefaultAnchorPreview.call(this)) {\n-            this.commands.push(initExtension(initAnchorPreview.call(this, this.options.anchorPreview), 'anchor-preview', this));\n-        }\n-\n-        if (shouldAddDefaultAutoLink.call(this)) {\n-            this.commands.push(initExtension(new MediumEditor.extensions.autoLink(), 'auto-link', this));\n-        }\n+        }, this);\n \n-        if (shouldAddDefaultImageDragging.call(this)) {\n-            this.commands.push(initExtension(new MediumEditor.extensions.imageDragging(), 'image-dragging', this));\n+        // Create toolbar\n+        var toolbarExtension = this.options.extensions['toolbar'];\n+        if (!toolbarExtension && isToolbarEnabled.call(this)) {\n+            toolbarExtension = new MediumEditor.extensions.toolbar(this.options.toolbar);\n         }\n \n-        if (shouldAddDefaultPlaceholder.call(this)) {\n-            var placeholderOpts = (typeof this.options.placeholder === 'string') ? {} : this.options.placeholder;\n-            this.commands.push(initExtension(initPlaceholder.call(this, placeholderOpts), 'placeholder', this));\n+        if (toolbarExtension) {\n+            this.extensions.push(initExtension(toolbarExtension, 'toolbar', this));\n         }","path":"src/js/core.js","position":251,"original_position":251,"commit_id":"d470e27aa221fe64c23c49db5bbd56d129abd67e","original_commit_id":"d470e27aa221fe64c23c49db5bbd56d129abd67e","user":{"login":"j0k3r","id":62333,"avatar_url":"https://avatars.githubusercontent.com/u/62333?v=3","gravatar_id":"","url":"https://api.github.com/users/j0k3r","html_url":"https://github.com/j0k3r","followers_url":"https://api.github.com/users/j0k3r/followers","following_url":"https://api.github.com/users/j0k3r/following{/other_user}","gists_url":"https://api.github.com/users/j0k3r/gists{/gist_id}","starred_url":"https://api.github.com/users/j0k3r/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/j0k3r/subscriptions","organizations_url":"https://api.github.com/users/j0k3r/orgs","repos_url":"https://api.github.com/users/j0k3r/repos","events_url":"https://api.github.com/users/j0k3r/events{/privacy}","received_events_url":"https://api.github.com/users/j0k3r/received_events","type":"User","site_admin":false},"body":"Oh I see, I didn't understand why you did that `if`. It's because you can pass a custom extension called `toolbar`. All right :)\r\nYou should add a comment about that","created_at":"2015-06-03T14:07:33Z","updated_at":"2015-06-03T14:07:33Z","html_url":"https://github.com/yabwe/medium-editor/pull/664#discussion_r31625621","pull_request_url":"https://api.github.com/repos/yabwe/medium-editor/pulls/664","_links":{"self":{"href":"https://api.github.com/repos/yabwe/medium-editor/pulls/comments/31625621"},"html":{"href":"https://github.com/yabwe/medium-editor/pull/664#discussion_r31625621"},"pull_request":{"href":"https://api.github.com/repos/yabwe/medium-editor/pulls/664"}}},"pull_request":{"url":"https://api.github.com/repos/yabwe/medium-editor/pulls/664","id":36673692,"html_url":"https://github.com/yabwe/medium-editor/pull/664","diff_url":"https://github.com/yabwe/medium-editor/pull/664.diff","patch_url":"https://github.com/yabwe/medium-editor/pull/664.patch","issue_url":"https://api.github.com/repos/yabwe/medium-editor/issues/664","number":664,"state":"open","locked":false,"title":"Convert Toolbar into an extension","user":{"login":"nmielnik","id":2444240,"avatar_url":"https://avatars.githubusercontent.com/u/2444240?v=3","gravatar_id":"","url":"https://api.github.com/users/nmielnik","html_url":"https://github.com/nmielnik","followers_url":"https://api.github.com/users/nmielnik/followers","following_url":"https://api.github.com/users/nmielnik/following{/other_user}","gists_url":"https://api.github.com/users/nmielnik/gists{/gist_id}","starred_url":"https://api.github.com/users/nmielnik/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nmielnik/subscriptions","organizations_url":"https://api.github.com/users/nmielnik/orgs","repos_url":"https://api.github.com/users/nmielnik/repos","events_url":"https://api.github.com/users/nmielnik/events{/privacy}","received_events_url":"https://api.github.com/users/nmielnik/received_events","type":"User","site_admin":false},"body":"### Summary\r\nThis PR covers converting the toolbar into a built-in extension, that is extendable and override-able.\r\n\r\nNow the following options will be passed as sub-options inside the toolbar options group:\r\n```js\r\nnew MediumEditor('.editor', {\r\n  toolbar: {\r\n    buttons: // array of button names,\r\n    align: // left | center | right (previously toolbarAlign),\r\n    diffLeft: // left offset of toolbar,\r\n    diffTop: // top offset of toolbar,\r\n    firstButtonClass: // class added to first button in toolbar,\r\n    lastButtonClass: // class added to last button in toolbar,\r\n    static: // static positioning of toolbar (previously staticToolbar),\r\n    sticky: // sticky positioning of toolbar (previously stickyToolbar),\r\n    updateOnEmptySelection: // updating static toolbar on collapsed selection\r\n  }\r\n});\r\n```\r\n\r\nFurther, the toolbar will be disabled by passing `false` as the `toolbar` option:\r\n```js\r\nnew MediumEditor('.editor', {\r\n  toolbar: false\r\n});\r\n```\r\n\r\n### Additional Changes\r\nIn order to separate the close dependency between MediumEditor and the toolbar, there were some extra changes that were needed:\r\n* Maintain a global array of editor instances to use for generating a unique id for each editor\r\n  * Previously the editor depended on counting the number of toolbars on the page to generate a unique-id\r\n* Expose a new `addBuiltInExtension()` method on MediumEditor.\r\n  * This allows the Toolbar to completely control creating and maintaining the buttons that go in the toolbar, even though they live in the `.extensions` array inside MediumEditor\r\n* Create a new `KeyboardCommands` extension which handles the <kbd>CTRL</kbd> + <kbd>B</kbd>, <kbd>CTRL</kbd> + <kbd>I</kbd>, and <kbd>CTRL</kbd> + <kbd>U</kbd> behavior.\r\n  * This was originally handled by the buttons, but now that the buttons are completely owned by the toolbar, this behavior should be allowed to exist even if the toolbar or buttons don't exist\r\n\r\n### Why are there so many changes?\r\n* The toolbar was referenced directly via `editor.toolbar` in an immense amount of places in the test code.  Thus, there's a ton of find-and-replace now that the toolbar has to be retrieved via a call to `.getExtensionByName()`\r\n* Converting how 9 toolbar options are passed into medium editor means updating a ton of the demos and tests as well\r\n* Converting the toolbar into an extendable extension took a decent amount of work!\r\n\r\n##### NOTE: Extensive wiki updates for the buttons and extensions documentation will be coming in the v5.0.0 release","created_at":"2015-06-01T21:37:27Z","updated_at":"2015-06-03T14:07:33Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1f78bcd7f62b4c26d52c583d060be116f88ff69a","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/yabwe/medium-editor/pulls/664/commits","review_comments_url":"https://api.github.com/repos/yabwe/medium-editor/pulls/664/comments","review_comment_url":"https://api.github.com/repos/yabwe/medium-editor/pulls/comments{/number}","comments_url":"https://api.github.com/repos/yabwe/medium-editor/issues/664/comments","statuses_url":"https://api.github.com/repos/yabwe/medium-editor/statuses/d470e27aa221fe64c23c49db5bbd56d129abd67e","head":{"label":"yabwe:toolbar-extension","ref":"toolbar-extension","sha":"d470e27aa221fe64c23c49db5bbd56d129abd67e","user":{"login":"yabwe","id":12655868,"avatar_url":"https://avatars.githubusercontent.com/u/12655868?v=3","gravatar_id":"","url":"https://api.github.com/users/yabwe","html_url":"https://github.com/yabwe","followers_url":"https://api.github.com/users/yabwe/followers","following_url":"https://api.github.com/users/yabwe/following{/other_user}","gists_url":"https://api.github.com/users/yabwe/gists{/gist_id}","starred_url":"https://api.github.com/users/yabwe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yabwe/subscriptions","organizations_url":"https://api.github.com/users/yabwe/orgs","repos_url":"https://api.github.com/users/yabwe/repos","events_url":"https://api.github.com/users/yabwe/events{/privacy}","received_events_url":"https://api.github.com/users/yabwe/received_events","type":"Organization","site_admin":false},"repo":{"id":10365411,"name":"medium-editor","full_name":"yabwe/medium-editor","owner":{"login":"yabwe","id":12655868,"avatar_url":"https://avatars.githubusercontent.com/u/12655868?v=3","gravatar_id":"","url":"https://api.github.com/users/yabwe","html_url":"https://github.com/yabwe","followers_url":"https://api.github.com/users/yabwe/followers","following_url":"https://api.github.com/users/yabwe/following{/other_user}","gists_url":"https://api.github.com/users/yabwe/gists{/gist_id}","starred_url":"https://api.github.com/users/yabwe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yabwe/subscriptions","organizations_url":"https://api.github.com/users/yabwe/orgs","repos_url":"https://api.github.com/users/yabwe/repos","events_url":"https://api.github.com/users/yabwe/events{/privacy}","received_events_url":"https://api.github.com/users/yabwe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/yabwe/medium-editor","description":"Medium.com WYSIWYG editor clone. Uses contenteditable API to implement a rich text solution.","fork":false,"url":"https://api.github.com/repos/yabwe/medium-editor","forks_url":"https://api.github.com/repos/yabwe/medium-editor/forks","keys_url":"https://api.github.com/repos/yabwe/medium-editor/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yabwe/medium-editor/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yabwe/medium-editor/teams","hooks_url":"https://api.github.com/repos/yabwe/medium-editor/hooks","issue_events_url":"https://api.github.com/repos/yabwe/medium-editor/issues/events{/number}","events_url":"https://api.github.com/repos/yabwe/medium-editor/events","assignees_url":"https://api.github.com/repos/yabwe/medium-editor/assignees{/user}","branches_url":"https://api.github.com/repos/yabwe/medium-editor/branches{/branch}","tags_url":"https://api.github.com/repos/yabwe/medium-editor/tags","blobs_url":"https://api.github.com/repos/yabwe/medium-editor/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yabwe/medium-editor/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yabwe/medium-editor/git/refs{/sha}","trees_url":"https://api.github.com/repos/yabwe/medium-editor/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yabwe/medium-editor/statuses/{sha}","languages_url":"https://api.github.com/repos/yabwe/medium-editor/languages","stargazers_url":"https://api.github.com/repos/yabwe/medium-editor/stargazers","contributors_url":"https://api.github.com/repos/yabwe/medium-editor/contributors","subscribers_url":"https://api.github.com/repos/yabwe/medium-editor/subscribers","subscription_url":"https://api.github.com/repos/yabwe/medium-editor/subscription","commits_url":"https://api.github.com/repos/yabwe/medium-editor/commits{/sha}","git_commits_url":"https://api.github.com/repos/yabwe/medium-editor/git/commits{/sha}","comments_url":"https://api.github.com/repos/yabwe/medium-editor/comments{/number}","issue_comment_url":"https://api.github.com/repos/yabwe/medium-editor/issues/comments{/number}","contents_url":"https://api.github.com/repos/yabwe/medium-editor/contents/{+path}","compare_url":"https://api.github.com/repos/yabwe/medium-editor/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yabwe/medium-editor/merges","archive_url":"https://api.github.com/repos/yabwe/medium-editor/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yabwe/medium-editor/downloads","issues_url":"https://api.github.com/repos/yabwe/medium-editor/issues{/number}","pulls_url":"https://api.github.com/repos/yabwe/medium-editor/pulls{/number}","milestones_url":"https://api.github.com/repos/yabwe/medium-editor/milestones{/number}","notifications_url":"https://api.github.com/repos/yabwe/medium-editor/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yabwe/medium-editor/labels{/name}","releases_url":"https://api.github.com/repos/yabwe/medium-editor/releases{/id}","created_at":"2013-05-29T17:40:11Z","updated_at":"2015-06-03T10:39:33Z","pushed_at":"2015-06-03T01:23:27Z","git_url":"git://github.com/yabwe/medium-editor.git","ssh_url":"git@github.com:yabwe/medium-editor.git","clone_url":"https://github.com/yabwe/medium-editor.git","svn_url":"https://github.com/yabwe/medium-editor","homepage":"https://yabwe.github.io/medium-editor/","size":13324,"stargazers_count":5054,"watchers_count":5054,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":622,"mirror_url":null,"open_issues_count":89,"forks":622,"open_issues":89,"watchers":5054,"default_branch":"master"}},"base":{"label":"yabwe:v5","ref":"v5","sha":"ef6f619a468ed79a89f0a108c034ea90177c3d88","user":{"login":"yabwe","id":12655868,"avatar_url":"https://avatars.githubusercontent.com/u/12655868?v=3","gravatar_id":"","url":"https://api.github.com/users/yabwe","html_url":"https://github.com/yabwe","followers_url":"https://api.github.com/users/yabwe/followers","following_url":"https://api.github.com/users/yabwe/following{/other_user}","gists_url":"https://api.github.com/users/yabwe/gists{/gist_id}","starred_url":"https://api.github.com/users/yabwe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yabwe/subscriptions","organizations_url":"https://api.github.com/users/yabwe/orgs","repos_url":"https://api.github.com/users/yabwe/repos","events_url":"https://api.github.com/users/yabwe/events{/privacy}","received_events_url":"https://api.github.com/users/yabwe/received_events","type":"Organization","site_admin":false},"repo":{"id":10365411,"name":"medium-editor","full_name":"yabwe/medium-editor","owner":{"login":"yabwe","id":12655868,"avatar_url":"https://avatars.githubusercontent.com/u/12655868?v=3","gravatar_id":"","url":"https://api.github.com/users/yabwe","html_url":"https://github.com/yabwe","followers_url":"https://api.github.com/users/yabwe/followers","following_url":"https://api.github.com/users/yabwe/following{/other_user}","gists_url":"https://api.github.com/users/yabwe/gists{/gist_id}","starred_url":"https://api.github.com/users/yabwe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yabwe/subscriptions","organizations_url":"https://api.github.com/users/yabwe/orgs","repos_url":"https://api.github.com/users/yabwe/repos","events_url":"https://api.github.com/users/yabwe/events{/privacy}","received_events_url":"https://api.github.com/users/yabwe/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/yabwe/medium-editor","description":"Medium.com WYSIWYG editor clone. Uses contenteditable API to implement a rich text solution.","fork":false,"url":"https://api.github.com/repos/yabwe/medium-editor","forks_url":"https://api.github.com/repos/yabwe/medium-editor/forks","keys_url":"https://api.github.com/repos/yabwe/medium-editor/keys{/key_id}","collaborators_url":"https://api.github.com/repos/yabwe/medium-editor/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/yabwe/medium-editor/teams","hooks_url":"https://api.github.com/repos/yabwe/medium-editor/hooks","issue_events_url":"https://api.github.com/repos/yabwe/medium-editor/issues/events{/number}","events_url":"https://api.github.com/repos/yabwe/medium-editor/events","assignees_url":"https://api.github.com/repos/yabwe/medium-editor/assignees{/user}","branches_url":"https://api.github.com/repos/yabwe/medium-editor/branches{/branch}","tags_url":"https://api.github.com/repos/yabwe/medium-editor/tags","blobs_url":"https://api.github.com/repos/yabwe/medium-editor/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/yabwe/medium-editor/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/yabwe/medium-editor/git/refs{/sha}","trees_url":"https://api.github.com/repos/yabwe/medium-editor/git/trees{/sha}","statuses_url":"https://api.github.com/repos/yabwe/medium-editor/statuses/{sha}","languages_url":"https://api.github.com/repos/yabwe/medium-editor/languages","stargazers_url":"https://api.github.com/repos/yabwe/medium-editor/stargazers","contributors_url":"https://api.github.com/repos/yabwe/medium-editor/contributors","subscribers_url":"https://api.github.com/repos/yabwe/medium-editor/subscribers","subscription_url":"https://api.github.com/repos/yabwe/medium-editor/subscription","commits_url":"https://api.github.com/repos/yabwe/medium-editor/commits{/sha}","git_commits_url":"https://api.github.com/repos/yabwe/medium-editor/git/commits{/sha}","comments_url":"https://api.github.com/repos/yabwe/medium-editor/comments{/number}","issue_comment_url":"https://api.github.com/repos/yabwe/medium-editor/issues/comments{/number}","contents_url":"https://api.github.com/repos/yabwe/medium-editor/contents/{+path}","compare_url":"https://api.github.com/repos/yabwe/medium-editor/compare/{base}...{head}","merges_url":"https://api.github.com/repos/yabwe/medium-editor/merges","archive_url":"https://api.github.com/repos/yabwe/medium-editor/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/yabwe/medium-editor/downloads","issues_url":"https://api.github.com/repos/yabwe/medium-editor/issues{/number}","pulls_url":"https://api.github.com/repos/yabwe/medium-editor/pulls{/number}","milestones_url":"https://api.github.com/repos/yabwe/medium-editor/milestones{/number}","notifications_url":"https://api.github.com/repos/yabwe/medium-editor/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/yabwe/medium-editor/labels{/name}","releases_url":"https://api.github.com/repos/yabwe/medium-editor/releases{/id}","created_at":"2013-05-29T17:40:11Z","updated_at":"2015-06-03T10:39:33Z","pushed_at":"2015-06-03T01:23:27Z","git_url":"git://github.com/yabwe/medium-editor.git","ssh_url":"git@github.com:yabwe/medium-editor.git","clone_url":"https://github.com/yabwe/medium-editor.git","svn_url":"https://github.com/yabwe/medium-editor","homepage":"https://yabwe.github.io/medium-editor/","size":13324,"stargazers_count":5054,"watchers_count":5054,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":622,"mirror_url":null,"open_issues_count":89,"forks":622,"open_issues":89,"watchers":5054,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/yabwe/medium-editor/pulls/664"},"html":{"href":"https://github.com/yabwe/medium-editor/pull/664"},"issue":{"href":"https://api.github.com/repos/yabwe/medium-editor/issues/664"},"comments":{"href":"https://api.github.com/repos/yabwe/medium-editor/issues/664/comments"},"review_comments":{"href":"https://api.github.com/repos/yabwe/medium-editor/pulls/664/comments"},"review_comment":{"href":"https://api.github.com/repos/yabwe/medium-editor/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/yabwe/medium-editor/pulls/664/commits"},"statuses":{"href":"https://api.github.com/repos/yabwe/medium-editor/statuses/d470e27aa221fe64c23c49db5bbd56d129abd67e"}}}}