Why aren't the attributes set on this self-closing haml_tag? - haml

I'm capturing haml output using the helper method haml_tag. However the particular element that I want to capture is a <meta/> tag and so I'm trying to figure out how to get a self-closing tag and also include attributes.
This works (almost)
haml_tag 'meta', '', name: :description, content: 'this is the description'
outputs:
<meta content='this is the description' name='description'></meta>
However I would like it to output:
<meta content='this is the description' name='description' />
This self-closes but doesn't print attributes...
If you pass a flag of :/ then it should be possible to self-close the tag however in that instance the attributes don't get printed out:
haml_tag 'meta', nil, :/, name: :description, content: 'this is the description'
outputs:
<meta />
How can I get the best of both worlds?

Just omit the second argument if you want an empty tag:
haml_tag 'meta', name: :description, content: 'this is the description'
produces:
<meta content='this is the description' name='description' />
Note that since meta is one of the default empty elements you don’t need the :/ argument, although you can add it if you want to be explicit:
haml_tag 'meta', :/, name: :description, content: 'this is the description'
produces the same output as above.
There is a bug here in Haml 4.0.5, as haml_tag isn’t respecting the format option. In HTML format the output should really be:
<meta content='this is the description' name='description'>
This is fixed in 4.1.0.beta.1.

Related

How to create custom meta tags in Vue Meta 3?

I am using Vue Meta 3 to provide meta data to the website. The API for this is here
I do not understand how to provide custom meta tags( e.g Open Graph tags such as og:type). This is what I have tried to do in a component:
setup() {
useMeta({
title: "Homepage",
meta: [
{name: "hunky:dory", content: "website"}
],
description: "This is the homepage."
})
},
The HTML that gets outputted ends up like this:
<head>
<title>Homepage</title>
<meta name="description" content="This is the homepage.">
<meta name="meta" content="website"> <!-- should be <meta name="hunky:dory content="website"> -->
</head>
If I change the code to this:
setup() {
useMeta({
title: "Homepage",
"hunky:dory": [
{content: "website"}
],
description: "This is the homepage."
})
},
I get illegal HTML output:
<head>
<title>Homepage</title>
<meta name="description" content="This is the homepage.">
<hunky:dory>website</hunky:dory> <!-- total nonsense -->
</head>
How do I get the output to be:
<head>
<title>Homepage</title>
<meta name="description" content="This is the homepage.">
<meta name="hunky:dory" content="website">
</head>
There are 2 parts to getting og meta working -- I think I can help with part 1:
Correct vue-meta syntax
Server-Side Rendering (SSR)
Part 1: vue-meta for Vue 3
I wrote this with vue-class-component, and it seems to be working:
meta = setup(() => useMeta(computed(() => ({
title: this.event?.name ?? 'Event not found',
og: {
image: this.event?.bannerUrl ?? 'http://yourwebsite.com/images/default-banner.png'
}
}))))
...which presumably translates to this in vanilla Vue 3:
setup() {
useMeta(
computed(() => ({
title: this.event?.name ?? 'Event not found',
og: {
image: this.event?.bannerUrl ?? 'http://yourwebsite.com/images/default-banner.png'
}
}))
)
}
Result:
<meta property="og:image" content="http://cloudstorage.com/images/event-123.png">
References:
GitHub -> vue-meta#next -> example for vue-router
Also hinted in the readme
Part 2: SSR
Once I'd done part 1, I realized that I hadn't setup SSR... so I'm only rendering the meta for my users, not for Facebook's crawler (not very useful). I'm afraid I haven't fixed this yet on my project; perhaps someone else can pitch in that part!
Until then, maybe this will get you started:
SSR options
Vue 3's native SSR
Note on SSR in the vue-meta readme
Note: vue-meta is under the Nuxt GitHub organization => you might consider migrating to Nuxt v3 (which is built on top of Vue):
Nuxt v3 tracker issue
Slides suggesting beta this month (June 2021).
A bit late but maybe not useless for anyone facing issues with Vue 3 (and vue-meta). With the below detailed woraround, you are not dependent on any 3rd party lib.
My project is currently in development stage in local environment (so not fully tested), but a probable workaround is using beforeCreate lifecycle hook for adding meta tags if you are using Options API in Vue 3 (with vue-router), SFC way (e.g. If you are using single-file-component views for "pages" and you want them all to have their custom meta info).
In the hook method you can create DOM nodes and append them to the head like:
...
beforeCreate(){
// adding title for current view/page using vue-i18n
let title = document.createElement(`TITLE`)
title.innerText = this.$t(`something`)
document.querySelector(`head`).appendChild(title)
// adding og:image
let ogImage = document.createElement(`META`)
ogImage.setAttribute(`name`,`og:image`)
ogImage.setAttribute(`content`,`YOUR-IMAGE-URL`)
document.querySelector(`head`).appendChild(ogImage)
}
...
I'm not sure yet if this is an efficient way to make it work, but gonna try to update this post when the project is in production.
I have tested this solution with chrome plugins like this one:
Localhost Open Graph Debugger
I was having the same issues then I came across this which solves the problem for me.
Here is the link to the original post: vue3 vue-meta showing name="meta"
In vue js 3 you should use the vue3-meta or alpha version. Then do the
following
metaInfo() {
return {
htmlAttrs: { lang: 'en', amp: true },
title: "page title",
description : "Page description",
twitter: {
title: "twitter title",
description: "twitter description",
card: "twitter card",
image: "twitter image",
},
og: {
title : 'og title!',
description : 'og description!',
type : 'og type',
url : 'og url',
image : 'og image',
site_name : 'og site name',
}
}
}
if you want to use meta name then change the config in main.js
import { createMetaManager, defaultConfig, plugin as metaPlugin } from 'vue-meta'
const metaManager = createMetaManager(false, {
...defaultConfig,
meta: { tag: 'meta', nameless: true },
});
and in your component use the meta name below
metaInfo() {
return {
meta: [
{'name' : 'author', 'content' : 'author'},
{ name: 'description', content: 'authors' },
]
}
}

TinyMCE not being saved when submitting using capybara and selenium

I have this feature test in rspec
fill_in "Name", "title"
#fill_in "Body", "my blog" # this is the old implementation before tinymce
within_frame("mce_0_ifr") do
page.driver.browser.find_element(:id, 'tinymce').send_keys("blog 123")
puts page.html
end
click_button "Submit"
From the output I can clearly see that the word "blog 123" was written in the body via
<body id="tinymce"><p>blog 123</p></body>
But I get a test fail because it does not create a new blog post.
Turns out the code is fine. I was getting an error due to tinymce and html5 required validation not working together. Therefore the data is never sent, and capybara moves on to the next expect thus rendering an error. Just incase someone get's into this problem I'll post how I solved it.
<script>
tinymce.init({
selector: "textarea.tinymce",
editor.on('change', function () {
editor.save();
})
})
</script>

Netlify CMS nested YAML using Middleman

I'm trying to get my Middleman page set up with Netlify CMS. I'm using have the following file structure:
data
> pages
> page1.yml
> page2.yml
Each page has this content:
de:
title: Title in German
en:
title: Title in English
Now I'd like to be able to edit these pages in Netlify CMS and basically have two text fields per page ("Title (DE)" and "Title (EN)").
I tried it with this config:
collections:
- label: Pages
name: pages
folder: data/pages/
fields:
- { label: Title (DE), name: de.title, widget: string, required: true }
- { label: Title (EN), name: en.title, widget: string, required: true }
But nothing shows up in the Netlify CMS backend:
What am I doing wrong?
I'm guessing your files aren't markdown with frontmatter? If you're using data files, eg. json/yaml/toml, you'll need to set the extension for the collection: https://www.netlifycms.org/docs/configuration-options/#extension-and-format
Also, you need a field named title, or else set identifier_field to the name of the field you'd like to use as the identifier (otherwise your files will show as blank tiles in the UI): https://www.netlifycms.org/docs/configuration-options/#identifier_field

Using Frontmatter with Dynamic Pages in Middleman 4

I have spent ample time researching this without finding a solution that worked. I would love it if someone could help me figure this out.
I’m trying to use Dynamic Pages in my setup, but need to include dynamic Frontmatter with this. But I can’t use Frontmatter in the template file, so I was thinking I could use a YAML data file instead? I tried various approaches, but none were successful. The dynamic pages load just fine, but every one of them will use the same Frontmatter unless I can pull in dynamic data instead.
My config includes:
["england", "france"].each do |team|
proxy "/teams/#{team}/index.html", "/teams/team.html", :locals => { :team_name => team }, :ignore => true
end
And my directory structure in this section looks like this:
teams
- index.html.erb
- team.html.erb
I began a YAML data file that includes:
england:
title: "Teams/England"
description: "England"
headline: "England"
addclass: "england cols"
france:
title: "Teams/France"
description: "France"
headline: "France"
addclass: "france cols"
When I use the aforementioned data in the template file as Frontmatter, it works just fine:
---
title: Teams/France
description: France
headline: France
addclass: france cols
---
One example of how I am using the data:
<%= current_page.data.addclass %>
My questions are as follows:
How can I use a YAML data file to serve unique data to each Dynamic Page?
Can I use the final URI segment ( “england” from /teams/england/, “france” from /teams/france/, etc.) to define which data set to use?
Can I do this without impacting other non-dynamic-pages (/matches/, /groups/, etc.) on the site?
Thank you so very much in advance.
I'd suggest changing your data format slightly. It'll allow you to pass the entire local data item to the template so you can use the data without needing to first "load it" into Frontmatter.
Adjust your teams.yml file (I've added the 'slug' value here):
items:
- title: "England"
slug: "england"
description: "England"
headline: "England"
addclass: "england cols"
- title: "France"
slug: "france"
description: "France"
headline: "France"
addclass: "france cols"
Change your config.rb block to (assuming teams.yml is at /data/teams.yml) - note the check to prevent errors if data is missing:
if File.exist?("data/teams.yml")
data.teams.items.each do |item|
p = item
proxy "teams/#{p.slug}.html", "teams/team.html", locals: { item: p }, ignore: true
end
end
This will pass all the data from the team item into the template. You won't have to "define which data set to use", since the template context will refer just to that data item.
Now, in your team.html.erb template, you can reference the data like this (in the template body, not in the Frontmatter):
<h1 class="<%= item.addclass %>"><%= item.title %></h1>
<h2><%= item.description %></h2>
<h3><%= item.headline %></h3>
This should give you two separate pages for England and France with their own unique data.
Unfortunately, Frontmatter doesn't like to be overwritten after a dynamic page is generated in Middleman. For overwriting Frontmatter that you use for metadata, specifically "title", I've had success with gem 'middleman-meta-tags' [ https://github.com/tiste/middleman-meta-tags ] which allows you to override page titles in the template body after it's been defined, sourced from the YAML data.

haml syntax issue - write separate word in tag, no mapping

I am pretty new to HAML, can any one explain how I can get it to render:
<html itemscope itemtype="http://schema.org/">
It's the "itemscope" thats causing the problem.
I have:
%html{ :itemtype => "http://schema.org"}
I don't seem to be able to add in "itemscope" anywhere without getting a mapping error.
Thanks for any help!
Try adding it as a boolean and telling it to format html5:
engine = Haml::Engine.new '%html{:itemscope => true :itemtype => "http://schema.org"}', :format => :html5
puts engine.render
Should render
<html itemscope itemtype="http://schema.org/">
Revisiting an old question, all that was needed was:
%html{itemscope: true, itemtype: "http://schema.org"}
and that will generate:
<html itemscope itemtype="http://schema.org/">