project-logbook 0.3.2 → 0.3.3
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.
package/README.md
CHANGED
package/dist/commands/build.js
CHANGED
|
@@ -5,7 +5,7 @@ import { getConfig, getWorkspaces } from '../lib/config.js';
|
|
|
5
5
|
import { layout, timelineTemplate } from '../lib/templates.js';
|
|
6
6
|
import { getStyles } from '../lib/styles.js';
|
|
7
7
|
import { getClientScript } from '../lib/logbook-client.js';
|
|
8
|
-
import { mdToHtml, buildProjectMdFiles, renderPost } from '../lib/build-helpers.js';
|
|
8
|
+
import { mdToHtml, buildProjectMdFiles, renderPost, generateBuildMeta } from '../lib/build-helpers.js';
|
|
9
9
|
import { mdToHtmlWithImages, copyImages } from '../lib/image-helpers.js';
|
|
10
10
|
import { getGitCommits, getGitTags } from '../lib/git-helpers.js';
|
|
11
11
|
import { formatRelativeDate, getMonthYear, getSortTime } from '../utils/date.js';
|
|
@@ -176,7 +176,7 @@ export async function build() {
|
|
|
176
176
|
currentPage,
|
|
177
177
|
totalPages,
|
|
178
178
|
}); // prettier-ignore
|
|
179
|
-
const buildMeta =
|
|
179
|
+
const buildMeta = generateBuildMeta(version, buildTime);
|
|
180
180
|
const timelineHtml = layout({
|
|
181
181
|
title: 'Timeline',
|
|
182
182
|
projectName: config.projectName,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { LogbookConfig } from './config.js';
|
|
2
2
|
import type { TimelineEntry } from './template-types.js';
|
|
3
3
|
export declare function mdToHtml(md: string): Promise<string>;
|
|
4
|
+
/** Process entry markdown with image path rewriting */
|
|
5
|
+
export declare function mdToHtmlWithImagePathRewrite(md: string): Promise<string>;
|
|
4
6
|
export declare function buildProjectMdFiles(projectRoot: string, outputDir: string, excludeDirs: string[], ctx: {
|
|
5
7
|
config: LogbookConfig;
|
|
6
8
|
version: string;
|
|
@@ -13,3 +15,8 @@ export declare function renderPost(data: TimelineEntry, i: number, allEntries: T
|
|
|
13
15
|
version: string;
|
|
14
16
|
buildTime: string;
|
|
15
17
|
}): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Generate the standard footer metadata string.
|
|
20
|
+
* Always hardcoded to 'Project Logbook CLI' with link to npm.
|
|
21
|
+
*/
|
|
22
|
+
export declare function generateBuildMeta(version: string, buildTime: string): string;
|
|
@@ -10,7 +10,7 @@ import rehypeStringify from 'rehype-stringify';
|
|
|
10
10
|
import matter from 'gray-matter';
|
|
11
11
|
import { layout, postTemplate } from './templates.js';
|
|
12
12
|
import { getGitCommits } from './git-helpers.js';
|
|
13
|
-
import { mdToHtmlWithImages, extractImagePathsFromMarkdown, copyImages } from './image-helpers.js';
|
|
13
|
+
import { mdToHtmlWithImages, extractImagePathsFromMarkdown, copyImages, rehypeRewriteImagePaths, } from './image-helpers.js';
|
|
14
14
|
/** Rehype plugin: rewrite relative .md links to /index.html equivalents. */
|
|
15
15
|
const rehypeRewriteMdLinks = () => {
|
|
16
16
|
return (tree) => {
|
|
@@ -46,10 +46,25 @@ const processor = unified()
|
|
|
46
46
|
.use(rehypeRewriteMdLinks)
|
|
47
47
|
.use(rehypeFormat)
|
|
48
48
|
.use(rehypeStringify);
|
|
49
|
+
/** Processor for entry content with image path rewriting */
|
|
50
|
+
const entryProcessor = unified()
|
|
51
|
+
.use(remarkParse)
|
|
52
|
+
.use(remarkGfm)
|
|
53
|
+
.use(remarkRehype)
|
|
54
|
+
.use(rehypeSlug)
|
|
55
|
+
.use(rehypeRewriteMdLinks)
|
|
56
|
+
.use(rehypeRewriteImagePaths)
|
|
57
|
+
.use(rehypeFormat)
|
|
58
|
+
.use(rehypeStringify);
|
|
49
59
|
export async function mdToHtml(md) {
|
|
50
60
|
const result = await processor.process(md);
|
|
51
61
|
return result.toString();
|
|
52
62
|
}
|
|
63
|
+
/** Process entry markdown with image path rewriting */
|
|
64
|
+
export async function mdToHtmlWithImagePathRewrite(md) {
|
|
65
|
+
const result = await entryProcessor.process(md);
|
|
66
|
+
return result.toString();
|
|
67
|
+
}
|
|
53
68
|
export async function buildProjectMdFiles(projectRoot, outputDir, excludeDirs, ctx) {
|
|
54
69
|
const entries = await fs.readdir(projectRoot, { withFileTypes: true });
|
|
55
70
|
for (const entry of entries) {
|
|
@@ -62,7 +77,7 @@ export async function buildProjectMdFiles(projectRoot, outputDir, excludeDirs, c
|
|
|
62
77
|
const outDir = join(outputDir, stem);
|
|
63
78
|
const mdContent = await fs.readFile(sourcePath, 'utf8');
|
|
64
79
|
const bodyHtml = await mdToHtml(mdContent);
|
|
65
|
-
const buildMeta =
|
|
80
|
+
const buildMeta = generateBuildMeta(ctx.version, ctx.buildTime);
|
|
66
81
|
const pageHtml = layout({
|
|
67
82
|
title: stem,
|
|
68
83
|
projectName: ctx.config.projectName,
|
|
@@ -103,7 +118,7 @@ async function renderLinkedMdFiles(markdownSources, entryPath, entryOutputDir, c
|
|
|
103
118
|
const mdContent = await fs.readFile(sourcePath, 'utf8');
|
|
104
119
|
const bodyHtml = await mdToHtml(mdContent);
|
|
105
120
|
const title = href.replace(/\.md$/i, '');
|
|
106
|
-
const buildMeta =
|
|
121
|
+
const buildMeta = generateBuildMeta(ctx.version, ctx.buildTime);
|
|
107
122
|
const pageHtml = layout({
|
|
108
123
|
title,
|
|
109
124
|
projectName: ctx.config.projectName,
|
|
@@ -141,8 +156,8 @@ export async function renderPost(data, i, allEntries, ctx) {
|
|
|
141
156
|
title: data.title ?? data.slug,
|
|
142
157
|
harness: data.harness ?? '',
|
|
143
158
|
content: storyHtml,
|
|
144
|
-
ticketHtml: ticketRaw ? await
|
|
145
|
-
logHtml: logRaw ? await
|
|
159
|
+
ticketHtml: ticketRaw ? await mdToHtmlWithImagePathRewrite(ticketRaw) : '',
|
|
160
|
+
logHtml: logRaw ? await mdToHtmlWithImagePathRewrite(logRaw) : '',
|
|
146
161
|
commits,
|
|
147
162
|
version: ctx.version,
|
|
148
163
|
jiraUrl,
|
|
@@ -150,7 +165,7 @@ export async function renderPost(data, i, allEntries, ctx) {
|
|
|
150
165
|
nextEntry: next ? { slug: next.slug, title: next.title ?? '', ticket: next.ticket } : null,
|
|
151
166
|
});
|
|
152
167
|
const descriptionRaw = typeof data.summary === 'string' ? data.summary.replace(/[*#`]/g, '').trim() : '';
|
|
153
|
-
const buildMeta =
|
|
168
|
+
const buildMeta = generateBuildMeta(ctx.version, ctx.buildTime);
|
|
154
169
|
const postHtml = layout({
|
|
155
170
|
title: data.title ?? data.slug,
|
|
156
171
|
projectName: ctx.config.projectName,
|
|
@@ -171,3 +186,10 @@ export async function renderPost(data, i, allEntries, ctx) {
|
|
|
171
186
|
}
|
|
172
187
|
await renderLinkedMdFiles([summaryContent, ticketRaw, logRaw], entryPath, entryOutputDir, ctx);
|
|
173
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Generate the standard footer metadata string.
|
|
191
|
+
* Always hardcoded to 'Project Logbook CLI' with link to npm.
|
|
192
|
+
*/
|
|
193
|
+
export function generateBuildMeta(version, buildTime) {
|
|
194
|
+
return `Generated by <a href="https://www.npmjs.com/package/project-logbook" target="_blank" rel="noopener noreferrer">Project Logbook CLI</a> v${version} • ${buildTime}`;
|
|
195
|
+
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import type { Root } from 'hast';
|
|
2
|
+
import type { Plugin } from 'unified';
|
|
1
3
|
/**
|
|
2
4
|
* Extract image paths from markdown content
|
|
3
5
|
*/
|
|
4
6
|
export declare function extractImagePathsFromMarkdown(content: string): string[];
|
|
7
|
+
/** Rehype plugin: rewrite relative image paths to use /images/ subfolder */
|
|
8
|
+
export declare const rehypeRewriteImagePaths: Plugin<[], Root>;
|
|
5
9
|
/**
|
|
6
10
|
* Process markdown with image collection enabled
|
|
7
11
|
* Returns { html, imagePaths }
|
|
@@ -58,6 +58,29 @@ function visitImages(node, visitor) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
|
+
/** Rehype plugin: rewrite relative image paths to use /images/ subfolder */
|
|
62
|
+
export const rehypeRewriteImagePaths = () => {
|
|
63
|
+
return (tree) => {
|
|
64
|
+
visitImages(tree, (node) => {
|
|
65
|
+
const src = node.properties?.src;
|
|
66
|
+
if (typeof src !== 'string')
|
|
67
|
+
return;
|
|
68
|
+
// Skip external URLs and data URIs
|
|
69
|
+
if (/^[a-z][a-z\d+\-.]*:/i.test(src))
|
|
70
|
+
return;
|
|
71
|
+
if (src.startsWith('data:'))
|
|
72
|
+
return;
|
|
73
|
+
// Skip already rewritten paths
|
|
74
|
+
if (src.startsWith('./images/') || src.startsWith('../images/'))
|
|
75
|
+
return;
|
|
76
|
+
// Skip absolute paths
|
|
77
|
+
if (src.startsWith('/'))
|
|
78
|
+
return;
|
|
79
|
+
// Rewrite relative paths to use /images/ subfolder
|
|
80
|
+
node.properties.src = `./images/${src}`;
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
};
|
|
61
84
|
/**
|
|
62
85
|
* Process markdown with image collection enabled
|
|
63
86
|
* Returns { html, imagePaths }
|
|
@@ -69,6 +92,7 @@ export async function mdToHtmlWithImages(md) {
|
|
|
69
92
|
.use(remarkGfm)
|
|
70
93
|
.use(remarkRehype)
|
|
71
94
|
.use(imageProcessor.rehypeCollectImages)
|
|
95
|
+
.use(rehypeRewriteImagePaths)
|
|
72
96
|
.use(rehypeSlug)
|
|
73
97
|
.use(rehypeFormat)
|
|
74
98
|
.use(rehypeStringify);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "project-logbook",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "A command-line tool for project logbooks.",
|
|
5
5
|
"workspaces": [
|
|
6
6
|
"demo-app"
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"test": "vitest run",
|
|
29
29
|
"pre": "npm run format && npm run lint && npm run test && npm run build && npm run knip && npm run madge && npm run dev build && npm run dev lint",
|
|
30
30
|
"next": "node scripts/create-ticket-from-backlog.js",
|
|
31
|
-
"link": "npm run build && npm link"
|
|
31
|
+
"link": "npm run build && npm link",
|
|
32
|
+
"open": "npm run build && node scripts/open-and-view-dist.js"
|
|
32
33
|
},
|
|
33
34
|
"keywords": [
|
|
34
35
|
"logbook",
|