@kenjura/ursa 0.5.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/.nvmrc ADDED
@@ -0,0 +1 @@
1
+ 16.18
@@ -0,0 +1,20 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "type": "node",
9
+ "request": "launch",
10
+ "name": "Launch Program",
11
+ "skipFiles": [
12
+ "<node_internals>/**"
13
+ ],
14
+ "env": {
15
+ "INCLUDE_FILTER": "Kaine",
16
+ },
17
+ "program": "${workspaceFolder}/src/serve.js"
18
+ }
19
+ ]
20
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,41 @@
1
+ # 0.5.0
2
+
3
+ 2023-05-08
4
+
5
+ - added INCLUDE_FILTER env var
6
+
7
+ # 0.4.2
8
+
9
+ 2023-03-01
10
+
11
+ - bug fixes
12
+
13
+ # 0.4.0
14
+
15
+ 2023-03-31
16
+
17
+ - Now a library
18
+
19
+ # 0.3.0
20
+
21
+ 2022-10-17
22
+
23
+ - Using express instead of http/node-static for serve
24
+ - Serve now waits for generation to finish
25
+ - Formatted files using prettier
26
+
27
+ # 0.2.0
28
+
29
+ 2022-03-30
30
+
31
+ - Added serve command
32
+ - Workaround for node-static broken npm package
33
+ - Added source static files and menu
34
+ - Lots of default styling (not that meta should be in there at all)
35
+ - Added TODO
36
+
37
+ # 0.1.0
38
+
39
+ 2022-03-30
40
+
41
+ - Initial POC
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ static site generator from MD/wikitext/YML
2
+
3
+ there are many like it, but this one's mine
4
+
5
+ # Developing
6
+
7
+ ```npm run serve```
8
+
9
+ Watches source and meta folder; on change, writes HTML to build folder.
10
+
11
+ Optional environment variables:
12
+ - SOURCE: path to the source folder, default `${cwd}/source`
13
+ - META: path to the meta folder, default `${cwd}/meta`
14
+ - BUILD: path to the build folder, default `${cwd}/build`
15
+
16
+ # Running
17
+
18
+ ## Run once, converting source folder into static html
19
+
20
+ ```npm start```
21
+
22
+ Defaults:
23
+ - source: the "source" directory in cwd
24
+ - meta: the "meta" directory in cwd
25
+ - output: the "build" directory in cwd
26
+
27
+ This is not very useful. Will make these configurable.
28
+
29
+
30
+ # Inputs and Outputs
31
+
32
+ SOURCE folder should have at least an index.md in it
package/TODO.md ADDED
@@ -0,0 +1,16 @@
1
+ # Basic Functionality
2
+
3
+ - [x] Enable static assets from meta in build (perhaps by copying them?)
4
+ - [x] Enable static assets from source in build
5
+ - [ ] Handle menus at different levels
6
+ - [x] Add a live-serve command that translates from source in real time (for testing)
7
+ - [ ] Deal with crashes when no menu file is found
8
+
9
+
10
+ # Wikitext
11
+ - [ ] Support original site styles
12
+ - [ ] Support original menu
13
+ - [ ] Fix links
14
+
15
+ # Mobile UI
16
+ - [ ] Konsta UI
package/lib/index.js ADDED
@@ -0,0 +1,9 @@
1
+ import { generate } from "../src/jobs/generate.js";
2
+
3
+ export default function generateSite({ source, meta, output }) {
4
+ if (!source) throw new Error("source is required");
5
+ if (!meta) throw new Error("meta is required");
6
+ if (!output) throw new Error("output is required");
7
+
8
+ generate({ source, meta, output });
9
+ }
@@ -0,0 +1,10 @@
1
+ a, .appear-as-link {
2
+ color: #136ac1;
3
+ cursor: pointer;
4
+ text-decoration: none;
5
+ transition: filter 0.3s, text-shadow 0.3;
6
+ }
7
+ a:hover, .appear-as-link:hover {
8
+ filter: brightness(2);
9
+ text-shadow: 0px 0px 3px rgb(255 255 255 / 25%);
10
+ }
@@ -0,0 +1,37 @@
1
+ export function CharacterSheet({ character }) {
2
+ return `<div class="character-sheet">
3
+ ${Attributes({ attributes: character.attributes })}
4
+ </div>`;
5
+ }
6
+ function Attributes({ attributes }) {
7
+ return `<div class="attributes">
8
+ <header>Attributes</header>
9
+ <table>
10
+ ${attributes
11
+ .map((attribute) => Attribute({ attribute }))
12
+ .join("")}
13
+ </table>
14
+ </div>`;
15
+ }
16
+ function Attribute({ attribute }) {
17
+ return `<tr>
18
+ <td>${attribute.name}</td>
19
+ <td>${Modifier({ attribute })}</td>
20
+ </tr>`;
21
+ }
22
+ function Modifier({ attribute }) {
23
+ const modifierLabel = renderModifierLabel(attribute.modifier);
24
+ const components = Object.entries(attribute.components)
25
+ .map(([key, val]) => `${key}: ${val}`)
26
+ .join("\n");
27
+
28
+ return `<span class="appear-as-link" title="${components}">${modifierLabel}</span>`;
29
+
30
+ function renderModifierLabel(modifier) {
31
+ if (isNaN(modifier)) return "?";
32
+ if (modifier > 0) return `+${modifier}`;
33
+ if (modifier === 0) return "+0";
34
+ if (modifier < 0) return modifier;
35
+ return "??";
36
+ }
37
+ }
@@ -0,0 +1,7 @@
1
+ import { CharacterSheet } from "./components.js";
2
+ import { createCharacterFromYamlObject } from "./model.js";
3
+
4
+ const yamlObject = window.meta.character;
5
+ const character = createCharacterFromYamlObject(yamlObject);
6
+ const characterHtml = CharacterSheet({ character });
7
+ document.querySelector("article").innerHTML = characterHtml;
@@ -0,0 +1,15 @@
1
+ export function createCharacterFromYamlObject(yamlObject) {
2
+ let character = Object.assign({}, yamlObject);
3
+ // TODO: validate character here
4
+ processAttributes(character);
5
+ return yamlObject;
6
+ }
7
+
8
+ function processAttributes(character) {
9
+ character.attributes.forEach((attribute) => {
10
+ attribute.modifier = Object.values(attribute.components).reduce(
11
+ (p, c) => p + c,
12
+ 0
13
+ );
14
+ });
15
+ }
@@ -0,0 +1,76 @@
1
+ <html>
2
+
3
+ <head>
4
+ <link rel="stylesheet" href="/public/default.css" />
5
+ <link rel="stylesheet" href="/public/cssui.bundle.min.css" />
6
+ <link rel="stylesheet" href="/public/character-sheet.css" />
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
8
+ <style>
9
+
10
+ </style>
11
+ </head>
12
+
13
+ <body data-template-id="character-sheet">
14
+ <nav id="nav-main">
15
+ <span id="menu-icon" class="material-symbols-outlined">
16
+ menu
17
+ </span>
18
+ ${menu}
19
+ </nav>
20
+ <nav id="tabs" level="2">
21
+ <!-- <ul>
22
+ <li><a href="#article">Article</a></li>
23
+ <li><a href="#character-sheet">Character Sheet</a></li>
24
+ </ul> -->
25
+
26
+ </nav>
27
+ <article>
28
+ <div id="tab-container" data-tabs>
29
+ <input checked="checked" id="tab1" type="radio" name="tab" data-tab="tab1" />
30
+ <input id="tab2" type="radio" name="tab" data-tab="tab2" />
31
+ <nav>
32
+ <label for="tab1" data-tab-label="tab1" role="tab">Article</label>
33
+ <label for="tab2" data-tab-label="tab2" role="tab">Character Sheet</label>
34
+ </nav>
35
+ <section data-tab-panel="tab1" role="tabpanel" aria-labelledby="tab1">
36
+ ${body}
37
+ </section>
38
+ <section data-tab-panel="tab2" role="tabpanel" aria-labelledby="tab2">
39
+ ${transformedMetadata}
40
+ </section>
41
+ </div>
42
+ </article>
43
+ <div id="global-nav">
44
+ global nav here
45
+ </div>
46
+
47
+ <script src="https://cdn.ably.com/lib/ably.min-1.js"></script>
48
+ <script>
49
+ const COMPROMISED_CLIENT_SIDE_SECRET_API_KEY =
50
+ 'thisiswheretheapikeywouldgoIFIHADONE';
51
+ const CHAT_CHANNEL_NAME = 'chat-channel';
52
+
53
+ var client = new Ably.Realtime(COMPROMISED_CLIENT_SIDE_SECRET_API_KEY);
54
+ let channel;
55
+ client.connection.on('connected', function () {
56
+ channel = client.channels.get(CHAT_CHANNEL_NAME);
57
+ channel.subscribe(function (message) {
58
+ // message.name; // 'greeting'
59
+ // message.data; // 'Hello World!'
60
+ });
61
+ });
62
+
63
+ function roll(mod) {
64
+ const d20 = Math.ceil(Math.random() * 20);
65
+ const result = d20 + mod;
66
+ body = `Rolled a ${d20} with a modifier of ${mod}. Result is ${result}.`;
67
+ channel.publish('test-message', {
68
+ author: 'me',
69
+ datetime: new Date(),
70
+ body,
71
+ });
72
+ }
73
+ </script>
74
+ </body>
75
+
76
+ </html>
@@ -0,0 +1,50 @@
1
+ nav#tabs {
2
+ position: absolute;
3
+ top: 0;
4
+ left: calc(50% - 20em);
5
+ background: rgba(255,255,255,0.1);
6
+ height: 40px;
7
+ }
8
+
9
+ nav#tabs li {
10
+ display: inline-block;
11
+ }
12
+ nav#tabs li a {
13
+ background: rgba(255,255,255,0.1);
14
+ height: 40px;
15
+ line-height: 40px;
16
+ }
17
+
18
+ article {
19
+ box-sizing: content-box;
20
+
21
+ }
22
+
23
+ div#tab-container {
24
+ --tab-panel-background: transparent;
25
+ --tab-background-color: rgba(255,255,255,0.25) !important;
26
+ }
27
+
28
+ [data-tab=tab1]:checked~nav [data-tab-label=tab1], [data-tab=tab2]:checked~nav [data-tab-label=tab2], [data-tab=tab3]:checked~nav [data-tab-label=tab3] {
29
+ --tab-background-color: rgba(255,255,255,0.55) !important;
30
+ }
31
+
32
+ #character-sheet .rollable {
33
+ display: inline-block;
34
+ position: relative;
35
+ left: 3px;
36
+ transition: filter 0.3s, transform 0.3s;
37
+
38
+ animation-play-state: paused;
39
+ }
40
+ #character-sheet .rollable:hover {
41
+ filter: brightness(1.5);
42
+ transform: scale(1.1);
43
+ animation-play-state: running;
44
+ }
45
+
46
+ #character-sheet .rollable .hexagon {
47
+ position: absolute;
48
+ top: 0px;
49
+ left: -7.5px;
50
+ }
@@ -0,0 +1,11 @@
1
+ :root{--cssui-animation-rotate:rotate(-180deg);--cssui-animation-timing:.25s;--cssui-font-family:-apple-system,blinkmacsystemfont,"Segoe UI",roboto,"Helvetica Neue",arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--cssui-gray-lighter:#e5e7eb;--cssui-gray-light:#d1d5db;--cssui-gray-dark:#4b5563;--cssui-gray-darkest:#1f2937;--cssui-primary:#14b8a6;--cssui-padding:1rem;--cssui-radius:4px}*{box-sizing:border-box}body{font-family:var(--cssui-font-family);margin:0}
2
+ [data-accordion]{--accordion-border-color:var(--cssui-gray-lighter);--accordion-panel-background:#fff;--accordion-panel-padding:var(--cssui-padding);--accordion-panel-text-color:var(--cssui-gray-darkest);--accordion-title-background:#fff;--accordion-title-spacing:1rem;--accordion-title-color:var(--cssui-gray-dark);border:1px solid var(--accordion-border-color);border-radius:var(--cssui-radius)}[data-accordion-item]{width:100%}[data-accordion-item]:not(:last-child){border-bottom:1px solid var(--accordion-border-color)}[data-accordion-item]>input{opacity:0;position:absolute;z-index:-1}[data-accordion-item]>label{align-items:center;background:var(--accordion-title-background);color:var(--accordion-title-color);cursor:pointer;display:flex;font-weight:700;justify-content:space-between;padding:var(--accordion-title-spacing)}[data-accordion-item]>input:checked+label,[data-accordion-item]>label:hover{--accordion-title-color:var(--cssui-gray-darkest);--accordion-title-background:var(--cssui-gray-lighter)}[data-accordion-item]>input:checked+label:hover{--accordion-title-background:var(--cssui-gray-light)}[data-accordion-item]>input:focus+label{outline:2px solid #101010;outline:2px solid highlight;outline:2px solid -webkit-focus-ring-color}[data-accordion-item]>input:focus:not(:focus-visible)+label{outline:none}[data-accordion-item]>label>svg{transition:all var(--cssui-animation-timing) ease-out}[data-accordion-panel]{background:var(--accordion-panel-background);color:var(--accordion-panel-text-color);max-height:0;padding:0 var(--accordion-panel-padding);transition:padding var(--cssui-animation-timing) ease;visibility:hidden}[data-accordion-item]>input:checked+label>svg{transform:rotate(-180deg)}[data-accordion-item]>input:checked~[data-accordion-panel]{max-height:100vh;padding:var(--accordion-panel-padding);visibility:visible}
3
+ [data-dropdown]{--dropdown-border-radius:var(--cssui-radius);--dropdown-border-color:var(--cssui-gray-light);--dropdown-link-background:var(--cssui-gray-lighter);--dropdown-link-color:var(--cssui-gray-darkest);--dropdown-panel-background:#fff;--dropdown-padding:var(--cssui-padding);border:1px solid var(--dropdown-border-color);border-radius:var(--dropdown-border-radius);position:relative;width:auto}[data-dropdown] summary{padding:var(--dropdown-padding);position:relative}[data-dropdown] summary:hover{background:var(--cssui-gray-lighter);cursor:pointer}[data-dropdown] summary::-webkit-details-marker{display:none}[data-dropdown] summary:focus{outline-width:3px}[data-dropdown] summary:after{border-bottom:0;border-left:.3rem solid transparent;border-right:.3rem solid transparent;border-top:.3rem solid;content:"";display:inline-block;margin-left:.255rem;position:absolute;right:var(--dropdown-padding);top:calc(var(--dropdown-padding)*1.75);vertical-align:.255rem}[data-dropdown][open] summary:after{transform:rotate(-180deg)}[data-dropdown] ul{background:var(--dropdown-panel-background);list-style:none;margin:0;padding-left:0}[data-dropdown] li{border-top:var(--dropdown-border,0) solid var(--dropdown-border-color);margin:0;padding:0}[data-dropdown] li>a{color:var(--dropdown-link-color);display:block;padding:var(--dropdown-padding);text-decoration:none}[data-dropdown] li>a:hover{background-color:var(--dropdown-link-background)}
4
+ [data-fullpage]{--fullpage-height:100vh;--fullpage-direction:x;--fullpage-scroll:mandatory;--slide-background:#cbd5e1;--slide-content-padding:calc(var(--slide-padding)*2);--slide-size:100%;--slide-snap-align:start;--slide-padding:2rem;--slide-arrow-color:#000;--slide-arrow-size:.675rem;height:var(--fullpage-height);position:relative;width:100%}[data-slides]{-webkit-overflow-scrolling:touch;display:flex;height:100%;overflow-x:scroll;position:relative;scroll-behavior:smooth;-ms-scroll-snap-type:var(--fullpage-direction) var(--fullpage-scroll);scroll-snap-type:var(--fullpage-direction) var(--fullpage-scroll);z-index:0}[data-slides]>[data-slide]{background-color:var(--slide-background);box-sizing:border-box;min-height:100%;min-width:var(--slide-size);padding:var(--slide-padding);position:relative;scroll-snap-align:var(--slide-snap-align)}[data-slides] [data-slide-content]{padding:var(--slide-content-padding)}[data-slides]>[data-slide]:first-child{--slide-background:#6ee7b7}[data-slides]>[data-slide]:nth-child(2){--slide-background:#67e8f9}[data-slides]>[data-slide]:nth-child(3){--slide-background:#93c5fd}[data-slides]>[data-slide]:nth-child(4){--slide-background:#c4b5fd}[data-fullpage]:after,[data-fullpage]:before{border:solid var(--slide-arrow-color);border-width:0 3px 3px 0;content:"";display:block;outline:0;padding:var(--slide-arrow-size);pointer-events:none;position:absolute;top:calc(50% - var(--slide-arrow-size));transform:translateY(-50%);z-index:1}[data-fullpage]:before{left:calc(var(--slide-padding) + var(--slide-arrow-size));transform:rotate(135deg);-webkit-transform:rotate(135deg)}[data-slides]>[data-slide="1"]~[data-fullpage]:before{display:none}[data-fullpage]:after{right:calc(var(--slide-padding) + var(--slide-arrow-size));transform:rotate(-45deg);-webkit-transform:rotate(-45deg)}[data-slide-arrow]{display:block;font-size:0;height:2rem;position:absolute;top:50%;transform:translateY(-50%);width:2rem;z-index:100}[data-slide-arrow=next]{right:var(--slide-padding)}[data-slide-arrow=prev]{left:var(--slide-padding)}
5
+ [data-modal]{--modal-background:#fff;--modal-level:9999;--modal-max-size:500px;--modal-overlay-background:rgba(0,0,0,.2);--modal-radius:8px;--modal-size:80%;--modal-spacing:1rem;align-items:center;display:flex;justify-content:center;opacity:0;transition:opacity .3s ease;visibility:hidden}[data-modal-overlay],[data-modal]{bottom:0;left:0;position:fixed;right:0;top:0}[data-modal-overlay]{background-color:var(--modal-overlay-background)}[data-modal-dialog]{background-color:var(--modal-background);border-radius:var(--modal-radius);max-width:var(--modal-max-size);opacity:0;padding:var(--modal-spacing);transform:translateY(-1rem);transition:opacity .3s ease,transform .3s ease;transition-delay:.2s;width:var(--modal-size);z-index:var(--modal-level)}[data-modal]:target{opacity:1;visibility:visible;z-index:var(--modal-level)}[data-modal]:target [data-modal-dialog]{opacity:1;transform:translateY(0)}[data-modal-close]{color:var(--cssui-gray-darkest);position:absolute;right:var(--modal-spacing);top:var(--modal-spacing)}
6
+ [data-range]{--range-thumb-color:var(--cssui-primary);--range-thumb-height:25px;--range-thumb-width:25px;--range-track-height:auto;--range-track-color:var(--cssui-gray-light);-webkit-appearance:none;background:var(--range-track-color);border-radius:var(--range-track-radius,0);height:var(--range-track-height);margin:1rem 0;outline:none;width:100%}[data-range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background:var(--range-thumb-color);border-radius:var(--range-thumb-radius,0);box-shadow:0 0 3px var(--cssui-gray-light);cursor:pointer;height:var(--range-thumb-height);-webkit-transition:background .2s ease;transition:background .2s ease;width:var(--range-thumb-width)}[data-range]::-moz-range-thumb{background:var(--range-thumb-color);border-radius:var(--range-thumb-radius,0);cursor:pointer;height:var(--range-thumb-height);-moz-transition:background .2s ease;transition:background .2s ease;width:var(--range-thumb-width)}[data-range=rounded]{--range-track-radius:4px;--range-track-height:10px;--range-thumb-radius:50%}[data-range]::-webkit-slider-thumb:hover{--range-thumb-color:var(--cssui-gray-darkest)}
7
+ [data-slideout-panel]{--slideout-animation:left .2s ease-in-out;--slideout-background:#fff;--slideout-shadow-color:#9ca3af;--slideout-padding:1rem;--slideout-position:-100%;--slideout-size:33vw;background:var(--slideout-background);bottom:0;box-shadow:0 4px 20px var(--slideout-shadow-color);left:var(--slideout-position);padding:var(--slideout-padding);position:fixed;top:0;transition:var(--slideout-animation);visibility:hidden;width:var(--slideout-size);z-index:9999}[data-slideout-panel]:target{--slideout-position:0;visibility:visible}[data-slideout-header]{align-items:center;display:flex;justify-content:space-between}[data-slideout-close]{color:var(--cssui-gray-darkest)}
8
+ [data-tabs]{--tab-border-color:#f3f4f6;--tab-panel-background:#fff;--tab-border-bottom-color:#9ca3af;--tab-border-bottom-width:2px;--tab-spacing:1rem .5rem}[data-tab]{opacity:0;pointer-events:none;position:absolute}[data-tab-panel]{background-color:var(--tab-panel-background);height:0;opacity:0;position:relative;transition:opacity .3s ease-in-out;visibility:hidden;z-index:1}nav{border-bottom:1px solid #d1d5db;display:flex}[data-tab-label]{background-color:var(--tab-background-color,none);border-bottom:var(--tab-border-bottom-width,0) solid transparent;border-top-left-radius:var(--tab-radius,0);border-top-right-radius:var(--tab-radius,0);bottom:-1px;cursor:pointer;padding:var(--tab-spacing,0);position:relative}[data-tab-label]:hover{border-bottom-color:var(--tab-border-bottom-color)}[data-tab=tab1]:checked~nav [data-tab-label=tab1],[data-tab=tab2]:checked~nav [data-tab-label=tab2],[data-tab=tab3]:checked~nav [data-tab-label=tab3]{--tab-background-color:#fff;border-bottom-color:#1d4ed8;box-shadow:var(--tab-active-shadow,0);z-index:10}[data-tab=tab1]:focus~nav [data-tab-label=tab1],[data-tab=tab2]:focus~nav [data-tab-label=tab2],[data-tab=tab3]:focus~nav [data-tab-label=tab3]{outline:2px auto #101010;outline:2px auto Highlight;outline:2px auto -webkit-focus-ring-color}[data-tab=tab1]:focus:not(:focus-visible)~nav [data-tab-label=tab1],[data-tab=tab2]:focus:not(:focus-visible)~nav [data-tab-label=tab2],[data-tab=tab3]:focus:not(:focus-visible)~nav [data-tab-label=tab3]{outline:none}[data-tab=tab1]:checked~nav~[data-tab-panel=tab1],[data-tab=tab2]:checked~nav~[data-tab-panel=tab2],[data-tab=tab3]:checked~nav~[data-tab-panel=tab3]{border:1px solid var(--tab-panel-border-color);height:auto;opacity:1;padding:var(--tab-spacing);visibility:visible;width:100%}
9
+ [data-toggle]{--toggle-width:60px;--toggle-height:calc(var(--toggle-width)/2);--toggle-radius:18px;--toggle-background:var(--cssui-gray-light);--toggle-padding:10px;--toggle-animation:ease-in-out;--toggle-animation-time:.2s;--toggle-switch-color:#fff;background:var(--toggle-background);border-radius:var(--toggle-radius);cursor:pointer;display:block;height:var(--toggle-height);padding:var(--toggle-padding);position:relative;width:var(--toggle-width)}[data-toggle-input],[data-toggle-input]:active{display:none}[data-toggle]:before{background:var(--toggle-switch-color);border-radius:100%;content:"";display:block;height:var(--toggle-height);left:0;line-height:34px;position:absolute;right:auto;text-indent:var(--toggle-height);top:0;transition:left var(--toggle-animation-time) var(--toggle-animation);width:var(--toggle-height);z-index:1}[data-toggle-input]+[data-toggle]{box-shadow:inset 0 0 0 0 var(--cssui-primary),0 0 0 2px var(--toggle-background)}[data-toggle-input]:checked+[data-toggle]:before{box-shadow:0 0 0 2px transparent,0 3px 3px rgba(0,0,0,.3);left:calc(100% - var(--toggle-height))}[data-toggle-input]:checked+[data-toggle]{box-shadow:inset 0 0 0 18px var(--cssui-primary),0 0 0 2px var(--cssui-primary)}
10
+ [data-tooltip]{--tooltip-background:var(--cssui-gray-darkest);--tooltip-padding:4px 6px;--tooltip-text-color:var(--cssui-gray-light);--tooltip-fontsize:.75rem;position:relative}[data-tooltip]:after,[data-tooltip]:before{opacity:0;transition:opacity .3s ease}[data-tooltip]:after{background-color:var(--tooltip-background);border-radius:var(--tooltip-radius,0);bottom:calc(100% + 2px);color:var(--tooltip-text-color);content:attr(title);display:inline-block;font-size:var(--tooltip-fontsize);left:50%;padding:var(--tooltip-padding);position:absolute;transform:translateX(-50%);white-space:nowrap;width:auto}[data-tooltip]:focus:after,[data-tooltip]:focus:before,[data-tooltip]:hover:after,[data-tooltip]:hover:before{opacity:1}[data-tooltip]:before{border-left:6px solid transparent;border-right:6px solid transparent;border-top:5px solid var(--tooltip-background);bottom:calc(100% - 2px);content:"";height:0;left:50%;position:absolute;transform:translateX(-50%);width:0}
11
+ /*# sourceMappingURL=cssui.bundle.min.css.map */
@@ -0,0 +1,22 @@
1
+ <html>
2
+
3
+ <head>
4
+ <link rel="stylesheet" href="/public/default.css" />
5
+ </head>
6
+
7
+ <body data-template-id="default">
8
+ <nav id="nav-main">
9
+ <span id="menu-icon" class="material-symbols-outlined">
10
+ menu
11
+ </span>
12
+ ${menu}
13
+ </nav>
14
+ <article>
15
+ ${body}
16
+ </article>
17
+ <div id="global-nav">
18
+ global nav here
19
+ </div>
20
+ </body>
21
+
22
+ </html>
@@ -0,0 +1,154 @@
1
+ @import url("https://fonts.googleapis.com/css2?family=Work+Sans:wght@100;300;400;600&display=swap");
2
+ @import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200");
3
+
4
+ body {
5
+ background-color: #123;
6
+ color: #ccc;
7
+ font-family: "Work Sans", sans-serif;
8
+ }
9
+ article {
10
+ max-width: 40em;
11
+ margin: 0 auto;
12
+ padding: 5em;
13
+ box-shadow: 0px 0px 5px 2px rgba(0, 0, 0, 0.3);
14
+ background-color: rgba(0, 0, 0, 0.15);
15
+ }
16
+ article aside {
17
+ float: right;
18
+ border: 1px solid #234;
19
+ margin: 0 0 20px 20px;
20
+ padding: 20px;
21
+ max-width: 40%;
22
+ }
23
+ article aside img {
24
+ max-width: 100%;
25
+ }
26
+ article a {
27
+ color: #136ac1;
28
+ text-decoration: none;
29
+ }
30
+
31
+ nav#nav-main {
32
+ position: fixed;
33
+ max-width: calc(50vw - 28rem);
34
+ left: 1rem;
35
+ top: 1rem;
36
+ font-weight: 300;
37
+ }
38
+ nav#nav-main a {
39
+ text-decoration: none;
40
+ box-sizing: border-box;
41
+ color: inherit;
42
+ display: inline-block;
43
+ padding: 0.15rem 1rem;
44
+ width: 100%;
45
+ position: relative;
46
+ }
47
+ nav#nav-main a:hover {
48
+ /* color: #7070b7; */
49
+ }
50
+ nav#nav-main ul {
51
+ margin: 0;
52
+ padding: 0;
53
+ }
54
+ nav#nav-main li {
55
+ list-style: none;
56
+ }
57
+ nav#nav-main ul ul {
58
+ display: none;
59
+ position: absolute;
60
+ background-color: #123;
61
+ /* padding: 10px; */
62
+ left: 100%;
63
+ top: 0;
64
+ height: 100%;
65
+ min-width: 100%;
66
+ overflow: auto;
67
+ }
68
+ nav#nav-main li {
69
+ /* position: relative; */
70
+ }
71
+ nav#nav-main li:hover > ul {
72
+ display: block;
73
+ background-color: rgba(255, 255, 255, 0.1);
74
+ }
75
+ nav#nav-main li:hover {
76
+ background-color: rgba(255, 255, 255, 0.1);
77
+ }
78
+ nav#nav-main li li {
79
+ width: 100%;
80
+ white-space: nowrap;
81
+ }
82
+ nav#nav-main li[data-has-children="true"] > a::after {
83
+ content: ">";
84
+ position: absolute;
85
+ top: 5px;
86
+ right: 2px;
87
+ opacity: 0.5;
88
+ font-size: 70%;
89
+ }
90
+
91
+ #global-nav {
92
+ position: fixed;
93
+ max-width: calc(50vw - 28rem);
94
+ left: 1rem;
95
+ bottom: 1rem;
96
+ font-weight: 300;
97
+ }
98
+
99
+ @media screen and (min-width:1200px) {
100
+ nav#nav-main #menu-icon {
101
+ display: none;
102
+ }
103
+ nav#mobile-menu {
104
+ display: none;
105
+ }
106
+ nav#desktop-menu {
107
+ display: block;
108
+ }
109
+ }
110
+
111
+ @media screen and (max-width:1199px) {
112
+ nav#mobile-menu {
113
+ display: block;
114
+ }
115
+ nav#desktop-menu {
116
+ display: none;
117
+ }
118
+ nav#nav-main {
119
+ font-size: 3rem;
120
+ }
121
+ nav#nav-main ul {
122
+ background-color: #123;
123
+ width: calc(100vw - 32px);
124
+ height: calc(100vw - 32px);
125
+ }
126
+ nav#nav-main > ul {
127
+ display: block; /* temp! */
128
+ }
129
+ nav#nav-main #menu-icon {
130
+ display: block;
131
+ }
132
+ nav#nav-main:hover > ul {
133
+ display: block;
134
+ }
135
+ article {
136
+ max-width: 100%;
137
+ }
138
+ nav#nav-main li {
139
+ position: relative;
140
+ }
141
+ nav#nav-main ul ul {
142
+ top: 100%;
143
+ left: 0;
144
+ }
145
+ }
146
+
147
+
148
+ .material-symbols-outlined {
149
+ font-variation-settings:
150
+ 'FILL' 0,
151
+ 'wght' 400,
152
+ 'GRAD' 0,
153
+ 'opsz' 48
154
+ }
@@ -0,0 +1 @@
1
+ foo bar
package/nodemon.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "restartable": "rs",
3
+ "ignore": [".git", "node_modules/**/node_modules", "build"],
4
+ "verbose": true,
5
+ "execMap": {
6
+ "js": "node --harmony"
7
+ },
8
+ "events": {
9
+ "restart": "osascript -e 'display notification \"App restarted due to:\n'$FILENAME'\" with title \"nodemon\"'"
10
+ },
11
+ "watch": ["src/", "docs/"],
12
+ "env": {
13
+ "NODE_ENV": "development"
14
+ },
15
+ "ext": "js,json,css,cjs,mjs,ts,tsx,html"
16
+ }
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@kenjura/ursa",
3
+ "author": "Andrew London <andrew@kenjura.com>",
4
+ "type": "module",
5
+ "version": "0.5.0",
6
+ "description": " static site generator from MD/wikitext/YML",
7
+ "main": "lib/index.js",
8
+ "scripts": {
9
+ "serve": "nodemon --config nodemon.json src/serve.js",
10
+ "serve:debug": "nodemon --config nodemon.json --inspect-brk src/serve.js",
11
+ "start": "node src/index.js",
12
+ "test": "echo \"Error: no test specified\" && exit 1"
13
+ },
14
+ "license": "ISC",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/kenjura/ursa.git"
18
+ },
19
+ "dependencies": {
20
+ "directory-tree": "^3.3.2",
21
+ "express": "^4.18.2",
22
+ "fs-extra": "^10.1.0",
23
+ "markdown-it": "^12.3.2",
24
+ "markdown-it-container": "^3.0.0",
25
+ "markdown-it-deflist": "^2.1.0",
26
+ "markdown-it-front-matter": "^0.2.3",
27
+ "markdown-it-sup": "^1.0.0",
28
+ "node-static": "github:cloudhead/node-static",
29
+ "node-watch": "^0.7.3",
30
+ "object-to-xml": "^2.0.0",
31
+ "recursive-readdir": "github:kenjura/recursive-readdir",
32
+ "yaml": "^2.1.3"
33
+ },
34
+ "devDependencies": {
35
+ "nodemon": "^2.0.15"
36
+ },
37
+ "bugs": {
38
+ "url": "https://github.com/kenjura/ursa/issues"
39
+ },
40
+ "homepage": "https://github.com/kenjura/ursa#readme",
41
+ "directories": {
42
+ "lib": "lib"
43
+ },
44
+ "keywords": [
45
+ "static-site",
46
+ "markdown"
47
+ ]
48
+ }
@@ -0,0 +1,25 @@
1
+ import yargs from 'yargs';
2
+
3
+ export function generate(argv) {
4
+ console.log({argv});
5
+ }
6
+
7
+
8
+ export function describeGenerate(yargs) {
9
+ return yargs
10
+ .option('sourceDir', {
11
+ alias: 's',
12
+ default: '.',
13
+ describe: 'path of source files (i.e. markdown, wikitext, yaml, etc)',
14
+ })
15
+ .option('meta', {
16
+ alias: 'm',
17
+ default: '.',
18
+ dsecribe: 'path of meta files (i.e. templates, styles, menu)',
19
+ })
20
+ .option('output', {
21
+ alias: 'o',
22
+ default: 'build',
23
+ dsecribe: 'path of output files (i.e. html)',
24
+ });
25
+ }
@@ -0,0 +1,38 @@
1
+ import { hasExt } from "../pathExtReader.js";
2
+ import { expect } from "chai";
3
+
4
+ describe("hasExt", () => {
5
+ it("returns true for /foo/bar.html", () => {
6
+ expect(hasExt("/foo/bar.html")).to.eq(true);
7
+ });
8
+ it("returns true for /foo/bar.md", () => {
9
+ expect(hasExt("/foo/bar.md")).to.eq(true);
10
+ });
11
+ it("returns true for /foo/bar.json", () => {
12
+ expect(hasExt("/foo/bar.json")).to.eq(true);
13
+ });
14
+ it("returns true for /bar.html", () => {
15
+ expect(hasExt("/bar.html")).to.eq(true);
16
+ });
17
+ it("returns true for /bar.html?query=string#anchor", () => {
18
+ expect(hasExt("/bar.html?query=string#anchor")).to.eq(true);
19
+ });
20
+ it("returns false for /foo/bar", () => {
21
+ expect(hasExt("/foo/bar")).to.eq(false);
22
+ });
23
+ it("returns false for /foo", () => {
24
+ expect(hasExt("/foo")).to.eq(false);
25
+ });
26
+ it("returns false for /foo/bar.", () => {
27
+ expect(hasExt("/foo/bar.")).to.eq(false);
28
+ });
29
+ it("returns false for /foo/bar?query=string#anchor", () => {
30
+ expect(hasExt("/foo/bar?query=string#anchor")).to.eq(false);
31
+ });
32
+ it("returns false for /", () => {
33
+ expect(hasExt("/")).to.eq(false);
34
+ });
35
+ it('returns false for ""', () => {
36
+ expect(hasExt("")).to.eq(false);
37
+ });
38
+ });