blazed-past-us 0.4.3 → 0.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
package/dist/cli/build.js CHANGED
@@ -4,7 +4,7 @@ import fs from 'node:fs';
4
4
  import fsPromises from 'node:fs/promises';
5
5
  import path from 'node:path';
6
6
  import { log } from '../engine/utils.js';
7
- import { generatePostMetadata, writeTransformedPostFile } from '../server/file-builder.js';
7
+ import { generatePostMetadata, writeTransformedPostFile, } from '../server/file-builder.js';
8
8
  /**
9
9
  * CLI entry point.
10
10
  * Resolves project paths and builds bundle.
@@ -1,13 +1,8 @@
1
- import type { PostMetaData, Config, PostDataType } from '../types';
2
- declare function getPostData(postsMetaData: PostMetaData[], slug: string, option: PostDataType): string | string[] | Date | undefined;
3
- declare function getAllPostsHTML(postsMetaData: PostMetaData[], baseURL: string): Promise<{
4
- slug: string;
5
- html: string | void;
6
- }[]>;
7
- declare function getPostsMetaData(baseURL: string, config: Config): Promise<PostMetaData[]>;
1
+ import type { PostMetadata, Config, PostDataType } from '../types';
2
+ declare function getPostData(postsMetadata: PostMetadata[], slug: string, option: PostDataType): string | string[] | Date | undefined;
8
3
  declare function getSlug(htmlFilename: string): string;
9
4
  declare function getTitle(htmlFilename: string): string;
10
5
  declare function getBrief(fileContent: string, lines: number): string;
11
6
  declare function getTags(fileContent: string): string[];
12
7
  declare function getColoredTagsHTML(tags: string, config: Config): string;
13
- export { getPostData, getAllPostsHTML, getPostsMetaData, getTitle, getTags, getBrief, getColoredTagsHTML, getSlug, };
8
+ export { getPostData, getTitle, getTags, getBrief, getColoredTagsHTML, getSlug };
@@ -1,32 +1,5 @@
1
- function getPostData(postsMetaData, slug, option) {
2
- return postsMetaData.find((post) => post.slug === slug)?.[option];
3
- }
4
- async function getAllPostsHTML(postsMetaData, baseURL) {
5
- const allPostsFilename = postsMetaData.map((el) => ({ slug: el.slug, filename: el.filename }));
6
- const allPostsHTML = [];
7
- for (const post of allPostsFilename) {
8
- const HTML = await fetch(`${baseURL}posts/${post.filename}`)
9
- .then((resp) => resp.text())
10
- .catch((error) => console.error(error));
11
- allPostsHTML.push({ slug: post.slug, html: HTML });
12
- }
13
- return allPostsHTML;
14
- }
15
- async function getPostsMetaData(baseURL, config) {
16
- const postsRelativeDataPath = config.posts_data_path;
17
- const postsPath = [baseURL, postsRelativeDataPath].join('');
18
- try {
19
- const resp = await fetch(postsPath);
20
- if (!resp.ok) {
21
- throw new Error(`HTTP error! Status: ${resp.status}`);
22
- }
23
- const data = await resp.json();
24
- return data;
25
- }
26
- catch (error) {
27
- console.error('Failed to fetch posts metadata:', error);
28
- throw error;
29
- }
1
+ function getPostData(postsMetadata, slug, option) {
2
+ return postsMetadata.find((post) => post.slug === slug)?.[option];
30
3
  }
31
4
  function getSlug(htmlFilename) {
32
5
  return htmlFilename.replace('.html', '');
@@ -69,4 +42,4 @@ function getColoredTagsHTML(tags, config) {
69
42
  })
70
43
  .join(`<span class="tag-separator">, </span>`);
71
44
  }
72
- export { getPostData, getAllPostsHTML, getPostsMetaData, getTitle, getTags, getBrief, getColoredTagsHTML, getSlug, };
45
+ export { getPostData, getTitle, getTags, getBrief, getColoredTagsHTML, getSlug };
@@ -1,3 +1,3 @@
1
- import { Views, PostMetaData } from '../types.js';
2
- declare function render(view: string, root: HTMLElement, views: Views, postsMetaData: PostMetaData[], postTagsFilter?: string, postSlug?: string): void;
1
+ import { Views, PostMetadata, PostHTML } from '../types.js';
2
+ declare function render(view: string, root: HTMLElement, views: Views, postsMetadata: PostMetadata[], postsHTML?: PostHTML[], postTagsFilter?: string, postSlug?: string): void;
3
3
  export { render };
@@ -1,14 +1,15 @@
1
1
  import { postExists, inject } from './utils.js';
2
- function render(view, root, views, postsMetaData, postTagsFilter, postSlug) {
2
+ function render(view, root, views, postsMetadata, postsHTML, postTagsFilter, postSlug) {
3
3
  const r = root;
4
4
  const { home, post, notFound } = views;
5
5
  switch (view) {
6
6
  case 'home':
7
- inject(r, home(postTagsFilter?.split(',')));
7
+ inject(r, home(postTagsFilter?.split(','), postsMetadata));
8
8
  break;
9
9
  case 'post':
10
- if (postSlug && postExists(postsMetaData, postSlug)) {
11
- post(postSlug).then((html) => inject(r, html));
10
+ if (postSlug && postExists(postsMetadata, postSlug)) {
11
+ const htmlContent = postsHTML?.find((p) => p.slug === postSlug)?.html;
12
+ post(postSlug, postsMetadata, htmlContent).then((html) => inject(r, html));
12
13
  }
13
14
  else {
14
15
  inject(r, notFound());
@@ -0,0 +1,5 @@
1
+ import { Config, PostMetadata, PostHTML } from '../types';
2
+ export declare function fetchResources(config: Config): Promise<void | {
3
+ postsMetadata: PostMetadata[];
4
+ postsHTML: PostHTML[];
5
+ }>;
@@ -0,0 +1,43 @@
1
+ export async function fetchResources(config) {
2
+ try {
3
+ const postsMetadata = await fetchPostsMetaData(config);
4
+ const postsHTML = await fetchAllPostsHTML(config.base_url, postsMetadata);
5
+ return { postsMetadata, postsHTML };
6
+ }
7
+ catch (error) {
8
+ console.log(`Failed to fetch resources.`);
9
+ console.error(error);
10
+ }
11
+ }
12
+ async function fetchAllPostsHTML(baseURL, postsMetadata) {
13
+ const allPostsFilename = postsMetadata.map((el) => ({
14
+ slug: el.slug,
15
+ filename: el.filename,
16
+ }));
17
+ const allPostsHTML = new Array();
18
+ for (const post of allPostsFilename) {
19
+ const HTML = await fetch(`${baseURL}posts/${post.filename}`)
20
+ .then((resp) => resp.text())
21
+ .catch((error) => console.error(error));
22
+ allPostsHTML.push({ slug: post.slug, html: HTML });
23
+ }
24
+ return allPostsHTML;
25
+ }
26
+ async function fetchPostsMetaData(config) {
27
+ // If config.base_url does not end with "/" append it.
28
+ const baseUrl = config.base_url.endsWith('/') ? config.base_url : config.base_url + '/';
29
+ const postsRelativeDataPath = 'posts/data.json';
30
+ const postsPath = [baseUrl, postsRelativeDataPath].join('');
31
+ try {
32
+ const resp = await fetch(postsPath);
33
+ if (!resp.ok) {
34
+ throw new Error(`HTTP error! Status: ${resp.status}`);
35
+ }
36
+ const data = await resp.json();
37
+ return data;
38
+ }
39
+ catch (error) {
40
+ console.error('Failed to fetch posts metadata:', error);
41
+ throw error;
42
+ }
43
+ }
@@ -1,10 +1,15 @@
1
- import { MsgColor, PostMetaData } from '../types';
2
- declare function postExists(postsMetaData: any[], slug: string): boolean;
1
+ import { Config, MsgColor, PostMetadata } from '../types';
2
+ declare function postExists(postsMetadata: any[], slug: string): boolean;
3
3
  declare function getPathnameFromLocationHash(locationHash: string): string;
4
4
  declare function beautifyDate(d: Date | undefined): undefined | string;
5
5
  declare function inject(root: HTMLElement, html: string): void;
6
6
  declare function log(msg: string, color: MsgColor): void;
7
- declare function boltRotator(document: HTMLDocument, elementID: string): void;
8
- declare function setTitle(document: HTMLDocument, elementID: string, packageName: string): void;
9
- declare function filterByUrlQueryIfPresent(postsMetaData: PostMetaData[], tags: string[]): PostMetaData[];
10
- export { postExists, beautifyDate, inject, log, boltRotator, setTitle, getPathnameFromLocationHash, filterByUrlQueryIfPresent, };
7
+ declare function activateBoltRotator(): void;
8
+ declare function setTitleAndSubtitle(packageName: string, config: Config): void;
9
+ declare function filterByUrlQueryIfPresent(postsMetadata: PostMetadata[], tags: string[]): PostMetadata[];
10
+ declare function getLocationHashSpecifics(window: Window): {
11
+ pathname: string;
12
+ queryString: string;
13
+ urlParams: URLSearchParams;
14
+ };
15
+ export { postExists, beautifyDate, inject, log, activateBoltRotator, setTitleAndSubtitle, getPathnameFromLocationHash, filterByUrlQueryIfPresent, getLocationHashSpecifics, };
@@ -1,7 +1,7 @@
1
1
  import chalk from 'chalk';
2
2
  import pkg from '../../package.json' with { type: 'json' };
3
- function postExists(postsMetaData, slug) {
4
- return postsMetaData.some((post) => post.slug === slug);
3
+ function postExists(postsMetadata, slug) {
4
+ return postsMetadata.some((post) => post.slug === slug);
5
5
  }
6
6
  function getPathnameFromLocationHash(locationHash) {
7
7
  return locationHash.split('/').splice(1).join('/');
@@ -36,19 +36,33 @@ function log(msg, color) {
36
36
  }
37
37
  console.log(`${chalk.blue(pkg.name + ' v' + pkg.version)} ${coloredMsg}`);
38
38
  }
39
- function boltRotator(document, elementID) {
40
- const el = document.getElementById(elementID);
41
- if (el) {
42
- el.classList.add('rotate');
43
- }
39
+ function activateBoltRotator() {
40
+ const logoElement = document.querySelector('.logo');
41
+ window.onhashchange = () => {
42
+ if (logoElement) {
43
+ logoElement.classList.add('rotate');
44
+ setTimeout(() => logoElement.classList.remove('rotate'), 400);
45
+ }
46
+ };
44
47
  }
45
- function setTitle(document, elementID, packageName) {
46
- const el = document.getElementById(elementID);
47
- if (el) {
48
- el.innerText = packageName.replaceAll('-', ' ');
48
+ function setTitleAndSubtitle(packageName, config) {
49
+ const titleElement = document.querySelector('.title');
50
+ const subtitleElement = document.querySelector('.subtitle');
51
+ if (titleElement) {
52
+ titleElement.innerHTML = packageName.replaceAll('-', ' ');
53
+ }
54
+ if (subtitleElement) {
55
+ subtitleElement.innerHTML = config.subtitle;
49
56
  }
50
57
  }
51
- function filterByUrlQueryIfPresent(postsMetaData, tags) {
52
- return postsMetaData.filter((post) => tags ? tags.some((tag) => post.tags.includes(tag)) : true);
58
+ function filterByUrlQueryIfPresent(postsMetadata, tags) {
59
+ return postsMetadata.filter((post) => tags ? tags.some((tag) => post.tags.includes(tag)) : true);
60
+ }
61
+ function getLocationHashSpecifics(window) {
62
+ const hashRoute = window.location.hash;
63
+ const pathname = getPathnameFromLocationHash(hashRoute);
64
+ const queryString = hashRoute.split('?')[1] || '';
65
+ const urlParams = new URLSearchParams(queryString);
66
+ return { pathname, queryString, urlParams };
53
67
  }
54
- export { postExists, beautifyDate, inject, log, boltRotator, setTitle, getPathnameFromLocationHash, filterByUrlQueryIfPresent, };
68
+ export { postExists, beautifyDate, inject, log, activateBoltRotator, setTitleAndSubtitle, getPathnameFromLocationHash, filterByUrlQueryIfPresent, getLocationHashSpecifics, };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './engine/getters';
2
2
  export * from './engine/utils';
3
3
  export * from './engine/render';
4
+ export * from './engine/requests';
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './engine/getters';
2
2
  export * from './engine/utils';
3
3
  export * from './engine/render';
4
+ export * from './engine/requests';
@@ -1,4 +1,4 @@
1
- import { PostMetaData } from '../types';
1
+ import { PostMetadata } from '../types';
2
2
  declare function writeTransformedPostFile(outputPath: string, postHtmlContent: string, filename: string): Promise<void>;
3
- declare function generatePostMetadata(data: Array<PostMetaData>, filePath: string, htmlFilename: string, postTags: string[]): Promise<void>;
3
+ declare function generatePostMetadata(data: Array<PostMetadata>, filePath: string, htmlFilename: string, postTags: string[]): Promise<void>;
4
4
  export { generatePostMetadata, writeTransformedPostFile };
@@ -20,7 +20,7 @@ async function parseMarkdown(_path) {
20
20
  .use(remarkParse)
21
21
  .use(remarkRehype)
22
22
  .use(rehypePrettyCode, {
23
- theme: JSON.parse(readFileSync(path.join(root, 'src/moonlight-li.json'), 'utf-8')),
23
+ theme: JSON.parse(readFileSync(path.join(root, 'src/code-block-theme.json'), 'utf-8')),
24
24
  keepBackground: false,
25
25
  })
26
26
  .use(rehypeStringify)
@@ -8,15 +8,16 @@
8
8
  </head>
9
9
  <body>
10
10
  <header>
11
- <div class="logo" id="logo">
12
- <div class="wrapper" id="logo-wrapper">
11
+ <div class="logo">
12
+ <div class="bolt-wrapper" id="bolt">
13
13
  <div class="top"></div>
14
14
  <div class="bottom"></div>
15
15
  </div>
16
16
  </div>
17
17
  <div>
18
18
  <div class="top">
19
- <a id="title" class="title" href="#/"></a>
19
+ <a class="title" href="#/"></a>
20
+ <div class="subtitle"></div>
20
21
  </div>
21
22
  </div>
22
23
  </header>
@@ -1,11 +1,6 @@
1
1
  {
2
2
  "base_url": "/blog/",
3
- "posts_data_path": "posts/data.json",
4
- "title_id": "title",
5
- "root_id": "root",
6
- "header_id": "header",
7
- "speed_element_id": "speed",
8
- "logo_id": "logo",
3
+ "subtitle": "notes from a dev...",
9
4
  "tags": {
10
5
  "javascript": { "color": "#f5dd42" },
11
6
  "typescript": { "color": "#42adf5" },
@@ -3,10 +3,10 @@ import * as blazed from 'blazed-past-us';
3
3
  import initRouter from './router';
4
4
  import pkg from '../package.json';
5
5
 
6
- const root = document.getElementById(config.root_id);
7
- const postsMetaData = await blazed.getPostsMetaData(import.meta.env.BASE_URL, config);
6
+ const root = document.getElementById('root');
7
+ const { postsMetadata, postsHTML } = await blazed.fetchResources(config);
8
8
 
9
- initRouter(root, postsMetaData);
9
+ initRouter(root, postsMetadata, postsHTML);
10
10
 
11
11
  /**
12
12
  * ----------------------------
@@ -15,9 +15,5 @@ initRouter(root, postsMetaData);
15
15
  * These are demo features included in the starter template.
16
16
  * You can safely remove any of them.
17
17
  */
18
- blazed.setTitle(document, config.title_id, pkg.name);
19
- blazed.boltRotator(document, config.logo_id);
20
-
21
- const postsHTML = await blazed.getAllPostsHTML(postsMetaData, import.meta.env.BASE_URL);
22
-
23
- export { root, postsMetaData, postsHTML };
18
+ blazed.setTitleAndSubtitle(pkg.name, config);
19
+ blazed.activateBoltRotator();
@@ -1,37 +1,29 @@
1
- import { render, postExists, getPathnameFromLocationHash } from 'blazed-past-us';
1
+ import { render, postExists, getLocationHashSpecifics } from 'blazed-past-us';
2
2
  import home from './views/home';
3
3
  import post from './views/post';
4
4
  import notFound from './views/notFound';
5
5
 
6
- export default function initRouter(root, postsMetaData) {
7
- // Render current route immediately.
8
- handleRoute(root, postsMetaData);
9
-
10
- window.addEventListener('hashchange', () => handleRoute(root, postsMetaData));
6
+ export default function initRouter(root, postsMetadata, postsHTML) {
7
+ routeRenderer(root, postsMetadata, postsHTML);
8
+ window.addEventListener('hashchange', () =>
9
+ routeRenderer(root, postsMetadata, postsHTML)
10
+ );
11
11
  }
12
12
 
13
- /**
14
- * GitHub Pages is a static file server. It does not understand client-side routing.
15
- * Everything after # stays client-side.
16
- *
17
- * This is the reason why we use hash routing.
18
- */
19
- async function handleRoute(root, postsMetaData) {
20
- const hashRoute = window.location.hash;
21
- const pathname = getPathnameFromLocationHash(hashRoute);
22
- const queryString = hashRoute.split('?')[1] || '';
23
- const urlParams = new URLSearchParams(queryString);
13
+ function routeRenderer(root, postsMetadata, postsHTML) {
14
+ const { pathname, queryString, urlParams } = getLocationHashSpecifics(window);
24
15
  const views = { home, post, notFound };
25
16
 
26
- if (pathname === '' || pathname === 'home' || queryString) {
27
- render('home', root, views, postsMetaData, urlParams.get('tags'));
28
- return;
29
- }
17
+ switch (true) {
18
+ case pathname === '' || pathname === 'home' || queryString:
19
+ render('home', root, views, postsMetadata, postsHTML, urlParams.get('tags'));
20
+ break;
30
21
 
31
- if (postExists(postsMetaData, pathname)) {
32
- render('post', root, views, postsMetaData, undefined, pathname);
33
- return;
34
- }
22
+ case postExists(postsMetadata, pathname):
23
+ render('post', root, views, postsMetadata, postsHTML, undefined, pathname);
24
+ break;
35
25
 
36
- render('404', root, views, postsMetaData);
26
+ default:
27
+ render('404', root, views, postsMetadata);
28
+ }
37
29
  }
@@ -1,26 +1,35 @@
1
1
  header {
2
2
  display: flex;
3
- justify-content: left;
4
- margin: 4.5rem 0 3.5rem 0;
5
- padding: 0 0 0 1rem;
3
+ flex-direction: row;
6
4
  align-items: center;
5
+ margin: 4.5rem 0 3.5rem 1rem;
7
6
  }
8
7
 
9
8
  header .top {
10
- justify-content: left;
11
9
  display: flex;
10
+ flex-direction: column;
12
11
  }
13
12
 
14
13
  header .top .title {
15
14
  font-family: 'Bangers Regular';
16
15
  font-size: 3.1rem;
17
16
  color: var(--light-blue-09);
17
+ letter-spacing: 0.15rem;
18
+ }
19
+
20
+ header .top .subtitle {
21
+ font-size: 0.85rem;
22
+ padding-left: 0.3rem;
23
+ font-family: 'Inter Extra Bold';
24
+ color: var(--light-yellow);
18
25
  text-transform: uppercase;
19
26
  letter-spacing: 0.15rem;
20
- display: inline-block;
27
+ opacity: 1;
28
+ animation: flicker 4s infinite;
21
29
  }
22
30
 
23
31
  header .logo {
32
+ border: 1px solid white;
24
33
  height: 6.25rem;
25
34
  border: 0.25rem solid var(--light-blue-09);
26
35
  border-radius: 50%;
@@ -35,18 +44,18 @@ header .logo {
35
44
  transform-origin: center center;
36
45
  }
37
46
 
38
- .logo #logo-wrapper {
47
+ .logo #bolt {
39
48
  animation: flicker 5s infinite;
40
49
  }
41
50
 
42
- .logo .wrapper {
51
+ .logo .bolt-wrapper {
43
52
  min-width: 3.75rem;
44
53
  min-height: 3.75rem;
45
54
  filter: drop-shadow(0 0 0.2rem #00edfa6e) drop-shadow(0 0 0.345rem #00edfa6b)
46
55
  drop-shadow(0 0 0.4275rem #00edfa69) drop-shadow(0 0 0.55rem #00edfa70);
47
56
  }
48
57
 
49
- .logo .wrapper .top {
58
+ .logo .bolt-wrapper .top {
50
59
  position: absolute;
51
60
  transform-origin: center;
52
61
  top: 19%;
@@ -57,7 +66,7 @@ header .logo {
57
66
  border-bottom: 1.384375rem solid #ffff90;
58
67
  }
59
68
 
60
- .logo .wrapper .bottom {
69
+ .logo .bolt-wrapper .bottom {
61
70
  position: absolute;
62
71
  transform-origin: center;
63
72
  top: 46%;
@@ -1,9 +1,8 @@
1
- import { postsMetaData } from '../main';
2
1
  import { beautifyDate, filterByUrlQueryIfPresent } from 'blazed-past-us';
3
2
 
4
- export default function home(tags) {
3
+ export default function home(tags, postsMetadata) {
5
4
  const baseURL = import.meta.env.BASE_URL;
6
- const postsToShow = filterByUrlQueryIfPresent(postsMetaData, tags);
5
+ const postsToShow = filterByUrlQueryIfPresent(postsMetadata, tags);
7
6
 
8
7
  return postsToShow
9
8
  .map(
@@ -1,15 +1,14 @@
1
- import { beautifyDate, getPostData, getPostHtml } from 'blazed-past-us';
2
- import { postsMetaData, postsHTML } from '../main';
1
+ import { beautifyDate, getPostData } from 'blazed-past-us';
3
2
 
4
- export default async function post(slug) {
5
- const title = getPostData(postsMetaData, slug, 'title');
6
- const date = beautifyDate(getPostData(postsMetaData, slug, 'created'));
3
+ export default async function post(slug, postsMetadata, htmlContent) {
4
+ const title = getPostData(postsMetadata, slug, 'title');
5
+ const date = beautifyDate(getPostData(postsMetadata, slug, 'created'));
7
6
 
8
7
  return `
9
8
  <div class="post">
10
9
  <div class="title capitalize-first">${title}</div>
11
10
  <div class="date">${date}</div>
12
- ${postsHTML.find((post) => post.slug === slug).html}
11
+ ${htmlContent}
13
12
  </div>
14
13
  `;
15
14
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "blazed-past-us",
3
- "version": "0.4.3",
3
+ "version": "0.5.5",
4
4
  "description": "A static blog framework made for developers that allows content to be written in Markdown directly from the IDE.",
5
5
  "license": "MIT",
6
6
  "author": "gass-git",