Extract specific tags using 'remark' in js - next.js

I am making a blog using markdown.
From next.js.
After reading markdown using fs, the process of converting it to html is as follows.
const markdownToHtml = async (markdownValue: string) => {
const processedValue = await unified()
.use(remarkParse)
.use(remarkHtml)
.process(markdownValue)
const stringedValue = processedValue.toString()
return stringedValue
}
This allowed me to express markdown as my blog post.
However, I would like to provide several posts and 'previews' on other pages.
Like this page.
enter image description here
In order to do that, I want to print only the p-tag.
<h2>sorry..</h2>
<p>Hi!</p>
<p><img src="/assets/cardTmp.jpg" alt="tmp"></p>
<p>hello world</p>
<p><strong>bye</strong></p>
All I need is 'Hi! hello world bye'.
Should I use a regular expression or javascript function?
Do you have any recommended methods or libraries?
I tried to use a regular expression, but I'm sure there's a cleaner and clearer way.

You can do that :
// Parse the HTML string into a DOM tree
const doc = new DOMParser().parseFromString(html, 'text/html');
// Get all the <p> tags from the document
const presult = doc.getElementsByTagName('p');
// Loop through the <p> tags
for (let i = 0; i < presult .length; i++) {
console.log(presult[i].textContent);
}

Related

How can I read an atom feed using svelte?

I'm currently learning Svelte and I would like to parse an atom feed and render it on the screen, but I'm not sure how to start getting the feed in. Can someone point me in the right direction on how to do this with Svelte?
This is pretty unrelated to Svelte, the main two things are:
Getting the feed content
Parsing the feed content
Once you have an object representation of the feed it can be rendered using Svelte like any other object.
If you want to do this fully client-side, including getting the feed-content, e.g. via fetch, you will probably run into cross-origin issues, depending on where the feed is from. So you might have to fetch the feed on the server and pass it to the client.
To parse the feed you can e.g. use the DOMParser:
const feedDocument = new DOMParser().parseFromString(atomXmlText, 'text/xml')
The resulting object is a DOM document that can be traversed or queried like an HTML document.
Basic example:
<script>
let items = [];
async function load() {
const res = await fetch('...');
const text = await res.text();
const feedDocument = new DOMParser().parseFromString(text, 'text/xml')
items = [...feedDocument.querySelectorAll('entry')].map(item => {
const title = item.querySelector('title').textContent;
const url = item.querySelector('link').attributes['href'].value;
return { title, url };
});
}
load()
</script>
<ul>
{#each items as { title, url }}
<li>
<a href={url} target="_blank" rel="noreferrer noopener">
{title}
</a>
</li>
{/each}
</ul>
REPL
(I could not find a proper feed with the correct CORS headers to allow a fetch, so the REPL does not actually fetch() anything.)
RSS example for NY Times (May break at any point)

Mailchimp/Mandrill and Handlebars changing preview text

I'm working with MailChimps Mandrill to send transnational emails with handlebars. The whole setup is done and the emails send absolutely fine - but when they arrive they still have the default Mailchimp template string for the preview text that look like:
|*MC_PREVIEW*|
Is anyone aware of a way to remove this from showing or change it? Currently I have to go into the code of the email in Mandrill and remove the block of code myself - wondering if there is a way to do that from Mailchimps end at all as it's a bit tedious every time an email template is updated and exported back to Mandrill to go in and remove it again.
Thanks in advance!
I've had this issue, and what helped me was first changing the Mandrill default merge tags to Handlebars, then re-exporting the templates from Mailchimp back to Mandrill.
This converts all *|Mailchimp|* style merge tags in the code of the email into {{handlebars}}-style.
Important Edit:
If your Mailchimp templates are using handlebars to define the merge tags, these will get escaped like so:
\{{mergeTag}}
You will either have to manually delete these backslashes to get the tags to work again, OR reformat the merge tags in Mailchimp to be in the *|MAILCHIMP|* style before exporting.
If you choose the latter, when converting a camelCase merge tag to Mailchimp style, just put it in all caps.
E.g. {{mergeTag}} becomes *|MERGETAG|*
We encountered the same issue and wrote a little lambda http endoint that we can trigger via slack integration to fix all our mandrill templates:
const mailchimpFactory = require('#mailchimp/mailchimp_transactional');
const mailchimp = mailchimpFactory(process.env.MAILCHIMP_API_KEY);
function fixTemplate({ name, code }) {
const regex = /\*\|MC_PREVIEW_TEXT\|\*/ig; // regexr.com/69390
const fixedBody = code.replace(regex, '');
console.log(`Updating ${name}`);
return mailchimp.templates.update({
name,
code: fixedBody,
});
}
// removes all mailchimp preview merge variables from all
// templates in mandrill (since we're using handlebars)
async function fixAllTemplates(event) {
const templates = await mailchimp.templates.list();
await Promise.all(templates.map(fixTemplate));
const templateList = templates.map(({ name }) => `\n> ${name}`).join('');
const msg = `*Mandrill Template Fixer:* Updated ${templates.length} templates. ${templateList}`;
console.log(msg);
return { statusCode: 200, body: msg };
}
module.exports = { fixAllTemplates };

Pull URL parameters into a WordPress "Raw HTML" content element

I'm using the URL Params plugin to pull parameters into regular content using a short code. But I have to use a Raw HTML block to insert Typeform code into the page and I want to be able to pass a URL parameter into the Typeform code to track the source of the form submission.
I can't figure out how to do it. The form is working fine at: https://HelloExit.com/instant-valuation
But I want to be able to send people to https://HelloExit.com/instant-valuation/?source=XXXX and pull the XXXX into the Typeform code as the "source" value in the "data-url"
Here's what I tried:
<script>
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
var source = getUrlVars()["source"];
</script>
<div
class="typeform-widget"
data-url="https://xgenius.typeform.com/to/zZHPPk?source=<script>document.write(source)</script>"
data-transparency="100"
data-hide-headers=true
data-hide-footer=true
style="width: 100%; height: 500px;">
</div>
<!-- Typeform embed code -->
<script>(function() { var qs,js,q,s,d=document, gi=d.getElementById,
ce=d.createElement, gt=d.getElementsByTagName, id="typef_orm",
b="https://embed.typeform.com/"; if(!gi.call(d,id)) { js=ce.call(d,"script"); js.id=id;
js.src=b+"embed.js"; q=gt.call(d,"script")[0]; q.parentNode.insertBefore(js,q) } })()
</script><div style="font-family: Sans-Serif;font-size: 12px;color: #999;opacity: 0.5;padding-top: 5px;"> powered by Typeform</div>
Any assistance would be greatly appreciated!
You're close, but you'll need to use Javascript to alter the data-url attribute of your div.
// ...
var source = getUrlVars()["source"];
// concatenate the url with your source variable
var newUrl = `https://xgenius.typeform.com/to/zZHPPk?source=${source}`;
// get the element whose attributes you want to dynamically set
// https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector
var widgetElement = document.querySelector('.typeform-widget');
// set the source attribute
// https://developer.mozilla.org/en-US/docs/Web/API/Element/setAttribute
widgetElement.setAttribute('data-url', newUrl);
Test this carefully, as it might still end up with a race condition (that is, the Typeform embed code might start running before you've updated the data-url attribute that it references).

How to change image to next one in hbs handlebars, nodejs with multer

I am building a classified ads website (like craigslist) with: handlebars (hbs), nodejs and multer for uploading images.
I have already created my own CRUD.
Users could post their ads for free, introducing their info for each ad:
user name
email
ad title
ad description
ad city
ad category
ad images (more than one if user needs)
I have a view, list.hbs, where ads show its information:
When users clicks on ad pictures, it will open like a modal box / pop up:
Everything perfect until here.
I save pictures in my ad.model, through multer like this:
image: {
imgName:{
type:String
},
imgPath:{
type:[String]
}
}
As you can see, I store path's pictures in an array to my mongodb database (managed by mongoose).
I.e:
"image" : {
"imgPath" : [
"uploads/e3c97fb10dd4c602054bedce194464b6",
"uploads/302fe7e147932d2b868a79b1799ba3f9"
]
}
The problem is here. I 've been trying to change image after clicking in each picture and it is impossible to do it.
I have tried via , but it looks like hbs doesn't work properly and don't read variables from handlebars:
I even tried passing through helper via onclick = myfunction({{#imageHelper}}{{/imageHelper}}), but it doesn't work...
Anybody knows how to handle this in handlebars? How to add js code to this view?
Note: my modal box / pop up is made it with pure html / css, no js or jquery in there.
I can't believe my mistake, how I didn't noticed before!
If you reach this question, or any question linked to handlebars - multer - javascript DOM, please, don't forget that template variables inside an onclick element MUST be quoted.
Mistake / Error
I passed through onclick element this:
<img onclick="myFun({{ad.reference}},{{ad.image.imgPath}})" class="imgAd" id="{{ad.reference}}" src="{{ad.image.imgPath.[0]}}"/>
And to manage the src and change images clicking everywhere on the image, I tried to do this:
...
<script>
let i = 0;
//next prev image
function myFun(ref,str){
const arr = str.split(',');
const len = arr.length;
if(i < len - 1){
i = i + 1;
document.getElementById(ref).src = arr[i]
}
else {
i = 0;
document.getElementById(ref).src = arr[i]
}
}
</script>
(This script above, just for change next picture, and so on)
Remember: if you pass variables like that, not quoted, js will throw errors, because it receives a "variable" like parameter, not a string.
In this case onclick received this:
uploads/b5e01da1707382ed915f314c0c77266c //variable, not string
Correct way:
<img onclick="myFun('{{ad.reference}}','{{ad.image.imgPath}}')" class="imgAd" id="{{ad.reference}}" display="block" src="{{ad.image.imgPath.[0]}}"/>
I passed a string, not a variable:
After I quoted each handlebar variable, I passed as string.
"uploads/b5e01da1707382ed915f314c0c77266c"
Now, the script will works. I get a string that I need to transform in an array to handle it:
<script>
let i = 0;
//next prev image
function myFun(ref,str){
const arr = str.split(',');
const len = arr.length;
if(i < len - 1){
i = i + 1;
document.getElementById(ref).src = arr[i]
}
else {
i = 0;
document.getElementById(ref).src = arr[i]
}
}
</script>
With this, I was able to manage DOM in each ad, changing images after clicking with nodejs, hbs and multer.

Handlebars : register helper based on template with 'body content'

I'm trying to implement some kind of 'macro' mechanism in a nodejs application using Handlebars (similar to the #bodyContent system in velocity.)
In my main template, I want to be able to write something like this :
{{#foobar who = user }}
<p>My body content</p>
{{/foobar}}
In a "views/helpers/foobar.html", I would have a file with a template, and some way to reference the "body content"
<p>Hello {{ who }}<p>
{{ bodyContent }}
<p>Bye !</p>
Based on the convention that the templates in "views/helpers" corresponds to a helper called with a single hash parameter, I want to automatically register them ; so I have something like this :
var helpers = "./views/helpers/";
fs.readdirSync(helpers).forEach(function (file) {
var source = fs.readFileSync(helpers + file, "utf8"),
helperName = /(.+)\.html/.exec(file).pop();
var helperTemplate = Handlebars.compile(source);
// We assume all helpers in the folder
// would take a hash as their first param
// We'll provide them with all the required context
Handlebars.registerHelper(helperName, function (options) {
var hash = options.hash || {};
// I want to somehow 'pass' the body Content ;
// The closest I have is 'this', but the markup is
// encoded, so I get a string with '<p>My body content</p>'
hash.bodyContent = options.fn(this);
console.log("Body Content", hash.bodyContent);
// Render the source as an handlebar template
// in the context of a hash
return helperTemplate(hash);
});
});
This does not work, as the tags are escaped, and so bodyContent is a String containing the markup, instead of the markup.
Is there a way I can fix my helper registration, or a built in mechanism in Handlebars to deal with this ?
Thanks
You need to use the {{{triple stashes}}} to unescape the HTML injection. So your template should look like:
<p>Hello {{ who }}<p>
{{{ bodyContent }}}
<p>Bye !</p>
You can read more here

Resources