-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f22a017
Showing
13 changed files
with
1,145 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
*.pyc | ||
*~ | ||
dist/ | ||
fiduswriter_languagetool.egg-info/ |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
include LICENSE | ||
include README.rst | ||
recursive-include languagetool/static * | ||
recursive-include languagetool/locale * |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
===== | ||
FidusWriter-Languagetool | ||
===== | ||
|
||
FidusWriter-Languagetool is a Fidus writer plugin to connect a Fidus Writer instance | ||
with Languagetool (LT). | ||
|
||
|
||
Installation | ||
----------- | ||
|
||
1. Install Fidus Writer if you haven't done so already. | ||
|
||
2. Within the virtual environment set up for your Fidus Writer instance, install the version of the plugin corresponding to your Fidus Writer installation. If you are running Fidus Writer 3.2, the command is:: | ||
|
||
pip install "fiduswriter-languagetool<3.3" | ||
|
||
3. Add "languagetool" to your INSTALLED_APPS setting in the configuration.py file | ||
like this:: | ||
|
||
INSTALLED_APPS += ( | ||
... | ||
'languagetool', | ||
) | ||
|
||
4. Add a setting for the URL where you will be running LT in the configuration.py file like this: | ||
|
||
LT_URL = 'http://localhost:8081' | ||
|
||
5. Create the needed JavaScript files by running this:: | ||
|
||
python manage.py transpile | ||
|
||
6. (Re)start your Fidus Writer server. |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# SOME DESCRIPTIVE TITLE. | ||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER | ||
# This file is distributed under the same license as the PACKAGE package. | ||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. | ||
# | ||
#, fuzzy | ||
msgid "" | ||
msgstr "" | ||
"Project-Id-Version: PACKAGE VERSION\n" | ||
"Report-Msgid-Bugs-To: \n" | ||
"POT-Creation-Date: 2017-09-14 00:58+0200\n" | ||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||
"Language-Team: LANGUAGE <[email protected]>\n" | ||
"Language: \n" | ||
"MIME-Version: 1.0\n" | ||
"Content-Type: text/plain; charset=UTF-8\n" | ||
"Content-Transfer-Encoding: 8bit\n" | ||
|
||
#: static/js/es6_modules/lt/dialog.js:13 | ||
msgid "Cancel" | ||
msgstr "" | ||
|
||
#: static/js/es6_modules/lt/editor.js:15 | ||
msgid "Finish language check" | ||
msgstr "" | ||
|
||
#: static/js/es6_modules/lt/editor.js:16 | ||
msgid "Remove lines left over in the text from language check." | ||
msgstr "" | ||
|
||
#: static/js/es6_modules/lt/editor.js:28 | ||
msgid "Check language" | ||
msgstr "" | ||
|
||
#: static/js/es6_modules/lt/editor.js:29 | ||
msgid "Check text for grammar and spelling issues." | ||
msgstr "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
from future.moves.urllib.parse import urljoin | ||
|
||
from tornado.web import RequestHandler, asynchronous, HTTPError | ||
from tornado.httpclient import AsyncHTTPClient | ||
from base.django_handler_mixin import DjangoHandlerMixin | ||
from django.conf import settings | ||
|
||
LT_URL = settings.LT_URL \ | ||
if settings.LT_URL else 'https://languagetool.org/api/' | ||
|
||
|
||
class Proxy(DjangoHandlerMixin, RequestHandler): | ||
@asynchronous | ||
def post(self, relative_url): | ||
user = self.get_current_user() | ||
if not user.is_authenticated(): | ||
self.set_status(401) | ||
self.finish() | ||
return | ||
body = self.request.body | ||
url = urljoin(LT_URL, '/v2/') + relative_url | ||
http = AsyncHTTPClient() | ||
http.fetch( | ||
url, | ||
method='POST', | ||
body=body, | ||
callback=self.on_response | ||
) | ||
|
||
# The response is asynchronous so that the getting of the data from the | ||
# remote server doesn't block the server connection. | ||
def on_response(self, response): | ||
if response.error: | ||
raise HTTPError(500) | ||
self.write(response.body) | ||
self.finish() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
import {dialogTemplate} from "./templates" | ||
import {removeDecorationsBetween} from "./statePlugin" | ||
|
||
export class DialogLT { | ||
constructor(editor, view, match) { | ||
this.editor = editor | ||
this.view = view | ||
this.match = match | ||
} | ||
|
||
init() { | ||
let buttons = [{ | ||
text: gettext('Cancel'), | ||
click: () => { | ||
this.dialog.dialog('close') | ||
}, | ||
class: 'fw-button fw-orange' | ||
}] | ||
let dialogDOM = dialogTemplate({ | ||
header: this.match.shortMessage, | ||
message: this.match.message, | ||
replacements: this.match.replacements | ||
}) | ||
this.dialog = jQuery(dialogDOM) | ||
this.dialog.dialog({ | ||
width: 320, | ||
height: 540, | ||
buttons, | ||
create: () => this.dialogCreate(), | ||
close: () => { | ||
this.dialog.dialog('destroy').remove() | ||
} | ||
}) | ||
} | ||
|
||
dialogCreate() { | ||
let that = this | ||
jQuery(this.dialog).on('click', '.replacement', function() { | ||
let id = parseInt(jQuery(this).data('id')) | ||
|
||
let replacement = that.match.replacements[id] | ||
if (replacement) { | ||
let removeDecosTr = removeDecorationsBetween( | ||
that.view.state, | ||
that.view.state.selection.from, | ||
that.view.state.selection.to | ||
) | ||
that.view.dispatch(removeDecosTr) | ||
|
||
let transaction = that.view.state.tr.replaceSelectionWith( | ||
that.view.state.schema.text(replacement.value), | ||
true | ||
) | ||
that.view.dispatch(transaction) | ||
} | ||
console.log(replacement) | ||
that.dialog.dialog('close') | ||
that.view.focus() | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import {languagetoolPlugin, setDecorations, removeDecorations} from "./statePlugin" | ||
|
||
export class EditorLT { | ||
constructor(editor) { | ||
this.editor = editor | ||
this.supportedLanguages = [] | ||
this.hasChecked = false | ||
} | ||
|
||
init() { | ||
let toolMenu = this.editor.menu.headerbarModel.content.find(menu => menu.id==='tools') | ||
|
||
toolMenu.content.unshift( | ||
{ | ||
title: gettext('Finish language check'), | ||
tooltip: gettext('Remove lines left over in the text from language check.'), | ||
action: editor => { | ||
this.removeMainDecos() | ||
this.removeFnDecos() | ||
this.hasChecked = false | ||
}, | ||
disabled: editor => !this.hasChecked | ||
} | ||
) | ||
|
||
toolMenu.content.unshift( | ||
{ | ||
title: gettext('Check language'), | ||
tooltip: gettext('Check text for grammar and spelling issues.'), | ||
action: editor => { | ||
let language = this.editor.view.state.doc.firstChild.attrs.language | ||
this.proofread(this.editor.view, language) | ||
this.proofread(this.editor.mod.footnotes.fnEditor.view, language) | ||
}, | ||
disabled: editor => !this.supportedLanguages.includes( | ||
editor.view.state.doc.firstChild.attrs.language | ||
) || this.editor.docInfo.access_rights !== 'write' | ||
} | ||
) | ||
this.editor.statePlugins.push( | ||
[languagetoolPlugin, () => ({editor: this.editor, editorLt: this})] | ||
) | ||
this.editor.mod.footnotes.fnEditor.fnStatePlugins.push( | ||
[languagetoolPlugin, () => ({editor: this.editor, editorLt: this})] | ||
) | ||
|
||
|
||
this.getSupportedLanguages() | ||
} | ||
|
||
getSupportedLanguages() { | ||
fetch('/proxy/languagetool/languages', { | ||
method: "POST", | ||
credentials: "same-origin", | ||
}).then(response => response.json()).then(json => { | ||
this.supportedLanguages = json.map(entry => entry.longCode) | ||
}) | ||
} | ||
|
||
proofread(view, language) { | ||
let text = this.getText(view.state.doc) | ||
let state = view.state | ||
fetch('/proxy/languagetool/check', { | ||
method: "POST", | ||
credentials: "same-origin", | ||
body: new URLSearchParams(Object.entries({ | ||
text, | ||
language | ||
})) | ||
}).then(response => response.json()).then(json => { | ||
if(view.state===state) { | ||
// No changes have been made while spell checking took place. | ||
this.markMatches(view, json.matches) | ||
this.hasChecked = true | ||
} else { | ||
// something has changed, run spellchecker again. | ||
this.proofread(view, language) | ||
} | ||
}) | ||
} | ||
|
||
getText(node) { | ||
let start = '', end = '' | ||
if (node.type.name==='text') { | ||
return node.text | ||
} else if (node.isBlock) { | ||
let text = '' | ||
let childCount = node.childCount, i | ||
for (i = 0; i < childCount; i++) { | ||
text += this.getText(node.child(i)) | ||
} | ||
if (node.type.name==='doc') { | ||
return text | ||
} else { | ||
return `\n${text}\n` | ||
} | ||
} else { | ||
return ' '.repeat(node.nodeSize) | ||
} | ||
} | ||
|
||
markMatches(view, matches) { | ||
if(!matches.length) { | ||
return | ||
} | ||
let tr = setDecorations(view.state, matches) | ||
if (tr) { | ||
view.dispatch(tr) | ||
} | ||
} | ||
|
||
removeFnDecos() { | ||
this.removeDecos(this.editor.mod.footnotes.fnEditor.view) | ||
} | ||
|
||
removeMainDecos() { | ||
this.removeDecos(this.editor.view) | ||
} | ||
|
||
removeDecos(view) { | ||
let tr = removeDecorations(view.state) | ||
if (tr) { | ||
view.dispatch(tr) | ||
} | ||
this.hasChecked = false | ||
} | ||
|
||
} |
Oops, something went wrong.