@dimm-city/print-md 0.1.11
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 +246 -0
- package/dist/CGATS21_CRPC1-g0e3k7kr.icc +0 -0
- package/dist/cli.js +94560 -0
- package/dist/favicon-wkbm9cjn.ico +0 -0
- package/dist/manifest.schema-16z94mx1.json +325 -0
- package/dist/paged.polyfill-hwhs8hd5.js +33287 -0
- package/dist/pagedjs-bridge-39th325p.js +104 -0
- package/dist/pagedjs-interface-vzkzgeb9.js +94 -0
- package/package.json +66 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// Cross-origin postMessage bridge for window.previewAPI.
|
|
2
|
+
//
|
|
3
|
+
// The viewer (Svelte toolbar) and this iframe are on different origins
|
|
4
|
+
// (SvelteKit on port A, print-md preview on port B), so the toolbar can't
|
|
5
|
+
// reach window.previewAPI directly. This bridge listens for command
|
|
6
|
+
// messages, calls the local previewAPI, and posts results / events back to
|
|
7
|
+
// the parent window.
|
|
8
|
+
//
|
|
9
|
+
// Protocol:
|
|
10
|
+
// parent -> iframe: { type: 'pmd:cmd', id: <number>, cmd: <string>, args?: [...] }
|
|
11
|
+
// iframe -> parent: { type: 'pmd:reply', id: <number>, ok: true, result: <any> }
|
|
12
|
+
// or { type: 'pmd:reply', id: <number>, ok: false, error: <string> }
|
|
13
|
+
// iframe -> parent: { type: 'pmd:event', name: 'pageChanged'|'renderingComplete'|'ready', detail }
|
|
14
|
+
//
|
|
15
|
+
// Commands map 1:1 to previewAPI methods: getTotalPages, getCurrentPage,
|
|
16
|
+
// goToPage, firstPage, prevPage, nextPage, lastPage, setViewMode, setZoom,
|
|
17
|
+
// toggleDebugMode. Plus a synthetic 'print' command that calls window.print().
|
|
18
|
+
//
|
|
19
|
+
// Additional messages:
|
|
20
|
+
// parent -> iframe: { type: 'pmd:inject-styles', id: <attr-name>, css: <string> }
|
|
21
|
+
// Inserts or replaces a <style data-{id}="true"> block in the iframe's <head>.
|
|
22
|
+
// Used to push view-mode CSS and debug CSS into the cross-origin iframe.
|
|
23
|
+
|
|
24
|
+
(function () {
|
|
25
|
+
'use strict';
|
|
26
|
+
|
|
27
|
+
function post(msg) {
|
|
28
|
+
try {
|
|
29
|
+
window.parent.postMessage(msg, '*');
|
|
30
|
+
} catch (_e) {
|
|
31
|
+
// No parent or sandboxed; ignore.
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function call(cmd, args) {
|
|
36
|
+
if (cmd === 'print') {
|
|
37
|
+
window.print();
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
var api = window.previewAPI;
|
|
41
|
+
if (!api || typeof api[cmd] !== 'function') {
|
|
42
|
+
throw new Error('Unknown command: ' + cmd);
|
|
43
|
+
}
|
|
44
|
+
return api[cmd].apply(api, args || []);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
window.addEventListener('message', function (e) {
|
|
48
|
+
var data = e.data;
|
|
49
|
+
if (!data || data.type !== 'pmd:cmd') return;
|
|
50
|
+
var id = data.id;
|
|
51
|
+
try {
|
|
52
|
+
var result = call(data.cmd, data.args);
|
|
53
|
+
post({ type: 'pmd:reply', id: id, ok: true, result: result });
|
|
54
|
+
} catch (err) {
|
|
55
|
+
post({
|
|
56
|
+
type: 'pmd:reply',
|
|
57
|
+
id: id,
|
|
58
|
+
ok: false,
|
|
59
|
+
error: err && err.message ? err.message : String(err),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
window.addEventListener('pageChanged', function (e) {
|
|
65
|
+
post({ type: 'pmd:event', name: 'pageChanged', detail: e.detail });
|
|
66
|
+
});
|
|
67
|
+
window.addEventListener('renderingComplete', function (e) {
|
|
68
|
+
post({ type: 'pmd:event', name: 'renderingComplete', detail: e.detail });
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Announce readiness as soon as previewAPI is defined.
|
|
72
|
+
function announceReady() {
|
|
73
|
+
if (window.previewAPI) {
|
|
74
|
+
post({ type: 'pmd:event', name: 'ready', detail: {} });
|
|
75
|
+
} else {
|
|
76
|
+
setTimeout(announceReady, 50);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
announceReady();
|
|
80
|
+
|
|
81
|
+
// Set background color via inline style on <html> (toolbar's bg-color picker).
|
|
82
|
+
window.addEventListener('message', function (e) {
|
|
83
|
+
var data = e.data;
|
|
84
|
+
if (!data || data.type !== 'pmd:bg-color') return;
|
|
85
|
+
document.documentElement.style.background = data.color;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// Inject or replace a named <style> block in the iframe's <head>.
|
|
89
|
+
// { type: 'pmd:inject-styles', id: <string>, css: <string> }
|
|
90
|
+
// The <style> element gets data-pmd-<id>="true" so subsequent calls update
|
|
91
|
+
// the same block rather than appending duplicates.
|
|
92
|
+
window.addEventListener('message', function (e) {
|
|
93
|
+
var data = e.data;
|
|
94
|
+
if (!data || data.type !== 'pmd:inject-styles') return;
|
|
95
|
+
var attrName = 'data-pmd-' + data.id;
|
|
96
|
+
var existing = document.querySelector('style[' + attrName + ']');
|
|
97
|
+
if (!existing) {
|
|
98
|
+
existing = document.createElement('style');
|
|
99
|
+
existing.setAttribute(attrName, 'true');
|
|
100
|
+
document.head.appendChild(existing);
|
|
101
|
+
}
|
|
102
|
+
existing.textContent = data.css;
|
|
103
|
+
});
|
|
104
|
+
})();
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// Interface adapter: exposes window.previewAPI for the parent toolbar.
|
|
2
|
+
// Paged.js paginates into .pagedjs_page elements. We use PagedConfig.after
|
|
3
|
+
// to know when rendering is done.
|
|
4
|
+
|
|
5
|
+
(function () {
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
var pages = [];
|
|
9
|
+
var currentIndex = 0;
|
|
10
|
+
var debugMode = false;
|
|
11
|
+
|
|
12
|
+
function refreshPages() {
|
|
13
|
+
pages = Array.from(document.querySelectorAll('.pagedjs_page'));
|
|
14
|
+
return pages;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function detectCurrentPage() {
|
|
18
|
+
if (pages.length === 0) return 0;
|
|
19
|
+
var scrollTop = window.scrollY || document.documentElement.scrollTop;
|
|
20
|
+
var threshold = scrollTop + window.innerHeight / 3;
|
|
21
|
+
for (var i = pages.length - 1; i >= 0; i--) {
|
|
22
|
+
if (pages[i].offsetTop <= threshold) return i;
|
|
23
|
+
}
|
|
24
|
+
return 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var api = {
|
|
28
|
+
getTotalPages: function () { refreshPages(); return pages.length; },
|
|
29
|
+
getCurrentPage: function () { return currentIndex + 1; },
|
|
30
|
+
goToPage: function (n) {
|
|
31
|
+
refreshPages();
|
|
32
|
+
currentIndex = Math.max(0, Math.min(n - 1, pages.length - 1));
|
|
33
|
+
// Use 'instant' so the scroll completes synchronously before notifyPageChange
|
|
34
|
+
// fires. 'smooth' interacts with the scroll-listener debounce timer and causes
|
|
35
|
+
// the parent Svelte toolbar to receive a stale page number on fast navigation.
|
|
36
|
+
pages[currentIndex].scrollIntoView({ behavior: 'instant', block: 'start' });
|
|
37
|
+
api.notifyPageChange();
|
|
38
|
+
},
|
|
39
|
+
getPageDimensions: function () {
|
|
40
|
+
var page = document.querySelector('.pagedjs_page');
|
|
41
|
+
return page ? { width: page.offsetWidth, height: page.offsetHeight } : null;
|
|
42
|
+
},
|
|
43
|
+
firstPage: function () { api.goToPage(1); },
|
|
44
|
+
prevPage: function () { api.goToPage(currentIndex); },
|
|
45
|
+
nextPage: function () { api.goToPage(currentIndex + 2); },
|
|
46
|
+
lastPage: function () { api.goToPage(pages.length); },
|
|
47
|
+
setViewMode: function (mode) {
|
|
48
|
+
document.body.classList.remove('view-single', 'view-spread', 'view-two-column');
|
|
49
|
+
if (mode) document.body.classList.add('view-' + mode);
|
|
50
|
+
},
|
|
51
|
+
setZoom: function (z) {
|
|
52
|
+
document.documentElement.style.setProperty('--pmd-zoom', z);
|
|
53
|
+
},
|
|
54
|
+
toggleDebugMode: function () {
|
|
55
|
+
debugMode = !debugMode;
|
|
56
|
+
document.body.classList.toggle('debug', debugMode);
|
|
57
|
+
return debugMode;
|
|
58
|
+
},
|
|
59
|
+
notifyPageChange: function () {
|
|
60
|
+
window.dispatchEvent(new CustomEvent('pageChanged', {
|
|
61
|
+
detail: { currentPage: api.getCurrentPage(), totalPages: pages.length }
|
|
62
|
+
}));
|
|
63
|
+
},
|
|
64
|
+
notifyRenderingComplete: function () {
|
|
65
|
+
window.dispatchEvent(new CustomEvent('renderingComplete', {
|
|
66
|
+
detail: { totalPages: pages.length }
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
window.previewAPI = api;
|
|
72
|
+
|
|
73
|
+
// Scroll tracking
|
|
74
|
+
var scrollTimer = null;
|
|
75
|
+
window.addEventListener('scroll', function () {
|
|
76
|
+
if (pages.length === 0) return;
|
|
77
|
+
if (scrollTimer) clearTimeout(scrollTimer);
|
|
78
|
+
scrollTimer = setTimeout(function () {
|
|
79
|
+
var idx = detectCurrentPage();
|
|
80
|
+
if (idx !== currentIndex) {
|
|
81
|
+
currentIndex = idx;
|
|
82
|
+
api.notifyPageChange();
|
|
83
|
+
}
|
|
84
|
+
}, 150);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
// Paged.js calls this when rendering is complete
|
|
88
|
+
window.PagedConfig = window.PagedConfig || {};
|
|
89
|
+
window.PagedConfig.after = function (flow) {
|
|
90
|
+
refreshPages();
|
|
91
|
+
console.log('Paged.js rendered ' + pages.length + ' pages');
|
|
92
|
+
api.notifyRenderingComplete();
|
|
93
|
+
};
|
|
94
|
+
})();
|
package/package.json
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dimm-city/print-md",
|
|
3
|
+
"version": "0.1.11",
|
|
4
|
+
"description": "Markdown-to-PDF converter for professional print layout using Paged.js and Ghostscript.",
|
|
5
|
+
"author": "itlackey",
|
|
6
|
+
"license": "MPL-2.0",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"markdown",
|
|
9
|
+
"pdf",
|
|
10
|
+
"print",
|
|
11
|
+
"pagedjs",
|
|
12
|
+
"ghostscript",
|
|
13
|
+
"book",
|
|
14
|
+
"publishing",
|
|
15
|
+
"ttrpg"
|
|
16
|
+
],
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/dimm-city/print-md.git"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/dimm-city/print-md#readme",
|
|
22
|
+
"bugs": {
|
|
23
|
+
"url": "https://github.com/dimm-city/print-md/issues"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"bin": {
|
|
27
|
+
"print-md": "./dist/cli.js"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist/",
|
|
31
|
+
"README.md",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build:npm": "bun scripts/build-npm.ts",
|
|
36
|
+
"prepublishOnly": "bun run build:npm",
|
|
37
|
+
"compile": "bun scripts/compile.ts",
|
|
38
|
+
"test": "bun test",
|
|
39
|
+
"typecheck": "tsc --noEmit"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"bun": ">=1.0.0",
|
|
43
|
+
"node": ">=18.0.0"
|
|
44
|
+
},
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"chokidar": "^5.0.0",
|
|
47
|
+
"ws": "^8.18.2",
|
|
48
|
+
"glob": "^13.0.0",
|
|
49
|
+
"citty": "^0.2.0",
|
|
50
|
+
"markdown-it": "^14.1.0",
|
|
51
|
+
"markdown-it-attrs": "^4.3.0",
|
|
52
|
+
"markdown-it-footnote": "^4.0.0",
|
|
53
|
+
"markdown-it-source-map": "^0.1.1",
|
|
54
|
+
"pagedjs": "^0.4.3",
|
|
55
|
+
"puppeteer-core": "^25.0.4",
|
|
56
|
+
"yaml": "^2.8.2"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"@dimm-city/print-md-lib": "workspace:*",
|
|
60
|
+
"@types/bun": "latest",
|
|
61
|
+
"playwright": "^1.60.0"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"typescript": "^5"
|
|
65
|
+
}
|
|
66
|
+
}
|