FEATURE: Convert HTML to Markdown while pasting in composer

This commit is contained in:
Vinoth Kannan 2017-12-05 22:53:39 +05:30 committed by Joffrey JAFFEUX
parent 067d454937
commit 6e054b2572
5 changed files with 75 additions and 10 deletions

View File

@ -9,6 +9,8 @@ import { emojiUrlFor } from 'discourse/lib/text';
import { getRegister } from 'discourse-common/lib/get-owner';
import { findRawTemplate } from 'discourse/lib/raw-templates';
import { determinePostReplaceSelection, clipboardData } from 'discourse/lib/utilities';
import { ajax } from 'discourse/lib/ajax';
import { popupAjaxError } from 'discourse/lib/ajax-error';
import deprecated from 'discourse-common/lib/deprecated';
// Our head can be a static string or a function that returns a string
@ -616,7 +618,7 @@ export default Ember.Component.extend({
Ember.run.scheduleOnce("afterRender", () => $textarea.focus());
},
_detectTable(text) {
_extractTable(text) {
if (text.endsWith("\n")) {
text = text.substring(0, text.length - 1);
}
@ -639,21 +641,43 @@ export default Ember.Component.extend({
paste(e) {
const clipboard = clipboardData(e);
const types = clipboard.types;
let preventDefault = false;
const placeholder = `${ I18n.t('pasting') }`;
let plainText = clipboard.getData("text/plain");
const html = clipboard.getData("text/html");
let handled = false;
if (types.some(t => t === "text/plain")) {
const text = clipboard.getData("text/plain");
const table = this._detectTable(text);
if (plainText) {
plainText = plainText.trim();
const table = this._extractTable(plainText);
if (table) {
this._addText(this._getSelected(), table);
preventDefault = true;
handled = true;
}
} else if (types.some(t => t === "Files")) {
preventDefault = true;
}
if (preventDefault) {
if (html && !handled) {
const self = this;
this.appEvents.trigger('composer:insert-text', placeholder);
handled = true;
ajax('/composer/parse_html', {
type: 'POST',
data: { html }
}).then(response => {
self.appEvents.trigger('composer:replace-text', placeholder, response.markdown);
}).catch(error => {
if (plainText) {
self.appEvents.trigger('composer:replace-text', placeholder, plainText);
} else {
popupAjaxError(error);
}
});
}
const uploadFiles = clipboard.types.includes("Files") && !plainText && !html;
if (handled || uploadFiles) {
e.preventDefault();
}
},

View File

@ -0,0 +1,12 @@
require_dependency 'html_to_markdown'
class ComposerController < ApplicationController
before_action :ensure_logged_in
def parse_html
markdown_text = HtmlToMarkdown.new(params[:html]).to_markdown
render json: { markdown: markdown_text }
end
end

View File

@ -309,6 +309,8 @@ en:
uploading_filename: "Uploading {{filename}}..."
uploaded: "Uploaded!"
pasting: "Pasting..."
enable: "Enable"
disable: "Disable"
undo: "Undo"

View File

@ -301,6 +301,7 @@ Discourse::Application.routes.draw do
get "session/current" => "session#current"
get "session/csrf" => "session#csrf"
get "composer_messages" => "composer_messages#index"
post "composer/parse_html" => "composer#parse_html"
resources :static
post "login" => "static#enter", constraints: { format: /(json|html)/ }

View File

@ -0,0 +1,26 @@
require 'rails_helper'
RSpec.describe ComposerController do
let(:user) { Fabricate(:user) }
describe '#parse_html' do
it "should not be able access without sign in" do
expect {
post "/composer/parse_html.json", params: {
html: "<strong>hello</strong>"
}
}.to raise_error(Discourse::NotLoggedIn)
end
it "should convert html tags to markdown text" do
sign_in(user)
post "/composer/parse_html.json", params: {
html: "<strong>hello</strong>"
}
expect(response.body).to eq("{\"markdown\":\"**hello**\"}")
end
end
end