Anki Forums

Retrieve HTML from editor

Hello,

I have created a small helper function to modify the text of the editor. For the moment, I am able to modify the text but not the underlying HTML. Any idea how I could do that?

Here is the code:

def formatting(editor, treatment) -> None:
    """
    Helper function used by formatting functions
    Allows to write new text in editor
    """
    # data = editor.web.selectedText()
    # data = editor.web.page().runJavaScript("document.getElementsByTagName('html')[0].innerHTML", callback_func)
    data_formatted = treatment(data)
    data_formatted_json = json.dumps(data_formatted)
    editor.web.eval(
        f"document.execCommand('inserthtml', false, {data_formatted_json});"
    )

I have tried to replace

data = editor.web.selectedText()

by

data = editor.web.page().runJavaScript(“document.getElementsByTagName(‘html’)[0].innerHTML”, callback_func)`

with a simple callback function defined as followed:

def callback_func(html):
print(html)

But it does not work. Any idea?

Since QWebEnginePage::runJavaScript() is a void method (returns None in Python), you cannot assign the result of the last executed javascript statement to a variable as the return value of runJavaScript(). The result will be delivered to the callback function as the first argument.

By the way, you can get the entire <html> element via document.documentElement. In addition, you can use aqt.webview.AnkiWebView.evalWithCallback() instead of page().runJavaScript().

def formatting(editor, treatment) -> None:
    def callback_func(value) -> None:
        data_formatted_json = json.dumps(treatment(value))
        editor.web.eval(
            f"document.execCommand('inserthtml', false, {data_formatted_json});"
        )

    # js = "document.documentElement.innerHTML;"
    js = "document.getElementsByTagName('html')[0].innerHTML;"
    # editor.web.evalWithCallback(js, callback_func)
    editor.web.page().runJavaScript(js, callback_func)
2 Likes

Thank you very much. Actually, the purpose of the function is to modify the text of the field, not the editor itself (I should have been clearer in my first message). The result of the new function was quite unexpected!

You might want to consider using editor.doPaste() instead of directly doing an eval call with document.execCommand('inserthtml', ...), because it eventually does that under-the-hood anyway. Then there’s no need to call json.dumps() manually either.

editor.doPaste(data_formatted, internal=False, extended=True)

Although it doesn’t let certain tags through so it kinda depends on exactly what you’re trying to insert.