How to parse links (or any HTML tags) from external source (e.g. json) in re-useable pug template? - checkbox

To my understanding, pug templtes are to be re-used. So I set up a collection for building forms and have partials like input.pug, textarea.pug, checkbox.pug, radio-buttons.pug`, etc.
In order to make sense of their reusability, they of course should show different text whenever they are used. Therefore I use - locals.msg = Some custom Text in the pug template that includes any of the form partials.
But as soon as it comes to provide more complex text that consists of links or contains styling elements (like b or a span tag with classes), the text is not parsed properly. This is what I have: a simple checkbox for GDPR acceptance that a user must click in a form. The explanation text is supposed to provide an external link to a page, where the user can read all about the site's data protection:
// parent pug template
div(class="[...]")
- var form = { id: 'for-gdpr', txt: 'I have read GDPR ...' }
include ./form/checkbox.pug
// checkbox pug template
label(class="flex items-baseline block w-full")
input(class="..." type="checkbox")
div(class="...")= form.txt
Of course this does not generate a proper link, instead that a-tag is "written out".
I also tried splitting text like this:
- var form = { msg1: 'I have read ', msg2: 'a(class="..." href="..." target="_blank" data protextion ', msg: ' and concur.'}
but to no avail.
How would I have to prepare the text in order to then parse it properly in a pug template?
Thank you!

Related

Oxygen - Advanced Custom Fields Repeater sub-fields - link fields

WordPress Repeater link fields: For testing purposes I have defined one link as an Array and the second link as URL. When adding the repeater to a template the output of one link is an Array and the other link is displayed as URL instead of the actual "link text". The link also doesn't open link in new tab as defined.
What's wrong with this setup? See attachments
Working solution to the problem described above:
It is important to know that my issue with ACF and Repeater is related to the Wordpress Oxygen builder.
In order to get get link fields with target blank you need to do the following:
CPT UI > create post type (set has Archive = true)
Custom Fields > Add field type Repeater, add sub-fields = field type set to text
Posts > Add Rows with link custom fields
Create Template > Add repeater to page, add text link module, set data to appropriate Field Name
Define link target: Add JS code block and add the following code
jQuery('a').each(function() {
var a = new RegExp('/' + window.location.host + '/');
if (!a.test(this.href)) {
jQuery(this).attr("target","_blank");
}
});

Fragment id linking in wagtail's rich text content

I have a bunch of content in a Wagtail 2.0 rich text field that looks like
Page heading
(intro blurb)
heading 1
(heading-1-relevant text)
heading 2
(heading-2-relevant text)
...
and I would like to give each heading an id so that any text can be made a link to jump to the relevant content. I can't seem to find an option to give headings an explicit id, and the "link" button in the rich text editor does not seem to let me pick active fragment identifiers in the content.
Is there a way to add fragment identifier based navigation on the same page work with Wagtail's rich text editor?
Revisiting my own question a year later because this is still something we need, the solution we came up with is to simply wrap the RichText html serialization, and putting fragment id injection on top:
import re
from django import template
from django.utils.text import slugify
from wagtail.core.rich_text import RichText
# We'll be wrapping the original RichText.__html__(), so make
# sure we have a reference to it that we can call.
__original__html__ = RichText.__html__
# This matches an h1/.../h6, using a regexp that is only
# guaranteed to work because we know that the source of
# the HTML code we'll be working with generates nice
# and predictable HTML code (and note the non-greedy
# "one or more" for the heading content).
heading_re = r"<h([1-6])([^>]*)>(.+?)</h\1>"
def add_id_attribute(match):
"""
This is a regexp replacement function that takes
in the above regex match results, and then turns:
<h1>some text</h1>
Into:
<h1><a id="some-text"></a>some text</h1>
where the id attribute value is generated by running
the heading text through Django's slugify() function.
"""
n = match.group(1)
attributes= match.group(2)
text_content = match.group(3)
id = slugify(text_content)
return f'<h{n}{attributes}><a id="{id}"></a>{text_content}</h{n}>'
def with_heading_ids(self):
"""
We don't actually change how RichText.__html__ works, we just replace
it with a function that does "whatever it already did", plus a
substitution pass that adds fragment ids and their associated link
elements to any headings that might be in the rich text content.
"""
html = __original__html__(self)
return re.sub(heading_re, add_id_attribute, html)
# Rebind the RichText's html serialization function such that
# the output is still entirely functional as far as wagtail
# can tell, except with headings enriched with fragment ids.
RichText.__html__ = with_heading_ids
This works rather well, does not require any hacking in draftail or wagtail, and is very easy to enable/disable simply by loading this code as part of the server startup process (we have it living in our wagtailcustom_tags.py file, so when Django loads up all template tag sets, the RichText "enrichment" kicks in automatically).
We had initially tried to extend the ... | richtext template filter, but while that's entirely possible, that only works for custom blocks we ourselves wrote, with our own custom templates, and so turned out to not be a solution given the idea that it should "just work".
To have control over the structure of your page body, it's preferable to encourage users to use heading blocks, rather than headings within the rich text block. Then you can have a heading block type which has two fields, a 'text' and an 'id', and you can specify a template that outputs the h element with the id attribute.
class Heading2Block(blocks.StructBlock):
heading = blocks.CharBlock(classname='full title')
link_id = blocks.CharBlock(help_text='For making hyperlinks to this heading')
class Meta:
template = 'blocks/h2.html'
Put the following in blocks/h2.html:
<h1{% if value.link_id %} id="{{ value.link_id|slugify }}"{% endif %}>{{ value.heading }}</h1>
In earlier versions of Wagtail it was possible to remove the h widget from the Hallo.js rich text editor, and this was a good way of encouraging user adoption of the heading block. Similar restriction is not currently present in Draftail, but there is a pull request which reimplements it.

Can the `linky` filter be used with text containing html tags?

From the linky docs it seems it should work with ng-bind-html. However, if the text contains html tags, then linky overrides the actual html interpretation to transform URLs into links.
This can be seen by for instance writing
Pretty text with some links:<br/><img src="http://something.com/lol.gif">
http://angularjs.org/,
mailto:us#somewhere.org,
another#somewhere.org,
and one more: ftp://127.0.0.1/.
in the example at the bottom of the linky docs page.
Is there a way to firstly sanitise and interpret html using ng-bind-html and only later parse the resulting text to add clickable links?

How to change valid HTML tags that get rendered in ng-bind-html?

I have a text editor (textAngular) that I've modified to limit the number of valid HTML tags I can generate using that tool. Now, I want to only support a limited number of HTML elements (h3, h4, h5, h6, ol, ul) to produce a news story but I want to disable some of the valid HTML rendered by ng-bind-html. Namely, I want to remove , tags as a valid tags because they could have disastrous results for this user generated content.
Is it possible to remove and tags as something rendered by ng-bind-html?
Unfortunately no, it isn't possible to config the valid HTML tags.
The ng-bind-html use the $sanitize service to strip invalid tags/attributes, and you can see in the source code that all the configurations are private.
// Safe Block Elements - HTML5
var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," +
"aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," +
"h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul"));
// Inline Elements - HTML5
var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," +
"bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," +
"samp,small,span,strike,strong,sub,sup,time,tt,u,var"));
If you really want it, one way you could do is to copy the angular-sanitize.js and modify the valid HTML tags configuration directly.
Please note that if you do it that way, all the ng-bind-html in your entire application will be also affected. If that is undesired, you have to write your own custom directive and inject/use your modified version of $sanitize instead.
If you're into modifying textAngular already, you could modify something around the taCustomRenderers Section of the code and use ta-bind instead of ng-bind-html. They do nearly the same thing except ta-bind runs all the extra renderers.
Custom Renderers Code: textAngularSetup, textAngular - probably in this one you can do your stripping out of unwanted code.

Meteor - how to link html element to database entry on click event?

I'm trying to figure out how to link an html picture element back to the database entry that was originally used to generate the picture link.
I am using Meteor:
- I have a database that contains photosets data from Flickr API
- In the HTML, I have a handlebar "each" script that iterates through each photoset in the database and then uses this info to generate the html for the photoset cover picture links.
- When the html renders, the photoset cover pictures are downloaded from Flickr and displayed to the screen.
I would like to be able to click on the photoset cover picture and then automatically generate the links to the pictures in the photoset. But I don't understand how to dynamically link the html picture elements back to their respective database entries that were originally used for generating the picture links. I need to be able to find the original database entries so that I can load the info needed for generation of subsequent links.
As a newb to all of this I'm not really sure where to start looking or what to try. I've wondered about creating an object with custom key pairs to 'memorise' the identity of each photoset picture. Is this the way to go, or is there an easier way that I am overlooking?
Thanks.
Say you have your pictures being put out this way:
Template.mytemplate.helpers({
picture:function() {
return pictures.find()
}
});
You can also do this instead, which is pretty much the same thing:
Template.mytemplate.picture = function() {
return pictures.find();
}
With the html
<template name="pictures">
{{#each picture}}
<img src="{{src}}" class="pictureselector"/>
{{/each}}
</template>
You can use events which can get data from that particular picture document/record
Template.mytemplate.events({
'click .pictureselector':function(event,template) {
console.log(this._id); //Should give you the `_id` of the picture that was clicked
}
});
this is the data context of the element that was clicked & generate the link you want using the data inside this.
Be careful if you use something with a callback inside the click like Meteor.call, you will have to relay the message down via var self = this otherwise the context of this would become the one of Meteor.call

Resources