Implement space-style (#796)

* Implement space-style
* Add reloading styles to System: Reload

---------

Co-authored-by: Zef Hemel <zef@zef.me>
pull/770/head^2
onespaceman 2024-03-09 06:26:58 -05:00 committed by GitHub
parent 2705fff52e
commit 95ae722a50
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 192 additions and 95 deletions

View File

@ -1,9 +1,14 @@
import { LRLanguage } from "@codemirror/language";
import {
cLanguage,
cmakeLanguage,
cppLanguage,
csharpLanguage,
cssLanguage,
dartLanguage,
diffLanguage,
dockerfileLanguage,
goLanguage,
htmlLanguage,
javaLanguage,
javascriptLanguage,
@ -12,7 +17,9 @@ import {
Language,
objectiveCLanguage,
objectiveCppLanguage,
perlLanguage,
postgresqlLanguage,
powerShellLanguage,
protobufLanguage,
pythonLanguage,
rustLanguage,
@ -20,19 +27,13 @@ import {
shellLanguage,
sqlLanguage,
StreamLanguage,
tclLanguage,
tomlLanguage,
typescriptLanguage,
xmlLanguage,
yamlLanguage,
goLanguage,
diffLanguage,
powerShellLanguage,
perlLanguage,
tclLanguage,
verilogLanguage,
vhdlLanguage,
dockerfileLanguage,
cmakeLanguage,
xmlLanguage,
yamlLanguage,
} from "./deps.ts";
import {
extendedMarkdownLanguage,
@ -58,7 +59,8 @@ export const builtinLanguages: Record<string, Language> = {
"postgres": StreamLanguage.define(postgresqlLanguage),
"rust": StreamLanguage.define(rustLanguage),
"rs": StreamLanguage.define(rustLanguage),
"css": StreamLanguage.define(sqlLanguage),
"css": StreamLanguage.define(cssLanguage),
"space-style": StreamLanguage.define(cssLanguage),
"html": htmlLanguage,
"python": StreamLanguage.define(pythonLanguage),
"py": StreamLanguage.define(pythonLanguage),

View File

@ -94,6 +94,12 @@ export function systemSyscalls(
}
}
},
"system.loadSpaceStyles": async () => {
if (!client) {
throw new Error("Not supported on server");
}
await client.loadCustomStyles();
},
"system.invokeSpaceFunction": (_ctx, name: string, ...args: any[]) => {
return commonSystem.invokeSpaceFunction(name, args);
},

View File

@ -132,6 +132,12 @@ functions:
events:
- page:index
# Style
indexSpaceStyle:
path: style.ts:indexSpaceStyle
events:
- page:index
# Hashtags
indexTags:
path: tags.ts:indexTags

62
plugs/index/style.ts Normal file
View File

@ -0,0 +1,62 @@
import { IndexTreeEvent } from "../../plug-api/types.ts";
import { collectNodesOfType, findNodeOfType } from "../../plug-api/lib/tree.ts";
import { ObjectValue } from "../../plug-api/types.ts";
import { indexObjects } from "./api.ts";
import { readSetting } from "$sb/lib/settings_page.ts";
import { cleanPageRef } from "$sb/lib/resolve.ts";
export type StyleObject = ObjectValue<{
style: string;
origin: string;
}>;
export async function indexSpaceStyle({ name, tree }: IndexTreeEvent) {
const allStyles: StyleObject[] = [];
// Also collect CSS from custom styles in settings
let customStylePages = await readSetting("customStyles", []);
if (!Array.isArray(customStylePages)) {
customStylePages = [customStylePages];
}
customStylePages = customStylePages.map((page: string) => cleanPageRef(page));
collectNodesOfType(tree, "FencedCode").map((t) => {
const codeInfoNode = findNodeOfType(t, "CodeInfo");
if (!codeInfoNode) {
return;
}
const fenceType = codeInfoNode.children![0].text!;
if (fenceType !== "space-style") {
if (
!customStylePages.includes(name) || fenceType !== "css"
) {
return;
}
}
const codeTextNode = findNodeOfType(t, "CodeText");
if (!codeTextNode) {
// Honestly, this shouldn't happen
return;
}
const codeText = codeTextNode.children![0].text!;
let codeOrigin = "";
if (customStylePages.includes(name)) {
codeOrigin = "settings";
} else if (name.startsWith("Library/")) {
codeOrigin = "library";
} else {
codeOrigin = "user";
}
allStyles.push({
ref: `${name}@${t.from!}`,
tag: "space-style",
style: codeText,
origin: codeOrigin,
});
});
await indexObjects<StyleObject>(name, allStyles);
}

View File

@ -25,6 +25,7 @@ import type {
CompleteEvent,
SlashCompletions,
} from "../plug-api/types.ts";
import { StyleObject } from "../plugs/index/style.ts";
import { throttle } from "$lib/async.ts";
import { PlugSpacePrimitives } from "$common/spaces/plug_space_primitives.ts";
import { EventedSpacePrimitives } from "$common/spaces/evented_space_primitives.ts";
@ -1095,27 +1096,24 @@ export class Client {
}
async loadCustomStyles() {
if (this.settings.customStyles) {
const accumulatedCSS: string[] = [];
let customStylePages = this.settings.customStyles;
if (!Array.isArray(customStylePages)) {
customStylePages = [customStylePages];
}
for (const customStylesPage of customStylePages) {
try {
const { text: stylesText } = await this.space.readPage(
cleanPageRef(customStylesPage),
const spaceStyles = await this.clientSystem.queryObjects<StyleObject>(
"space-style",
{},
);
// Analogous to yamlSettingsRegex in settings.ts
const cssBlockRegex = /^(```+|~~~+)css\r?\n([\S\s]+)\1/m;
const match = cssBlockRegex.exec(stylesText);
if (!match) {
if (!spaceStyles) {
return;
}
accumulatedCSS.push(match[2]);
} catch (e: any) {
console.error("Failed to load custom styles", e);
}
// Sort stylesheets (last declared styles take precedence)
// Order is 1: Imported styles, 2: Other styles, 3: customStyles from Settings
const sortOrder = ["library", "user", "settings"];
spaceStyles.sort((a, b) =>
sortOrder.indexOf(a.origin) - sortOrder.indexOf(b.origin)
);
const accumulatedCSS: string[] = [];
for (const s of spaceStyles) {
accumulatedCSS.push(s.style);
}
const customStylesContent = accumulatedCSS.join("\n\n");
this.ui.viewDispatch({
@ -1125,7 +1123,6 @@ export class Client {
});
document.getElementById("custom-styles")!.innerHTML = customStylesContent;
}
}
async runCommandByName(name: string, args?: any[]) {
const cmd = this.ui.viewState.commands.get(name);

View File

@ -66,6 +66,10 @@ export function editorSyscalls(client: Client): SysCallMapping {
"system.loadSpaceScripts",
[],
);
await client.clientSystem.system.localSyscall(
"system.loadSpaceStyles",
[],
);
},
"editor.openUrl": (_ctx, url: string, existingWindow = false) => {
if (!existingWindow) {

View File

@ -12,5 +12,7 @@ These are the block types that ship with SilverBullet, but [[Plugs]] can define
* `query`: [[Live Queries]]
* `toc`: [[Table of Contents]]
* `embed`: [[Live Embeds]]
* `space-script`: [[Space Script]]
* `space-style`: [[Space Style]]
The fenced code block syntax is also used to get [[Markdown/Syntax Highlighting]] for numerous programming languages.

View File

@ -6,9 +6,9 @@ Silverbullet supports [admonitions](https://github.com/community/community/discu
> **warning** This is a
> warning admonition
Custom admonitions can be added in [[STYLES]] using the following format:
Custom admonitions can be added in a [[Space Style]] using the following format:
```css
```space-style
// Replace the keyword with a word or phrase of your choice
.sb-admonition[admonition="keyword"] {
// The icon can be a link or an embedded image like shown here

View File

@ -1,12 +1,9 @@
This page contains settings for configuring SilverBullet and its Plugs. Changing any of these will go into effect immediately in most cases except `indexPage` and `customStyles`, which require a reload.
This page contains settings for configuring SilverBullet and its Plugs. Changing any of these will go into effect immediately in most cases except `indexPage` which requires a reload.
```yaml
# Initial page to load when launching SB, can contain template variables
indexPage: "[[SilverBullet]]"
# Load custom CSS styles from the following page, can also be an array
customStyles: "[[STYLES]]"
# Hide the sync button
hideSyncButton: false

View File

@ -1,49 +0,0 @@
In [[SETTINGS]] you can define a `customStyles` setting that links to a page like this. SilverBullet will load the specified page, find a CSS code block inside that page and load it upon boot (an example can be found below).
This can be used to achieve various things, such as overriding the default editor font or setting wider page widths. What CSS styles you can override is not very well documented, youll have to reverse-engineer things a bit for now, unfortunately.
```css
#sb-root {
/* Uncomment the next line to set the editor font to Courier */
/* --editor-font: "Courier" !important; */
/* Uncomment the next line to set the editor width to 1400px */
/* --editor-width: 1400px !important; */
}
/* Choose another header color */
#sb-top {
/* background-color: #ffe54a !important; */
}
/* You can even change the appearance of buttons */
button {
/* align-items: center;
background-color: #fff;
border-radius: 6px;
box-shadow: transparent 0 0 0 3px,rgba(18, 18, 18, .1) 0 6px 20px;
box-sizing: border-box;
color: #121212;
cursor: pointer;
display: inline-flex;
flex: 1 1 auto;
font-family: Inter,sans-serif;
font-size: 0.6rem;
justify-content: center;
line-height: 1;
margin: 0.2rem;
outline: none;
padding: 0.3rem 0.4rem;
text-align: center;
text-decoration: none;
transition: box-shadow .2s,-webkit-box-shadow .2s;
white-space: nowrap;
border: 0;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation; */
}
button:hover {
/* box-shadow: #121212 0 0 0 3px, transparent 0 0 0 0; */
}
```

70
website/Space Style.md Normal file
View File

@ -0,0 +1,70 @@
Space Style is [[Space Script]]s stylish sibling. It enables you to add your own styling to SilverBullet with `space-style` [[Blocks]].
This can be used to achieve various things, such as overriding the default editor font or setting wider page widths. It is also possible to develop custom themes this way.
To apply the updated styles, either reload the client or run the {[System: Reload]} command.
Many styles can be set with [variables](https://github.com/silverbulletmd/silverbullet/blob/main/web/styles/theme.scss) but not everything is covered. Youll have to reverse-engineer those parts, unfortunately.
# Examples
All the actual CSS in these examples is commented out as to not affect this very website.
```space-style
html {
/* Changes to the default theme */
/* Such as the accent color */
/*--ui-accent-color: #464cfc;*/
}
html[data-theme="dark"] {
/* Changes to the dark theme */
/*--ui-accent-color: #464cfc;*/
}
html {
/* Uncomment the next line to set the editor font to Courier */
/* --editor-font: "Courier" !important; */
/* Uncomment the next line to set the editor width to 1400px */
/* --editor-width: 1400px !important; */
}
/* Choose another header color */
html {
/*--top-background-color: #eee;*/
}
/* Or modify the element directly */
#sb-top {
/*background-color: #eee !important;*/
}
/* You can even change the appearance of buttons */
button {
/* align-items: center;
background-color: #fff;
border-radius: 6px;
box-shadow: transparent 0 0 0 3px,rgba(18, 18, 18, .1) 0 6px 20px;
box-sizing: border-box;
color: #121212;
cursor: pointer;
display: inline-flex;
flex: 1 1 auto;
font-family: Inter,sans-serif;
font-size: 0.6rem;
justify-content: center;
line-height: 1;
margin: 0.2rem;
outline: none;
padding: 0.3rem 0.4rem;
text-align: center;
text-decoration: none;
transition: box-shadow .2s,-webkit-box-shadow .2s;
white-space: nowrap;
border: 0;
user-select: none;
-webkit-user-select: none;
touch-action: manipulation; */
}
button:hover {
/* box-shadow: #121212 0 0 0 3px, transparent 0 0 0 0; */
}
```

View File

@ -1,6 +1,6 @@
Dark theme, originally [shared here](https://discord.com/channels/1028543811191836782/1028543811984568373/1141715540755361833). Make sure you switch SilverBullet to {[Editor: Toggle Dark Mode|dark mode]} to use.
```css
```space-style
html[data-theme="dark"], html[data-theme="dark"]{
--root-background-color: rgba(30,33,38,255);
--root-color: rgba(255,255,255,0.6);