Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 15 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ function getDependencyVersion(dependencyName) {
}
const mf2version = getDependencyVersion("microformats-parser");

function htmlToMf2(url, html, res) {
function readExperimental(params) {
const experimental = {};
for (const flag of ["lang", "textContent", "metaformats"]) {
if (params[flag] === "true") experimental[flag] = true;
}
return Object.keys(experimental).length > 0 ? { experimental } : {};
}

function htmlToMf2(url, html, experimental, res) {
try {
const body = mf2(html, { baseUrl: url });
const body = mf2(html, { baseUrl: url, ...experimental });
res
.header("content-type", "application/json; charset=UTF-8")
.send(JSON.stringify(body, null, 2));
Expand All @@ -35,23 +43,25 @@ app.use(express.static("public"));
app.get("/", async (req, res) => {
if (req.query.url) {
const url = req.query.url;
const experimental = readExperimental(req.query);
await fetch(url, {
headers: {
accept: "text/html, text/mf2+html",
},
method: "GET",
}).then(async (response) => {
const html = await response.text();
htmlToMf2(url, html, res);
htmlToMf2(url, html, experimental, res);
});
} else {
res.render("index.html.ejs", {
version: `${pkg.version} (lib: ${mf2version})`,
site_version: pkg.version,
mf2_version: mf2version,
});
}
});
app.post("/", express.urlencoded({ extended: false }), (req, res) => {
htmlToMf2(req.body.url, req.body.html, res);
htmlToMf2(req.body.url, req.body.html, {}, res);
});

app.listen(port, () => {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
"microformats-parser": "^2.0.6"
},
"devDependencies": {
"prettier": "^3.9.5"
"prettier": "^3.9.6"
}
}
283 changes: 180 additions & 103 deletions views/index.html.ejs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
Expand All @@ -10,132 +10,209 @@
<title>Node Microformats Parser</title>

<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css"
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css"
integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ"
integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB"
crossorigin="anonymous"
/>
<style>
form label {
font-weight: bold;
display: block;
}

form textarea,
form input[type="url"] {
font-family: "SF Mono", Menlo, Monaco, Consolas, "Liberation Mono",
"Courier New", monospace;
}

form .form-control:disabled {
cursor: default;
background: #efefef;
color: black;
}

.help {
color: #999;
font-weight: normal;
}

#json {
font-size: 0.7em;
}

/* disable bootstrap animations */
.form-control,
.btn {
transition: none;
}
</style>
<link rel="icon" href="favicon.ico" type="image/x-icon" />
<link
rel="icon"
href="https://microformats.io/assets/images/microformats-logo.svg"
type="image/svg+xml"
/>
</head>

<body>
<main id="mf2" class="container">
<h1 class="mt-5 mb-3">Microformats Parser (Node) <%- version -%></h1>

<form action="/" accept-charset="UTF-8" method="get">
<div class="form-group">
<label for="url">Enter a URL</label>
<input
id="url"
class="form-control form-control-lg"
type="url"
name="url"
placeholder="https://example.com/person.html"
/>
</div>

<button type="submit" class="btn btn-lg btn-success">Parse</button>
</form>

<h2 class="h4 my-5">OR parse just a snippet of HTML</h2>

<form method="post" action="/" class="mb-5">
<div class="form-group">
<label for="html">HTML</label>
<textarea
id="html"
name="html"
rows="6"
class="form-control form-control-lg"
></textarea>
</div>

<div class="form-group">
<label for="url">Base URL</label>
<input
id="url"
name="url"
type="url"
class="form-control form-control-lg"
required
/>
</div>

<button type="submit" class="btn btn-lg btn-success">Parse</button>
</form>

<hr />

<p>
Drag this link to your bookmarks toolbar to parse a page with one
click!<br />
</p>
<a
class="btn btn-primary btn-sm"
href="javascript:(function(){document.location.href='https://node.microformats.io/?url='+encodeURIComponent(document.location.href);}())"
>mf2 parser</a
>

<hr />
<div class="container">
<h1 class="mt-5 mb-3">Microformats Parser (Node)</h1>

<main>
<section class="mb-5">
<h2 class="h4">Parse a URL</h2>

<form action="/" accept-charset="UTF-8" method="get">
<div class="mb-3">
<label for="url" class="form-label fw-bold">Enter a URL</label>
<input
required
id="url"
class="form-control form-control-lg font-monospace"
type="url"
name="url"
placeholder="https://example.com/person.html"
/>
</div>

<fieldset class="mb-3">
<legend
class="text-body-secondary text-uppercase small fw-semibold mb-2"
>
Experimental options
</legend>
<div class="form-check mb-1">
<input
id="url-lang"
name="lang"
class="form-check-input"
type="checkbox"
value="true"
aria-describedby="url-lang-help"
/>
<label class="form-check-label fw-bold" for="url-lang"
>Language parsing</label
>
<div id="url-lang-help" class="form-text">
Include the <code>lang</code> attribute on microformats and
<code>e-*</code> properties.
</div>
</div>
<div class="form-check mb-1">
<input
id="url-textContent"
name="textContent"
class="form-check-input"
type="checkbox"
value="true"
aria-describedby="url-textContent-help"
/>
<label class="form-check-label fw-bold" for="url-textContent"
>Better text content</label
>
<div id="url-textContent-help" class="form-text">
Collapse consecutive whitespace and treat
<code>&lt;br&gt;</code>/<code>&lt;p&gt;</code> as line breaks.
</div>
</div>
<div class="form-check">
<input
id="url-metaformats"
name="metaformats"
class="form-check-input"
type="checkbox"
value="true"
aria-describedby="url-metaformats-help"
/>
<label class="form-check-label fw-bold" for="url-metaformats"
>Metaformats parsing</label
>
<div id="url-metaformats-help" class="form-text">
Fall back to <code>&lt;meta&gt;</code> tags to infer content,
following the separate
<a href="https://microformats.org/wiki/metaformats"
>metaformats</a
>
spec.
</div>
</div>
</fieldset>

<button type="submit" class="btn btn-lg btn-success">Parse</button>
</form>
</section>

<section class="mb-5">
<h2 class="h4 mb-5">OR parse just a snippet of HTML</h2>

<form method="post" action="/">
<div class="mb-3">
<label for="html" class="form-label fw-bold">HTML</label>
<textarea
required
id="html"
name="html"
rows="6"
class="form-control form-control-lg font-monospace"
></textarea>
</div>

<div class="mb-3">
<label for="base-url" class="form-label fw-bold">Base URL</label>
<input
required
id="base-url"
name="url"
type="url"
class="form-control form-control-lg font-monospace"
/>
</div>

<button type="submit" class="btn btn-lg btn-success">Parse</button>
</form>
</section>

<section class="card mb-5">
<div class="card-body">
<h2 class="h4 card-title">Bookmarklet</h2>
<p class="card-text">
Drag this link to your bookmarks toolbar to parse a page with one
click!
</p>
<a
class="btn btn-primary btn-sm"
href="javascript:(function(){document.location.href='https://node.microformats.io/?url='+encodeURIComponent(document.location.href);}())"
onclick="event.preventDefault()"
>mf2 parser</a
>
</div>
</section>
</main>

<footer class="my-5">
<ul>
<li><a href="https://microformats.io">About Microformats</a></li>
<li>
<ul class="d-xl-flex flex-xl-wrap">
<li class="col-xl-6 order-xl-1">
<a href="https://microformats.io">About Microformats</a>
</li>
<li class="col-xl-6 order-xl-2">
<a
href="https://github.com/microformats/microformats-parser-website-node"
>Source code for this site</a
>
<span class="badge text-bg-light">v<%- site_version -%></span>
</li>
<li>
<li class="col-xl-6 order-xl-4">
<a href="https://github.com/microformats/microformats-parser"
>Source code for the Microformats JavaScript Parser</a
>
<span class="badge text-bg-light">v<%- mf2_version -%></span>
</li>

<li>
<li id="parser-list" class="col-xl-6 order-xl-3">
Other Microformats Parser websites:
<a href="https://go.microformats.io">Go</a>,
<a href="https://php.microformats.io">PHP</a>,
<a href="https://python.microformats.io">Python</a>,
<a href="https://ruby.microformats.io">Ruby</a>, and
<a href="https://rust.microformats.io">Rust</a>.
</li>
<li class="col-xl-6 order-xl-5">
<a href="https://microformats.org/wiki/microformats2#Parsers"
>More Microformats parsers</a
>
</li>
</ul>
<p class="text-center mt-5 pt-5">
<a
href="https://creativecommons.org/publicdomain/zero/1.0"
rel="license"
class="link-secondary link-underline-opacity-25"
>CC0</a
>
</p>
</footer>
</main>

<script type="module">
const nodeList = document
.getElementById("parser-list")
.querySelectorAll("a");
const values = Array.from(nodeList, (node) => [
Math.random(),
node.href,
node.innerText,
]).toSorted(([v1], [v2]) => v2 - v1);
nodeList.forEach((node, ix) => {
node.href = values[ix][1];
node.innerText = values[ix][2];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interesting, so it looks like the parsers are sorted randomly now. I'm curious; what's the value of that?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“just for my own fun”, was what I wrote on the Python PR 😄

The more serious answer would be how I do not want the list to convey some preference for one parser over the other. Any stable sort, like alphabetic, would have five out of six parser pages out the same link first (alphabetically: Go).

Of course that is still just a personal preference thing where I wanted to mix it up! I found this way of doing it as a small progressive enhancement a nice little tweak. And it means it can be implemented by all the different languages’ front-ends as it does not rely on server-side randomisation.

});
</script>
</div>
</body>
</html>
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -359,10 +359,10 @@ path-to-regexp@^8.0.0:
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.4.2.tgz#795c420c4f7ca45c5b887366f622ee0c9852cccd"
integrity sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==

prettier@^3.9.5:
version "3.9.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.9.5.tgz#4fec97736e33b9d0b620b48914fe93b530e835ad"
integrity sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==
prettier@^3.9.6:
version "3.9.6"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.9.6.tgz#b3ea5146515d40fc53f18aa63f74dfab1e10dbf6"
integrity sha512-OpN0zzVdiaiAhxpuuj5efpIS4sY9j7bY6uR5mnj5yPzGkdkjNKSJeUThPb60Jw29QuAZgA4o+/iB49kFiaBX6g==

proxy-addr@^2.0.7:
version "2.0.7"
Expand Down