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

Editor Consolidation #28

Merged
merged 8 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
use s9e\TextFormatter\Configurator;

return [
(new Extend\Frontend('admin'))
->js(__DIR__.'/js/dist/admin.js'),

(new Extend\Frontend('forum'))
->js(__DIR__.'/js/dist/forum.js')
->css(__DIR__.'/less/forum.less'),
Expand Down
1 change: 0 additions & 1 deletion js/admin.js

This file was deleted.

2 changes: 0 additions & 2 deletions js/dist/admin.js

This file was deleted.

1 change: 0 additions & 1 deletion js/dist/admin.js.map

This file was deleted.

12 changes: 0 additions & 12 deletions js/src/admin/index.js

This file was deleted.

21 changes: 3 additions & 18 deletions js/src/forum/components/MarkdownButton.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import Component from 'flarum/Component';
import icon from 'flarum/helpers/icon';
import apply from '../util/apply';

const modifierKey = navigator.userAgent.match(/Macintosh/) ? '⌘' : 'ctrl';

export default class MarkdownButton extends Component {
oncreate(vnode) {
Expand All @@ -13,8 +10,8 @@ export default class MarkdownButton extends Component {

view() {
return (
<button className="Button Button--icon Button--link" title={this.title()} data-hotkey={this.attrs.hotkey}
onclick={this.click.bind(this)} onkeydown={this.keydown.bind(this)}>
<button className="Button Button--icon Button--link" title={this.attrs.title} data-hotkey={this.attrs.hotkey}
onkeydown={this.keydown.bind(this)} onclick={this.attrs.onclick}>
{icon(this.attrs.icon)}
</button>
);
Expand All @@ -23,19 +20,7 @@ export default class MarkdownButton extends Component {
keydown(event) {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
this.click();
this.element.click();
}
}

click() {
return apply(this.element, this.attrs.style);
}

title() {
let tooltip = this.attrs.title;

if (this.attrs.hotkey) tooltip += ` <${modifierKey}-${this.attrs.hotkey}>`;

return tooltip;
}
}
21 changes: 1 addition & 20 deletions js/src/forum/components/MarkdownToolbar.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,9 @@
import Component from 'flarum/Component';

const modifierKey = navigator.userAgent.match(/Macintosh/) ? 'Meta' : 'Control';

export default class MarkdownToolbar extends Component {
oncreate(vnode) {
super.oncreate(vnode);

this.attrs.setShortcutHandler(this.shortcut.bind(this));
}

view(vnode) {
return <div id="MarkdownToolbar" data-for={this.attrs.for} style={{ display: 'inline-block' }}>
return <div class="MarkdownToolbar">
Copy link
Member

Choose a reason for hiding this comment

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

Is this change from id to class necessary? Are we intentionally breaking styles that use the ID here?

Copy link
Member

Choose a reason for hiding this comment

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

I do agree with this change, just in case theres two of these toolbars on screen at the same time, despite how ridiculously unlikely that would be

Copy link
Contributor

Choose a reason for hiding this comment

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

I also agree with this change, while in theory it shouldn't be needed it also makes a lot of sense.

Copy link
Sponsor Member Author

Choose a reason for hiding this comment

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

Iirc, there isn't ID based stuff anywhere else in the composer hierarchy. I don't think it should be here either.

{vnode.children}
</div>;
}

shortcut(event) {
if ((event.metaKey && modifierKey === 'Meta') || (event.ctrlKey && modifierKey === 'Control')) {
const button = this.element.querySelector(`[data-hotkey="${event.key}"]`);

if (button) {
button.click();
event.preventDefault()
}
}
}
}
71 changes: 47 additions & 24 deletions js/src/forum/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,68 @@
* https://github.com/github/markdown-toolbar-element/blob/master/LICENSE
*/

import { extend, override } from 'flarum/extend';
import { extend } from 'flarum/extend';
import TextEditor from 'flarum/components/TextEditor';
import BasicEditorDriver from 'flarum/common/utils/BasicEditorDriver';
import styleSelectedText from 'flarum/common/utils/styleSelectedText';

import MarkdownToolbar from './components/MarkdownToolbar';
import MarkdownButton from './components/MarkdownButton';
import MarkdownEditorDriver from './util/MarkdownEditorDriver';

let shortcutHandler = () => { };
const modifierKey = navigator.userAgent.match(/Macintosh/) ? '⌘' : 'ctrl';

app.initializers.add('flarum-markdown', function (app) {
let index = 1;
const styles = {
'header': { prefix: '### ' },
'bold': { prefix: '**', suffix: '**', trimFirst: true },
'italic': { prefix: '_', suffix: '_', trimFirst: true },
'quote': { prefix: '> ', multiline: true, surroundWithNewlines: true },
'code': { prefix: '`', suffix: '`', blockPrefix: '```', blockSuffix: '```' },
'link': { prefix: '[', suffix: '](https://)', replaceNext: 'https://', scanFor: 'https?://' },
'image': { prefix: '![', suffix: '](https://)', replaceNext: 'https://', scanFor: 'https?://' },
'unordered_list': { prefix: '- ', multiline: true, surroundWithNewlines: true },
'ordered_list': { prefix: '1. ', multiline: true, orderedList: true }
}

extend(TextEditor.prototype, 'oninit', function () {
this.textareaId = 'textarea' + (index++);
});
const applyStyle = (id) => {
// This is a nasty hack that breaks encapsulation of the editor.
// In future releases, we'll need to tweak the editor driver interface
// to support triggering events like this.
styleSelectedText(app.composer.editor.el, styles[id]);
}

override(TextEditor.prototype, 'buildEditor', function (_, dom) {
return new MarkdownEditorDriver(dom, this.buildEditorParams());
});
function makeShortcut(id, key) {
return function (e) {
if (e.key === key && (e.metaKey && modifierKey === '⌘' || e.ctrlKey && modifierKey === 'ctrl')) {
applyStyle(id);
}
}
}

extend(TextEditor.prototype, 'buildEditorParams', function (params) {
params.textareaId = this.textareaId;
params.shortcutHandler = shortcutHandler;
app.initializers.add('flarum-markdown', function (app) {
extend(BasicEditorDriver.prototype, 'keyHandlers', function (items) {
items.add('bold', makeShortcut('bold', 'b'));
items.add('italic', makeShortcut('italic', 'i'));
});

extend(TextEditor.prototype, 'toolbarItems', function (items) {
const tooltip = name => app.translator.trans(`flarum-markdown.forum.composer.${name}_tooltip`);
const tooltip = (name, hotkey) => {
return app.translator.trans(`flarum-markdown.forum.composer.${name}_tooltip`) + (hotkey ? ` <${modifierKey}-${hotkey}>` : '');
};

const makeApplyStyle = (id) => {
return () => applyStyle(id);
}

items.add('markdown', (
<MarkdownToolbar for={this.textareaId} setShortcutHandler={handler => shortcutHandler = handler}>
<MarkdownButton title={tooltip('header')} icon="fas fa-heading" style={{ prefix: '### ' }} />
<MarkdownButton title={tooltip('bold')} icon="fas fa-bold" style={{ prefix: '**', suffix: '**', trimFirst: true }} hotkey="b" />
<MarkdownButton title={tooltip('italic')} icon="fas fa-italic" style={{ prefix: '_', suffix: '_', trimFirst: true }} hotkey="i" />
<MarkdownButton title={tooltip('quote')} icon="fas fa-quote-left" style={{ prefix: '> ', multiline: true, surroundWithNewlines: true }} />
<MarkdownButton title={tooltip('code')} icon="fas fa-code" style={{ prefix: '`', suffix: '`', blockPrefix: '```', blockSuffix: '```' }} />
<MarkdownButton title={tooltip('link')} icon="fas fa-link" style={{ prefix: '[', suffix: '](https://)', replaceNext: 'https://', scanFor: 'https?://' }} />
<MarkdownButton title={tooltip('image')} icon="fas fa-image" style={{ prefix: '![', suffix: '](https://)', replaceNext: 'https://', scanFor: 'https?://' }} />
<MarkdownButton title={tooltip('unordered_list')} icon="fas fa-list-ul" style={{ prefix: '- ', multiline: true, surroundWithNewlines: true }} />
<MarkdownButton title={tooltip('ordered_list')} icon="fas fa-list-ol" style={{ prefix: '1. ', multiline: true, orderedList: true }} />
<MarkdownButton title={tooltip('header')} icon="fas fa-heading" onclick={makeApplyStyle('header')} />
<MarkdownButton title={tooltip('bold', 'b')} icon="fas fa-bold" onclick={makeApplyStyle('bold')} />
<MarkdownButton title={tooltip('italic', 'i')} icon="fas fa-italic" onclick={makeApplyStyle('italic')} />
<MarkdownButton title={tooltip('quote')} icon="fas fa-quote-left" onclick={makeApplyStyle('quote')} />
<MarkdownButton title={tooltip('code')} icon="fas fa-code" onclick={makeApplyStyle('code')} />
<MarkdownButton title={tooltip('image')} icon="fas fa-image" onclick={makeApplyStyle('image')} />
<MarkdownButton title={tooltip('unordered_list')} icon="fas fa-list-ul" onclick={makeApplyStyle('unordered_list')} />
<MarkdownButton title={tooltip('ordered_list')} icon="fas fa-list-ol" onclick={makeApplyStyle('ordered_list')} />
</MarkdownToolbar>
), 100);
});
Expand Down
94 changes: 0 additions & 94 deletions js/src/forum/util/MarkdownEditorDriver.js

This file was deleted.

50 changes: 0 additions & 50 deletions js/src/forum/util/apply.js

This file was deleted.

Loading