I am using product tags as a way to filter what users see depending on if they are commercial or consumer customers. I have managed to get the tags into the class of each product displayed in a collection using the following code. The {{itemTags}} is being used to pass the value over into the HTML.
itemHtml = itemHtml.replace(/{{itemTags}}/g, data.tags);
<div class="{{itemTags}}">
The only issue is that all of the tags are displayed in a string with no spaces and commas in between each one. Resulting in the following class being added as an example.
class="accessories,Consumer,DJI Air 2S,live,pre-order,preorder"
Is it possible to remove the commas and add spaces in between each tag?
use the replace tag in liquid
itemHtml = itemHtml.replace(/{{itemTags | replace: "," , " " }}/g, data.tags);
Related
So I have a set of strings, with some "custom markdown" that I have created. My intention is to render these strings as HTML in the frontend. Let's say, I have this string:
This is a string <color>that I need</color> to\nrender <caution>safely in the browser</caution>. This is some trailing text
I would be expecting to get something like:
This is a string <span class="primaryColor">that I need</span> to<br>render <div class="caution">safely in the browser</div>. This is some trailing text
And the way I do it right now is with some basic Regex:
toHtml = text
.replace(/<color>(.*)<\/color>/gim, "<span class='primaryColor'>$1</span>")
.replace(/\\n/g, "<br>")
.replace(/<caution>(.*)<\/caution>/gims, "<div class='caution'>$1</div>")
This works fine and returns the correct string. And then for printing, in the template I just:
<div id="container" v-html="result"></div>
My problem is that at some point I expect users to be able to enter this strings themselves, and that would be displayed to other users too. So for sure, I am gonna be vulnerable to XSS attacks.
Is there any alternative I can use to avoid this? I have been looking at https://github.com/Vannsl/vue-3-sanitize which looks like a good way of just allowing the div, span and br tags that I am using, and set the allowed attributes to be only class for all the tags. Would this be safe enough? Is there something else I should do?
In that case, I believe it will not be necessary to sanitize it in the backend too, right? Meaning, there will be no way for the web browser to execut malicious code, even if the string in the server contains <script>malicious code</script>, right?
My problem is that at some point I expect users to be able to enter this strings themselves
So, Do we have a form input for the users to enter the string which you mentioned in the post ? If Yes, My suggestion is that you can sanitize the user input at first place before passing to the backend. So that in backend itself no malicious code should be stored.
Hence, By using string.replace() method. You can first replace the malicious tags for ex. <script>, <a, etc. from the input string and then store that in a database.
Steps you can follow :
Create a blacklist variable which will contain the regex of non-allowed characters/strings.
By using string.replace(), replace all the occurrence of the characters available in the string as per the blacklist regex with the empty string.
Store the sanitized string in database.
So that, You will not get worried about the string coming from backend and you can bind that via v-html without any harm.
How does one go about formatting a phone number in Shopify using Liquid? The shop.phone object seems to output in a way that is specific to shop settings.
Much can be accomplished with only a few Liquid filters.
For example, we wanted to make phone numbers clickable within email notifications. Below is how shop.phone outputs the number for our shop.
(555) 555-5555
Fortunately, the filter method outputs directly to the page so there is no need to assign a variable.
{{ shop.phone | remove: "(" | remove: ")" | replace: " ", "-" }}
Our finished snippet looked like this:
{{shop.phone}}
Hi i am trying to scrap e-commerce page, but cant get prices.
I have page with this lines:
<span class="price">255,<sup>99</sup>€</span>
<span class="price">255 €</span>
But i can't extracts all price to one line.
I tried:
response.xpath('//span[#class="price"]/text()').extract()
But it ignores text in <sup> tag...
What i am doing wrong? please help.
You need to add another slash before text. So it addresses ALL nodes.
response.xpath('//span[#class="price"]//text()').extract()
Text='255,'
Text='99'
Text='€'
You should put double splash instead of single one.
response.xpath('//span[#class="price"]//text()').extract()
This statement returns all text under the specified tag as list object.
Note that the returned list may have some useless elements just like empty or return carriage character.
So you can use regex if you want extract only price information.
response.xpath('//span[#class="price"]//text()').re(r'[\d.,]+')
The currency symbol was ignored.
['255,','99','255']
Finally if you want get 255.99 from the page
''.join(response.xpath('//span[#class="price"][1]//text()').re(r'[\d.,]+')).replace(",",".")
You get all products first.
Final code:
products = response.xpath('//*[#class="catalog-table"]//td')
for prod in products:
price = ''.join(prod.xpath('//span[#class="price"][1]//text()').re(r'[\d.,]+')).replace(",",".")
print price
Check source HTML. There is in the source:
I was searching for the same question for the whole day and find this answer perfect for this
response.xpath('//meta[#itemprop="price"]/#content').get()
my variants title is “pack/4 bottles:4/PK”
“4/PK” is needed for shipping company to catch specific item.
However, it looks ugly when "4/PK" is displayed on page
Is there a way to hide it? Which liquid template should i touch?
Should I use
{{variant.title|move:'4/PK'}}
where should i put this code?
While this sounds more like something that should be assigned as an option for your variants instead of in the title, you can hide the part of the variants title that you don't want via using split and first
https://help.shopify.com/themes/liquid/filters/string-filters#split
split can be used to split a string (in this case your variant.title) into an array based on a set delimiter to divide it.
So you could do something only the lines of
{{variant.title | split: ':' | first }}
In your case, the output of the above would be: pack/4 bottles.
As for which liquid templates you will need to edit this into ... it will depend on your store. However some common areas would be:
product.liquid
cart.liquid
I highly recommend you read the the shopify liquid documents Here
Also, make sure to make a backup theme before doing any liquid changes in your theme that you are unsure of.
Hope this helps!
I am templating pdfs in Netsuite using freemarker and I want to display the footer only on the last page. I have been doing some research, but couldn't find a solution (since looks like the environment does not allow me to include or import libs), so I thought that just comparing the number of the page with the total pages in an if tag would be a nice and easy workaround. I already know how to display the numbers by using the <pagenumber/> and <totalpages/> tags, but still cannot get them as values so I can use them like this:
<#if (pagenumber == totalpages) >
... footer html...
</#if>
Any ideas of how or where can I get those values from?
The approach you are trying won't work, because you are mixing BFO and Freemarker syntax. Netsuite uses two different "engines" to process PDF Templates. The first step is Freemarker, which merges the record fields with your template and produces an XML file, which is then converted by BFO into a PDF file. The <totalpages/> element is meaningless to Freemarker, as it is only converted into a number by BFO later.
Unfortunately, the ability to add a footer to only the last page of a document is currently a limitation of BFO, as per the BFO FAQ:
At the moment we do not have a facility for explicitly assigning a
footer or header to the last page in a document when the number of
pages is unknown.
You CAN add it after a page break - and put the page break at the end of the body
<pbr footer="nlfooter" footer-height="25%"></pbr>
</body>
The issue here is - on a one page output - you will get 2 pages minimum... it will always ADD a page for the disclaimer / footer...