@@ -3,6 +3,16 @@ import { join, parse } from "path";
33import matter from "gray-matter";
44import toml from "@iarna/toml";
55import { DateTime } from "luxon";
6+import { getPostBySlug, getPostSlugs } from "@urbit/foundation-design-system";
7+
8+// NB Gavin: This could be much simpler if we converted everything to a more common standard, like YAML
9+const options = {
10+ engines: {
11+ toml: toml.parse.bind(toml),
12+ },
13+ language: "toml",
14+ delimiters: "+++",
15+};
616
717const directories = (dir) => {
818 switch (dir) {
@@ -25,49 +35,6 @@ const directories = (dir) => {
2535 }
2636};
2737
28−export function getPostSlugs(key) {
29− const dir = fs.existsSync(directories(key))
30− ? fs.readdirSync(directories(key), { withFileTypes: true })
31− : [];
32− return dir
33− .filter((f) => f.isFile() && f.name !== "_index.md")
34− .map((f) => f.name);
35−}
36−
37−// NB Gavin: This could be much simpler if we converted everything to a more common standard, like YAML
38−const options = {
39− engines: {
40− toml: toml.parse.bind(toml),
41− },
42− language: "toml",
43− delimiters: "+++",
44−};
45−
46−export function getPostBySlug(slug, fields = [], key) {
47− const realSlug = slug.replace(/\.md$/, "");
48− const fullPath = join(directories(key), `${realSlug}.md`);
49− const fileContents = fs.readFileSync(fullPath, "utf8");
50− const { data, content } = matter(fileContents, options);
51− const items = {};
52−
53− // Ensure only the minimal needed data is exposed
54− fields.forEach((field) => {
55− if (field === "slug") {
56− items[field] = realSlug;
57− }
58−
59− if (field === "content") {
60− items[field] = content;
61− }
62−
63− if (data[field]) {
64− items[field] = data[field];
65− }
66− });
67−
68− return items;
69−}
70−
7138export function getAllPosts(fields = [], key, sort = "") {
7239 const slugs = getPostSlugs(key);
7340 const posts = slugs
@@ -116,32 +83,6 @@ export function getDocsPaths() {
11683 return getAllPaths(directories("docs"), []);
11784}
11885
119−export function getNextPost(slug, fields = [], key, sort = "date") {
120− let resultPost = null;
121−
122− getAllPosts(fields, key, sort).forEach((post, index, array) => {
123− if (post.slug === slug) {
124− if (typeof array[index - 1] !== "undefined") {
125− resultPost = array[index - 1];
126− }
127− }
128− });
129− return resultPost;
130−}
131−
132−export function getPreviousPost(slug, fields = [], key, sort = "date") {
133− let resultPost = null;
134−
135− getAllPosts(fields, key, sort).forEach((post, index, array) => {
136− if (post.slug === slug) {
137− if (typeof array[index + 1] !== "undefined") {
138− resultPost = array[index + 1];
139− }
140− }
141− });
142− return resultPost;
143−}
144−
14586export function formatDateWithTime(d) {
14687 const date = DateTime.fromISO(d, {
14788 setZone: true,
@@ -149,73 +90,11 @@ export function formatDateWithTime(d) {
14990 return date;
15091}
15192
152−export function capitalize(str) {
153− return str.charAt(0).toUpperCase() + str.slice(1);
154−}
155−
156−// Takes an ISO 8601 date string
157−// Returns a time relative to the IANA timezone and iso8601 date
158−export function generateDisplayDate(iso8601, zone = "America/Los_Angeles") {
159− return DateTime.fromISO(iso8601, { zone });
160−}
161−
162−// Takes an ISO 8601 date string
163−// Returns a time relative to user's current timezone
164−export function generateRealtimeDate(iso8601) {
165− return DateTime.fromISO(iso8601).setZone("system");
166−}
167−
16893// Formats a DateTime object to something like "July 15, 2021, 5:00 PM"
16994export function formatDateAndTime(dateTimeObject) {
17095 return dateTimeObject.toLocaleString(DateTime.DATETIME_HUGE);
17196}
17297
173−// Formats a DateTime object to something like "5:00 PM"
174−export function formatTime(dateTimeObject) {
175− const dt = dateTimeObject.toLocaleString(DateTime.TIME_SIMPLE);
176− return dt.replace(/:00/g, "");
177−}
178−
179−export function formatTimeZone(dateTimeObject) {
180− return dateTimeObject.offsetNameShort;
181−}
182−
183−// Formats a DateTime object to something like "Jul 15, 2021"
184−export function formatDate(dateTimeObject) {
185− return dateTimeObject.toLocaleString(DateTime.DATE_FULL);
186−}
187−
188−// export function generateCrumbs(path) {
189−// const crumbs = path.split('/')
190−// return crumbs
191−// .filter(v => v !== '')
192−// .map((crumb, index) => ({
193−// name: capitalize(crumb),
194−// key: crumb,
195−// path: crumbs.slice(0, index+2).join('/'),
196−// }))
197−// }
198−
199−export const getPage = (path) => {
200− try {
201− let fileContents = fs.readFileSync(`${path}.md`, "utf8");
202− if (fileContents) {
203− const { data, content } = matter(fileContents, options);
204− return { data, content };
205− }
206− } catch {
207− try {
208− let fileContents = fs.readFileSync(`${path}/_index.md`, "utf8");
209− if (fileContents) {
210− const { data, content } = matter(fileContents, options);
211− return { data, content };
212− }
213− } catch {
214− console.error("no md file for slug");
215− }
216− }
217−};
218−
21998// Returns an array of unique grants categories
22099export function getGrantsCategories() {
221100 const paths = fs.readdirSync(directories("grants"));