jazzband / django-tinymce

TinyMCE integration for Django
http://django-tinymce.readthedocs.org/
MIT License
1.29k stars 316 forks source link

paste_preprocess & paste_postprocess don't work when set in TINYMCE_DEFAULT_CONFIG #166

Closed mattarchie closed 4 years ago

mattarchie commented 8 years ago

When I try to add paste_preprocess or paste_postprocess to my TINYMCE_DEFAULT_CONFIG, I get an error saying "unexpected token p" in my web console. Here is the full traceback:

Uncaught SyntaxError: Unexpected token p
    e.extend.parseJSON    @ jquery.min.js:2
    initTinyMCE           @ init_tinymce.js:4
    (anonymous function)  @ init_tinymce.js:21
    e.extend.each         @ jquery.min.js:2
    e.fn.e.each           @ jquery.min.js:2
    (anonymous function)  @ init_tinymce.js:20
    o                     @ jquery.min.js:2
    p.fireWith            @ jquery.min.js:2
    e.extend.ready        @ jquery.min.js:2
    c.addEventListener.B  @ jquery.min.js:2

This is my configuration:

# Tinymce Config
TINYMCE_JS_URL = os.path.join(STATIC_URL, "tiny_mce/tiny_mce.js")
TINYMCE_JS_ROOT = os.path.join(STATIC_ROOT, "tiny_mce")
TINYMCE_DEFAULT_CONFIG = {
    'theme':'advanced',
    'theme_advanced_buttons1':'bold,italic,underline,|,bullist,numlist,outdent,indent,|,undo,redo,|,link,unlink',
    'menubar':'false',
    'plugins':'paste',
    'paste_text_linebreaktype':'combined',
    'paste_postprocess':"function(pl, o) { o.content = strip_tags(o.content,'<div>');}",
    'paste_remove_spans':'true',
    'paste_retain_style_properties':'text-decoration',
}

I get this issue when including either pre or post processing for paste, whether or not any of the other options for the paste plugin are included or not.

mattarchie commented 8 years ago

Turns out that the web console from Firefox was more specific and told me that there were missing double quotes and exactly where they were missing, though it wasn't hard to guess. I updated code added in #3 to include the proper double quotes and thus the error has been fixed.

(p.s. any idea how I get rid of an accidentally pushed commit after having done a git reset? the acad4f6 commit above wasn't the full change and was made before I updated my repo to the upstream version on aljosa/django-tinymce. I reset my branch before merging in the upstream version and making the correct commit. Now I can't seem to figure out how to remove the initial commit from github... :/ )

mattarchie commented 8 years ago

Well, I guess I didn't actually fix the issue like I thought I did, there is another issue with p being undefined in a javascript file, I will look into it. I'll remove the merge request I made...

Here's the chrome trace:

Uncaught TypeError: Cannot read property 'apply' of undefined
k.create.execCallback @ tiny_mce.js:1
(anonymous function) @ editor_plugin.js:1
tinymce.create.dispatch @ tiny_mce.js:1
h @ editor_plugin.js:1
(anonymous function) @ editor_plugin.js:1

and the firefox trace:

TypeError: p is undefined
.execCallback() tiny_mce.js:1
.init/<() editor_plugin.js:1
.dispatch() tiny_mce.js:1
h() editor_plugin.js:1
g/<() editor_plugin.js:1
mattarchie commented 8 years ago

Okay, so my new issue is that the tinymce.resolve() function is not properly resolving the anonymous function I'm providing as the callback function for paste_postprocess. tiny_mce.js (line 1, column 173920 - 173935) and tiny_mce_src.js (line 13166 - 13167).

mattarchie commented 8 years ago

Yeah, okay, so the resolve function is not built to handle anonymous functions... actually, I'm really not sure it's built to handle functions at all. It looks like it's only meant to handle constructions like 'tinymce.ui.Control' and 'tinymce.ui.Menu', etc. resolve() splits the string on the '.' and then starts at a given context (or the entire window if no context is given) and then loops looking for the next element in the array from the split string within the reduced context. It then returns a function that it is able to call apply() on and do whatever that function intends.

I'm honestly very unsure of why this is even something being used for the paste_postprocess and paste_preprocess config options, but it definitely isn't working as is.

While I've been able to diagnose the problem to this point, I do not know enough to determine how to proceed with fixing this issue. Any help would be appreciated.

Natim commented 8 years ago

Thank you @mattarchie for digging the issue. Could you please put an example of a small demo app showing the problem so that we can try to figure out what is going on?

mattarchie commented 8 years ago

I should be able to get the issue to show up in the provided test app, let me take a look and see. That would be the simplest for showing the problem.

Natim commented 8 years ago

Ok great.

mattarchie commented 8 years ago

Unfortunately, I'm having more problems getting the test app to work, so I'll have to try to grab a small piece of my own project that would work on its own and try that out. Not sure how long that will take, but I'll let you know when I have a demo for you.

As a note, the documentation says to use syncdb to create your database, but in Django 1.9 syncdb was deprecated and removed. Not sure how to manage the database without either syncdb or by using south... so I tried downgrading Django and ran into a bunch of issues with different versions not understanding various parts of the tinymce code... Also, I could not figure out how to get my changes to the default settings to actually take and adjust the theme/buttons/plugins beings used in the testapp.

mattarchie commented 8 years ago

Okay, I did get it to work. I forgot about having to dig into the python directory to actually make changes to what was installed by django-tinymce. Here is a list of the changes I had to make within env/local/lib/python2.7/site-packages/

TINYMCE_DEFAULT_CONFIG = {
    'theme':'advanced',
    'theme_advanced_buttons1':'bold,italic,underline,|,bullist,numlist,outdent,indent,|,undo,redo,|,link,unlink',
    'menubar':False,
    'plugins':'paste',
    'paste_remove_spans':True, #doesn't seem to remove spans with underlining
    'paste_text_linebreaktype':'p',
    #'paste_text_sticky_default':True, #this removes all text decoration
    #'paste_retain_style_properties':'text-decoration', #doesn't seem to be necessary
    'paste_preprocess':"function(pl,o){o.content=strip_tags(o.content,'<div>');}", #once this is fixed in django-tinymce, it will allow me to strip only specific tags to make them all p tags.
}

and I also set TINYMCE_COMPRESSOR = False because I got a 500 error related to the compressor

To reproduce...

  1. the original error I made this issue about, leave out the change to widgets.py and you'll notice the tinymce widget doesn't load and you get a JSON error. (I had made a pull request with just this fix to widgets before I realized there was a bigger problem, so I closed #168 as it only fixed one piece of the problem.)
  2. the new error with resolve(), include the change in widgets.py and then try to paste any text into the tinymce widget. You should see an error about not being about to call apply on undefined - or something to that affect depending on your browser, etc.

By the way, I did this test running Django 1.4.22 (which is the version my own project is running - I can't upgrade further yet due to compatibility issues) and django-tinymce 2.3.0. With that version of django, you cannot run the django-admin shortcut, so I used env/bin/django-admin.py in place of django-admin as I followed the guide for testing that tinymce in the documentation.

I hope this helps.

tidenhub commented 8 years ago

Hey, our team just had the same problem with Django 1.9.9 and django-tinymce 2.4.0. We used the suggestion from mattarchie and changed in tinymce/widgets.py line 74 to this: mce_json = mce_json[:index] + ', \"' + k + '\":\"' + js_functions[k].strip() + '\"' + mce_json[index:]

mattarchie commented 8 years ago

@tidenhub I'm glad this was helpful. Did you run into the same issue with resolve() or perhaps that was addressed between version 2.3.0 and 2.4.0?

tidenhub commented 7 years ago

@mattarchie Sry, I think we didn't.