Compare commits

...

36 Commits

Author SHA1 Message Date
Nick Stokoe
38af618fc1 * - remove 11ty stuff
This branch is about ghost
2026-01-26 11:50:47 +00:00
Nick Stokoe
df0fbfd1e2 zip/ - add files which consitute the Ghost import zip
Names somewhat tided and duplicates culled, relative to the old 11ty files
2026-01-26 11:46:33 +00:00
Nick Stokoe
bd0c9bb174 whenwe-tidied.json 2026-01-25 22:56:18 +00:00
Nick Stokoe
b52a691246 to-ghost.js - scrappy script for importing whenwe-tidied.json
whenwe-tidied.json is the drupal export, with some alterations to
de-duplicate images and fix a few other things.
2026-01-25 22:55:28 +00:00
Nick Stokoe
f45a90978a WIP 2026-01-24 19:05:32 +00:00
Nick Stokoe
72a49ac52e unpack-whenwe-json.js -> bin/unpack-whenwe-json.js
Just to be tidy.
2023-05-09 21:23:58 +01:00
Nick Stokoe
5e8be866b4 src/README.md - brief intro for this folder 2023-05-09 21:22:40 +01:00
Nick Stokoe
03b73cbae5 README.md - first draft 2023-05-09 21:22:40 +01:00
Nick Stokoe
daf10449e3 src/_config.yml - delete, unused now we use Eleventy 2023-05-09 21:09:52 +01:00
Nick Stokoe
a37b8e68d3 package.json - add build and deploy scripts
bin/deploy wraps the rsync command.
2023-05-09 15:42:59 +01:00
Nick Stokoe
0f5d81e59f theme fixes - and use url filter to allow non root folder deploying 2023-05-09 15:42:26 +01:00
Nick Stokoe
5ebd808a20 src/_images/.htaccess - spurious leftover from Drupal, remove 2023-05-09 15:41:57 +01:00
Nick Stokoe
c391cd96f0 very minimal theme 2023-05-09 14:33:01 +01:00
Nick Stokoe
65813f28f5 .eleventy.js - pass through with rename of assets and images
rc/index.html - update path following passthrough rename
2023-05-09 14:32:54 +01:00
Nick Stokoe
6b97640b61 src/_images/ - remove dupes 2023-05-09 14:32:54 +01:00
Nick Stokoe
f2606bbfc6 _articles/4d1cc620-43cf-4945-b44c-e4c56f668c1f.md - correct image path 2023-05-09 14:32:54 +01:00
Nick Stokoe
800f9b7c8e src/_images/ - remove trailing space from names 2023-05-09 14:32:54 +01:00
Nick Stokoe
3900c58641 src/_people/ - reimport people 2023-05-09 12:25:35 +01:00
Nick Stokoe
07c8038c6f src/_pages/ - reimport pages 2023-05-09 12:25:12 +01:00
Nick Stokoe
c2cb27d0f0 unpack-whenwe-json.js - tweak to serialise lists of things as JSON
Which should work in YAML
2023-05-09 12:24:36 +01:00
Nick Stokoe
af5c5ffde8 src/_articles/ - reimport
using unpack-whenwe-json.js, tweaked
2023-05-09 12:24:06 +01:00
Nick Stokoe
0f48194d81 unpack-whenwe-json.js - indent, untabify 2023-05-09 12:07:18 +01:00
Nick Stokoe
fbfed95657 index.md - delete, unused 2023-05-09 12:02:14 +01:00
Nick Stokoe
fc1d35edd7 wip - 2023-01-05 14:47:16 +00:00
Nick Stokoe
2bdd8579ab .editorconfig 2023-01-05 14:45:48 +00:00
Nick Stokoe
19efd62543 package.json - add server runscript 2023-01-05 14:45:26 +00:00
Nick Stokoe
56c4c1feb3 .gitignore - /_site/ 2022-12-28 13:47:34 +00:00
Nick Stokoe
8a7187c803 fixup 2022-12-28 13:47:11 +00:00
Nick Stokoe
843416ff27 index.md - very basic index page! 2022-12-28 13:46:53 +00:00
Nick Stokoe
9120b153fd package.json - npm install --save-dev @11ty/eleventy 2022-12-28 13:46:32 +00:00
Nick Stokoe
677b9c795b whenwe.json - temp commit! 2022-12-28 12:35:29 +00:00
Nick Stokoe
152d2d8993 unpack-whenwe-json.js - convert html to markdown 2022-12-28 12:35:16 +00:00
Nick Stokoe
063c6742b2 .gitignore /node_modules/ 2022-12-27 18:16:06 +00:00
Nick Stokoe
a154e21f8b .gitignore /out/ 2022-12-27 18:11:13 +00:00
Nick Stokoe
013ca966ef unpack-whenwe-json.js - unpacks a drupal node-export of whenwe's nodes 2022-12-27 18:11:08 +00:00
Nick Stokoe
b6a9eddffa package.json - initial version 2022-12-27 18:08:00 +00:00
378 changed files with 16404 additions and 0 deletions

22
.editorconfig Normal file
View File

@@ -0,0 +1,22 @@
# Cross-platform formatting config
# See https://EditorConfig.org
# top-most EditorConfig file
root = true
# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
[{*.{js,json,css,scss,html,jsx},.babelrc}]
# Set default charset
charset = utf-8
# 4 space indentation
indent_style = space
indent_size = 2
[*.{yml,yaml}]
indent_style = space
indent_size = 2

3
.gitignore vendored
View File

@@ -0,0 +1,3 @@
/out/
/node_modules/
/_site/

53
README.md Normal file
View File

@@ -0,0 +1,53 @@
# WhenWe
Whenwe is dead. Long love Whenwe?
A "when-we" is a nostagic reminisce. This is an archive of when-wes, currently.
However, it may grow into a database of mini-biographies. Time will tell...
## Structure
- `src/` - the website content and templates
- `bin/` - helper scripts
Everything in the top directory are configs and documentation, like this.
## Requirements
The site is built using [Eleventy][eleventy]. We assume you have Git, NodeJS and NPM installed.
## Installation for development or deployment
git clone $whenwe_repo_url
cd whenwe
npm install
## Development
npm run server
Now you should be able to visit the development site in your browser at http://localhost:8080
If you edit the content in `src/` - it should rebuild the site. Your browser should refresh automatically, but if not, refresh it manually.
See the [README.md](./src/) in `src/` for more information.
## Deployment
Currently the destination is configured in package.json, as part of the definition of the `deploy` run-script. To change the destination, change that.
`rsync` is used for deploying the site. Therefore you need to have that installed and on the path.
You will need `ssh` access to the destination. Setting that up is outside the scope of this document, but if you have your own web space, you will probably know about this already, and if not, you will need the assistance of someone who does. Setting up your ssh client depends on your OS - there are guides online.
But given that, the deploy process goes like this:
npm run build
npm run deploy
## Issues and questions
These can be submitted via the issue tracker attached to this repository. You may need to create an account.
[eleventy]: https://www.11ty.dev/

20
package.json Normal file
View File

@@ -0,0 +1,20 @@
{
"name": "conversion",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "rm -rf _site && eleventy --pathprefix '~nick/whenwe/'",
"deploy": "bin/deploy nick@mixian.noodlefactory.co.uk:public_html/whenwe/",
"server": "eleventy --serve",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"node-html-markdown": "^1.3.0"
},
"devDependencies": {
"@11ty/eleventy": "^1.0.2"
}
}

328
to-ghost.js Normal file
View File

@@ -0,0 +1,328 @@
const data = require("./whenwe-tidied.json");
const fs = require("fs");
//const sh = require("sanitize-html");
const {
NodeHtmlMarkdown,
NodeHtmlMarkdownOptions,
} = require("node-html-markdown");
const nhm = new NodeHtmlMarkdown({
useLinkReferenceDefinitions: true,
useInlineLinks: true,
});
function date(datestr) {
if (datestr) {
const [Y, M, D, h, m, s] = datestr.split(/[^0-9]/);
return new Date(Date.UTC.call(null, Y, M - 1, D, h, m, s)).toISOString();
} else return "";
}
const tag_index = {
// 1: { id: 1, name: "", slug: "" },
};
const user_index = {
"6975f732f0a00f00018346d1": {
id: "6975f732f0a00f00018346d1",
name: "Janet Woolley",
slug: "janet",
},
};
const meta_index = {};
const author_index = {};
const ghost_data = {
meta: {
exported_on: new Date().valueOf(),
version: "5.0.0", // Ghost version the import is valid for
},
data: {
posts: [],
// Optionally define post metadata
posts_meta: [
/*
{
post_id: "1234", // This must be the same as the post it references
feature_image_alt: "A group of people waving at the camera",
feature_image_caption: "The team says hello!",
},
*/
],
// Define the tags
tags: [],
// Relate posts to tags
posts_tags: [],
// Define the users
/*
users: [
{
id: "5678", // Unique ID for this author
name: "Jo Bloggs",
slug: "jo-blogs",
email: "jo@example.com",
profile_image: "/content/images/2025/scenic-background.jpg",
roles: [
"Contributor", // Contributor | Author| Editor | Administrator
],
},
],
*/
// Relate posts to authors
},
};
function convertCase(
str, //: string,
format, // 'camel' | 'pascal' | 'snake' | 'kebab'
) {
const sanitiseString = (str) =>
str
.trim()
.replace(/[^a-zA-Z0-9\s]/g, "")
.replace(/\s+/g, " ");
const formatted = sanitiseString(str);
switch (format) {
case "camel":
return formatted
.toLowerCase()
.replace(/ (\\w)/g, (_, char) => char.toUpperCase());
case "pascal":
return formatted.replace(/(?:^| )(\w)/g, (_, char) => char.toUpperCase());
case "snake":
return formatted.toLowerCase().replace(/\s+/g, "_");
case "kebab":
return formatted.toLowerCase().replace(/\s+/g, "-");
default:
throw new Error("Unsupported format type");
}
}
function mk_tag(name, id, slug) {
id ??= convertCase(name, "kebab");
slug ??= id;
tag_index[id] ??= { id, name, slug };
return id;
}
function mk_author(post_id, author_id) {
author_index[post_id] = { post_id, author_id };
}
function mk_meta(post_id, feature_image_caption, feature_image_alt) {
if (feature_image_alt || feature_image_caption)
meta_index[post_id] = {
feature_image_alt,
feature_image_caption,
post_id,
};
}
function img_path(filename) {
if (!filename) throw new Error("No filename");
return "content/images/" + filename.trim();
}
function img(filename, height, width, title, alt) {
if (!filename) return undefined;
if (typeof filename !== "string")
throw new Error("not a string: " + filename);
return {
row: 0,
src: img_path(filename),
width: width ?? 100,
height: height ?? 100,
filename: filename,
};
}
function sanitize(body) {
return nhm
.translate(body)
.replaceAll(/https?:\/[^"]*?\/public\//g, "content/images/2026/01/")
.replaceAll(/[?]itok=[A-Za-z0-9_-]*/g, "");
}
function sanitize_html(body) {
return body
.replaceAll(/https?:\/[^"]*?\/public\//g, "content/images/2026/01/")
.replaceAll(/[?]itok=[^ ]*/g, "");
}
for (const node of data) {
let body = sanitize_html(node.body.und[0].safe_value);
const id = Number(node.nid);
const lexical = {
root: {
children: [],
direction: "ltr",
format: "",
indent: 0,
type: "root",
version: 1,
},
};
let author = node.field_original_author?.und?.[0]?.value;
let feature_image = node.field_featured_image?.und?.[0]?.filename;
let tags = [];
mk_meta(
id,
node.field_featured_image?.und?.[0]?.title,
node.field_featured_image?.und?.[0]?.alt,
);
mk_author(id, "6975f732f0a00f00018346d1");
const category_id = node.field_category?.und?.[0]?.tid;
if (category_id) {
tags.push(
mk_tag(
"category-" + category_id,
"Category " + category_id,
"category-" + category_id,
),
);
}
/*
lexical.root.children.push({
children: [
{
type: "markdown",
version: 1,
markdown: sanitize(body),
},
],
direction: "ltr",
format: "",
indent: 0,
type: "paragraph",
version: 1,
});
*/
switch (node.type) {
case "article":
{
tags.push(mk_tag("Story", "story", "story"));
let images = node.field_basic_image_image?.und;
if (images) {
// console.error(">>", images);
/*
images = images.map((image) =>
img(image.filename, img.height, image.width, img.title, img.alt),
);
*/
images = images.map(
(image) =>
`
<div class="kg-gallery-image">
<img src="${img_path(image.filename)}" width="${image.width}" height="${image.height}" loading="lazy" alt="${image.alt}" title="${image.title}">
</div>
`,
);
body += `
<hr>
<figure class="kg-card kg-gallery-card kg-width-wide">
<div class="kg-gallery-container">
<div class="kg-gallery-row">
${images.join("")}
</div>
</div>
<figcaption></figcaption>
</figure>
`;
/*
lexical.root.children.push({
type: "gallery",
version: 1,
images,
caption: "",
});
*/
}
}
break;
case "person":
{
const surname_at_birth = node.field_surname_at_birth?.und?.[0]?.value;
const other_surnames = node.field_other_surnames?.und?.[0]?.value;
tags.push(mk_tag("Person", "person", "person"));
if (surname_at_birth) {
tags.push(
mk_tag(
surname_at_birth,
"surname-" + convertCase(surname_at_birth, "kebab"),
),
);
}
if (other_surnames) {
tags.push(
mk_tag(
other_surnames,
"surname-" + convertCase(other_surnames, "kebab"),
),
);
}
/*
forename_at_birth: node.field_forename_at_birth?.und?.[0]?.value,
other_forenames: node.field_other_forenames?.und?.[0]?.value,
title: node.field_title?.und?.[0]?.value,
date_of_birth: date(node.field_date_of_birth?.und?.[0]?.value),
date_of_death: date(node.field_date_of_death?.und?.[0]?.value),
parent_of: node.field_parent_of?.und?.[0]?.value,
child_of: node.field_child_of?.und?.[0]?.value,
partner_of: node.field_partner_of?.und?.[0]?.value,
// lifetime: node.field_lifetime?.und?.[0]?.value,
*/
}
break;
}
for (const tag_id of tags) {
ghost_data.data.posts_tags.push({
post_id: id,
tag_id,
});
}
ghost_data.data.posts.push({
id,
type: "post",
title: node.title,
slug: node.path.alias.replace(/^.*[/]/, ""),
html: body,
feature_image: img(feature_image)?.src,
created_at: new Date(Number(node.created) * 1000).toISOString(),
updated_at: new Date(Number(node.changed) * 1000).toISOString(),
status: "draft",
});
// const author = node.field_original_author?.und?.[0]?.value;
/*
{
id: "1234", // The post ID, which is refered to in other places in this file
title: "My Blog Post Title",
slug: "my-blog-post-title",
html: "<p>Hello world, this is an article</p>", // You could use `lexical` instead to to represent your content
comment_id: "1234-old-cms-post-id", // The ID from the old CMS, which can be output in the theme
feature_image: "/content/images/2024/waving.jpg",
type: "post", // post | page
status: "published", // published | draft
visibility: "public", // public | members | paid
created_at: "2025-06-30 15:31:36",
updated_at: "2025-07-02 08:22:14",
published_at: "2025-06-30 15:35:36",
custom_excerpt: "My custom excerpt",
},*/
}
ghost_data.data.tags = Object.values(tag_index);
ghost_data.data.posts_authors = Object.values(author_index);
ghost_data.data.posts_meta = Object.values(meta_index);
console.log(JSON.stringify(ghost_data, null, 2));

14818
whenwe-tidied.json Normal file

File diff suppressed because one or more lines are too long

1
whenwe.json Normal file

File diff suppressed because one or more lines are too long

1159
zip/content.json Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 931 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 813 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 802 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 693 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 945 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 581 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 662 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 627 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 625 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 943 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 732 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 743 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 614 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 985 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 846 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 792 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 878 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 705 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 999 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 707 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 855 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1018 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 994 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 938 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 831 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 563 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 651 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 821 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 562 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 801 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 758 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 745 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 497 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 776 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 612 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 618 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1001 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 KiB

Some files were not shown because too many files have changed in this diff Show More