Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making external links open in a new window in wagtail

I recently implemented adding target="_blank" to external links like this:

@hooks.register('after_edit_page')
def do_after_page_edit(request, page):
    if hasattr(page, "body"):
        soup = BeautifulSoup(page.body)
        for a in soup.findAll('a'):
            if hasattr(a, "href"):
            a["target"] = "_blank"
        page.body = str(soup)
        page.body = page.body.replace("<html><head></head><body>", "")
        page.body = page.body.replace("</body></html>", "")
        page.body = page.body.replace("></embed>", "/>")
        page.save()

@hooks.register('construct_whitelister_element_rules')
def whitelister_element_rules():
    return {
        'a': attribute_rule({'href': check_url, 'target': True}),
    }

Problems:

  1. Beautiful soup messes with the output, adding html, head & body tags - Don't put html, head and body tags automatically, beautifulsoup

  2. It also messes with the embed tags - How to get BeautifulSoup 4 to respect a self-closing tag?

  3. Hence my crappy "fix" manually replacing parts of the output with blank strings.

Question:

What is the correct and best way to do this?

like image 349
Chris Barry Avatar asked Oct 23 '15 11:10

Chris Barry


1 Answers

Have been struggling with the same problem and couldn’t achieve it using wagtailhooks. My initial solution was to manipulate the content in base.html, using a filter. The filter to cut pieces of code works perfectly when placed in the content block, example:

{{ self.body|cut: ‘ href="http:’}}

Above filter deletes parts of the content, but unfortunately ‘replace’ is not available as a filter (I´m using Python 3.x). Therefor my next approach was building a custom_filter to create ´replace´ as filter option. Long story short: It partly worked but only if the content was converted from the original ‘StreamValue’ datatype to ‘string’. This conversion resulted in content with all html tags shown, so the replacement did not result in working html. I couldn´t get the content back to StreamValue again and no other Python datatype remedied the issue. Eventually JQuery got the job done for me:

$(document).ready(function(){
$('a[href^="http://"]').attr('target', '_blank');
});        

This code adds ‘target="_blank"’ to each link containing ‘http://’, so all internal links stay in the existing tab. It needs to be placed at the end of your base.html (or similar) and of course you need to load JQuery before you run it. Got my answer from here . Don’t know if JQuery is the correct and best way to do it, but it works like a charm for me with minimal coding.

like image 150
MartijnL Avatar answered Oct 05 '22 12:10

MartijnL