200 lines
5.0 KiB
JavaScript
Raw Normal View History

import { load } from "cheerio";
import { readFile, writeFileSync, mkdirSync, cpSync, rmSync } from "fs";
2023-10-11 21:37:28 -04:00
import process from "child_process";
2024-07-08 19:13:48 -04:00
import stores from "./stores.json" with { type: "json" };
function mkDir(path) {
try {
return mkdirSync(path)
} catch (err) {
if (err.code !== 'EEXIST') throw err
}
}
function writeFile(path, content) {
try {
writeFileSync(path, content);
} catch (err) {
if (err) throw err;
}
console.log(`${path} updated.`);
}
function slugify(str) {
return str
.toLowerCase()
.replace(/é/g, "e")
.replace(/&/g, " and ")
.replace(/ /g, "-")
.replace(/[']+/g, "")
.replace(/[^\w-]+/g, "-")
.replace(/-+/g, "-")
.replace(/^-|-$/g, "");
}
function cleanWebsite(str) {
return str
.toLowerCase()
.replace(/^https?:\/\//g, "")
.replace(/^www./g, "")
.replace(/\/$/g, "");
}
2024-12-21 14:52:57 -05:00
function metaDescription({ name, meta, description }) {
if (meta.length > 155) {
console.log(`warning: meta tag for ${name} is too long: ${meta.length}`)
}
return meta || description.length > 155 ? description.slice(0, 153) + "..." : description || "A guide to and map of every independent bookstore in New York City. We have a complete list of community bookstores in NYC with locations and descriptions."
}
2023-10-11 21:37:28 -04:00
function GetRecentChanges() {
const res = process
.execSync('git log -15 --pretty=format:"%ct %s"')
2023-10-11 21:37:28 -04:00
.toString();
return res.split("\n");
}
function ChangeLog(logs) {
let res = "\n";
let i = 0;
logs.forEach((l) => {
if (
i > 3 ||
l.includes("[skip]") ||
l.includes("[ignore]") ||
l.includes("caddy") ||
l.includes("renovate")
) {
return;
}
i++;
2023-10-11 21:37:28 -04:00
const s = l.split(" ");
const date = new Date(s[0] * 1000).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
});
res = res + `<li>${date} - ${s.slice(1).join(" ")}</li>\n`;
});
return res;
}
2023-03-07 17:56:58 -05:00
function TableViewTemplate(rows) {
let table = "<table>";
2023-03-07 17:56:58 -05:00
rows.forEach((row, key) => {
row.rowNumber = key;
table = table + TableRowTemplate(row);
});
return table + "</table>";
}
function TableRowTemplate({ rowNumber, name, slug, address, city }) {
2023-03-07 17:56:58 -05:00
return `
<tr id="${rowNumber}" class="spotRow">
<td class="name"><a href="/${slugify(name)}/">${name}</a></td>
<td><a href="/${slugify(name)}/">${address}, ${city}</a></td>
2023-03-07 17:56:58 -05:00
</tr>`;
}
function TitleTemplate({ name }) {
return `${name} | Independent Bookstores in New York City - Best Community Bookstores in NYC`;
}
function SelectedStoreTemplate({
name,
address,
city,
postcode,
website,
events,
cafe,
description,
}) {
return `
<h2>${name}</h2>
<p class="address">${address}</p>
<p></p>
<p class="address">
${city}, NY ${postcode}
</p>
<p>
View in:
<a
href="https://maps.google.com/maps?q=${encodeURIComponent(
name
)}+${address},${city},NY"
target="_blank"
>Google Maps</a
>
<a
href="http://maps.apple.com/?q=${encodeURIComponent(
name
)}&address=${address},${city},NY"
target="_blank"
>Apple Maps</a
>
</p>
<ul>
${
website
? `<li><a href="${website}" target="_blank">${cleanWebsite(
website
)}</a></li>`
: ""
}
<li class="storeDetails">Events: ${events}</li>
<li class="storeDetails">Caf&eacute;: ${cafe}</li>
</ul>
${description ? `<p class="description">${description}</p>` : ""}`;
}
readFile("./index.tmpl.html", function (err, data) {
2023-10-11 21:37:28 -04:00
const changeList = GetRecentChanges();
if (err) {
throw err;
}
const $ = load(data);
stores.sort(function (a, b) {
var aname = a.name.toLowerCase();
var bname = b.name.toLowerCase();
return aname === bname ? 0 : +(aname > bname) || -1;
});
2023-03-07 17:56:58 -05:00
$("#Stores").html(TableViewTemplate(stores));
$("#storeCount").html(stores.length);
2022-03-19 16:28:26 -04:00
$("#updatedOn").html(
new Date().toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})
);
2023-10-11 21:37:28 -04:00
$("#changesList").html(ChangeLog(changeList));
const cssurl = $("link[type='text/css']").attr("href").split("?")[0];
2022-03-20 10:43:25 -04:00
$("link[type='text/css']").attr("href", cssurl + "?" + new Date().getTime());
rmSync("./build", { recursive: true, force: true });
mkDir("./build")
writeFile("./build/index.html", $.html())
cpSync("./site.css", "./build/site.css");
cpSync("./robots.txt", "./build/robots.txt");
cpSync("./img", "./build/img", {recursive: true});
cpSync("./stores.json", "./build/stores.json");
stores.forEach((store) => {
$("#selected").html(SelectedStoreTemplate(store));
$("#info").addClass("hidden");
let title = TitleTemplate(store);
$("title").html(title);
$("meta[name='title']").attr("content", title);
$("meta[name='description']").attr("content", metaDescription(store));
mkDir(`./build/${slugify(store.name)}`);
writeFile(`./build/${slugify(store.name)}/index.html`, $.html());
});
});