Metalsmith static site pages are missing metadata - node.js

I've been attempting a tutorial to set up Metalsmith, and I've gotten to the end of part 1.
I've install node.js and modules. The IDE is Visual Studio 2013 with Node.js tools installed. I've put a basic structure in and I'm trying to get a single page to render with a template.
The instructions tell to put into a file the following:
---
title: Home
template: home.hbt
---
This is your first page
With a template like:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{{ title }} | Metalsmith Page</title>
</head>
<body>
<div class="main-wrapper">
{{{ contents }}}
</div>
</body>
</html>
The tutorial says that it should render out into a html page but the result I am getting is something like:
--- title: Home template: home.hbt --- This is your first page
When I use the markdown renderer it gives
<p>---
title: Home</p>
<h2 id="template-home-hbt">template: home.hbt</h2>
<p>This is your first page</p>
Debugging the code shows that when it gets to the renderer the YAML front-matter metadata is missing. This seems to be important as the plugins use the metadata to render the page.

The key to the solution lay in the three strange charatcers at the begining of the markdown rendered page

and the YAML front-matter warning:
UTF-8 Character Encoding Warning
If you use UTF-8 encoding, make sure that no BOM header characters exist in your files or very, very bad things will happen to Jekyll. This is especially relevant if you’re running Jekyll on Windows.
Looking at the buffer loaded in Node.js showed the utf8 BOM characters.
One solution would be to make the IDE stop saving it as utf8 with BOM but for me that wasn't a viable option.
I created a workaround as a few small lines that has to be run before any other metalsmith plugin.
var stripBom = require('strip-bom');
var front = require('front-matter');
var extend = require('extend');
// **snip**
.use(function __utf8BOM_workaround(files, metalsmith, done)
{
setImmediate(done);
Object.keys(files).forEach(function (file)
{
var data = files[file];
var parsed = front(stripBom(data.contents.toString()));
data = extend({}, data, parsed.attributes);
data.contents = new Buffer(parsed.body);
files[file] = data;
});
})

Related

Typesetting MathJax in a string of HTML server-side

I was pretty easily able to get npm's mathjax-full working, for parsing TeX to CommonHTML:
const MathJax = await require("mathjax-full").init({
options: {
enableAssistiveMml: true
},
loader: {
source: {},
load: ["adaptors/liteDOM", "tex-chtml"]
},
tex: {
packages: ["base", "ams", "newcommand"]
},
chtml: {
fontURL: "https://cdn.jsdelivr.net/npm/mathjax#3/es5/output/chtml/fonts/woff-v2"
},
startup: {
typeset: false
}
});
MathJax.tex2chtmlPromise("x^2-2x+1", {
display: true,
em: 16,
ex: 8
}).then((node) => {
var adaptor = MathJax.startup.adaptor;
console.log(adaptor.outerHTML(node));
});
However, unlike typeset/typesetPromise, rather than a DOM node or string of HTML, this works with the TeX directly. Of course I could parse the page myself, finding MathJax delimiters (outside of code blocks) and passing the contents to tex2chtmlPromise, but this would have the potential of bugs or differences in behavior between a client-side preview using MathJax's typeset and the server-side rendered version.
I've looked around in the internals of the liteDOM adaptor quite a bit, but can't seem to find any way of setting the innerHTML of its body, if that would be the correct approach (which would allow me to just use typesetPromise normally).
Is there a recommended way to do what I'm trying to do, namely, take some HTML, and typeset it with MathJax without parsing for the delimiters myself?
The MathJax node demos repository includes examples of how to process an HTML page that should give you what you need. There are several different ways to load and call mathJax, so there are separate directories that illustrate each of them. You are using the "simple" approach, but may also want to look at the "component" and "direct" approaches. Look for files that end in -page.
The main idea for the simple case is to use the document option in the startup section of your MathJax configuration. This allows you to provide a serialized HTML string to be used as the document to be processed. So in your case, you could change
startup: {
typeset: false
}
to
startup: {
typeset: false,
document: html
}
where html is the HTML string to be processed. E.g.,
html = `
<!DOCTYPE html>
<html>
<head>
<title>My Document</title>
</head>
<body>
<p>
Some math: \(E = mc^2\).
</p>
</body>
</html>
`;
If you want the same invocation of your node app to be able to process multiple pages, then you will need to use the "direct" approach, as illustrated in direct/tex2chtml-page, and do these lines for each html file you want to process. You can reuse the same output jax, but should create a new InputJax and MathDocument for each page you process.

How to send scraped data to index html file to load

I am new to node.js and Puppeteer and may not be asking this correctly. I was able to create a web scraper to grab data. What I am wanting to do is send this information I received and push it to a HTML file to load locally on my machine to show the results instead of having it inside my console.
Is there anyway to do this?
Do I need to use another framework?
Any useful tips or resources would be great!
To create a HTML file, you can use your variables and fs.writeFileSync to generate a HTML file with your content.
Example:
const fs = require('fs');
// ... crawling is done, variable are filled
const result1 = 'Some data';
const result2 = 'More crawled data';
const resultHtml = `<!DOCTYPE html>
<html lang="de">
<head><title>Crawling results</title></head>
<body>
<p>Result 1: ${result1}</p>
<p>Result 2: ${result2}</p>
<p>...</p>
</body>
</html>`;
fs.writeFileSync('results.html', resultHtml);
You can then open the results.html file locally in your browser to view the results.
You can use a templating language like handlebars to render the data to an HTML template and write the result to an HTML file.

Why am I not able to load a module from within embedded JavaScript?

My objective is to store some data in a module and then be able to retrieve
that data for display using embedded javascript contained in an HTML document. My code for testing this is shown in the following 3 files:
File 1: The HTML (/var/www/html/modTest.html)
<html>
<head>
<title>Module Test</title>
<% var myModule = require("/var/www/cgi-bin/node_modules/modTest") %>
</head>
<body>
<p>Color: <%= myModule.color %>
</body>
</html>
File 2: The Module (/var/www/cgi-bin/node_modules/modTest.js)
var color = "Blue";
module.exports.color = color;
File 3: The CGI Script (/var/www/cgi-bin)
#!/bin/node
var fs = require("fs");
var ejs = require("ejs")
console.log("Content-type: text/html\n");console.log(ejs.render(fs.readFileSync('/var/www/html/modTest.html','utf8')));
When I load the URL of the cgi script into my browser I get a blank page. There is an error message in the httpd error log compaining that "require" is not defined. Can anyone please tell me why this is and (more importantly) how to fix it? Thanks for any input.
... doug
you need require.js or webpack/browserify to link/pack your javascript together for client side and to load your modules with a require - otherwise you would need to include every javascript file in as a
<script src="...">
tag seperately.

YUI error: Uncaught ReferenceError: YUI is not defined

I am a jQuery user and just learning YUI. I have the following code and I keep the error that YUI is not defined. I know it is an issue with linking to the library but I'm not exactly sure what. I had someone else test my code where they had YUI held locally and it worked fine. If I need to do this, how do I obtain a copy of the min.js file? When you download a copy from the YUI site its a tonne of files...
<head>
<title>YUI3 Test</title
<script src="http://yui.yahooapis.com/3.2.0/build/yui/yui-min.js"></script>
</head>
<body>
<div id="menu">
<p>Click here to test.</p>
</div>
<script>
YUI().use('node', 'event', function (Y){
var changeText = function(e){
e.target.setHTML("<p>Now you see the test working.</p>");
}
var node = Y.one("#menu");
node.on("click", changeText);
//node.on("click", function(e){
// Y.one(node).load('menu.html');
//});
});
</script>
</body>
Thanks!
You're missing a > after </title. This may be causing the script tag not to be recognized and so it's not loading.
Here it is broken: http://jsbin.com/ubaxoy/1/edit
And here it works after adding the missing >: http://jsbin.com/ubaxoy/2/edit
I also had to change setHTML to setContent because YUI 3.2 didn't have setHTML yet. I'd also recommend you to use a newer version of YUI, from 3.9.1 up. There have been a number of great additions since 3.2.

Problems with including files for ASP in IIS 7.5

thanks for taking the time to read this question of mine, which I'm sure is a school boy error but for the life of me, cannot see it.
I have an ASP page which has the following contents:
<!-- #include file="include.asp" -->
<%
Dim ConfigFile
ConfigFile = Left(Request.ServerVariables("URL"), InStr(Request.ServerVariables("URL"),"/framework/lib/dms/asp/"))
ConfigFile = ConfigFile & "project/config/ConfigDms.inc.asp"
%>
<HTML>
<HEAD>
</HEAD>
<BODY>
<%=ConfigFile%>
</BODY>
</HTML>
Which works when accessed as a stand-alone page, or when called via an iFrame (don't ask). However, if I add the line "include ConfigFile" the page returns a 404 error in IIS. The value of ConfigFile is "/cms/project/config/ConfigDms.inc.asp", as printed out in the body of the page.
If I add the line "include https://xxx.xxx.xxx.xxx/cms/project/config/ConfigDms.inc.asp" to replace the original include statement, it works as intended.
Now I'm sure that this is a configuration error, but either though I put the ASP setting "enableParentPaths" to true and scrip "errorsenttobrowser" to true, I'm still not getting anywhere.
I have identical code on another server running an older version of IIS and it is working fine, however, I never setup the original server and have no documentation for setting up the new server.
The ASP script which causes the 404 error looks like:
<!-- #include file="include.asp" -->
<%
Dim ConfigFile
ConfigFile = Left(Request.ServerVariables("URL"), InStr(Request.ServerVariables("URL"),"/framework/lib/dms/asp/"))
ConfigFile = ConfigFile & "project/config/ConfigDms.inc.asp"
include ConfigFile
%>
<HTML>
<HEAD>
</HEAD>
<BODY>
<%=ConfigFile%>
</BODY>
</HTML>
But this file works fine:
<!-- #include file="include.asp" -->
<%
Dim ConfigFile
ConfigFile = Left(Request.ServerVariables("URL"), InStr(Request.ServerVariables("URL"),"/framework/lib/dms/asp/"))
ConfigFile = ConfigFile & "project/config/ConfigDms.inc.asp"
include "https://xxx.xxx.xxx.xxx/cms/project/config/ConfigDms.inc.asp"
%>
<HTML>
<HEAD>
</HEAD>
<BODY>
<%=ConfigFile%>
</BODY>
</HTML>
Regards
The reasoning for getting 404 errors when trying to access a particular page, was indeed correct. A colleague of mine changed the default error messages for bespoke ones, but failed to copy the actual HTML error pages onto the server.
This meant a 500 error was detected, tried to display the 500.html page but couldn't find it and hence displayed a 404 error.....
Sorry for anyone who has spent time reading this...

Resources