* [Major] Introduce a new `Ref` and `Path` type
This introduces a new `Ref` and `Path` type, which try to be as lightweight and rigorous as possible. More description in the PR
* [Minor] Updated Syntax
* [Minor] Updated Type
* [Minor] Renamed file
* [Minor] Updated type
* [Minor] Updated Syntax
* [Major] Rename css classes for wiki links
Previously all the parts of a wiki link were tagged with `sb-wiki-link-page`. This didn't make a whole lot of sense. Also the tag `sb-wiki-link` was could never render, because of the way `HighlightStyle` works. Now every part of a wiki link will be tagged with `sb-wiki-link` (i.e. the link, the alias, the dimensions). Invalid and missing links will be styled separately in a later commit.
* [Minor] Adjust to new API
* [Minor] Small changes
* [Minor] Function and file renames
* [Major] Syscall adjusments
Change behavior of `getCurrentPath` to actually return what's now considered a `Path`. `getCurrentPage(Meta)` now also correctly returns for documents. We could consider a rename to get rid of the `page` association
* [Major] Rework `Client`
Mostly minor adjustments for the new API. Some major changes in `navigateWithinPage` and some unecessary checks removed now
* [Major] Errors on navigate
This now throws an error when the user tries to navigate to a link that is invalid
* [Major] Minor adjustments and remove some old bulk
This does the typicall adjustments to the new API. A thing to consider is that invalid links aren't indexed. Also removed old code about template and query stuff. And reused a regex instead of copy pasting it.
* [Minor] Cleanup editor ui
* [Minor] Adjust to new API
* [Minor] Adjust to new API and reduce ugly regex
* [Minor] New API
* [Minor] Rework link cm plugin
* [Major] Rework wiki links
A lot of code cleanup, reworked for new APIs and also introduces "invalid links"
* [Minor] Part of the editor ui rework
* [Major] Adjust to new API
This also removes the `looksLikePathWithExtension` check. I don't think it was necessary.
* [Minor] PArt of editor ui rewrite
* [Minor] Adjust to new API
* [Major] Adjust renderer to new API
Invalid links now link to `#`
* [Major] Rewrite navigator
This still needs major rework, currently in a "got it working" state
* [Minor] Adjust file name
* [Minor] Mistake during rebase
* [Minor] Navigate to end of header
* [Minor] Remove `tweakEditorDOM` and use proper CM extensions
* [Major] Heavily clean up the navigation code
* [Minor] Make `PageNavigator` closable again
* [Minor] Small fixes to reduce errors bubbling up
* [Minor] Show error message if navigate fails
* [Major] Remove legacy `navigate({ kind = ` syntax
This removes the old navigation syntax. It's still supported but the user will be warned then using it. I also added some validation to editor.navigate for user provided refs.
* [Minor] Make notifications errors
* [Minor] Don't fail if header isn't found
* [Minor] Typo
* [Major] Remove cleanPageRef
* [Minor] Small bug
* [Minor] Align behavior between render and editor
* [Major] Remove `PageRef`. Pretty sure it's obsolete
* [Major] Remove pos from header as it's an invalid ref
* [Minor] Align with original behavior
* [Minor] Get tests working again
* [Minor] check that indexPage is valid
* [Major] Rewrite `resolve.ts` file
* [Minor] More tests, more fixes
* [Minor] Don't just append .md this is weird
* [Minor] More edge cases
* [Minor] Version bumping hono somehow fixes the `/` case
* [Minor] Smaller TODOs
* [Major] We can be a littler looser on the restrictions
* [Major] Change header indexing, to index with pos
* [Minor] More fixes for headers
* [Minor] Rename for clarity
* [Minor] Change more regexes to named groups
* [Major] Inline content rewrite
* [Minor] Fix TODO
* [Minor] Bump index version
* [Major] New Space Primitive to check paths
* [Minor] Fix #1214
* [Minor] Fix #1169
* [Minor] Remove TODO
This check is probably not needed anymore. Unsure. May look into it later
* [Minor] small bug
* [Minor] Not a good rebase without me needing to fix it afterwards
* [Minor] Improve fallback for file upload
* [Minor] Some fixes on the for resolving
* [Minor] Removed doubled test case
* [Minor] Resolve #860
* [Minor] Turn flash notification into an error
* [Minor] Change handling of `.` paths
* [Minor] Show empty URL for index page
* [Minor] Push correct ref to history
* [Major] Capture mini editor events in capture phase
This fixes the issue were when pressing arrowup or arrowdown changed the cursor position inside the editor
* [Major] Add prefix to `FilterList`
This now fixes issues were if you had a prefixed page you con't properly search for it, because the search considered the prefix as part of the name
* [Minor] A little rigor for empty headers
* [Major] Fix #1404
* [Minor] `parseInt` returns `NaN` handle that
* [Minor] Use `fileName`
* [Minor] Fix comment
* [Minor] Fixes
* [Major] disallow `foo.png.md` and `/../`, etc. cases
* [Major] Change name of conflicted pages
* [Minor] Remove unecessary check
* [Minor] Remove some split code
* [Minor] Allow deletion of invalid files
* [Minor] Bug in the regex
* [Minor] Give some possibility of fixing incorrect names
* [Minor] Tiny bug with header completion
* [Major] Docs
* [Minor] Ignore errors for navigation inside of a page
This could be a problem when SB e.g. cached a scrollTop for a page, which, because e.g. the file is now deleted, doesn't exist anymore and thus CM throws an error, when trying to navigate
* Update conflicted copy regex in Maintenance.md
---------
Co-authored-by: Zef Hemel <zef@zef.me>
93 lines
3.0 KiB
TypeScript
93 lines
3.0 KiB
TypeScript
import type { Context } from "hono";
|
|
import { utcDateString } from "./util.ts";
|
|
import {
|
|
getNameFromPath,
|
|
isMarkdownPath,
|
|
parseToRef,
|
|
} from "@silverbulletmd/silverbullet/lib/ref";
|
|
import { parse } from "../web/markdown_parser/parse_tree.ts";
|
|
import { extendedMarkdownLanguage } from "../web/markdown_parser/parser.ts";
|
|
import { renderMarkdownToHtml } from "../web/markdown/markdown_render.ts";
|
|
import type { ServerOptions } from "./http_server.ts";
|
|
import type { AssetBundle } from "../lib/asset_bundle/bundle.ts";
|
|
import { htmlEscape } from "../web/markdown/html_render.ts";
|
|
import type { SpacePrimitives } from "../lib/spaces/space_primitives.ts";
|
|
|
|
// Server-side renders a markdown file to HTML
|
|
export async function renderHtmlPage(
|
|
spacePrimitives: SpacePrimitives,
|
|
path: string,
|
|
c: Context,
|
|
options: ServerOptions,
|
|
clientAssetBundle: AssetBundle,
|
|
): Promise<Response> {
|
|
const ref = parseToRef(path) ?? parseToRef(options.indexPage)!;
|
|
|
|
let html = "";
|
|
let title = "SilverBullet"; // Default to simply SilverBullet initially
|
|
let lastModified = utcDateString(Date.now());
|
|
if (!options.auth && options.readOnly) {
|
|
// Only attempt server-side rendering when this site is not protected by auth and running in read-only mode
|
|
if (isMarkdownPath(ref.path)) {
|
|
title = getNameFromPath(ref.path);
|
|
try {
|
|
const { data, meta } = await spacePrimitives.readFile(
|
|
ref.path,
|
|
);
|
|
lastModified = utcDateString(meta.lastModified);
|
|
|
|
if (c.req.header("If-Modified-Since") === lastModified) {
|
|
// Not modified, empty body status 304
|
|
return c.body(null, 304);
|
|
}
|
|
const text = new TextDecoder().decode(data);
|
|
const tree = parse(extendedMarkdownLanguage, text);
|
|
html = renderMarkdownToHtml(tree);
|
|
} catch (e: any) {
|
|
if (e.message !== "Not found") {
|
|
console.error("Error server-side rendering page", e);
|
|
}
|
|
}
|
|
} else {
|
|
// If it it's a file with an extension and it doesn't exist we can't really create a new one/recover
|
|
try {
|
|
await spacePrimitives.getFileMeta(ref.path);
|
|
} catch (e: any) {
|
|
if (e.message !== "Not found") {
|
|
return c.notFound();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const templateData = {
|
|
TITLE: title,
|
|
DESCRIPTION: stripHtml(html).substring(0, 255),
|
|
CONTENT: html,
|
|
HOST_URL_PREFIX: options.hostUrlPrefix ?? "",
|
|
};
|
|
|
|
html = clientAssetBundle.readTextFileSync(".client/index.html");
|
|
|
|
// Replace each template variable with its corresponding value
|
|
for (const [key, value] of Object.entries(templateData)) {
|
|
const placeholder = `{{${key}}}`;
|
|
const stringValue = typeof value === "boolean"
|
|
? (value ? "true" : "false")
|
|
: (key === "DESCRIPTION" ? htmlEscape(value) : String(value));
|
|
html = html.replace(placeholder, stringValue);
|
|
}
|
|
return c.html(
|
|
html,
|
|
200,
|
|
{
|
|
"Last-Modified": lastModified,
|
|
},
|
|
);
|
|
}
|
|
|
|
function stripHtml(html: string): string {
|
|
const regex = /<[^>]*>/g;
|
|
return html.replace(regex, "");
|
|
}
|