From d1f4d5a7399b5f551734ccb10ae8836ad7d8cb6f Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Wed, 20 Jun 2018 13:35:33 +0930 Subject: [PATCH] Webpack (#33) See https://github.com/flarum/core/pull/1367 * Replace gulp with webpack and npm scripts for JS compilation * Set up Travis CI to commit compiled JS * Restructure `js` directory; only one instance of npm, forum/admin are "submodules" * Restructure `less` directory --- extensions/mentions/.deploy.enc | Bin 0 -> 3248 bytes extensions/mentions/.gitattributes | 2 +- extensions/mentions/.gitignore | 4 +- extensions/mentions/.travis.yml | 15 + extensions/mentions/bootstrap.php | 6 +- extensions/mentions/js/forum.js | 10 + extensions/mentions/js/forum/Gulpfile.js | 10 - .../mentions/js/forum/dist/extension.js | 1322 ----- extensions/mentions/js/forum/package.json | 8 - extensions/mentions/js/package-lock.json | 4700 +++++++++++++++++ extensions/mentions/js/package.json | 14 + .../forum}/addComposerAutocomplete.js | 4 +- .../src => src/forum}/addMentionedByList.js | 0 .../forum}/addPostMentionPreviews.js | 0 .../src => src/forum}/addPostQuoteButton.js | 4 +- .../src => src/forum}/addPostReplyAction.js | 2 +- .../forum}/components/AutocompleteDropdown.js | 0 .../forum}/components/MentionsUserPage.js | 0 .../components/PostMentionedNotification.js | 0 .../forum}/components/PostQuoteButton.js | 2 +- .../components/UserMentionedNotification.js | 0 .../{forum/src/main.js => src/forum/index.js} | 16 +- .../{forum/src => src/forum}/utils/reply.js | 0 .../src => src/forum}/utils/selectedText.js | 0 .../src => src/forum}/utils/textFormatter.js | 0 extensions/mentions/js/webpack.config.js | 3 + .../less/{forum/extension.less => forum.less} | 0 extensions/mentions/scripts/compile.sh | 27 - 28 files changed, 4762 insertions(+), 1387 deletions(-) create mode 100644 extensions/mentions/.deploy.enc create mode 100644 extensions/mentions/.travis.yml create mode 100644 extensions/mentions/js/forum.js delete mode 100644 extensions/mentions/js/forum/Gulpfile.js delete mode 100644 extensions/mentions/js/forum/dist/extension.js delete mode 100644 extensions/mentions/js/forum/package.json create mode 100644 extensions/mentions/js/package-lock.json create mode 100644 extensions/mentions/js/package.json rename extensions/mentions/js/{forum/src => src/forum}/addComposerAutocomplete.js (98%) rename extensions/mentions/js/{forum/src => src/forum}/addMentionedByList.js (100%) rename extensions/mentions/js/{forum/src => src/forum}/addPostMentionPreviews.js (100%) rename extensions/mentions/js/{forum/src => src/forum}/addPostQuoteButton.js (91%) rename extensions/mentions/js/{forum/src => src/forum}/addPostReplyAction.js (92%) rename extensions/mentions/js/{forum/src => src/forum}/components/AutocompleteDropdown.js (100%) rename extensions/mentions/js/{forum/src => src/forum}/components/MentionsUserPage.js (100%) rename extensions/mentions/js/{forum/src => src/forum}/components/PostMentionedNotification.js (100%) rename extensions/mentions/js/{forum/src => src/forum}/components/PostQuoteButton.js (96%) rename extensions/mentions/js/{forum/src => src/forum}/components/UserMentionedNotification.js (100%) rename extensions/mentions/js/{forum/src/main.js => src/forum/index.js} (78%) rename extensions/mentions/js/{forum/src => src/forum}/utils/reply.js (100%) rename extensions/mentions/js/{forum/src => src/forum}/utils/selectedText.js (100%) rename extensions/mentions/js/{forum/src => src/forum}/utils/textFormatter.js (100%) create mode 100644 extensions/mentions/js/webpack.config.js rename extensions/mentions/less/{forum/extension.less => forum.less} (100%) delete mode 100755 extensions/mentions/scripts/compile.sh diff --git a/extensions/mentions/.deploy.enc b/extensions/mentions/.deploy.enc new file mode 100644 index 0000000000000000000000000000000000000000..addfced11ab58daadfa9ff3bc1d9bdedfb965e19 GIT binary patch literal 3248 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 literal 0 HcmV?d00001 diff --git a/extensions/mentions/.gitattributes b/extensions/mentions/.gitattributes index 053481a3e..16ac2892f 100644 --- a/extensions/mentions/.gitattributes +++ b/extensions/mentions/.gitattributes @@ -2,4 +2,4 @@ .gitignore export-ignore .travis.yml export-ignore -js/*/dist/*.js -diff +js/dist/* -diff diff --git a/extensions/mentions/.gitignore b/extensions/mentions/.gitignore index 43eeee7fe..7f43257e7 100644 --- a/extensions/mentions/.gitignore +++ b/extensions/mentions/.gitignore @@ -2,5 +2,5 @@ composer.phar .DS_Store Thumbs.db -bower_components -node_modules \ No newline at end of file +node_modules +js/dist/* diff --git a/extensions/mentions/.travis.yml b/extensions/mentions/.travis.yml new file mode 100644 index 000000000..79eacd253 --- /dev/null +++ b/extensions/mentions/.travis.yml @@ -0,0 +1,15 @@ +language: minimal + +sudo: false + +cache: + directories: + - $HOME/.npm + +jobs: + include: + - stage: build + if: branch = master AND type = push + script: curl -s https://raw.githubusercontent.com/flarum/core/master/.travis/build.sh | bash -s - + -k $encrypted_e5bd9d54e015_key + -i $encrypted_e5bd9d54e015_iv diff --git a/extensions/mentions/bootstrap.php b/extensions/mentions/bootstrap.php index 67b38fc97..b20093c4e 100644 --- a/extensions/mentions/bootstrap.php +++ b/extensions/mentions/bootstrap.php @@ -16,9 +16,9 @@ use Illuminate\Contracts\View\Factory; return [ (new Extend\Assets('forum')) - ->asset(__DIR__.'/js/forum/dist/extension.js') - ->asset(__DIR__.'/less/forum/extension.less') - ->bootstrapper('flarum/mentions/main'), + ->js(__DIR__.'/js/dist/forum.js') + ->asset(__DIR__.'/less/forum.less'), + function (Dispatcher $events, Factory $views) { $events->subscribe(Listener\AddPostMentionedByRelationship::class); $events->subscribe(Listener\FormatPostMentions::class); diff --git a/extensions/mentions/js/forum.js b/extensions/mentions/js/forum.js new file mode 100644 index 000000000..cc78f6edc --- /dev/null +++ b/extensions/mentions/js/forum.js @@ -0,0 +1,10 @@ +/* + * This file is part of Flarum. + * + * (c) Toby Zerner + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +export * from './src/forum'; diff --git a/extensions/mentions/js/forum/Gulpfile.js b/extensions/mentions/js/forum/Gulpfile.js deleted file mode 100644 index 0dc548119..000000000 --- a/extensions/mentions/js/forum/Gulpfile.js +++ /dev/null @@ -1,10 +0,0 @@ -var gulp = require('flarum-gulp'); - -gulp({ - modules: { - 'flarum/mentions': 'src/**/*.js' - }, - files: [ - 'node_modules/textarea-caret/index.js' - ] -}); diff --git a/extensions/mentions/js/forum/dist/extension.js b/extensions/mentions/js/forum/dist/extension.js deleted file mode 100644 index 6fad09bc2..000000000 --- a/extensions/mentions/js/forum/dist/extension.js +++ /dev/null @@ -1,1322 +0,0 @@ -/* jshint browser: true */ - -(function () { - -// The properties that we copy into a mirrored div. -// Note that some browsers, such as Firefox, -// do not concatenate properties, i.e. padding-top, bottom etc. -> padding, -// so we have to do every single property specifically. -var properties = [ - 'direction', // RTL support - 'boxSizing', - 'width', // on Chrome and IE, exclude the scrollbar, so the mirror div wraps exactly as the textarea does - 'height', - 'overflowX', - 'overflowY', // copy the scrollbar for IE - - 'borderTopWidth', - 'borderRightWidth', - 'borderBottomWidth', - 'borderLeftWidth', - 'borderStyle', - - 'paddingTop', - 'paddingRight', - 'paddingBottom', - 'paddingLeft', - - // https://developer.mozilla.org/en-US/docs/Web/CSS/font - 'fontStyle', - 'fontVariant', - 'fontWeight', - 'fontStretch', - 'fontSize', - 'fontSizeAdjust', - 'lineHeight', - 'fontFamily', - - 'textAlign', - 'textTransform', - 'textIndent', - 'textDecoration', // might not make a difference, but better be safe - - 'letterSpacing', - 'wordSpacing', - - 'tabSize', - 'MozTabSize' - -]; - -var isBrowser = (typeof window !== 'undefined'); -var isFirefox = (isBrowser && window.mozInnerScreenX != null); - -function getCaretCoordinates(element, position, options) { - if(!isBrowser) { - throw new Error('textarea-caret-position#getCaretCoordinates should only be called in a browser'); - } - - var debug = options && options.debug || false; - if (debug) { - var el = document.querySelector('#input-textarea-caret-position-mirror-div'); - if ( el ) { el.parentNode.removeChild(el); } - } - - // mirrored div - var div = document.createElement('div'); - div.id = 'input-textarea-caret-position-mirror-div'; - document.body.appendChild(div); - - var style = div.style; - var computed = window.getComputedStyle? getComputedStyle(element) : element.currentStyle; // currentStyle for IE < 9 - - // default textarea styles - style.whiteSpace = 'pre-wrap'; - if (element.nodeName !== 'INPUT') - style.wordWrap = 'break-word'; // only for textarea-s - - // position off-screen - style.position = 'absolute'; // required to return coordinates properly - if (!debug) - style.visibility = 'hidden'; // not 'display: none' because we want rendering - - // transfer the element's properties to the div - properties.forEach(function (prop) { - style[prop] = computed[prop]; - }); - - if (isFirefox) { - // Firefox lies about the overflow property for textareas: https://bugzilla.mozilla.org/show_bug.cgi?id=984275 - if (element.scrollHeight > parseInt(computed.height)) - style.overflowY = 'scroll'; - } else { - style.overflow = 'hidden'; // for Chrome to not render a scrollbar; IE keeps overflowY = 'scroll' - } - - div.textContent = element.value.substring(0, position); - // the second special handling for input type="text" vs textarea: spaces need to be replaced with non-breaking spaces - http://stackoverflow.com/a/13402035/1269037 - if (element.nodeName === 'INPUT') - div.textContent = div.textContent.replace(/\s/g, '\u00a0'); - - var span = document.createElement('span'); - // Wrapping must be replicated *exactly*, including when a long word gets - // onto the next line, with whitespace at the end of the line before (#7). - // The *only* reliable way to do that is to copy the *entire* rest of the - // textarea's content into the created at the caret position. - // for inputs, just '.' would be enough, but why bother? - span.textContent = element.value.substring(position) || '.'; // || because a completely empty faux span doesn't render at all - div.appendChild(span); - - var coordinates = { - top: span.offsetTop + parseInt(computed['borderTopWidth']), - left: span.offsetLeft + parseInt(computed['borderLeftWidth']) - }; - - if (debug) { - span.style.backgroundColor = '#aaa'; - } else { - document.body.removeChild(div); - } - - return coordinates; -} - -if (typeof module != 'undefined' && typeof module.exports != 'undefined') { - module.exports = getCaretCoordinates; -} else if(isBrowser){ - window.getCaretCoordinates = getCaretCoordinates; -} - -}()); -; -'use strict'; - -System.register('flarum/mentions/addComposerAutocomplete', ['flarum/extend', 'flarum/components/ComposerBody', 'flarum/helpers/avatar', 'flarum/helpers/username', 'flarum/helpers/highlight', 'flarum/utils/KeyboardNavigatable', 'flarum/utils/string', 'flarum/mentions/components/AutocompleteDropdown'], function (_export, _context) { - "use strict"; - - var extend, ComposerBody, avatar, usernameHelper, highlight, KeyboardNavigatable, truncate, AutocompleteDropdown; - function addComposerAutocomplete() { - extend(ComposerBody.prototype, 'config', function (original, isInitialized) { - if (isInitialized) return; - - var composer = this; - var $container = $('
'); - var dropdown = new AutocompleteDropdown({ items: [] }); - var $textarea = this.$('textarea').wrap('
'); - var searched = []; - var mentionStart = void 0; - var typed = void 0; - var searchTimeout = void 0; - - var applySuggestion = function applySuggestion(replacement) { - var insert = replacement + ' '; - - var content = composer.content(); - composer.editor.setValue(content.substring(0, mentionStart - 1) + insert + content.substr($textarea[0].selectionStart)); - - var index = mentionStart - 1 + insert.length; - composer.editor.setSelectionRange(index, index); - - dropdown.hide(); - }; - - this.navigator = new KeyboardNavigatable(); - this.navigator.when(function () { - return dropdown.active; - }).onUp(function () { - return dropdown.navigate(-1); - }).onDown(function () { - return dropdown.navigate(1); - }).onSelect(dropdown.complete.bind(dropdown)).onCancel(dropdown.hide.bind(dropdown)).bindTo($textarea); - - $textarea.after($container).on('click keyup', function (e) { - var _this = this; - - // Up, down, enter, tab, escape, left, right. - if ([9, 13, 27, 40, 38, 37, 39].indexOf(e.which) !== -1) return; - - var cursor = this.selectionStart; - - if (this.selectionEnd - cursor > 0) return; - - // Search backwards from the cursor for an '@' symbol. If we find one, - // we will want to show the autocomplete dropdown! - var value = this.value; - mentionStart = 0; - for (var i = cursor - 1; i >= cursor - 30; i--) { - var character = value.substr(i, 1); - if (character === '@') { - mentionStart = i + 1; - break; - } - } - - dropdown.hide(); - dropdown.active = false; - - if (mentionStart) { - typed = value.substring(mentionStart, cursor).toLowerCase(); - - var makeSuggestion = function makeSuggestion(user, replacement, content) { - var className = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ''; - - var username = usernameHelper(user); - if (typed) { - username.children[0] = highlight(username.children[0], typed); - } - - return m( - 'button', - { className: 'PostPreview ' + className, - onclick: function onclick() { - return applySuggestion(replacement); - }, - onmouseenter: function onmouseenter() { - dropdown.setIndex($(this).parent().index()); - } }, - m( - 'span', - { className: 'PostPreview-content' }, - avatar(user), - username, - ' ', - ' ', - content - ) - ); - }; - - var userMatches = function userMatches(user) { - var names = [user.username(), user.displayName()]; - - return names.some(function (value) { - return value.toLowerCase().substr(0, typed.length) === typed; - }); - }; - - var buildSuggestions = function buildSuggestions() { - var suggestions = []; - - // If the user has started to type a username, then suggest users - // matching that username. - if (typed) { - app.store.all('users').forEach(function (user) { - if (!userMatches(user)) return; - - suggestions.push(makeSuggestion(user, '@' + user.username(), '', 'MentionsDropdown-user')); - }); - } - - // If the user is replying to a discussion, or if they are editing a - // post, then we can suggest other posts in the discussion to mention. - // We will add the 5 most recent comments in the discussion which - // match any username characters that have been typed. - var composerPost = composer.props.post; - var discussion = composerPost && composerPost.discussion() || composer.props.discussion; - if (discussion) { - discussion.posts().filter(function (post) { - return post && post.contentType() === 'comment' && (!composerPost || post.number() < composerPost.number()); - }).sort(function (a, b) { - return b.time() - a.time(); - }).filter(function (post) { - var user = post.user(); - return user && userMatches(user); - }).splice(0, 5).forEach(function (post) { - var user = post.user(); - suggestions.push(makeSuggestion(user, '@' + user.username() + '#' + post.id(), [app.translator.trans('flarum-mentions.forum.composer.reply_to_post_text', { number: post.number() }), ' — ', truncate(post.contentPlain(), 200)], 'MentionsDropdown-post')); - }); - } - - if (suggestions.length) { - dropdown.props.items = suggestions; - m.render($container[0], dropdown.render()); - - dropdown.show(); - var coordinates = getCaretCoordinates(_this, mentionStart); - var width = dropdown.$().outerWidth(); - var height = dropdown.$().outerHeight(); - var parent = dropdown.$().offsetParent(); - var left = coordinates.left; - var top = coordinates.top + 15; - if (top + height > parent.height()) { - top = coordinates.top - height - 15; - } - if (left + width > parent.width()) { - left = parent.width() - width; - } - dropdown.show(left, top); - } else { - dropdown.active = false; - dropdown.hide(); - } - }; - - dropdown.active = true; - - buildSuggestions(); - - dropdown.setIndex(0); - dropdown.$().scrollTop(0); - - clearTimeout(searchTimeout); - if (typed) { - searchTimeout = setTimeout(function () { - var typedLower = typed.toLowerCase(); - if (searched.indexOf(typedLower) === -1) { - app.store.find('users', { filter: { q: typed }, page: { limit: 5 } }).then(function () { - if (dropdown.active) buildSuggestions(); - }); - searched.push(typedLower); - } - }, 250); - } - } - }); - }); - } - - _export('default', addComposerAutocomplete); - - return { - setters: [function (_flarumExtend) { - extend = _flarumExtend.extend; - }, function (_flarumComponentsComposerBody) { - ComposerBody = _flarumComponentsComposerBody.default; - }, function (_flarumHelpersAvatar) { - avatar = _flarumHelpersAvatar.default; - }, function (_flarumHelpersUsername) { - usernameHelper = _flarumHelpersUsername.default; - }, function (_flarumHelpersHighlight) { - highlight = _flarumHelpersHighlight.default; - }, function (_flarumUtilsKeyboardNavigatable) { - KeyboardNavigatable = _flarumUtilsKeyboardNavigatable.default; - }, function (_flarumUtilsString) { - truncate = _flarumUtilsString.truncate; - }, function (_flarumMentionsComponentsAutocompleteDropdown) { - AutocompleteDropdown = _flarumMentionsComponentsAutocompleteDropdown.default; - }], - execute: function () {} - }; -});; -'use strict'; - -System.register('flarum/mentions/addMentionedByList', ['flarum/extend', 'flarum/Model', 'flarum/models/Post', 'flarum/components/CommentPost', 'flarum/components/PostPreview', 'flarum/helpers/punctuateSeries', 'flarum/helpers/username', 'flarum/helpers/icon'], function (_export, _context) { - "use strict"; - - var extend, Model, Post, CommentPost, PostPreview, punctuateSeries, username, icon; - function addMentionedByList() { - Post.prototype.mentionedBy = Model.hasMany('mentionedBy'); - - extend(CommentPost.prototype, 'footerItems', function (items) { - var _this = this; - - var post = this.props.post; - var replies = post.mentionedBy(); - - if (replies && replies.length) { - // If there is only one reply, and it's adjacent to this post, we don't - // really need to show the list. - if (replies.length === 1 && replies[0].number() === post.number() + 1) { - return; - } - - var hidePreview = function hidePreview() { - _this.$('.Post-mentionedBy-preview').removeClass('in').one('transitionend', function () { - $(this).hide(); - }); - }; - - var config = function config(element, isInitialized) { - if (isInitialized) return; - - var $this = $(element); - var timeout = void 0; - - var $preview = $('
    '); - $this.append($preview); - - $this.children().hover(function () { - clearTimeout(timeout); - timeout = setTimeout(function () { - if (!$preview.hasClass('in') && $preview.is(':visible')) return; - - // When the user hovers their mouse over the list of people who have - // replied to the post, render a list of reply previews into a - // popup. - m.render($preview[0], replies.map(function (reply) { - return m( - 'li', - { 'data-number': reply.number() }, - PostPreview.component({ - post: reply, - onclick: hidePreview - }) - ); - })); - $preview.show(); - setTimeout(function () { - return $preview.off('transitionend').addClass('in'); - }); - }, 500); - }, function () { - clearTimeout(timeout); - timeout = setTimeout(hidePreview, 250); - }); - - // Whenever the user hovers their mouse over a particular name in the - // list of repliers, highlight the corresponding post in the preview - // popup. - $this.find('.Post-mentionedBy-summary a').hover(function () { - $preview.find('[data-number="' + $(this).data('number') + '"]').addClass('active'); - }, function () { - $preview.find('[data-number]').removeClass('active'); - }); - }; - - var users = []; - var repliers = replies.sort(function (reply) { - return reply.user() === app.session.user ? -1 : 0; - }).filter(function (reply) { - var user = reply.user(); - if (users.indexOf(user) === -1) { - users.push(user); - return true; - } - }); - - var limit = 4; - var overLimit = repliers.length > limit; - - // Create a list of unique users who have replied. So even if a user has - // replied twice, they will only be in this array once. - var names = repliers.slice(0, overLimit ? limit - 1 : limit).map(function (reply) { - var user = reply.user(); - - return m( - 'a', - { href: app.route.post(reply), - config: m.route, - onclick: hidePreview, - 'data-number': reply.number() }, - app.session.user === user ? app.translator.trans('flarum-mentions.forum.post.you_text') : username(user) - ); - }); - - // If there are more users that we've run out of room to display, add a "x - // others" name to the end of the list. Clicking on it will display a modal - // with a full list of names. - if (overLimit) { - var count = repliers.length - names.length; - - names.push(app.translator.transChoice('flarum-mentions.forum.post.others_text', count, { count: count })); - } - - items.add('replies', m( - 'div', - { className: 'Post-mentionedBy', config: config }, - m( - 'span', - { className: 'Post-mentionedBy-summary' }, - icon('reply'), - app.translator.transChoice('flarum-mentions.forum.post.mentioned_by' + (repliers[0].user() === app.session.user ? '_self' : '') + '_text', names.length, { - count: names.length, - users: punctuateSeries(names) - }) - ) - )); - } - }); - } - - _export('default', addMentionedByList); - - return { - setters: [function (_flarumExtend) { - extend = _flarumExtend.extend; - }, function (_flarumModel) { - Model = _flarumModel.default; - }, function (_flarumModelsPost) { - Post = _flarumModelsPost.default; - }, function (_flarumComponentsCommentPost) { - CommentPost = _flarumComponentsCommentPost.default; - }, function (_flarumComponentsPostPreview) { - PostPreview = _flarumComponentsPostPreview.default; - }, function (_flarumHelpersPunctuateSeries) { - punctuateSeries = _flarumHelpersPunctuateSeries.default; - }, function (_flarumHelpersUsername) { - username = _flarumHelpersUsername.default; - }, function (_flarumHelpersIcon) { - icon = _flarumHelpersIcon.default; - }], - execute: function () {} - }; -});; -'use strict'; - -System.register('flarum/mentions/addPostMentionPreviews', ['flarum/extend', 'flarum/components/CommentPost', 'flarum/components/PostPreview', 'flarum/components/LoadingIndicator'], function (_export, _context) { - "use strict"; - - var extend, CommentPost, PostPreview, LoadingIndicator; - function addPostMentionPreviews() { - extend(CommentPost.prototype, 'config', function () { - var contentHtml = this.props.post.contentHtml(); - - if (contentHtml === this.oldPostContentHtml || this.isEditing()) return; - - this.oldPostContentHtml = contentHtml; - - var parentPost = this.props.post; - var $parentPost = this.$(); - - this.$('.UserMention, .PostMention').each(function () { - m.route.call(this, this, false, {}, { attrs: { href: this.getAttribute('href') } }); - }); - - this.$('.PostMention').each(function () { - var $this = $(this); - var id = $this.data('id'); - var timeout = void 0; - - // Wrap the mention link in a wrapper element so that we can insert a - // preview popup as its sibling and relatively position it. - var $preview = $('