seemore 1.9.0 → 1.10.0
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 +2 -2
- package/dist/cli/index.js +51 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/package.json +1 -1
- package/src/app/export/copyMarkdown.ts +58 -0
- package/src/app/export/exportPage.ts +18 -35
- package/src/app/export/standalone.ts +3 -1
- package/src/app/export/themeToggle.ts +37 -0
- package/src/app/layout/PageActions.tsx +48 -11
- package/src/app/styles/globals.css +11 -5
- package/src/shared/types.ts +3 -1
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ Typical use cases include:
|
|
|
81
81
|
- **Full MDX** — when Markdown isn't enough, `.mdx` pages take real JSX: your own React components, inline SVG, custom classes and CSS; `<Callout>`, `<Card>`, `<CodeBlockTabs>` and friends come built in, with no imports to write
|
|
82
82
|
- **Static export** — `seemore build` prerenders every page to its own HTML file, `404.html` included, and adds the conventions individual hosts look for (`_redirects`, `200.html`, `.nojekyll`)
|
|
83
83
|
- **Search built in** — static, zero-setup full-text search out of the box, with shareable highlighted results; [Algolia](https://algolia.com) and [Orama Cloud](https://orama.com) for hosted indexes
|
|
84
|
-
- **Page actions** — an Actions button on every page:
|
|
84
|
+
- **Page actions** — an Actions button on every page: copy the page as Markdown, or export it as one self-contained HTML file, with the CLI equivalent in `seemore export <file>`
|
|
85
85
|
- **12 themes** — dark and light follow the system, with a toggle that remembers your choice; your own CSS always wins
|
|
86
86
|
- **Rich Markdown** — GitHub Flavoured Markdown, admonitions, steps, `[[wikilinks]]`, [Mermaid](https://mermaid.js.org) and [D2](https://d2lang.com) diagrams, click-to-zoom images, embedded PDFs
|
|
87
87
|
- **Editor integration** — one extension covers VS Code, Cursor, Antigravity and other VS Code-compatible editors, remote workspaces included
|
|
@@ -175,7 +175,7 @@ export default {
|
|
|
175
175
|
footer: { text: '© 2026' },
|
|
176
176
|
editLink: { base: 'https://github.com/you/repo/edit/main/docs' },
|
|
177
177
|
search: 'static', // or { provider: 'orama-cloud', endpoint, apiKey } / { provider: 'algolia', appId, apiKey, indexName }
|
|
178
|
-
pageActions: ['
|
|
178
|
+
pageActions: ['copy-markdown', 'export-html'],
|
|
179
179
|
exclude: ['drafts/**'],
|
|
180
180
|
};
|
|
181
181
|
```
|
package/dist/cli/index.js
CHANGED
|
@@ -130,7 +130,7 @@ var FEATURES = [
|
|
|
130
130
|
"search.highlight",
|
|
131
131
|
"social.cards"
|
|
132
132
|
];
|
|
133
|
-
var ACTION_IDS = ["
|
|
133
|
+
var ACTION_IDS = ["copy-markdown", "export-html"];
|
|
134
134
|
|
|
135
135
|
// src/node/config/features.ts
|
|
136
136
|
var FEATURE_DEFAULTS = {
|
|
@@ -247,7 +247,7 @@ var searchSchema = z.union([
|
|
|
247
247
|
indexName: z.string()
|
|
248
248
|
})
|
|
249
249
|
]);
|
|
250
|
-
var pageActionsSchema = z.array(z.enum(ACTION_IDS)).default(["
|
|
250
|
+
var pageActionsSchema = z.array(z.enum(ACTION_IDS)).default(["copy-markdown", "export-html"]);
|
|
251
251
|
var configSchema = z.object({
|
|
252
252
|
/**
|
|
253
253
|
* Optional here, but required whenever a config file exists — load.ts enforces that,
|
|
@@ -836,6 +836,7 @@ import mdx from "@mdx-js/rollup";
|
|
|
836
836
|
|
|
837
837
|
// src/node/vite/mdx.ts
|
|
838
838
|
import remarkFrontmatter from "remark-frontmatter";
|
|
839
|
+
import { remarkLLMs } from "fumadocs-core/mdx-plugins/remark-llms";
|
|
839
840
|
import {
|
|
840
841
|
rehypeCode,
|
|
841
842
|
rehypeToc,
|
|
@@ -997,6 +998,23 @@ function remarkSeemoreLinks(options) {
|
|
|
997
998
|
visit(tree, "definition", rewrite);
|
|
998
999
|
};
|
|
999
1000
|
}
|
|
1001
|
+
function remarkSeemoreMarkdownSource() {
|
|
1002
|
+
return (tree, file) => {
|
|
1003
|
+
const source = String(file.value);
|
|
1004
|
+
visit(tree, "yaml", (node) => {
|
|
1005
|
+
node.data = { ...node.data, _stringify: { text: "" } };
|
|
1006
|
+
});
|
|
1007
|
+
visit(tree, "blockquote", (node) => {
|
|
1008
|
+
const first = node.children[0];
|
|
1009
|
+
if (first === void 0 || first.type !== "paragraph") return;
|
|
1010
|
+
if (!ALERT_MARKER.test(textOf(first))) return;
|
|
1011
|
+
const start = node.position?.start.offset;
|
|
1012
|
+
const end = node.position?.end.offset;
|
|
1013
|
+
if (start === void 0 || end === void 0) return;
|
|
1014
|
+
node.data = { ...node.data, _stringify: { text: source.slice(start, end) } };
|
|
1015
|
+
});
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1000
1018
|
function virtualPath(contentRoot, file) {
|
|
1001
1019
|
if (typeof file.path !== "string" || file.path === "") return "";
|
|
1002
1020
|
return toPosix(relative(contentRoot, file.path));
|
|
@@ -1019,11 +1037,20 @@ function rehypeSeemorePositions() {
|
|
|
1019
1037
|
}
|
|
1020
1038
|
|
|
1021
1039
|
// src/node/vite/mdx.ts
|
|
1040
|
+
var MARKDOWN_EXPORT = "_markdown";
|
|
1022
1041
|
function createRemarkPlugins(options) {
|
|
1023
1042
|
return [
|
|
1024
1043
|
// Strips the `---` block so it never renders. Its data already came from the scan.
|
|
1025
1044
|
[remarkFrontmatter, ["yaml"]],
|
|
1026
1045
|
remarkGfm,
|
|
1046
|
+
// Early, and deliberately: this snapshots the page as Markdown for the copy action, and
|
|
1047
|
+
// the further down the chain it sits the less the copy resembles what the author wrote.
|
|
1048
|
+
// Here, a GitHub alert is still `> [!NOTE]` and a diagram is still a ```mermaid fence,
|
|
1049
|
+
// rather than the `<Callout>`/`<Mermaid>` JSX the plugins below turn them into. The
|
|
1050
|
+
// frontmatter strip is the one thing that must come first — its keys are metadata, not
|
|
1051
|
+
// content. Heading ids stay off: `## Title [#title]` is noise in a paste.
|
|
1052
|
+
remarkSeemoreMarkdownSource,
|
|
1053
|
+
[remarkLLMs, { as: MARKDOWN_EXPORT, headingIds: false }],
|
|
1027
1054
|
remarkHeading,
|
|
1028
1055
|
remarkAdmonition,
|
|
1029
1056
|
remarkDirectiveAdmonition,
|
|
@@ -1856,6 +1883,27 @@ var THEME_TOGGLE = `<button type="button" class="seemore-export-theme-toggle" ar
|
|
|
1856
1883
|
<svg class="seemore-icon-light" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
|
|
1857
1884
|
<svg class="seemore-icon-dark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
|
|
1858
1885
|
</button>`;
|
|
1886
|
+
var THEME_INIT = `<script>(function () {
|
|
1887
|
+
var KEY = 'seemore-export-theme';
|
|
1888
|
+
var root = document.documentElement;
|
|
1889
|
+
var saved = null;
|
|
1890
|
+
try { saved = localStorage.getItem(KEY); } catch (e) {}
|
|
1891
|
+
var query = window.matchMedia('(prefers-color-scheme: dark)');
|
|
1892
|
+
var apply = function (dark) { root.classList.toggle('dark', dark); };
|
|
1893
|
+
|
|
1894
|
+
apply(saved === 'dark' || saved === 'light' ? saved === 'dark' : query.matches);
|
|
1895
|
+
query.addEventListener('change', function (event) {
|
|
1896
|
+
var override = null;
|
|
1897
|
+
try { override = localStorage.getItem(KEY); } catch (e) {}
|
|
1898
|
+
if (override !== 'dark' && override !== 'light') apply(event.matches);
|
|
1899
|
+
});
|
|
1900
|
+
|
|
1901
|
+
// The toggle lives in the body, so its click handler is bound by each export's runtime;
|
|
1902
|
+
// this only records the choice, which is what pins the file against the OS from then on.
|
|
1903
|
+
window.__seemoreRememberTheme = function () {
|
|
1904
|
+
try { localStorage.setItem(KEY, root.classList.contains('dark') ? 'dark' : 'light'); } catch (e) {}
|
|
1905
|
+
};
|
|
1906
|
+
})();</script>`;
|
|
1859
1907
|
|
|
1860
1908
|
// src/cli/export.ts
|
|
1861
1909
|
async function runExport(options) {
|
|
@@ -1954,6 +2002,7 @@ function assemble(input) {
|
|
|
1954
2002
|
`<title>${escapeHtml(title)}</title>`,
|
|
1955
2003
|
description === void 0 ? "" : `<meta name="description" content="${escapeHtml(description)}">`,
|
|
1956
2004
|
'<meta name="generator" content="seemore">',
|
|
2005
|
+
THEME_INIT,
|
|
1957
2006
|
favicon,
|
|
1958
2007
|
`<style>
|
|
1959
2008
|
${inlineCssUrls(css, config.base, outDir, contentRoot).replaceAll("</style", "<\\/style")}</style>`,
|