Layout for pages generated from a collection with output set to true - jekyll

I build a style guide in Jekyll and have a collection set up for each of the components. It uses only front-matter to display data about the styles. A file could look like this:
---
title: "Button Big Fixed"
type: interactive elements
description: "A big button with a fixed height."
code:
html: |
<button class="expanderBtn icon">Button</button>
css: |
.test {
font-size: 20px;
text-align: center;
}
colors:
- name: Brand Blue
hex: "#006CFF"
notes: Used as the background
- name: Hover
hex: "#7FB5FF"
notes: Brand Blue with 50% opacity
- name: Clicked
hex: "#4091FF"
notes: Brand Blue with 75% opacity
- name: Text
hex: "#000000"
notes: Text should be black for best legibility
---
Now, for a permalink feature, I'd like to use output: true. However, the documents that get generated are empty because I only use front matter.
Is there any way to set a custom template or something similar, so I can render the front matter on the page generated by output: true?

You can add a default template for each collection in your _config.yml. This looks like this:
defaults:
- scope:
path: ''
values:
layout: 'page'
- scope:
path: ''
type: 'guides'
values:
layout: 'guide'
It means: use the page.html file in the _layouts directory for everything except for the collection 'guides'. For 'guides' you should use guide.html. Create this file in your _layouts folder. In this guide.html file you call parts of the frontmatter by using:
page.title
page.description
page.etc
Good luck!

Related

Gatsby mdx pages not rendering fully when placed in subfolder of src/pages

I have been converting a WordPress site to Gatsby, and everything works nicely with gatsby develop, however after building with gatsby build some pages seem to render with only the page body and no wrapper layout or styling. I am using markdown pages with mdx, and I have all my markdown files under subfolders of the src/pages directory, like this:
src/pages/
--project/
--contact.md
--outputs.md
--project.md
--sources.md
--software/
--apps.md
--frontend.md
--system.md
The above structure is more for organizational reasons than anything else (there are many more mdx files in reality). It does also correspond to the overall path structure of the site, however. In my built site, when I go to http://localhost:9000/contact the page renders perfectly, but when I visit http://localhost:9000/project or any other pages relating to that folder I only see the page body (the text content), with no layout component wrapper or styling. Everything under the software folder renders fine.
Each markdown file has a slug defined in the usual way in the frontmatter. The slug defined in src/project/project.md is just '/project'. The slug for src/project/contact.md is '/project/contact'.
Clearly the presence of src/pages/project/project.md is causing problems, but I can't figure out exactly why. I tried renaming that to src/pages/project/index.md, but that did nothing. Interestingly, when I look at public/project I see an index.html at the top level, with subfolders for each subpage, each containing its index.html. For public/software there is no index.html at the top level.
My gatsby-config.js (relevant parts):
{
resolve: `gatsby-source-filesystem`,
options: {
name: `pages`,
path: `${__dirname}/src/pages`,
},
},
{
resolve: `gatsby-plugin-mdx`,
options: {
extensions: [`.md`, `.mdx`, `.markdown`],
gatsbyRemarkPlugins: [
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 1024,
},
},
],
},
},
My template (under templates/page.js - I use some MUI components):
export default function SitePageTemplate({ data: { mdx } }) {
const { frontmatter, body } = mdx;
const { title } = frontmatter;
return (
<Layout>
<Seo title={title} />
<Container fixed>
<Stack direction="row" justifyContent="space-between">
<SideBar/>
<div style={ { padding: "0 0 0 3.5%", width: "75%" } }>
<MDXRenderer>{body}</MDXRenderer>
</div>
</Stack>
</Container>
</Layout>
);
}
export const pageQuery = graphql`
query ($id: String!) {
mdx(id: { eq: $id }) {
body
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
}
}
}`
My gatsby-node.js:
const path = require("path");
exports.createPages = async ({ graphql, actions, reporter }) => {
const { createPage } = actions
createPage({
path: "/using-dsg",
component: require.resolve("./src/templates/using-dsg.js"),
context: {},
defer: true,
})
const result = await graphql(`
query MARKDOWN {
allMdx {
edges {
node {
id
frontmatter {
date(formatString: "MMMM DD, YYYY")
slug
title
}
}
}
}
}
`);
if (result.errors) {
reporter.panicOnBuild("🚨 ERROR: Loading \"createPages\" query");
}
const md = result.data.allMdx.edges;
md.forEach(({ node }, index) => {
createPage({
// This component will wrap our MDX content
component: path.resolve("./src/templates/page.js"),
// Pass any value you want to access inside the template. They'll be available via `props`.
context: {
id: node.id
},
// Slug defined with frontmatter in each MDX file.
path: node.frontmatter.slug
});
});
}
If I place all the markdown files flat under the src/pages directory the problem goes away. But I would like to retain the above folder layout so that the markdown is organized properly. How can I do this whilst at the same time avoiding this problem?
OK, returning to this issue after a few months, I think I finally solved it. A warning I was also getting turned out to be the real clue - initially I had thought it unrelated to this issue. At develop and at build time I was getting a warning in the following format:
warn Non-deterministic routing danger: Attempting to create page: "/project/contact/", but page
"/project/contact" already exists
Others have reported this warning, but none of the reasons or propsed fixes seemed to relate to my problem. Looking at my gatsby-config.js, however, I noticed that I had at some time included the gatsby-plugin-page-creator plugin. I suspected that somehow this might be generating pages in addition to the mdx plugin. And it seemed as if this was right - removing the plugin removed both the warnings about duplicate page creation and also fixed my rendering problems. Everything looks fine now, for both development and production versions of my site.
I can't remember why I originally included this plugin - I was originally using the mdx extension for my markdown files, and I think I needed gatsby-plugin-page-creator so that files with that extension would be correctly interpreted as markdown. I now use the standard md extension, and removing gatsby-plugin-page-creator doesn't cause any problems.

Does lovelace-floorplan allow to navigate through the Home Assistant tabs?

I would like to know if lovelace-floorplan can be used for navigating through the Home Assistant tabs, like picture-elements does. If this is the case, could you provide some yaml example for configuring this feature?
As far as I know, inkscape can be used for adding links into a SVG file. Even though it achieves my goal, the problem is that not only the tab, but the entire home assistant is reloaded (waste of time and resources).
Yes.
- cards:
type: 'custom:floorplan-card'
- config:
image: /local/floorplan/examples/simple/simple.svg?v=1.1.14
log_level: error
rules:
- element: floorplan.some_button
action:
service: floorplan.page_navigate
data:
page_id: tab_name
I have found a solution checking the floorplan.js code. The following piece of code is able to paginate between 3 different svg files which are defined in the same tab.
This is the code:
title: Floor Plan Test
type: 'custom:floorplan-card'
config:
log_level: info
pages:
- image: /local/test1.svg?v=1.1.15
log_level: info
page_id: page1
rules:
- element: button_1a
action:
service: floorplan.page_navigate
data:
page_id: page3
- element: button_2a
action:
service: floorplan.page_navigate
data:
page_id: page2
stylesheet: /local/style.css?v=1.1.14
- image: /local/test2.svg?v=1.1.15
log_level: info
page_id: page2
rules:
- element: button_2a
action:
service: floorplan.page_navigate
data:
page_id: page3
stylesheet: /local/style.css?v=1.1.14
- image: /local/test3.svg?v=1.1.15
log_level: info
page_id: page3
stylesheet:/local/style.css?v=1.1.14
master_page:
content_element: floorplan
rules:
- element: button_3a
action:
service: floorplan.page_navigate
data:
page_id: page1
I'll appreciate any comment, thanks!

Front-matter defaults in VuePress config

I'm trying to switch my documentation site from GitBook to Vuepress and got stuck with front-matter variables. In GitBook, you just add variables in the config and then use them anywhere on the page as {{ book.variable_name }}. In Vuepress, at glance, things seem to be trickier.
I need to configure several variables that are used across the whole site, so adding them to each page would be a complete nightmare. The documentation tells nothing about how to configure front-matter variables but has a link to the Jekyll site. On the Jekyll site, I found this article that is exactly what I want to achieve. The problem is that I have no idea how to use this info in config.
Any help is highly appreciated. I asked this question in the official repo but that didn't help.
To define some variables that you could access anywhere in your site, you can add them to your theme config.
If you haven't already got one, create a config.js file at .vuepress/config.js.
This file should export an object.
You want to add a themeConfig: {} to this.
Properties you set on the themeConfig object will be available throughout your site on $themeConfig.
//- .vuepress/config.js
module.exports = {
themeConfig: {
//- Define your variables here
author: 'Name',
foo: 'bar'
}
}
{{ $themeConfig.author }} //- 'Name'
{{ $themeConfig.foo }} //- 'bar
You can also make this easy to override locally / per page, by using global computed functions. (This could also provide a cleaner way to access the variables)
Adding an enhanceApp.js file in the same place as config.js, will give you access to the Vue instance - where you can define a mixin for all components.
You can define some computed properties in this mixin that first check for a value in the pages frontmatter data and then fall back to the value set in the themeConfig. Allowing you to set some default values that can be locally overridden per page.
//- .vuepress/enhanceApp.js
export default ({ Vue }) => {
Vue.mixin({
computed: {
author() {
const { $themeConfig, $frontmatter } = this
return $frontmatter.author || $themeConfig.author
},
foo() {
const { $themeConfig, $frontmatter } = this
return $frontmatter.foo || $themeConfig.foo
}
}
})
}
{{ author }} //- 'Name'
{{ foo }} //- 'bar
Vuepress config docs
Vuepress app level enhancement

Jade outputting raw HTML inside <pre> tags

I am new to using jade and have this simple script:
extends layout
block page
- var menu = 'events'
block content
div event
each item in events
| Event name: #{item.name} Venue: #{item.venue} Drink Price Score: #{item.drink_prices}
Which I expect to output as:
Event name: example Venue: The ex. Drink Price Score: 7
With some header and footer content above and below.
However the following is output:
When I check the Chrome Inspector the code is put as a string between 'pre' tags.
Why is this happening and how do I get this to render normally? Thanks!
EDIT SOLUTION
The error was occuring in my controller code event.js
exports.list = function(req, res, next) {
req.models.Event.list(function(error, events) {
if (error) return next(error);
// res.send({events:events}); <-- offending line
res.render('event', { events: events } );
});
};
If this is the output you want:
Event name: example Venue: The ex. Drink Price Score: 7
Then this is the code you need
each item in events
| Event name: #{item.name} Venue: #{item.venue} Drink Price Score: #{item.drink_prices}
You put h2 tags on each line, so of course it's going to spit out each line wrapped in <h2> tags. I'm not sure why you expected differently.
The jade language is just an abstraction over HTML and the Jade compiler spits out HTML to be rendered by the browser. Jade is not the browser and browsers don't understand Jade code. Jade isn't going to read the Jade code and present you with a pretty page. It's going to spit out HTML that the browser does understand. Jade is just there to help you write cleaner looking HTML, then the Jade compiler turns the Jade document into an HTML document that the browser knows how to render.

What tools are available for translating (human) languages within HTML code?

Is there a tool or task runner that can take an HTML document in one language, parse out the content in general/specific HTML tags, run that content through Google translate, then put it back into the markup in the right place in new files? Basically, digest one source file and output multiple variations in different (non-computer) languages.
What I'm hoping for is:
index.html
<!DOCTYPE html>
<html>
<body>
привет мир!
</body>
</html>
Gets compiled to:
en/index.html
<!DOCTYPE html>
<html>
<body>
Hello World!
</body>
</html>
ru/index.html
<!DOCTYPE html>
<html>
<body>
привет мир!
</body>
</html>
ch/index.html
<!DOCTYPE html>
<html>
<body>
你好世界!
</body>
</html>
I obviously don't mind setting up some sort of Gruntfile or whatever that dictates the languages, destinations, etc.
Take a look at get-translation or grunt-google-translate. Also Google Translate has simple REST API, you can write your own plugin from the scratch or use something like grunt-restful.
I was able to piece together a solution using Ruby and Grunt. This could be refactored to be more robust, but it was a working solution, so I ran with it. Keep in mind, the translating script overwrites the source files. Only the Grunt starts making duplicates in new destinations.
Using the easy_translate Rub gem I wrote this script:
#!/usr/bin/ruby
require 'easy_translate'
EasyTranslate.api_key = '' # Get from google
target_path = '' # path to translate
Dir.glob(target_path) do |item|
next if item == '.' or item == '..' or item == '.svn'
contents = ""
update = ""
File.open(item, "r") do |file|
contents += file.read
update += EasyTranslate.translate(contents, :from => :russian, :to => :en)
end
File.open(item, "w"){ }
File.open(item, "w") do |file|
file.write(update)
end
end
Walking through this, each file in the target_path is checked if it’s a worthwhile item we make variables contents and update we’ll use to place in the old and new versions of the contents of the file, respectively. Then we open the file and fill up those variable. On line 20 we empty the file, then in the last block on lines 22-24 we write the update string into the file. I used File.open(item, "w") {} instead of .truncate(0) because I was getting random Unicode characters added to the contents of the file with the latter option. Again, overwriting the files in the translation process is not ideal. It'd be better to make a copy in a new destination, but I didn't do that.
The Ruby script returned a single line of minified HTML and broke Smarty templating, so I used used grunt-prettify and grunt-text-replace to prettify the HTML for ease of use and to make the Smarty stuff work again. The Gruntfile looks like this:
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
'prettify': {
options: {
indent: 4,
indent_char: ' ',
wrap_line_length: 0,
brace_style: 'expand',
"unformatted": [
"a",
"code",
"pre"
]
},
all: {
expand: true,
cwd: 'static_ugly',
ext: '.html',
src: ['*.html'],
dest: 'static_pretty'
}
},
'replace': {
fix_smarty: {
src: ['static_pretty/*.html'],
overwrite: true,
replacements: [{
from: '{/ Strip',
to: '{/strip'
},{
from: '{$ This-> setLayout ',
to: '{$this->setLayout'
},{
from: '{$ this- > setPageTitle ',
to: '{$this->setPageTitle'
},{
from: '$ this-> setPageTitle ',
to: '$this->setPageTitle'
},{
from: '{$ smarty.block.footer ',
to: '{$smarty.block.footer'
}]
}
}
});
grunt.loadNpmTasks('grunt-prettify');
grunt.loadNpmTasks('grunt-text-replace');
grunt.registerTask('default', ['prettify', 'replace']);
};
There was a lot more find/replace stuff that I left out since it's project-specific. This solution pretty much does what I wanted in the original question. I did some manual moving around of files in the name of getting it done, but I believe I'll be using a variation of this moving forward and consider it a work in progress.