tsondb 0.7.4 → 0.7.5

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.
@@ -84,7 +84,7 @@ switch (passedArguments.command.name) {
84
84
  break;
85
85
  case "serve":
86
86
  debug(`running command: serve`);
87
- await serve(config.schema, config.dataRootPath, config.defaultLocales, config.homeLayoutSections, config.serverOptions);
87
+ await serve(config.schema, config.dataRootPath, config.defaultLocales, config.homeLayoutSections, config.serverOptions, config.customStylesheetPath);
88
88
  break;
89
89
  case "validate":
90
90
  debug(`running command: validate`);
@@ -8,6 +8,7 @@ export type Config = {
8
8
  defaultLocales: string[];
9
9
  dataRootPath: string;
10
10
  homeLayoutSections?: HomeLayoutSection[];
11
+ customStylesheetPath?: string;
11
12
  };
12
13
  export type ServerOptions = {
13
14
  port: number;
@@ -9,7 +9,7 @@ type ValidationOptions = {
9
9
  };
10
10
  export declare const validate: (schema: Schema, dataRootPath: string, options?: Partial<ValidationOptions>) => Promise<void>;
11
11
  export declare const generateAndValidate: (schema: Schema, outputs: Output[], dataRootPath: string, validationOptions?: Partial<ValidationOptions>) => Promise<void>;
12
- export declare const serve: (schema: Schema, dataRootPath: string, defaultLocales: string[], homeLayoutSections?: HomeLayoutSection[], serverOptions?: Partial<ServerOptions>) => Promise<void>;
12
+ export declare const serve: (schema: Schema, dataRootPath: string, defaultLocales: string[], homeLayoutSections?: HomeLayoutSection[], serverOptions?: Partial<ServerOptions>, customStylesheetPath?: string) => Promise<void>;
13
13
  export declare const generateValidateAndServe: (schema: Schema, outputs: Output[], dataRootPath: string, defaultLocales: string[], homeLayoutSections?: HomeLayoutSection[], serverOptions?: Partial<ServerOptions>, validationOptions?: Partial<ValidationOptions>) => Promise<void>;
14
14
  export declare const format: (schema: Schema, dataRootPath: string) => Promise<void>;
15
15
  export {};
@@ -57,7 +57,7 @@ export const generateAndValidate = async (schema, outputs, dataRootPath, validat
57
57
  const instancesByEntityName = await getInstancesByEntityName(dataRootPath, entities);
58
58
  _validate(dataRootPath, entities, instancesByEntityName, validationOptions);
59
59
  };
60
- export const serve = async (schema, dataRootPath, defaultLocales, homeLayoutSections, serverOptions) => {
60
+ export const serve = async (schema, dataRootPath, defaultLocales, homeLayoutSections, serverOptions, customStylesheetPath) => {
61
61
  if (defaultLocales.length === 0) {
62
62
  throw new Error("At least one default locale must be specified to start the server.");
63
63
  }
@@ -66,7 +66,7 @@ export const serve = async (schema, dataRootPath, defaultLocales, homeLayoutSect
66
66
  debug("prepared folders");
67
67
  const instancesByEntityName = await getInstancesByEntityName(dataRootPath, entities);
68
68
  debug("loaded instances");
69
- await createServer(schema, dataRootPath, instancesByEntityName, defaultLocales, homeLayoutSections, serverOptions);
69
+ await createServer(schema, dataRootPath, instancesByEntityName, defaultLocales, homeLayoutSections, serverOptions, customStylesheetPath);
70
70
  };
71
71
  export const generateValidateAndServe = async (schema, outputs, dataRootPath, defaultLocales, homeLayoutSections, serverOptions, validationOptions) => {
72
72
  await generateOutputs(schema, outputs);
@@ -35,4 +35,4 @@ declare global {
35
35
  }
36
36
  }
37
37
  }
38
- export declare const createServer: (schema: Schema, dataRootPath: string, instancesByEntityName: InstancesByEntityName, defaultLocales: string[], homeLayoutSections?: HomeLayoutSection[], options?: Partial<ServerOptions>) => Promise<void>;
38
+ export declare const createServer: (schema: Schema, dataRootPath: string, instancesByEntityName: InstancesByEntityName, defaultLocales: string[], homeLayoutSections?: HomeLayoutSection[], options?: Partial<ServerOptions>, customStylesheetPath?: string) => Promise<void>;
@@ -16,7 +16,7 @@ const staticNodeModule = (moduleName) => {
16
16
  }
17
17
  return express.static(dirname(pathToPackageJson));
18
18
  };
19
- export const createServer = async (schema, dataRootPath, instancesByEntityName, defaultLocales, homeLayoutSections, options) => {
19
+ export const createServer = async (schema, dataRootPath, instancesByEntityName, defaultLocales, homeLayoutSections, options, customStylesheetPath) => {
20
20
  const { port } = { ...defaultOptions, ...options };
21
21
  const app = express();
22
22
  app.use(express.static(join(import.meta.dirname, "../../../../public")));
@@ -44,6 +44,15 @@ export const createServer = async (schema, dataRootPath, instancesByEntityName,
44
44
  "preact-iso": "/js/node_modules/preact-iso/src/index.js",
45
45
  },
46
46
  }, null, 2);
47
+ const customStylesheetLinkHeader = customStylesheetPath
48
+ ? `
49
+ <link rel="stylesheet" href="/css/custom.css">`
50
+ : "";
51
+ if (customStylesheetPath) {
52
+ app.use("/css/custom.css", (_req, res) => {
53
+ res.sendFile(customStylesheetPath);
54
+ });
55
+ }
47
56
  app.get(/^\/.*/, (_req, res) => {
48
57
  res.send(`<!DOCTYPE html>
49
58
  <html lang="en">
@@ -51,7 +60,7 @@ export const createServer = async (schema, dataRootPath, instancesByEntityName,
51
60
  <meta charset="UTF-8">
52
61
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
53
62
  <title>TSONDB</title>
54
- <link rel="stylesheet" href="/css/styles.css">
63
+ <link rel="stylesheet" href="/css/styles.css">${customStylesheetLinkHeader}
55
64
  <script type="importmap">${importMap}</script>
56
65
  </head>
57
66
  <body>
@@ -20,6 +20,10 @@ export type InlineMarkdownNode = {
20
20
  export type BlockMarkdownNode = {
21
21
  kind: "paragraph";
22
22
  content: InlineMarkdownNode[];
23
+ } | {
24
+ kind: "heading";
25
+ level: number;
26
+ content: InlineMarkdownNode[];
23
27
  } | {
24
28
  kind: "list";
25
29
  ordered: boolean;
@@ -38,6 +42,9 @@ export type BlockSyntaxMarkdownNode = InlineMarkdownNode | {
38
42
  } | {
39
43
  kind: "tablemarker";
40
44
  content: string;
45
+ } | {
46
+ kind: "headingmarker";
47
+ content: string;
41
48
  };
42
49
  export declare const parseBlockMarkdown: (text: string) => BlockMarkdownNode[];
43
50
  export declare const parseBlockMarkdownForSyntaxHighlighting: (text: string) => BlockSyntaxMarkdownNode[];
@@ -234,6 +234,19 @@ const paragraphRule = {
234
234
  ...nodesForTrailingWhitespace(result[2]),
235
235
  ],
236
236
  };
237
+ const headingRule = {
238
+ pattern: /^(#+)( +)([^\s\n][^\n]*?)(\n{2,}|\s*$)/,
239
+ map: result => ({
240
+ kind: "heading",
241
+ level: result[1]?.length ?? 1,
242
+ content: parseInlineMarkdown(result[3] ?? "", false),
243
+ }),
244
+ mapHighlighting: result => [
245
+ { kind: "headingmarker", content: (result[1] ?? "") + (result[2] ?? "") },
246
+ ...parseInlineMarkdown(result[3] ?? "", true),
247
+ ...nodesForTrailingWhitespace(result[4]),
248
+ ],
249
+ };
237
250
  const removeSurroundingPipes = (text) => text.replace(/^\|/, "").replace(/\|$/, "");
238
251
  const tableMarker = (text) => ({
239
252
  kind: "tablemarker",
@@ -273,7 +286,7 @@ const tableRule = {
273
286
  ...nodesForTrailingWhitespace(result[6]),
274
287
  ],
275
288
  };
276
- const blockRules = [tableRule, listRule, paragraphRule];
289
+ const blockRules = [headingRule, tableRule, listRule, paragraphRule];
277
290
  const parseActiveBlockRule = (rule, res) => [
278
291
  rule.map(res),
279
292
  ];
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { useLocation } from "preact-iso";
3
- import { useCallback, useEffect, useState } from "preact/hooks";
3
+ import { useCallback, useContext, useEffect, useState } from "preact/hooks";
4
4
  import { getGitStatusForDisplay, getLabelForGitStatus, isChangedInIndex, isChangedInWorkingDir, } from "../../shared/utils/git.js";
5
5
  import { getAllEntities } from "../api/declarations.js";
6
6
  import { commitStagedFiles, createBranch, getBranches, getStatus, pullCommits, pushCommits, stageAllFiles, stageFileOfEntity, switchBranch, unstageAllFiles, unstageFileOfEntity, } from "../api/git.js";
7
+ import { GitContext } from "../context/git.js";
7
8
  import { useSetting } from "../hooks/useSettings.js";
8
9
  const filterFilesForDisplay = (predicate, entities, data) => Object.entries(data.instances)
9
10
  .map(([entityName, instances]) => [
@@ -23,7 +24,7 @@ const GitFileList = ({ filesByEntity, onFile, isIndex = false }) => filesByEntit
23
24
  }) })] }, entityName))) }));
24
25
  export const Git = () => {
25
26
  const [locales] = useSetting("displayedLocales");
26
- const [isOpen, setIsOpen] = useState(false);
27
+ const [isOpen] = useContext(GitContext);
27
28
  const [commitsAhead, setCommitsAhead] = useState(0);
28
29
  const [commitsBehind, setCommitsBehind] = useState(0);
29
30
  const [commitMessage, setCommitMessage] = useState("");
@@ -157,9 +158,7 @@ export const Git = () => {
157
158
  }
158
159
  });
159
160
  };
160
- return (_jsxs("aside", { class: "git", children: [_jsx("h2", { class: "h1-faded", children: "Version Control" }), _jsx("button", { onClick: () => {
161
- setIsOpen(b => !b);
162
- }, children: "File changes" }), _jsxs("div", { className: `git-overlay ${isOpen ? "git-overlay--open" : ""}`, children: [_jsxs("div", { class: "sync", children: [_jsxs("button", { onClick: push, children: ["Push", commitsAhead > 0 ? ` (${commitsAhead.toString()})` : ""] }), _jsxs("button", { onClick: pull, children: ["Pull", commitsBehind > 0 ? ` (${commitsBehind.toString()})` : ""] })] }), _jsxs("div", { className: "branch", children: [_jsx("div", { className: "select-wrapper", children: _jsx("select", { value: currentBranch, onInput: onSwitchBranch, children: allBranches.map(branch => (_jsx("option", { value: branch, children: branch }, branch))) }) }), _jsx("button", { onClick: onCreateBranch, children: "New branch" })] }), _jsxs("div", { class: "commit", children: [_jsx("input", { type: "text", value: commitMessage, onInput: event => {
161
+ return (_jsxs("aside", { class: "git", children: [_jsx("h2", { class: "h1-faded", children: "Version Control" }), _jsxs("div", { className: `git-overlay ${isOpen ? "git-overlay--open" : ""}`, children: [_jsxs("div", { class: "sync", children: [_jsxs("button", { onClick: push, children: ["Push", commitsAhead > 0 ? ` (${commitsAhead.toString()})` : ""] }), _jsxs("button", { onClick: pull, children: ["Pull", commitsBehind > 0 ? ` (${commitsBehind.toString()})` : ""] })] }), _jsxs("div", { className: "branch", children: [_jsx("div", { className: "select-wrapper", children: _jsx("select", { value: currentBranch, onInput: onSwitchBranch, children: allBranches.map(branch => (_jsx("option", { value: branch, children: branch }, branch))) }) }), _jsx("button", { onClick: onCreateBranch, children: "New branch" })] }), _jsxs("div", { class: "commit", children: [_jsx("input", { type: "text", value: commitMessage, onInput: event => {
163
162
  setCommitMessage(event.currentTarget.value);
164
163
  }, placeholder: "added X to instance Y, \u2026" }), _jsx("button", { onClick: commit, disabled: commitMessage.length === 0 || indexFiles.length === 0, children: "Commit" })] }), _jsxs("div", { className: "git-section-title", children: [_jsx("h3", { children: "Files to be committed" }), _jsx("button", { onClick: unstageAll, children: "Unstage all" })] }), _jsx(GitFileList, { filesByEntity: indexFiles, isIndex: true, onFile: unstage }), _jsxs("div", { className: "git-section-title", children: [_jsx("h3", { children: "Working tree changes" }), _jsx("button", { onClick: stageAll, children: "Stage all" })] }), _jsx(GitFileList, { filesByEntity: workingTreeFiles, onFile: stage })] })] }));
165
164
  };
@@ -1,5 +1,10 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "preact/jsx-runtime";
2
+ import { useContext } from "preact/hooks";
3
+ import { GitContext } from "../context/git.js";
2
4
  import { Settings } from "./Settings.js";
3
5
  export const Layout = ({ breadcrumbs, children }) => {
4
- return (_jsxs(_Fragment, { children: [_jsxs("header", { children: [_jsx("nav", { children: _jsx("ol", { children: breadcrumbs.map(({ url, label }) => (_jsx("li", { children: _jsx("a", { href: url, children: label }) }, url))) }) }), _jsx(Settings, {})] }), _jsx("main", { children: children })] }));
6
+ const [_, setIsGitOpen] = useContext(GitContext);
7
+ return (_jsxs(_Fragment, { children: [_jsxs("header", { children: [_jsx("nav", { children: _jsx("ol", { children: breadcrumbs.map(({ url, label }) => (_jsx("li", { children: _jsx("a", { href: url, children: label }) }, url))) }) }), _jsxs("div", { class: "nav-buttons", children: [_jsx("button", { class: "git-toggle", onClick: () => {
8
+ setIsGitOpen(b => !b);
9
+ }, children: "File changes" }), _jsx(Settings, {})] })] }), _jsx("main", { children: children })] }));
5
10
  };
@@ -12,7 +12,7 @@ export const StringTypeInput = ({ type, value, disabled, onChange }) => {
12
12
  const errors = validateStringConstraints(type, value);
13
13
  return (_jsx("div", { class: "field field--string", children: isMarkdown ? (_jsxs(_Fragment, { children: [_jsxs("div", { class: "editor editor--markdown", children: [_jsxs("div", { class: "textarea-grow-wrap", children: [_jsx("textarea", { value: value, minLength: minLength, maxLength: maxLength, onInput: event => {
14
14
  onChange(event.currentTarget.value);
15
- }, "aria-invalid": errors.length > 0, disabled: disabled }), _jsxs("p", { class: "help", children: ["This textarea supports", " ", _jsx("a", { href: "https://www.markdownguide.org/getting-started/", target: "_blank", rel: "noreferrer", children: "Markdown" }), "."] }), _jsx(MarkdownHighlighting, { class: "textarea-grow-wrap__mirror editor-highlighting", string: value })] }), _jsx(ValidationErrors, { disabled: disabled, errors: errors })] }), _jsx("div", { class: "preview", children: _jsx(Markdown, { string: value }) })] })) : (_jsxs("div", { class: "editor", children: [_jsx("input", { type: "text", value: value, minLength: minLength, maxLength: maxLength, pattern: pattern === undefined
15
+ }, "aria-invalid": errors.length > 0, disabled: disabled }), _jsxs("p", { class: "help", children: ["This textarea supports", " ", _jsx("a", { href: "https://www.markdownguide.org/getting-started/", target: "_blank", rel: "noreferrer", children: "Markdown" }), "."] }), _jsx(MarkdownHighlighting, { class: "textarea-grow-wrap__mirror editor-highlighting", string: value })] }), _jsx(ValidationErrors, { disabled: disabled, errors: errors })] }), _jsx("div", { class: "preview", children: _jsx(Markdown, { string: value, outerHeadingLevel: 2 }) })] })) : (_jsxs("div", { class: "editor", children: [_jsx("input", { type: "text", value: value, minLength: minLength, maxLength: maxLength, pattern: pattern === undefined
16
16
  ? undefined
17
17
  : pattern.startsWith("^(?:") && pattern.endsWith(")$")
18
18
  ? pattern.slice(4, -2)
@@ -0,0 +1,3 @@
1
+ import type { SetStateAction } from "preact/compat";
2
+ import type { Dispatch } from "preact/hooks";
3
+ export declare const GitContext: import("preact").Context<[isOpen: boolean, setIsOpen: Dispatch<SetStateAction<boolean>>]>;
@@ -0,0 +1,2 @@
1
+ import { createContext } from "preact";
2
+ export const GitContext = createContext([false, () => { }]);
@@ -1,12 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { render } from "preact";
3
3
  import { LocationProvider, Route, Router, useLocation } from "preact-iso";
4
- import { useEffect } from "preact/hooks";
4
+ import { useEffect, useState } from "preact/hooks";
5
5
  import { getAllEntities } from "./api/declarations.js";
6
6
  import { getWebConfig } from "./api/index.js";
7
7
  import { Git } from "./components/Git.js";
8
8
  import { ConfigContext } from "./context/config.js";
9
9
  import { EntitiesContext } from "./context/entities.js";
10
+ import { GitContext } from "./context/git.js";
10
11
  import { SettingsContext } from "./context/settings.js";
11
12
  import { useMappedAPIResource } from "./hooks/useMappedAPIResource.js";
12
13
  import { useSettings } from "./hooks/useSettings.js";
@@ -20,6 +21,7 @@ const mapEntities = (data) => data.declarations
20
21
  .sort((a, b) => a.declaration.name.localeCompare(b.declaration.name));
21
22
  const App = ({ config }) => {
22
23
  const settingsContext = useSettings(config);
24
+ const [isGitOpen, setIsGitOpen] = useState(false);
23
25
  const [entities, reloadEntities] = useMappedAPIResource(getAllEntities, mapEntities, settingsContext.settings.displayedLocales);
24
26
  const location = useLocation();
25
27
  useEffect(() => {
@@ -27,7 +29,7 @@ const App = ({ config }) => {
27
29
  alert("Error reloading entities: " + String(error));
28
30
  });
29
31
  }, [location.path, reloadEntities]);
30
- return (_jsx(ConfigContext.Provider, { value: config, children: _jsx(SettingsContext.Provider, { value: settingsContext, children: _jsx(LocationProvider, { children: _jsxs(EntitiesContext.Provider, { value: { entities: entities ?? [], reloadEntities }, children: [_jsxs(Router, { children: [_jsx(Route, { path: "/", component: Home }), _jsx(Route, { path: "/entities/:name", component: Entity }), _jsx(Route, { path: "/entities/:name/instances/create", component: CreateInstance }), _jsx(Route, { path: "/entities/:name/instances/:id", component: Instance }), _jsx(Route, { default: true, component: NotFound })] }), _jsx(Git, {})] }) }) }) }));
32
+ return (_jsx(ConfigContext.Provider, { value: config, children: _jsx(SettingsContext.Provider, { value: settingsContext, children: _jsx(GitContext.Provider, { value: [isGitOpen, setIsGitOpen], children: _jsx(LocationProvider, { children: _jsxs(EntitiesContext.Provider, { value: { entities: entities ?? [], reloadEntities }, children: [_jsxs(Router, { children: [_jsx(Route, { path: "/", component: Home }), _jsx(Route, { path: "/entities/:name", component: Entity }), _jsx(Route, { path: "/entities/:name/instances/create", component: CreateInstance }), _jsx(Route, { path: "/entities/:name/instances/:id", component: Instance }), _jsx(Route, { default: true, component: NotFound })] }), _jsx(Git, {})] }) }) }) }) }));
31
33
  };
32
34
  const config = await getWebConfig();
33
35
  const root = document.getElementById("app");
@@ -2,6 +2,7 @@ import type { FunctionalComponent } from "preact";
2
2
  import type { BlockMarkdownNode } from "../../shared/utils/markdown.ts";
3
3
  type Props = {
4
4
  node: BlockMarkdownNode;
5
+ outerHeadingLevel?: number;
5
6
  };
6
7
  export declare const BlockMarkdown: FunctionalComponent<Props>;
7
8
  export {};
@@ -1,9 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
2
2
  import { InlineMarkdown } from "./InlineMarkdown.js";
3
- export const BlockMarkdown = ({ node }) => {
3
+ export const BlockMarkdown = ({ node, outerHeadingLevel = 0 }) => {
4
4
  switch (node.kind) {
5
5
  case "paragraph":
6
6
  return (_jsx("p", { children: node.content.map((inline, ii) => (_jsx(InlineMarkdown, { node: inline }, ii))) }));
7
+ case "heading":
8
+ const Tag = `h${(node.level + outerHeadingLevel).toString()}`;
9
+ return (_jsx(Tag, { children: node.content.map((inline, ii) => (_jsx(InlineMarkdown, { node: inline }, ii))) }));
7
10
  case "list":
8
11
  if (node.ordered) {
9
12
  return (_jsx("ol", { children: node.content.map((item, ii) => (_jsx("li", { children: item.content.map((inline, iii) => (_jsx(InlineMarkdown, { node: inline }, iii))) }, ii))) }));
@@ -6,6 +6,8 @@ export const BlockMarkdownHighlighting = ({ node }) => {
6
6
  return _jsx("span", { class: "list-item-marker", children: node.content });
7
7
  case "tablemarker":
8
8
  return _jsx("span", { class: "table-marker", children: node.content });
9
+ case "headingmarker":
10
+ return _jsx("span", { class: "heading-marker", children: node.content });
9
11
  default:
10
12
  return _jsx(InlineMarkdown, { node: node });
11
13
  }
@@ -2,6 +2,7 @@ import type { FunctionalComponent } from "preact";
2
2
  type Props = {
3
3
  class?: string;
4
4
  string: string;
5
+ outerHeadingLevel?: number;
5
6
  };
6
7
  export declare const Markdown: FunctionalComponent<Props>;
7
8
  export {};
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment } from "preact/jsx-runtime";
2
2
  import { parseBlockMarkdown } from "../../shared/utils/markdown.js";
3
3
  import { BlockMarkdown } from "./BlockMarkdown.js";
4
- export const Markdown = ({ class: className, string }) => {
4
+ export const Markdown = ({ class: className, string, outerHeadingLevel, }) => {
5
5
  const blocks = parseBlockMarkdown(string);
6
- const blockElements = blocks.map((block, i) => (_jsx(BlockMarkdown, { node: block }, `md-block-${i.toString()}`)));
6
+ const blockElements = blocks.map((block, i) => (_jsx(BlockMarkdown, { node: block, outerHeadingLevel: outerHeadingLevel }, `md-block-${i.toString()}`)));
7
7
  if (className) {
8
8
  return _jsx("div", { class: className, children: blockElements });
9
9
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tsondb",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "",
5
5
  "license": "ISC",
6
6
  "author": "Lukas Obermann",
@@ -134,6 +134,11 @@ header nav ol {
134
134
  margin: 0;
135
135
  }
136
136
 
137
+ .nav-buttons {
138
+ display: flex;
139
+ gap: 0.5rem;
140
+ }
141
+
137
142
  main {
138
143
  grid-area: main;
139
144
  }
@@ -875,6 +880,12 @@ main:has(.form-footer) {
875
880
 
876
881
  aside.git {
877
882
  grid-area: aside;
883
+ position: absolute;
884
+ top: 5rem;
885
+ right: 0;
886
+ width: 30rem;
887
+ max-width: calc(100% - 1.5rem);
888
+ max-height: calc(100% - 6.5rem);
878
889
  }
879
890
 
880
891
  aside.git h2 {
@@ -886,13 +897,18 @@ aside.git h2 {
886
897
  width: 30rem;
887
898
  border-left: 1px solid var(--separator-color);
888
899
  padding-left: 1rem;
900
+ top: unset;
901
+ right: unset;
902
+ position: static;
903
+ max-height: none;
904
+ max-width: none;
889
905
  }
890
906
 
891
907
  aside.git h2 {
892
908
  display: block;
893
909
  }
894
910
 
895
- aside.git > button {
911
+ .git-toggle {
896
912
  display: none;
897
913
  }
898
914
  }