mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
try with manual writing
This commit is contained in:
@@ -5,6 +5,36 @@
|
||||
data-shoelace-version="{{ meta.version }}"
|
||||
>
|
||||
<head>
|
||||
<!--
|
||||
JSPM Generator Import Map
|
||||
Edit URL: https://generator.jspm.io/#jcs9DoMwDIbhDF16kW4kpFO7cYkeIASTGBmDEvNz+zaduhSJwdInvY9vF6Wub/ViQSHoVMQQqZzoITfW6qeuDWFr/JTgMJLjsLgA2ficT6jBrS77hLOcwPtIilCau37o+rdMhwm84FpIgr68/28LZ9dDFWWkQ7NF4G/coK38NM4TA0vVQY8MRdfa2g8tjhfiKAE
|
||||
-->
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"highlight.js/lib/core": "https://ga.jspm.io/npm:highlight.js@11.9.0/es/core.js",
|
||||
"highlight.js/lib/languages/css": "https://ga.jspm.io/npm:highlight.js@11.9.0/es/languages/css.js",
|
||||
"highlight.js/lib/languages/javascript": "https://ga.jspm.io/npm:highlight.js@11.9.0/es/languages/javascript.js",
|
||||
"highlight.js/lib/languages/xml": "https://ga.jspm.io/npm:highlight.js@11.9.0/es/languages/xml.js",
|
||||
"lit": "https://ga.jspm.io/npm:lit@2.8.0/index.js",
|
||||
"lit/directives/ref.js": "https://ga.jspm.io/npm:lit@2.8.0/directives/ref.js",
|
||||
"lit/directives/unsafe-html.js": "https://ga.jspm.io/npm:lit@2.8.0/directives/unsafe-html.js",
|
||||
"lit/directives/when.js": "https://ga.jspm.io/npm:lit@2.8.0/directives/when.js",
|
||||
"web-component-define": "https://ga.jspm.io/npm:web-component-define@2.0.11/src/index.js"
|
||||
},
|
||||
"scopes": {
|
||||
"https://ga.jspm.io/": {
|
||||
"@lit/reactive-element": "https://ga.jspm.io/npm:@lit/reactive-element@1.6.3/reactive-element.js",
|
||||
"@open-wc/dedupe-mixin": "https://ga.jspm.io/npm:@open-wc/dedupe-mixin@1.4.0/index.js",
|
||||
"lit-element/lit-element.js": "https://ga.jspm.io/npm:lit-element@3.3.3/lit-element.js",
|
||||
"lit-html": "https://ga.jspm.io/npm:lit-html@2.8.0/lit-html.js",
|
||||
"lit-html/": "https://ga.jspm.io/npm:lit-html@2.8.0/"
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<script async src="https://ga.jspm.io/npm:es-module-shims@1.8.0/dist/es-module-shims.js" crossorigin="anonymous"></script>
|
||||
{# Metadata #}
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script type="module">
|
||||
import "https://cdn.jsdelivr.net/npm/light-pen@1.1.2/+esm"
|
||||
<script type="module" src="/assets/scripts/light-pen/exports/index.js">
|
||||
</script>
|
||||
|
||||
<light-pen style="height: 100%; padding: 8px;" resize-position="30" sandbox-settings="
|
||||
|
||||
11
docs/assets/scripts/light-pen/CHANGELOG.md
Normal file
11
docs/assets/scripts/light-pen/CHANGELOG.md
Normal file
@@ -0,0 +1,11 @@
|
||||
## 1.1.0
|
||||
|
||||
- A number of fixes including allowing `<template>` elements to be slotted into `<light-pen>` and `<light-preview>`
|
||||
|
||||
## 1.0.2
|
||||
|
||||
- fix: issues with `>` and `<`
|
||||
|
||||
## 1.0.1
|
||||
|
||||
- fix: allow any HTML Element for templating
|
||||
21
docs/assets/scripts/light-pen/LICENSE
Normal file
21
docs/assets/scripts/light-pen/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Konnor Rogers
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
96
docs/assets/scripts/light-pen/README.md
Normal file
96
docs/assets/scripts/light-pen/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Light(weight) Code(pen)
|
||||
|
||||
## Demo
|
||||
|
||||
<https://konnorrogers.github.io/light-pen>
|
||||
|
||||
## Purpose
|
||||
|
||||
A small lightweight editor using `<pre><code></code></pre>` and a `<textarea>`
|
||||
|
||||
Inspired by Chris Ferdinandi
|
||||
|
||||
## Install
|
||||
|
||||
```
|
||||
npm install light-pen
|
||||
```
|
||||
|
||||
## Getting started
|
||||
|
||||
```js
|
||||
// Auto-register <light-pen>
|
||||
import "light-pen"
|
||||
|
||||
// Registry yourself
|
||||
import LightPen "light-pen/exports/light-pen.js"
|
||||
|
||||
LightPen.define() // Registers `<light-pen>`
|
||||
|
||||
// Register under another name
|
||||
import LightPen "light-pen/exports/light-pen.js"
|
||||
LightPen.define("other-name")
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```html
|
||||
<light-pen></light-pen>
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
|
||||
### Slotting in HTML / CSS / JS
|
||||
|
||||
```html
|
||||
<light-pen>
|
||||
<script type="text/plain" slot="html">
|
||||
<div style="color: red;">
|
||||
<div>Hi there friends</div>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Sup dude
|
||||
</p>
|
||||
</script>
|
||||
|
||||
<script type="text/plain" slot="css">
|
||||
p {
|
||||
color: green;
|
||||
}
|
||||
</script>
|
||||
|
||||
<script type="text/plain" slot="js">
|
||||
console.log("Hi")
|
||||
</script>
|
||||
</light-pen>
|
||||
```
|
||||
|
||||
### Changing the title
|
||||
|
||||
```html
|
||||
<light-pen>
|
||||
<div slot="title">My Awesome Editor</div>
|
||||
</light-pen>
|
||||
```
|
||||
|
||||
### Opening languages by default
|
||||
|
||||
`<light-pen>` Takes a string of comma separated languages to open on initial render.
|
||||
|
||||
```
|
||||
<light-pen open-languages="html,css,js">
|
||||
</light-pen>
|
||||
```
|
||||
|
||||
More to come for more docs coming on how to change things!
|
||||
|
||||
## Roadmap
|
||||
|
||||
- [ ] - Implement an extendable `LightPenBase` which includes a pluggable syntax highlighter and theme.
|
||||
- [ ] - Implement `<textarea>` rendering hooks to add CodeMirror for more robuste setups.
|
||||
- [ ] - Add vertical resizing of `<textarea>`
|
||||
- [ ] - More documentation around customization.
|
||||
- [ ] - Add a console logger
|
||||
>>>>>>> 7b592c8f5f05ed82d439d7950450eec06dc3ab66
|
||||
@@ -0,0 +1,44 @@
|
||||
// @ts-check
|
||||
// import { expandTypesPlugin } from './expand-types.js'
|
||||
|
||||
const globs = ['exports/**/*.{d.ts,js}', 'internal/**/*.{d.ts,js}', 'types/**/*.d.ts']
|
||||
|
||||
export default {
|
||||
/** Globs to analyze */
|
||||
globs,
|
||||
/** Globs to exclude */
|
||||
exclude: ['node_modules', 'docs'],
|
||||
/** Directory to output CEM to */
|
||||
outdir: '.',
|
||||
/** Run in dev mode, provides extra logging */
|
||||
dev: process.argv.includes("--verbose"),
|
||||
/** Run in watch mode, runs on file changes */
|
||||
watch: process.argv.includes("--watch"),
|
||||
/** Include third party custom elements manifests */
|
||||
dependencies: true,
|
||||
/** Output CEM path to `package.json`, defaults to true */
|
||||
packagejson: true,
|
||||
/** Enable special handling for litelement */
|
||||
litelement: true,
|
||||
/** Enable special handling for catalyst */
|
||||
catalyst: false,
|
||||
/** Enable special handling for fast */
|
||||
fast: false,
|
||||
/** Enable special handling for stencil */
|
||||
stencil: false,
|
||||
// overrideModuleCreation: ({ts, globs}) => {
|
||||
// const program = ts.createProgram(globs, {target: ts.ScriptTarget.ESNext, module: ts.ModuleKind.ESNext, allowJs: true, checkJs: true});
|
||||
//
|
||||
// // If we dont do this, everything blows up.
|
||||
// program.getTypeChecker()
|
||||
//
|
||||
// return program.getSourceFiles().filter(sf => globs.find(glob => {
|
||||
// return sf.fileName.includes(glob)
|
||||
// }))
|
||||
// },
|
||||
// /** Provide custom plugins */
|
||||
// plugins: [
|
||||
// /** You can now pass the typeChecker to your plugins */
|
||||
// expandTypesPlugin({ globs })
|
||||
// ],
|
||||
}
|
||||
1984
docs/assets/scripts/light-pen/custom-elements.json
Normal file
1984
docs/assets/scripts/light-pen/custom-elements.json
Normal file
File diff suppressed because it is too large
Load Diff
38
docs/assets/scripts/light-pen/docs/.gitignore
vendored
Normal file
38
docs/assets/scripts/light-pen/docs/.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
# Bridgetown
|
||||
output
|
||||
.bridgetown-cache
|
||||
.bridgetown-metadata
|
||||
.bridgetown-webpack
|
||||
|
||||
# Dependency folders
|
||||
node_modules
|
||||
bower_components
|
||||
vendor
|
||||
|
||||
# Caches
|
||||
.sass-cache
|
||||
.npm
|
||||
.node_repl_history
|
||||
|
||||
# Ignore bundler config.
|
||||
/.bundle
|
||||
|
||||
# Ignore Byebug command history file.
|
||||
.byebug_history
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# Mac files
|
||||
.DS_Store
|
||||
|
||||
# Yarn
|
||||
yarn-error.log
|
||||
yarn-debug.log*
|
||||
.pnp/
|
||||
.pnp.js
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
src/bridgetown
|
||||
src/meta.json
|
||||
1
docs/assets/scripts/light-pen/docs/.ruby-version
Normal file
1
docs/assets/scripts/light-pen/docs/.ruby-version
Normal file
@@ -0,0 +1 @@
|
||||
ruby-3.0.4
|
||||
49
docs/assets/scripts/light-pen/docs/Gemfile
Normal file
49
docs/assets/scripts/light-pen/docs/Gemfile
Normal file
@@ -0,0 +1,49 @@
|
||||
source "https://rubygems.org"
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
####
|
||||
# Welcome to your project's Gemfile, used by Rubygems & Bundler.
|
||||
#
|
||||
# To install a plugin, run:
|
||||
#
|
||||
# bundle add new-plugin-name -g bridgetown_plugins
|
||||
#
|
||||
# This will ensure the plugin is added to the correct Bundler group.
|
||||
#
|
||||
# When you run Bridgetown commands, we recommend using a binstub like so:
|
||||
#
|
||||
# bin/bridgetown start (or console, etc.)
|
||||
#
|
||||
# This will help ensure the proper Bridgetown version is running.
|
||||
####
|
||||
|
||||
# If you need to upgrade/switch Bridgetown versions, change the line below
|
||||
# and then run `bundle update bridgetown`
|
||||
gem "bridgetown", "~> 1.3"
|
||||
|
||||
# Uncomment to add file-based dynamic routing to your project:
|
||||
# gem "bridgetown-routes", "~> 1.3"
|
||||
|
||||
# Uncomment to use the Inspectors API to manipulate the output
|
||||
# of your HTML or XML resources:
|
||||
gem "nokogiri", "~> 1.13"
|
||||
|
||||
# Puma is a Rack-compatible server used by Bridgetown
|
||||
# (you can optionally limit this to the "development" group)
|
||||
gem "puma", "~> 5.6"
|
||||
|
||||
gem "bridgetown-quick-search", "~> 2.0"
|
||||
|
||||
# gem "asset_mapper", "~> 1.0"
|
||||
gem "asset_mapper", "~> 1.0"
|
||||
|
||||
# gem "rack-cors", "~> 2.0"
|
||||
|
||||
gem "rack-cors", "~> 2.0"
|
||||
|
||||
gem "custom_elements_manifest_parser", "~> 0.2.4"
|
||||
|
||||
gem "ruby-lsp", "~> 0.11.1", :group => :development, require: false
|
||||
gem "yard", "~> 0.9.34", :group => :development
|
||||
gem "solargraph", "~> 0.49.0", :group => :development
|
||||
gem "debug", "~> 1.8", :group => :development
|
||||
241
docs/assets/scripts/light-pen/docs/Gemfile.lock
Normal file
241
docs/assets/scripts/light-pen/docs/Gemfile.lock
Normal file
@@ -0,0 +1,241 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activemodel (7.0.8)
|
||||
activesupport (= 7.0.8)
|
||||
activesupport (7.0.8)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
tzinfo (~> 2.0)
|
||||
addressable (2.8.5)
|
||||
public_suffix (>= 2.0.2, < 6.0)
|
||||
amazing_print (1.5.0)
|
||||
asset_mapper (1.0.1)
|
||||
dry-configurable (~> 1.0)
|
||||
dry-files (~> 1.0)
|
||||
dry-initializer (~> 3.0)
|
||||
dry-types (~> 1.5)
|
||||
rake (>= 10)
|
||||
zeitwerk (~> 2.5)
|
||||
ast (2.4.2)
|
||||
backport (1.2.0)
|
||||
base64 (0.1.1)
|
||||
benchmark (0.2.1)
|
||||
bridgetown (1.3.1)
|
||||
bridgetown-builder (= 1.3.1)
|
||||
bridgetown-core (= 1.3.1)
|
||||
bridgetown-paginate (= 1.3.1)
|
||||
bridgetown-builder (1.3.1)
|
||||
bridgetown-core (= 1.3.1)
|
||||
bridgetown-core (1.3.1)
|
||||
activemodel (>= 6.0, < 8.0)
|
||||
activesupport (>= 6.0, < 8.0)
|
||||
addressable (~> 2.4)
|
||||
amazing_print (~> 1.2)
|
||||
colorator (~> 1.0)
|
||||
erubi (~> 1.9)
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects (~> 0.3)
|
||||
hash_with_dot_access (~> 1.2)
|
||||
i18n (~> 1.0)
|
||||
kramdown (~> 2.1)
|
||||
kramdown-parser-gfm (~> 1.0)
|
||||
liquid (~> 5.0)
|
||||
listen (~> 3.0)
|
||||
rake (>= 13.0)
|
||||
roda (~> 3.46)
|
||||
rouge (~> 3.0)
|
||||
serbea (~> 1.0)
|
||||
thor (~> 1.1)
|
||||
tilt (~> 2.0)
|
||||
zeitwerk (~> 2.5)
|
||||
bridgetown-paginate (1.3.1)
|
||||
bridgetown-core (= 1.3.1)
|
||||
bridgetown-quick-search (2.0.0)
|
||||
bridgetown (>= 1.2.0.beta2, < 2.0)
|
||||
colorator (1.1.0)
|
||||
concurrent-ruby (1.2.2)
|
||||
custom_elements_manifest_parser (0.2.4)
|
||||
dry-struct (~> 1.0)
|
||||
dry-types (~> 1.0)
|
||||
dry-validation (~> 1.0)
|
||||
debug (1.8.0)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
diff-lcs (1.5.0)
|
||||
dry-configurable (1.1.0)
|
||||
dry-core (~> 1.0, < 2)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-core (1.0.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-files (1.0.1)
|
||||
dry-inflector (1.0.0)
|
||||
dry-initializer (3.1.1)
|
||||
dry-logic (1.5.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-core (~> 1.0, < 2)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-schema (1.13.3)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-configurable (~> 1.0, >= 1.0.1)
|
||||
dry-core (~> 1.0, < 2)
|
||||
dry-initializer (~> 3.0)
|
||||
dry-logic (>= 1.4, < 2)
|
||||
dry-types (>= 1.7, < 2)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-struct (1.6.0)
|
||||
dry-core (~> 1.0, < 2)
|
||||
dry-types (>= 1.7, < 2)
|
||||
ice_nine (~> 0.11)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-types (1.7.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-core (~> 1.0)
|
||||
dry-inflector (~> 1.0)
|
||||
dry-logic (~> 1.4)
|
||||
zeitwerk (~> 2.6)
|
||||
dry-validation (1.10.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
dry-core (~> 1.0, < 2)
|
||||
dry-initializer (~> 3.0)
|
||||
dry-schema (>= 1.12, < 2)
|
||||
zeitwerk (~> 2.6)
|
||||
e2mmap (0.1.0)
|
||||
erubi (1.12.0)
|
||||
faraday (2.7.11)
|
||||
base64
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-follow_redirects (0.3.0)
|
||||
faraday (>= 1, < 3)
|
||||
faraday-net_http (3.0.2)
|
||||
ffi (1.15.5)
|
||||
hash_with_dot_access (1.2.0)
|
||||
activesupport (>= 5.0.0, < 8.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
ice_nine (0.11.2)
|
||||
io-console (0.6.0)
|
||||
irb (1.8.1)
|
||||
rdoc
|
||||
reline (>= 0.3.8)
|
||||
jaro_winkler (1.5.6)
|
||||
json (2.6.3)
|
||||
kramdown (2.4.0)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
language_server-protocol (3.17.0.3)
|
||||
liquid (5.4.0)
|
||||
listen (3.8.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
minitest (5.20.0)
|
||||
nio4r (2.5.8)
|
||||
nokogiri (1.13.9-arm64-darwin)
|
||||
racc (~> 1.4)
|
||||
nokogiri (1.13.9-x86_64-linux)
|
||||
racc (~> 1.4)
|
||||
parallel (1.23.0)
|
||||
parser (3.2.2.4)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
psych (5.1.0)
|
||||
stringio
|
||||
public_suffix (5.0.3)
|
||||
puma (5.6.5)
|
||||
nio4r (~> 2.0)
|
||||
racc (1.6.0)
|
||||
rack (3.0.8)
|
||||
rack-cors (2.0.1)
|
||||
rack (>= 2.0.0)
|
||||
rainbow (3.1.1)
|
||||
rake (13.0.6)
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rbs (2.8.4)
|
||||
rdoc (6.5.0)
|
||||
psych (>= 4.0.0)
|
||||
regexp_parser (2.8.1)
|
||||
reline (0.3.9)
|
||||
io-console (~> 0.5)
|
||||
reverse_markdown (2.1.1)
|
||||
nokogiri
|
||||
rexml (3.2.6)
|
||||
roda (3.72.0)
|
||||
rack
|
||||
rouge (3.30.0)
|
||||
rubocop (1.56.4)
|
||||
base64 (~> 0.1.1)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.2.2.3)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.28.1, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.29.0)
|
||||
parser (>= 3.2.1.0)
|
||||
ruby-lsp (0.11.1)
|
||||
language_server-protocol (~> 3.17.0)
|
||||
sorbet-runtime (>= 0.5.5685)
|
||||
yarp (>= 0.12, < 0.13)
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
serbea (1.0.1)
|
||||
activesupport (>= 6.0)
|
||||
erubi (>= 1.10)
|
||||
tilt (~> 2.0)
|
||||
solargraph (0.49.0)
|
||||
backport (~> 1.2)
|
||||
benchmark
|
||||
bundler (~> 2.0)
|
||||
diff-lcs (~> 1.4)
|
||||
e2mmap
|
||||
jaro_winkler (~> 1.5)
|
||||
kramdown (~> 2.3)
|
||||
kramdown-parser-gfm (~> 1.1)
|
||||
parser (~> 3.0)
|
||||
rbs (~> 2.0)
|
||||
reverse_markdown (~> 2.0)
|
||||
rubocop (~> 1.38)
|
||||
thor (~> 1.0)
|
||||
tilt (~> 2.0)
|
||||
yard (~> 0.9, >= 0.9.24)
|
||||
sorbet-runtime (0.5.11064)
|
||||
stringio (3.0.8)
|
||||
thor (1.2.2)
|
||||
tilt (2.3.0)
|
||||
tzinfo (2.0.6)
|
||||
concurrent-ruby (~> 1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
yard (0.9.34)
|
||||
yarp (0.12.0)
|
||||
zeitwerk (2.6.12)
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-21
|
||||
arm64-darwin-22
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
asset_mapper (~> 1.0)
|
||||
bridgetown (~> 1.3)
|
||||
bridgetown-quick-search (~> 2.0)
|
||||
custom_elements_manifest_parser (~> 0.2.4)
|
||||
debug (~> 1.8)
|
||||
nokogiri (~> 1.13)
|
||||
puma (~> 5.6)
|
||||
rack-cors (~> 2.0)
|
||||
ruby-lsp (~> 0.11.1)
|
||||
solargraph (~> 0.49.0)
|
||||
yard (~> 0.9.34)
|
||||
|
||||
BUNDLED WITH
|
||||
2.3.5
|
||||
2
docs/assets/scripts/light-pen/docs/Procfile.dev
Normal file
2
docs/assets/scripts/light-pen/docs/Procfile.dev
Normal file
@@ -0,0 +1,2 @@
|
||||
bridgetown: bin/bridgetown start --skip-frontend
|
||||
esbuild: pnpm run esbuild-dev
|
||||
70
docs/assets/scripts/light-pen/docs/README.md
Normal file
70
docs/assets/scripts/light-pen/docs/README.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Bridgetown Website README
|
||||
|
||||
Welcome to your new Bridgetown website! You can update this README file to provide additional context and setup information for yourself or other contributors.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Install](#install)
|
||||
- [Development](#development)
|
||||
- [Commands](#commands)
|
||||
- [Deployment](#deployment)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [GCC](https://gcc.gnu.org/install/)
|
||||
- [Make](https://www.gnu.org/software/make/)
|
||||
- [Ruby](https://www.ruby-lang.org/en/downloads/)
|
||||
- `>= 2.7`
|
||||
- [Bridgetown Gem](https://rubygems.org/gems/bridgetown)
|
||||
- `gem install bridgetown -N`
|
||||
- [Node](https://nodejs.org)
|
||||
- `>= 12`
|
||||
- [Yarn](https://yarnpkg.com)
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
cd bridgetown-site-folder
|
||||
bundle install && yarn install
|
||||
```
|
||||
> Learn more: [Bridgetown Getting Started Documentation](https://www.bridgetownrb.com/docs/).
|
||||
|
||||
## Development
|
||||
|
||||
To start your site in development mode, run `bin/bridgetown start` and navigate to [localhost:4000](https://localhost:4000/)!
|
||||
|
||||
Use a [theme](https://github.com/topics/bridgetown-theme) or add some [plugins](https://www.bridgetownrb.com/plugins/) to get started quickly.
|
||||
|
||||
### Commands
|
||||
|
||||
```sh
|
||||
# running locally
|
||||
bin/bridgetown start
|
||||
|
||||
# build & deploy to production
|
||||
bin/bridgetown deploy
|
||||
|
||||
# load the site up within a Ruby console (IRB)
|
||||
bin/bridgetown console
|
||||
```
|
||||
|
||||
> Learn more: [Bridgetown CLI Documentation](https://www.bridgetownrb.com/docs/command-line-usage)
|
||||
|
||||
## Deployment
|
||||
|
||||
You can deploy Bridgetown sites on hosts like Render or Vercel as well as traditional web servers by simply building and copying the output folder to your HTML root.
|
||||
|
||||
> Read the [Bridgetown Deployment Documentation](https://www.bridgetownrb.com/docs/deployment) for more information.
|
||||
|
||||
## Contributing
|
||||
|
||||
If repo is on GitHub:
|
||||
|
||||
1. Fork it
|
||||
2. Clone the fork using `git clone` to your local development machine.
|
||||
3. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
4. Commit your changes (`git commit -am 'Add some feature'`)
|
||||
5. Push to the branch (`git push origin my-new-feature`)
|
||||
6. Create a new Pull Request
|
||||
49
docs/assets/scripts/light-pen/docs/Rakefile
Normal file
49
docs/assets/scripts/light-pen/docs/Rakefile
Normal file
@@ -0,0 +1,49 @@
|
||||
require "bridgetown"
|
||||
|
||||
Bridgetown.load_tasks
|
||||
|
||||
# Run rake without specifying any command to execute a deploy build by default.
|
||||
task default: :deploy
|
||||
|
||||
#
|
||||
# Standard set of tasks, which you can customize if you wish:
|
||||
#
|
||||
desc "Build the Bridgetown site for deployment"
|
||||
task :deploy => [:clean, "frontend:build"] do
|
||||
Bridgetown::Commands::Build.start
|
||||
end
|
||||
|
||||
desc "Build the site in a test environment"
|
||||
task :test do
|
||||
ENV["BRIDGETOWN_ENV"] = "test"
|
||||
Bridgetown::Commands::Build.start
|
||||
end
|
||||
|
||||
desc "Runs the clean command"
|
||||
task :clean do
|
||||
Bridgetown::Commands::Clean.start
|
||||
end
|
||||
|
||||
namespace :frontend do
|
||||
desc "Build the frontend with esbuild for deployment"
|
||||
task :build do
|
||||
sh "yarn run esbuild"
|
||||
end
|
||||
|
||||
desc "Watch the frontend with esbuild during development"
|
||||
task :dev do
|
||||
sh "yarn run esbuild-dev"
|
||||
rescue Interrupt
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Add your own Rake tasks here! You can use `environment` as a prerequisite
|
||||
# in order to write automations or other commands requiring a loaded site.
|
||||
#
|
||||
# task :my_task => :environment do
|
||||
# puts site.root_dir
|
||||
# automation do
|
||||
# say_status :rake, "I'm a Rake tast =) #{site.config.url}"
|
||||
# end
|
||||
# end
|
||||
27
docs/assets/scripts/light-pen/docs/bin/bridgetown
Executable file
27
docs/assets/scripts/light-pen/docs/bin/bridgetown
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'bridgetown' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
||||
|
||||
bundle_binstub = File.expand_path("bundle", __dir__)
|
||||
|
||||
if File.file?(bundle_binstub)
|
||||
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
||||
load(bundle_binstub)
|
||||
else
|
||||
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
||||
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
||||
end
|
||||
end
|
||||
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
load Gem.bin_path("bridgetown-core", "bridgetown")
|
||||
27
docs/assets/scripts/light-pen/docs/bin/bt
Executable file
27
docs/assets/scripts/light-pen/docs/bin/bt
Executable file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env ruby
|
||||
# frozen_string_literal: true
|
||||
|
||||
#
|
||||
# This file was generated by Bundler.
|
||||
#
|
||||
# The application 'bridgetown' is installed as part of a gem, and
|
||||
# this file is here to facilitate running it.
|
||||
#
|
||||
|
||||
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
|
||||
|
||||
bundle_binstub = File.expand_path("bundle", __dir__)
|
||||
|
||||
if File.file?(bundle_binstub)
|
||||
if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
|
||||
load(bundle_binstub)
|
||||
else
|
||||
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
||||
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
||||
end
|
||||
end
|
||||
|
||||
require "rubygems"
|
||||
require "bundler/setup"
|
||||
|
||||
load Gem.bin_path("bridgetown-core", "bridgetown")
|
||||
48
docs/assets/scripts/light-pen/docs/bridgetown.config.yml
Normal file
48
docs/assets/scripts/light-pen/docs/bridgetown.config.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
baseurl: "" # OPTIONAL: the subpath of your site, e.g. /blog
|
||||
url: "" # the base hostname & protocol for your site, e.g. https://example.com
|
||||
destination: output
|
||||
|
||||
development:
|
||||
url: "localhost:4000"
|
||||
# production:
|
||||
# url: "https://konnorrogers.github.io"
|
||||
# base_path: "/light-pen"
|
||||
|
||||
template_engine: erb
|
||||
permalink: pretty
|
||||
|
||||
collections:
|
||||
documentation:
|
||||
output: true
|
||||
|
||||
defaults:
|
||||
- scope:
|
||||
path: "images"
|
||||
values:
|
||||
image: true
|
||||
|
||||
- scope:
|
||||
path: "_documentation"
|
||||
values:
|
||||
layout: doc
|
||||
permalink: /:categories/:slug
|
||||
category_order: 0
|
||||
doc_order: 0
|
||||
|
||||
- scope:
|
||||
path: "_documentation/guides"
|
||||
values:
|
||||
category: guides
|
||||
category_order: 10
|
||||
|
||||
- scope:
|
||||
path: "_documentation/components"
|
||||
values:
|
||||
category: components
|
||||
category_order: 20
|
||||
|
||||
- scope:
|
||||
path: "_documentation/references"
|
||||
values:
|
||||
category: references
|
||||
category_order: 30
|
||||
16
docs/assets/scripts/light-pen/docs/config.ru
Normal file
16
docs/assets/scripts/light-pen/docs/config.ru
Normal file
@@ -0,0 +1,16 @@
|
||||
# This file is used by Rack-based servers during the Bridgetown boot process.
|
||||
|
||||
require "bridgetown-core/rack/boot"
|
||||
|
||||
Bridgetown::Rack.boot
|
||||
|
||||
require "rack/cors"
|
||||
|
||||
use Rack::Cors do
|
||||
allow do
|
||||
origins '*'
|
||||
resource '/*', headers: :any, methods: :get
|
||||
end
|
||||
end
|
||||
|
||||
run RodaApp.freeze.app # see server/roda_app.rb
|
||||
310
docs/assets/scripts/light-pen/docs/config/esbuild.defaults.js
Normal file
310
docs/assets/scripts/light-pen/docs/config/esbuild.defaults.js
Normal file
@@ -0,0 +1,310 @@
|
||||
// This file is created and managed by Bridgetown.
|
||||
// Instead of editing this file, add your overrides to `esbuild.config.js`
|
||||
//
|
||||
// To update this file to the latest version provided by Bridgetown,
|
||||
// run `bridgetown esbuild update`. Any changes to this file will be overwritten
|
||||
// when an update is applied hence we strongly recommend adding overrides to
|
||||
// `esbuild.config.js` instead of editing this file.
|
||||
//
|
||||
// Shipped with Bridgetown v1.1.0
|
||||
|
||||
const path = require("path")
|
||||
const fsLib = require("fs")
|
||||
const fs = fsLib.promises
|
||||
const { pathToFileURL, fileURLToPath } = require("url")
|
||||
const glob = require("glob")
|
||||
const postcss = require("postcss")
|
||||
const postCssImport = require("postcss-import")
|
||||
const readCache = require("read-cache")
|
||||
|
||||
// Detect if an NPM package is available
|
||||
const moduleAvailable = name => {
|
||||
try {
|
||||
require.resolve(name)
|
||||
return true
|
||||
} catch (e) { }
|
||||
return false
|
||||
}
|
||||
|
||||
// Generate a Source Map URL (used by the Sass plugin)
|
||||
const generateSourceMappingURL = sourceMap => {
|
||||
const data = Buffer.from(JSON.stringify(sourceMap), "utf-8").toString("base64")
|
||||
return `/*# sourceMappingURL=data:application/json;charset=utf-8;base64,${data} */`
|
||||
}
|
||||
|
||||
// Import Sass if available
|
||||
let sass
|
||||
if (moduleAvailable("sass")) {
|
||||
sass = require("sass")
|
||||
}
|
||||
|
||||
// Glob plugin derived from:
|
||||
// https://github.com/thomaschaaf/esbuild-plugin-import-glob
|
||||
// https://github.com/xiaohui-zhangxh/jsbundling-rails/commit/b15025dcc20f664b2b0eb238915991afdbc7cb58
|
||||
const importGlobPlugin = () => ({
|
||||
name: "import-glob",
|
||||
setup: (build) => {
|
||||
build.onResolve({ filter: /\*/ }, async (args) => {
|
||||
if (args.resolveDir === "") {
|
||||
return; // Ignore unresolvable paths
|
||||
}
|
||||
|
||||
const adjustedPath = args.path.replace(/^bridgetownComponents\//, "../../src/_components/")
|
||||
|
||||
return {
|
||||
path: adjustedPath,
|
||||
namespace: "import-glob",
|
||||
pluginData: {
|
||||
path: adjustedPath,
|
||||
resolveDir: args.resolveDir,
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
build.onLoad({ filter: /.*/, namespace: "import-glob" }, async (args) => {
|
||||
const files = glob.sync(args.pluginData.path, {
|
||||
cwd: args.pluginData.resolveDir,
|
||||
}).sort()
|
||||
|
||||
const importerCode = `
|
||||
${files
|
||||
.map((module, index) => `import * as module${index} from '${module}'`)
|
||||
.join(';')}
|
||||
const modules = {${files
|
||||
.map((module, index) => `
|
||||
"${module.replace("../../src/_components/", "")}": module${index},`)
|
||||
.join("")}
|
||||
};
|
||||
export default modules;
|
||||
`
|
||||
|
||||
return { contents: importerCode, resolveDir: args.pluginData.resolveDir }
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
// Plugin for PostCSS
|
||||
const postCssPlugin = (options, configuration) => ({
|
||||
name: "postcss",
|
||||
async setup(build) {
|
||||
// Process .css files with PostCSS
|
||||
build.onLoad({ filter: (configuration.filter || /\.css$/) }, async (args) => {
|
||||
const additionalFilePaths = []
|
||||
const css = await fs.readFile(args.path, "utf8")
|
||||
|
||||
// Configure import plugin so PostCSS can properly resolve `@import`ed CSS files
|
||||
const importPlugin = postCssImport({
|
||||
filter: itemPath => !itemPath.startsWith("/"), // ensure it doesn't try to import source-relative paths
|
||||
load: async filename => {
|
||||
let contents = await readCache(filename, "utf-8")
|
||||
const filedir = path.dirname(filename)
|
||||
// We'll want to track any imports later when in watch mode:
|
||||
additionalFilePaths.push(filename)
|
||||
|
||||
// We need to transform `url(...)` in imported CSS so the filepaths are properly
|
||||
// relative to the entrypoint. Seems icky to have to hack this! C'est la vie...
|
||||
contents = contents.replace(/url\(['"]?\.\/(.*?)['"]?\)/g, (_match, p1) => {
|
||||
const relpath = path.relative(args.path, path.resolve(filedir, p1)).replace(/^\.\.\//, "")
|
||||
return `url("${relpath}")`
|
||||
})
|
||||
return contents
|
||||
}
|
||||
})
|
||||
|
||||
// Process the file through PostCSS
|
||||
const result = await postcss([importPlugin, ...options.plugins]).process(css, {
|
||||
map: true,
|
||||
...options.options,
|
||||
from: args.path,
|
||||
});
|
||||
|
||||
return {
|
||||
contents: result.css,
|
||||
loader: "css",
|
||||
watchFiles: [args.path, ...additionalFilePaths],
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
// Plugin for Sass
|
||||
const sassPlugin = (options) => ({
|
||||
name: "sass",
|
||||
async setup(build) {
|
||||
// Process .scss and .sass files with Sass
|
||||
build.onLoad({ filter: /\.(sass|scss)$/ }, async (args) => {
|
||||
if (!sass) {
|
||||
console.error("error: Sass is not installed. Try running `yarn add sass` and then building again.")
|
||||
return
|
||||
}
|
||||
|
||||
const modulesFolder = pathToFileURL("node_modules/")
|
||||
|
||||
const localOptions = {
|
||||
importers: [{
|
||||
// An importer that redirects relative URLs starting with "~" to
|
||||
// `node_modules`.
|
||||
findFileUrl(url) {
|
||||
if (!url.startsWith('~')) return null
|
||||
return new URL(url.substring(1), modulesFolder)
|
||||
}
|
||||
}],
|
||||
sourceMap: true,
|
||||
...options
|
||||
}
|
||||
const result = sass.compile(args.path, localOptions)
|
||||
|
||||
const watchPaths = result.loadedUrls
|
||||
.filter((x) => x.protocol === "file:" && !x.pathname.startsWith(modulesFolder.pathname))
|
||||
.map((x) => x.pathname)
|
||||
|
||||
let cssOutput = result.css.toString()
|
||||
|
||||
if (result.sourceMap) {
|
||||
const basedir = process.cwd()
|
||||
const sourceMap = result.sourceMap
|
||||
|
||||
const promises = sourceMap.sources.map(async source => {
|
||||
const sourceFile = await fs.readFile(fileURLToPath(source), "utf8")
|
||||
return sourceFile
|
||||
})
|
||||
sourceMap.sourcesContent = await Promise.all(promises)
|
||||
|
||||
sourceMap.sources = sourceMap.sources.map(source => {
|
||||
return path.relative(basedir, fileURLToPath(source))
|
||||
})
|
||||
|
||||
cssOutput += '\n' + generateSourceMappingURL(sourceMap)
|
||||
}
|
||||
|
||||
return {
|
||||
contents: cssOutput,
|
||||
loader: "css",
|
||||
watchFiles: [args.path, ...watchPaths],
|
||||
}
|
||||
})
|
||||
},
|
||||
})
|
||||
|
||||
// Set up defaults and generate frontend bundling manifest file
|
||||
const bridgetownPreset = (outputFolder) => ({
|
||||
name: "bridgetownPreset",
|
||||
async setup(build) {
|
||||
// Ensure any imports anywhere starting with `/` are left verbatim
|
||||
// so they can be used in-browser for actual `src` repo files
|
||||
build.onResolve({ filter: /^\// }, args => {
|
||||
return { path: args.path, external: true }
|
||||
})
|
||||
|
||||
build.onStart(() => {
|
||||
console.log("esbuild: frontend bundling started...")
|
||||
})
|
||||
|
||||
// Generate the final output manifest
|
||||
build.onEnd(async (result) => {
|
||||
if (!result.metafile) {
|
||||
console.warn("esbuild: build process error, cannot write manifest")
|
||||
return
|
||||
}
|
||||
await fs.writeFile(path.join(outputFolder, 'meta.json'), JSON.stringify(result.metafile), { encoding: "utf8" })
|
||||
|
||||
const manifest = {}
|
||||
const entrypoints = []
|
||||
|
||||
// We don't need `frontend/` cluttering up everything
|
||||
// const stripPrefix = (str) => str.replace(/^frontend\//, "")
|
||||
|
||||
// For calculating the file size of bundle output
|
||||
const fileSize = (path) => {
|
||||
const { size } = fsLib.statSync(path)
|
||||
const i = Math.floor(Math.log(size) / Math.log(1024))
|
||||
return (size / Math.pow(1024, i)).toFixed(2) * 1 + ['B', 'KB', 'MB', 'GB', 'TB'][i]
|
||||
}
|
||||
|
||||
// Let's loop through all the various outputs
|
||||
// for (const key in result.metafile.outputs) {
|
||||
// const value = result.metafile.outputs[key]
|
||||
// const inputs = Object.keys(value.inputs)
|
||||
// const pathShortener = new RegExp(`^${outputFolder}\\/_bridgetown\\/static\\/`, "g")
|
||||
// const outputPath = key.replace(pathShortener, "")
|
||||
|
||||
// if (value.entryPoint) {
|
||||
// // We have an entrypoint!
|
||||
// manifest[stripPrefix(value.entryPoint)] = outputPath
|
||||
// entrypoints.push([outputPath, fileSize(key)])
|
||||
// } else if (key.match(/index(\.js)?\.[^-.]*\.css/) && inputs.find(item => item.match(/\.(s?css|sass)$/))) {
|
||||
// // Special treatment for index.css
|
||||
// manifest[stripPrefix(inputs.find(item => item.match(/\.(s?css|sass)$/)))] = outputPath
|
||||
// entrypoints.push([outputPath, fileSize(key)])
|
||||
// } else if (inputs.length > 0) {
|
||||
// // Naive implementation, we'll just grab the first input and hope it's accurate
|
||||
// manifest[stripPrefix(inputs[0])] = outputPath
|
||||
// }
|
||||
// }
|
||||
|
||||
// const manifestFolder = path.join(process.cwd(), ".bridgetown-cache", "frontend-bundling")
|
||||
// await fs.mkdir(manifestFolder, { recursive: true })
|
||||
// await fs.writeFile(path.join(manifestFolder, "manifest.json"), JSON.stringify(manifest))
|
||||
|
||||
console.log("esbuild: frontend bundling complete!")
|
||||
console.log("esbuild: entrypoints processed:")
|
||||
entrypoints.forEach(entrypoint => {
|
||||
const [entrypointName, entrypointSize] = entrypoint
|
||||
console.log(` - ${entrypointName}: ${entrypointSize}`)
|
||||
})
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Load the PostCSS config from postcss.config.js or whatever else is a supported location/format
|
||||
const postcssrc = require("postcss-load-config")
|
||||
const postCssConfig = postcssrc.sync()
|
||||
|
||||
module.exports = async (outputFolder, esbuildOptions) => {
|
||||
esbuildOptions.plugins = esbuildOptions.plugins || []
|
||||
// Add the PostCSS & glob plugins to the top of the plugin stack
|
||||
esbuildOptions.plugins.unshift(postCssPlugin(postCssConfig, esbuildOptions.postCssPluginConfig || {}))
|
||||
if (esbuildOptions.postCssPluginConfig) delete esbuildOptions.postCssPluginConfig
|
||||
esbuildOptions.plugins.unshift(importGlobPlugin())
|
||||
// Add the Sass plugin
|
||||
esbuildOptions.plugins.push(sassPlugin(esbuildOptions.sassOptions || {}))
|
||||
// Add the Bridgetown preset
|
||||
esbuildOptions.plugins.push(bridgetownPreset(outputFolder))
|
||||
|
||||
// esbuild, take it away!
|
||||
const esbuild = require("esbuild")
|
||||
|
||||
const watch = process.argv.includes("--watch")
|
||||
|
||||
const config = {
|
||||
bundle: true,
|
||||
loader: {
|
||||
".jpg": "file",
|
||||
".png": "file",
|
||||
".gif": "file",
|
||||
".svg": "file",
|
||||
".woff": "file",
|
||||
".woff2": "file",
|
||||
".ttf": "file",
|
||||
".eot": "file",
|
||||
},
|
||||
resolveExtensions: [".tsx", ".ts", ".jsx", ".js", ".css", ".scss", ".sass", ".json", ".js.rb"],
|
||||
nodePaths: ["frontend/javascript", "frontend/styles"],
|
||||
minify: process.argv.includes("--minify"),
|
||||
sourcemap: true,
|
||||
target: "es2016",
|
||||
entryPoints: ["frontend/javascript/index.js"],
|
||||
entryNames: "[dir]/[name].[hash]",
|
||||
outdir: path.join(process.cwd(), `${outputFolder}/bridgetown/static`),
|
||||
publicPath: "/bridgetown/static",
|
||||
metafile: true,
|
||||
...esbuildOptions,
|
||||
}
|
||||
|
||||
if (watch) {
|
||||
const context = await esbuild.context(config).catch(() => process.exit(1))
|
||||
await context.watch().catch(() => process.exit(1))
|
||||
} else {
|
||||
await esbuild.build(config).catch(() => process.exit(1))
|
||||
}
|
||||
}
|
||||
20
docs/assets/scripts/light-pen/docs/config/initializers.rb
Normal file
20
docs/assets/scripts/light-pen/docs/config/initializers.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
Bridgetown.configure do |config|
|
||||
config.url = ENV.fetch("URL", "https://konnorrogers.github.io")
|
||||
config.base_path = ENV.fetch("BASE_PATH", "/light-pen")
|
||||
config.base_url = config.url + config.base_path
|
||||
init :"bridgetown-quick-search"
|
||||
|
||||
# init :ssr
|
||||
# init :"bridgetown-routes"
|
||||
# only :server do
|
||||
# roda do |app|
|
||||
# app.plugin :default_headers,
|
||||
# 'Content-Type'=>'text/html',
|
||||
# 'Strict-Transport-Security'=>'max-age=16070400;',
|
||||
# 'X-Content-Type-Options'=>'nosniff',
|
||||
# 'X-Frame-Options'=>'deny',
|
||||
# 'X-XSS-Protection'=>'1; mode=block',
|
||||
# 'Access-Control-Allow-Origin'=>'*'
|
||||
# end
|
||||
# end
|
||||
end
|
||||
27
docs/assets/scripts/light-pen/docs/config/puma.rb
Normal file
27
docs/assets/scripts/light-pen/docs/config/puma.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
# Puma is a fast, concurrent web server for Ruby & Rack
|
||||
#
|
||||
# Learn more at: https://puma.io
|
||||
#
|
||||
port ENV.fetch("BRIDGETOWN_PORT") { 4000 }
|
||||
|
||||
# You can adjust the number of workers (separate processes) and threads
|
||||
# (per process) based on your production system
|
||||
#
|
||||
if ENV["BRIDGETOWN_ENV"] == "production"
|
||||
workers ENV.fetch("BRIDGETOWN_CONCURRENCY") { 4 }
|
||||
end
|
||||
|
||||
max_threads_count = ENV.fetch("BRIDGETOWN_MAX_THREADS") { 5 }
|
||||
min_threads_count = ENV.fetch("BRIDGETOWN_MIN_THREADS") { max_threads_count }
|
||||
threads min_threads_count, max_threads_count
|
||||
|
||||
# Preload the application for maximum performance
|
||||
#
|
||||
preload_app!
|
||||
|
||||
# Use the Bridgetown logger format
|
||||
#
|
||||
require "bridgetown-core/rack/logger"
|
||||
log_formatter do |msg|
|
||||
Bridgetown::Rack::Logger.message_with_prefix msg
|
||||
end
|
||||
57
docs/assets/scripts/light-pen/docs/esbuild.config.js
Normal file
57
docs/assets/scripts/light-pen/docs/esbuild.config.js
Normal file
@@ -0,0 +1,57 @@
|
||||
// @ts-check
|
||||
const { spawn } = require("child_process");
|
||||
|
||||
// const glob = require("glob")
|
||||
const build = require("./config/esbuild.defaults.js")
|
||||
|
||||
const AssetMapper = require("asset-mapper-esbuild").default
|
||||
// Update this if you need to configure a destination folder other than `output`
|
||||
const outputFolder = "src"
|
||||
|
||||
// You can customize this as you wish, perhaps to add new esbuild plugins.
|
||||
//
|
||||
// ```
|
||||
const path = require("path")
|
||||
const esbuildCopy = require('esbuild-plugin-copy').default
|
||||
// const esbuildOptions = {
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// You can also support custom base_path deployments via changing `publicPath`.
|
||||
//
|
||||
// ```
|
||||
// const esbuildOptions = { publicPath: "/my_subfolder/_bridgetown/static" }
|
||||
// ```
|
||||
const watch = process.argv.includes("--watch")
|
||||
|
||||
const esbuildOptions = {
|
||||
target: "es2020",
|
||||
entryPoints: {
|
||||
"javascript/index": "frontend/javascript/index.js",
|
||||
"javascript/defer": "frontend/javascript/defer.js",
|
||||
"light-pen/exports/light-pen": "../exports/light-pen.js",
|
||||
"light-pen/exports/light-preview": "../exports/light-preview.js",
|
||||
},
|
||||
define: {
|
||||
"process.env.BASE_PATH": `"${process.env.BASE_PATH}"`
|
||||
},
|
||||
publicPath: path.join(process.env.BASE_PATH, "bridgetown", "static"),
|
||||
outdir: path.join(process.cwd(), outputFolder, "bridgetown", "static"),
|
||||
splitting: true,
|
||||
format: "esm",
|
||||
plugins: [
|
||||
esbuildCopy({
|
||||
assets: {
|
||||
from: [path.resolve(__dirname, 'node_modules/@shoelace-style/shoelace/dist/assets/icons/**/*.svg')],
|
||||
to: [path.resolve(__dirname, 'src/shoelace-assets/assets/icons')],
|
||||
},
|
||||
verbose: false
|
||||
}),
|
||||
AssetMapper({
|
||||
manifestFile: path.join(process.cwd(), ".bridgetown-cache", "asset-mapper-manifest.json"),
|
||||
// outputRoot: path.join(process.cwd(), process.env.BASE_PATH)
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
build(outputFolder, esbuildOptions)
|
||||
@@ -0,0 +1,21 @@
|
||||
// @ts-check
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class ClipboardController extends Controller {
|
||||
connect () {
|
||||
this.element.addEventListener("clipboard-copy", this.showSuccess)
|
||||
}
|
||||
|
||||
showSuccess = () => {
|
||||
this.element.classList.add("clipboard--success")
|
||||
this.element.classList.remove("clipboard--idle")
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout)
|
||||
}
|
||||
|
||||
this.timeout = setTimeout(() => {
|
||||
this.element.classList.remove("clipboard--success")
|
||||
this.element.classList.add("clipboard--idle")
|
||||
}, 2_000)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
export default class extends Controller {
|
||||
connect() {
|
||||
// console.log("Hello, Stimulus!", this.element)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class ScrollSpyController extends Controller {
|
||||
connect () {
|
||||
this.observer = new IntersectionObserver(this.handleIntersect, { rootMargin: '0px 0px' });
|
||||
|
||||
this.linkMap = new WeakMap();
|
||||
this.visibleSet = new WeakSet();
|
||||
|
||||
this.observeLinks()
|
||||
this.updateActiveLinks()
|
||||
|
||||
this.selector = ["1","2","3","4","5","6"].map((str) => "h" + str + "[id]").join(",")
|
||||
document.querySelectorAll(this.selector).forEach((header) => {
|
||||
this.observer.observe(header);
|
||||
});
|
||||
|
||||
document.addEventListener("turbo:load", this.observeLinks)
|
||||
document.addEventListener("turbo:load", this.updateActiveLinks)
|
||||
|
||||
this.observeLinks()
|
||||
this.updateActiveLinks()
|
||||
}
|
||||
|
||||
disconnect () {
|
||||
this.observer.disconnect()
|
||||
}
|
||||
|
||||
get links () {
|
||||
return [...document.querySelectorAll('#table-of-contents li a')];
|
||||
}
|
||||
|
||||
handleIntersect = (entries) => {
|
||||
entries.forEach(entry => {
|
||||
// Remember which targets are visible
|
||||
if (entry.isIntersecting) {
|
||||
this.visibleSet.add(entry.target);
|
||||
} else {
|
||||
this.visibleSet.delete(entry.target);
|
||||
}
|
||||
});
|
||||
|
||||
this.updateActiveLinks();
|
||||
}
|
||||
|
||||
updateActiveLinks = () => {
|
||||
const links = this.links;
|
||||
// Find the first visible target and activate the respective link
|
||||
links.find(link => {
|
||||
const target = this.linkMap.get(link);
|
||||
|
||||
if (target && this.visibleSet.has(target)) {
|
||||
links.forEach(el => el.parentElement.classList.toggle('is-active', el === link));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
observeLinks = () => {
|
||||
this.links.forEach(link => {
|
||||
const hash = link.hash.slice(1);
|
||||
const target = hash ? document.querySelector(`main #${hash}`) : null;
|
||||
|
||||
if (target) {
|
||||
this.linkMap.set(link, target);
|
||||
this.observer.observe(target);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
export default class SearchController extends Controller {
|
||||
show () {
|
||||
document.querySelector("bridgetown-ninja-keys").open()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
export default class SideNavController extends Controller {
|
||||
async open() {
|
||||
document.addEventListener("sl-hide", this.reset)
|
||||
this.drawer.removeAttribute("hidden")
|
||||
|
||||
this.scrollTop = window.scrollY;
|
||||
document.body.classList.add('fixed-body');
|
||||
// Scroll the wrapper, rather than setting an offset
|
||||
// via `top` or `transform`.
|
||||
document.body.scroll(0, this.scrollTop);
|
||||
await this.drawer.show()
|
||||
}
|
||||
|
||||
reset = () => {
|
||||
window.scrollTo(0, this.scrollTop);
|
||||
document.body.classList.remove('fixed-body');
|
||||
}
|
||||
|
||||
async close () {
|
||||
document.removeEventListener("sl-hide", this.reset)
|
||||
this.reset()
|
||||
await this.drawer.hide()
|
||||
}
|
||||
|
||||
async toggle() {
|
||||
if (this.drawer.open) {
|
||||
await this.open()
|
||||
} else {
|
||||
await this.close()
|
||||
}
|
||||
}
|
||||
|
||||
get drawer() {
|
||||
return document.querySelector("#side-nav-drawer")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
|
||||
|
||||
export default class ThemeSwitcher extends Controller {
|
||||
constructor (...args) {
|
||||
super(...args)
|
||||
|
||||
this.handleSelect = (e) => {
|
||||
window.applyTheme(e.detail.item.value)
|
||||
}
|
||||
|
||||
this.handleShortcut = (event) => {
|
||||
if (
|
||||
event.key === '\\' &&
|
||||
!event.composedPath().some(el => {
|
||||
return (
|
||||
['input', 'textarea'].includes(el?.tagName?.toLowerCase()) ||
|
||||
el.hasAttribute?.("contenteditable") ||
|
||||
el.getAttribute?.("role") === "textbox"
|
||||
)
|
||||
})
|
||||
) {
|
||||
event.preventDefault();
|
||||
|
||||
window.applyTheme(window.themeIsDark() ? 'light' : 'dark');
|
||||
}
|
||||
}
|
||||
|
||||
this.setLight = () => {
|
||||
window.applyTheme("light")
|
||||
}
|
||||
|
||||
this.setDark = () => {
|
||||
window.applyTheme("dark")
|
||||
}
|
||||
|
||||
// Set the initial theme and sync the UI
|
||||
window.applyTheme(window.getTheme());
|
||||
}
|
||||
|
||||
connect () {
|
||||
this.element.addEventListener("sl-select", this.handleSelect)
|
||||
document.addEventListener("keydown", this.handleShortcut)
|
||||
|
||||
// Update the theme when the preference changes
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', this.setDark);
|
||||
window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', this.setLight);
|
||||
|
||||
// Set the initial theme and sync the UI
|
||||
window.applyTheme(window.getTheme());
|
||||
}
|
||||
|
||||
disconnect () {
|
||||
this.element.removeEventListener("sl-select", this.handleSelect)
|
||||
document.removeEventListener("keydown", this.handleShortcut)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
import "../styles/defer.css"
|
||||
import { BridgetownNinjaKeys } from "@konnorr/bridgetown-quick-search/ninja-keys.js"
|
||||
|
||||
;(window.requestIdleCallback || window.setTimeout)(async () => {
|
||||
// const { BridgetownNinjaKeys } = await import("@konnorr/bridgetown-quick-search/ninja-keys.js")
|
||||
|
||||
/** @type {import("konnors-ninja-keys").INinjaAction[]} */
|
||||
const staticData = [
|
||||
{
|
||||
id: "theme-light",
|
||||
icon: "<sl-icon name='sun'></sl-icon>",
|
||||
title: "Light Mode",
|
||||
section: "Theme",
|
||||
keywords: "theme",
|
||||
handler () {
|
||||
window.applyTheme("light");
|
||||
return {keepOpen: true}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "theme-dark",
|
||||
icon: "<sl-icon name='moon'></sl-icon>",
|
||||
title: "Dark Mode",
|
||||
section: "Theme",
|
||||
keywords: "theme",
|
||||
handler () {
|
||||
window.applyTheme("dark");
|
||||
return {keepOpen: true}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "theme-system",
|
||||
icon: "<sl-icon name='display'></sl-icon>",
|
||||
title: "System",
|
||||
section: "Theme",
|
||||
keywords: "theme",
|
||||
handler () {
|
||||
window.applyTheme("system");
|
||||
return {keepOpen: true}
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
;(class extends BridgetownNinjaKeys {
|
||||
constructor (...args) {
|
||||
super(...args)
|
||||
this.staticData = staticData
|
||||
}
|
||||
|
||||
createData() {
|
||||
this.results = this.showResultsForQuery(this._search || "*").reverse()
|
||||
|
||||
this.results.forEach((result) => {
|
||||
result.icon = `<sl-icon name="link-45deg"></sl-icon>`
|
||||
})
|
||||
|
||||
return [
|
||||
...this.staticData,
|
||||
...this.results,
|
||||
]
|
||||
}
|
||||
|
||||
open () {
|
||||
this.scrollTop = window.scrollY;
|
||||
document.body.classList.add('fixed-body');
|
||||
// Scroll the wrapper, rather than setting an offset
|
||||
// via `top` or `transform`.
|
||||
document.body.scroll(0, this.scrollTop);
|
||||
|
||||
this.nonModals.forEach((el) => {
|
||||
el.setAttribute("inert", "")
|
||||
})
|
||||
super.open()
|
||||
}
|
||||
|
||||
close () {
|
||||
document.body.classList.remove('fixed-body');
|
||||
window.scrollTo(0, this.scrollTop);
|
||||
super.close()
|
||||
this.nonModals.forEach((el) => el.removeAttribute("inert"))
|
||||
}
|
||||
|
||||
get nonModals () {
|
||||
return [...document.body.children].filter((el) => el.localName !== "bridgetown-ninja-keys")
|
||||
}
|
||||
}).define("bridgetown-ninja-keys")
|
||||
})
|
||||
@@ -0,0 +1,61 @@
|
||||
import "../styles/index.css"
|
||||
import { Application } from "@hotwired/stimulus"
|
||||
|
||||
// Shoelace
|
||||
import { setBasePath } from "@shoelace-style/shoelace/dist/utilities/base-path.js";
|
||||
|
||||
import LazyLoader from "./src/lazy-loader.js"
|
||||
|
||||
import * as Turbo from "@hotwired/turbo"
|
||||
window.Turbo = Turbo
|
||||
import "./src/layout.js"
|
||||
//
|
||||
LazyLoader()
|
||||
//
|
||||
setBasePath(process.env.BASE_PATH + "/shoelace-assets")
|
||||
|
||||
// Import all JavaScript & CSS files from src/_components
|
||||
import components from "bridgetownComponents/**/*.{js,jsx,js.rb,css}"
|
||||
|
||||
window.Stimulus = Application.start()
|
||||
|
||||
import controllers from "./controllers/**/*.{js,js.rb}"
|
||||
Object.entries(controllers).forEach(([filename, controller]) => {
|
||||
if (filename.includes("_controller.") || filename.includes("-controller.")) {
|
||||
const identifier = filename.replace("./controllers/", "")
|
||||
.replace(/[_-]controller..*$/, "")
|
||||
.replace("_", "-")
|
||||
.replace("/", "--")
|
||||
|
||||
Stimulus.register(identifier, controller.default)
|
||||
}
|
||||
})
|
||||
|
||||
;(() => {
|
||||
if (!window.scrollPositions) {
|
||||
window.scrollPositions = {};
|
||||
}
|
||||
|
||||
function preserveScroll() {
|
||||
document.querySelectorAll('[data-preserve-scroll').forEach(element => {
|
||||
scrollPositions[element.id] = element.scrollTop;
|
||||
});
|
||||
}
|
||||
|
||||
function restoreScroll(event) {
|
||||
if (event.detail && event.detail.newBody) {
|
||||
event.detail.newBody.querySelectorAll('[data-preserve-scroll]').forEach(element => {
|
||||
element.scrollTop = scrollPositions[element.id];
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelectorAll('[data-preserve-scroll').forEach(element => {
|
||||
element.scrollTop = scrollPositions[element.id];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
window.addEventListener('turbo:before-cache', preserveScroll);
|
||||
window.addEventListener('turbo:before-render', restoreScroll);
|
||||
window.addEventListener('turbo:render', restoreScroll);
|
||||
})();
|
||||
@@ -0,0 +1,10 @@
|
||||
class ExternalIcon extends HTMLElement {
|
||||
connectedCallback () {
|
||||
this.attachShadow({ mode: "open" })
|
||||
this.shadowRoot.innerHTML = `<sl-icon name="box-arrow-up-right"></sl-icon><sl-visually-hidden>Opens in new window</sl-visually-hidden>`
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.customElements.get("external-icon")) {
|
||||
window.customElements.define("external-icon", ExternalIcon)
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
import {LitElement, html, css} from "lit"
|
||||
|
||||
class KrLayout extends LitElement {
|
||||
static styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
box-sizing: border-box;
|
||||
min-height: var(--height);
|
||||
--height: 100vh;
|
||||
--height: 100dvh;
|
||||
|
||||
--menu-width: auto;
|
||||
--main-width: 1fr;
|
||||
--aside-width: auto;
|
||||
|
||||
/** This is a best guess. We'll attempt to calculate this with a resize observer. **/
|
||||
--header-height: 68.33px;
|
||||
}
|
||||
|
||||
:host([variant="documentation"]) {
|
||||
--menu-width: 250px;
|
||||
--main-width: 105ch;
|
||||
--aside-width: auto;
|
||||
}
|
||||
|
||||
:host([variant="documentation"])::part(body) {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
*, *:after, *:before {
|
||||
box-sizing: border-box;;
|
||||
}
|
||||
|
||||
[part~="base"] {
|
||||
display: grid;
|
||||
/** Header, Main, Footer **/
|
||||
grid-template-rows: minmax(0, auto) minmax(0, 1fr) minmax(0, auto);
|
||||
min-height: var(--height);
|
||||
}
|
||||
|
||||
[part~="header"] {
|
||||
max-width: 100%;
|
||||
position: sticky;
|
||||
background: white;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
:is(.header, .aside, .menu, .footer) ::slotted(*) {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
:is(.aside, .menu) ::slotted(*) {
|
||||
min-width: 100%;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
[part~="header"] {
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
[part~="body"] {
|
||||
display: grid;
|
||||
/** Menu, Main, Aside **/
|
||||
grid-template-columns: minmax(0, var(--menu-width)) minmax(0, var(--main-width)) minmax(0, var(--aside-width));
|
||||
grid-template-rows: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
[part~="aside"],
|
||||
[part~="menu"] {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
max-height: calc(var(--height) - var(--header-height));
|
||||
overflow: auto;
|
||||
position: sticky;
|
||||
top: var(--header-height);
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
|
||||
[part~="main"] {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
/* main-header, main, main-footer */
|
||||
grid-template-rows: minmax(0, auto) minmax(0, 1fr) minmax(0, auto);
|
||||
}
|
||||
|
||||
[part~="footer"] {}
|
||||
|
||||
sl-visually-hidden:not(:focus-within) {
|
||||
position: absolute !important;
|
||||
width: 1px !important;
|
||||
height: 1px !important;
|
||||
clip: rect(0 0 0 0) !important;
|
||||
clip-path: inset(50%) !important;
|
||||
border: none !important;
|
||||
overflow: hidden !important;
|
||||
white-space: nowrap !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.skip-links {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: calc(var(--header-height, 48px) - 2px);
|
||||
width: 100vw;
|
||||
z-index: 4;
|
||||
background-color: inherit;
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
place-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
`
|
||||
|
||||
static properties = {
|
||||
main_id: { attribute: "main-id", reflect: true }
|
||||
}
|
||||
|
||||
constructor () {
|
||||
super()
|
||||
this.main_id = "main"
|
||||
}
|
||||
|
||||
createResizeObserver (slot) {
|
||||
return new ResizeObserver((entries) => {
|
||||
for (const entry of entries) {
|
||||
if (entry.contentBoxSize) {
|
||||
const contentBoxSize = entry.borderBoxSize[0];
|
||||
this.style.setProperty(`--${slot}-height`, `${contentBoxSize.blockSize}px`)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
connectedCallback () {
|
||||
super.connectedCallback?.()
|
||||
|
||||
this.headerResizeObserver = this.createResizeObserver("header");
|
||||
this.footerResizeObserver = this.createResizeObserver("footer");
|
||||
|
||||
setTimeout(() => {
|
||||
this.header = this.shadowRoot.querySelector("[part~='header']")
|
||||
this.headerResizeObserver.observe(this.header)
|
||||
|
||||
// this.footer = this.shadowRoot.querySelector("[part~='main-footer']")
|
||||
// this.footerResizeObserver.observe(this.footer)
|
||||
})
|
||||
}
|
||||
|
||||
disconnectedCallback () {
|
||||
super.disconnectedCallback?.()
|
||||
this.headerResizeObserver.unobserve(this.header)
|
||||
// this.footerResizeObserver.unobserve(this.footer)
|
||||
}
|
||||
|
||||
render () {
|
||||
return html`
|
||||
<sl-visually-hidden class="skip-links" part="skip-links">
|
||||
<slot name="skip-links">
|
||||
<a href=${`#${this.main_id}`} part="skip-link">
|
||||
${this.skipToMain || "Skip to main"}
|
||||
</a>
|
||||
</slot>
|
||||
</sl-visually-hidden>
|
||||
|
||||
<div class="base" part="base">
|
||||
<div class="header" part="header">
|
||||
<slot name="header"></slot>
|
||||
</div>
|
||||
|
||||
<div class="body" part="body">
|
||||
<div class="menu" part="menu">
|
||||
<slot name="menu"></slot>
|
||||
</div>
|
||||
|
||||
<div class="main" part="main">
|
||||
<div class="main-header" part="main-header">
|
||||
<slot name="main-header"></slot>
|
||||
</div>
|
||||
|
||||
<div class="main-content" part="main-content"><slot></slot></div>
|
||||
|
||||
<div class="main-footer" part="main-footer">
|
||||
<slot name="main-footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="aside" part="aside">
|
||||
<slot name="aside"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="footer" part="footer">
|
||||
<slot name="footer"></slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div part="dialog" class="dialog">
|
||||
<slot name="dialog"></slot>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
}
|
||||
|
||||
if (!window.customElements.get("kr-layout")) {
|
||||
window.customElements.define("kr-layout", KrLayout)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
import LazyLoader from "web-component-lazy-loader";
|
||||
|
||||
export default function lazyLoader() {
|
||||
return new LazyLoader({
|
||||
components: {
|
||||
"light-pen": {
|
||||
register () {
|
||||
import("light-pen/exports/light-pen-register.js")
|
||||
}
|
||||
},
|
||||
"light-preview": {
|
||||
register () {
|
||||
import("light-pen/exports/light-preview-register.js")
|
||||
}
|
||||
},
|
||||
"clipboard-copy": {
|
||||
register() {
|
||||
import("@github/clipboard-copy-element");
|
||||
},
|
||||
},
|
||||
"external-icon": {
|
||||
register() {
|
||||
import("./external-icon.js");
|
||||
},
|
||||
},
|
||||
|
||||
// Shoelace
|
||||
"sl-alert": {
|
||||
register() {
|
||||
import("@shoelace-style/shoelace/dist/components/alert/alert.js");
|
||||
},
|
||||
},
|
||||
// "sl-breadcrumb": {
|
||||
// register () { import("@shoelace-style/shoelace/dist/components/breadcrumb/breadcrumb.js"); }
|
||||
// },
|
||||
// "sl-breadcrumb-item": {
|
||||
// register () { import("@shoelace-style/shoelace/dist/components/breadcrumb-item/breadcrumb-item.js"); }
|
||||
// },
|
||||
"sl-button": {
|
||||
register() {
|
||||
import("@shoelace-style/shoelace/dist/components/button/button.js");
|
||||
},
|
||||
},
|
||||
"sl-divider": {
|
||||
register() {
|
||||
import("@shoelace-style/shoelace/dist/components/divider/divider.js");
|
||||
},
|
||||
},
|
||||
"sl-drawer": {
|
||||
register() {
|
||||
import("@shoelace-style/shoelace/dist/components/drawer/drawer.js");
|
||||
},
|
||||
},
|
||||
"sl-dropdown": {
|
||||
register() {
|
||||
import(
|
||||
"@shoelace-style/shoelace/dist/components/dropdown/dropdown.js"
|
||||
);
|
||||
},
|
||||
},
|
||||
"sl-icon": {
|
||||
register() {
|
||||
import("@shoelace-style/shoelace/dist/components/icon/icon.js");
|
||||
},
|
||||
},
|
||||
"sl-icon-button": {
|
||||
register() {
|
||||
import(
|
||||
"@shoelace-style/shoelace/dist/components/icon-button/icon-button.js"
|
||||
);
|
||||
},
|
||||
},
|
||||
"sl-menu": {
|
||||
register() {
|
||||
import("@shoelace-style/shoelace/dist/components/menu/menu.js");
|
||||
},
|
||||
},
|
||||
"sl-menu-item": {
|
||||
register() {
|
||||
import(
|
||||
"@shoelace-style/shoelace/dist/components/menu-item/menu-item.js"
|
||||
);
|
||||
},
|
||||
},
|
||||
"sl-menu-label": {
|
||||
register() {
|
||||
import(
|
||||
"@shoelace-style/shoelace/dist/components/menu-label/menu-label.js"
|
||||
);
|
||||
},
|
||||
},
|
||||
"sl-visually-hidden": {
|
||||
register() {
|
||||
import(
|
||||
"@shoelace-style/shoelace/dist/components/visually-hidden/visually-hidden.js"
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
}).start();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
@import "./components/_alert.css";
|
||||
@import "./components/_aspect_ratio.css";
|
||||
@import "./components/_blog.css";
|
||||
@import "./components/_button.css";
|
||||
@import "./components/_call_to_action.css";
|
||||
@import "./components/_clipboard.css";
|
||||
@import "./components/_contact.css";
|
||||
@import "./components/_footer.css";
|
||||
@import "./components/_header.css";
|
||||
@import "./components/_hero.css";
|
||||
@import "./components/_input.css";
|
||||
@import "./components/_layout.css";
|
||||
@import "./components/_list.css";
|
||||
@import "./components/_link.css";
|
||||
@import "./components/_logo.css";
|
||||
@import "./components/_main_list.css";
|
||||
@import "./components/_pagination.css";
|
||||
@import "./components/_side_nav.css";
|
||||
@import "./components/_syntax_block.css";
|
||||
@import "./components/_table_of_contents.css";
|
||||
@import "./components/_text.css";
|
||||
@import "./components/_theme_switcher.css";
|
||||
@import "./components/_top_nav.css";
|
||||
@import "./components/_tables.css";
|
||||
@@ -0,0 +1,42 @@
|
||||
/** For for prose sections, blogging concerns, Markdown, etc. */
|
||||
|
||||
/** Pretty syntax blocks */
|
||||
pre.highlight {
|
||||
padding: 0.85rem 1rem;
|
||||
margin: 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
code
|
||||
.highlighter-rouge,
|
||||
.highlight {
|
||||
border-radius: 8px;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.4;
|
||||
font-family: var(--sl-font-mono);
|
||||
}
|
||||
|
||||
code,
|
||||
.highlight,
|
||||
.highlighter-rouge {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Inline code blocks */
|
||||
code,
|
||||
code.highlight,
|
||||
code.highlighter-rouge {
|
||||
/** Layout */
|
||||
display: inline-block;
|
||||
font-size: 0.85em;
|
||||
padding: 0.1em 0.4em;
|
||||
margin: 4px 0;
|
||||
border-radius: 6px;
|
||||
white-space: break-spaces;
|
||||
vertical-align: middle;
|
||||
|
||||
/* Decoration */
|
||||
background-color: var(--code-background-color);
|
||||
color: var(--code-color);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 100%;
|
||||
line-height: 1.5;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeSpeed;
|
||||
scrollbar-gutter: stable;
|
||||
font-family: var(--sl-font-sans);
|
||||
background-color: var(--body-color);
|
||||
color: var(--text-color);
|
||||
display: grid;
|
||||
grid-template-rows: minmax(0, 1fr);
|
||||
min-height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
img, picture, video, canvas, svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
input, button, textarea, select {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
p, h1, h2, h3, h4, h5, h6 {
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: var(--sl-font-sans);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
button {
|
||||
appearance: none;
|
||||
border: none;
|
||||
background: none;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5,h6 {
|
||||
scroll-margin-top: calc(80px + 2em);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-top: var(--sl-spacing-large);
|
||||
margin-bottom: var(--sl-spacing-small);
|
||||
}
|
||||
|
||||
main p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.25rem;
|
||||
margin: 0;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
h3, h4 {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
h5, h6 {
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0.5em;
|
||||
margin-bottom: 0.5em;
|
||||
padding: 0;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p, li {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
li {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
ul {
|
||||
line-height: 1.8;
|
||||
list-style: disc outside;
|
||||
}
|
||||
|
||||
ul ul {
|
||||
list-style: circle outside;
|
||||
}
|
||||
|
||||
ul ul ul {
|
||||
list-style: square outside;
|
||||
}
|
||||
|
||||
ul ul ul ul {
|
||||
list-style: disc outside;
|
||||
}
|
||||
|
||||
[tabindex="-1"] {
|
||||
outline: transparent;
|
||||
}
|
||||
|
||||
a,
|
||||
kr-layout::part(skip-link) {
|
||||
word-wrap: anywhere;
|
||||
/* outline: transparent; */
|
||||
/* Unable to distinguish identifier, this makes links obvious */
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: solid;
|
||||
text-decoration-color: var(--link-color);
|
||||
text-underline-offset: 0.25em;
|
||||
color: var(--link-color);
|
||||
border-radius: 2px;
|
||||
display: inline;
|
||||
padding: 0.25em;
|
||||
margin: -0.25em;
|
||||
line-height: 1.2;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
kr-layout::part(skip-link):is(:hover),
|
||||
a:is(:hover) {
|
||||
color: var(--link-color-focus);
|
||||
}
|
||||
|
||||
|
||||
kr-layout::part(skip-link):is(:focus-visible),
|
||||
a:is(:focus-visible) {
|
||||
box-shadow: 0px 0px 3px 3px var(--sl-color-primary-600);
|
||||
outline: transparent;
|
||||
/* for when Safari supports border-radius */
|
||||
/* outline: 3px solid var(--sl-color-primary-600); */
|
||||
/* outline-offset: 4px; */
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
kr-layout::part(skip-link):is(:focus),
|
||||
a:is(:focus) {
|
||||
box-shadow: 0px 0px 3px 3px var(--sl-color-primary-600);
|
||||
outline: transparent;
|
||||
/* for when Safari supports border-radius */
|
||||
/* outline: 3px solid var(--sl-color-primary-600); */
|
||||
/* outline-offset: 4px; */
|
||||
}
|
||||
}
|
||||
|
||||
code > span {
|
||||
line-height: var(--sl-line-height-dense);
|
||||
}
|
||||
|
||||
kbd {
|
||||
font-family: var(--sl-font-mono);
|
||||
font-size: 87.5%;
|
||||
background-color: var(--sl-color-neutral-50);
|
||||
border-radius: 4px;
|
||||
border: solid 1px var(--sl-color-neutral-200);
|
||||
box-shadow: inset 0 1px 0 var(--sl-color-neutral-0);
|
||||
padding: 2px 5px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
a external-icon {
|
||||
padding-top: 0.25em;
|
||||
font-size: 0.75em;
|
||||
margin-inline-start: -0.15em;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-inline-start: 4px solid var(--divider-color);
|
||||
margin-inline-start: 0.5rem;
|
||||
padding: 0.75rem;
|
||||
background-color: var(--sl-color-neutral-50);
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
@import "./overrides/bridgetown-ninja-keys.css";
|
||||
@import "./overrides/shoelace.css";
|
||||
@@ -0,0 +1,13 @@
|
||||
sl-alert {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
|
||||
sl-alert p {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
sl-alert::part(base) {
|
||||
box-shadow: 3px 3px 6px 1px var(--sl-color-neutral-100);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
[style*="--aspect-ratio"] > :first-child {
|
||||
width: 100%;
|
||||
}
|
||||
[style*="--aspect-ratio"] > img {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[style*="--aspect-ratio"] {
|
||||
position: relative;
|
||||
}
|
||||
[style*="--aspect-ratio"]::before {
|
||||
content: "";
|
||||
display: block;
|
||||
padding-bottom: calc(100% / (var(--aspect-ratio)));
|
||||
}
|
||||
[style*="--aspect-ratio"] > :first-child {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
.blog-link:focus {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.blog-link:focus .blog-link__card::part(base) {
|
||||
box-shadow: 0px 0px 4px 1px var(--sl-color-primary-700);
|
||||
}
|
||||
|
||||
.blog-link__card::part(base) {
|
||||
transform: translateY(0px);
|
||||
transition: transform 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
.blog-link:is(:focus, :hover) .blog-link__card::part(base) {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.blog-link,
|
||||
.blog-link:focus {
|
||||
color: var(--sl-color-neutral-700);
|
||||
}
|
||||
|
||||
.blog-link:is(:hover) {
|
||||
color: var(--sl-color-primary-900);
|
||||
}
|
||||
|
||||
.blog-link:is(:hover) .blog-link__card::part(base) {
|
||||
border: 1px solid var(--sl-color-primary-700);
|
||||
background-color: var(--sl-color-primary-50);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/** Button */
|
||||
.button {
|
||||
padding: 0.4em 0.6em;
|
||||
display: block;
|
||||
position: relative;
|
||||
width: auto;
|
||||
cursor: pointer;
|
||||
|
||||
display: inline-flex;
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
border-style: solid;
|
||||
border-width: var(--sl-input-border-width);
|
||||
font-family: var(--sl-input-font-family);
|
||||
font-weight: var(--sl-font-weight-semibold);
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
transition: var(--sl-transition-x-fast) background-color, var(--sl-transition-x-fast) color,
|
||||
var(--sl-transition-x-fast) border, var(--sl-transition-x-fast) box-shadow;
|
||||
background-color: var(--sl-color-neutral-0);
|
||||
border-color: var(--sl-color-neutral-300);
|
||||
color: var(--sl-color-neutral-700);
|
||||
font-size: var(--sl-button-font-size-medium);
|
||||
border-radius: var(--sl-input-border-radius-medium);
|
||||
}
|
||||
|
||||
.button::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.button:focus {
|
||||
outline: transparent;
|
||||
}
|
||||
|
||||
.button:focus-visible {
|
||||
outline: var(--sl-focus-ring);
|
||||
outline-offset: var(--sl-focus-ring-offset);
|
||||
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: var(--sl-color-primary-50);
|
||||
border-color: var(--sl-color-primary-300);
|
||||
color: var(--sl-color-primary-700);
|
||||
}
|
||||
|
||||
.button:active {
|
||||
background-color: var(--sl-color-primary-100);
|
||||
border-color: var(--sl-color-primary-400);
|
||||
color: var(--sl-color-primary-700);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
.call-to-action__items {
|
||||
margin-top: 1.75rem;
|
||||
margin-bottom: 3rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.reason__grid {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.reason__grid > * {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.reason__grid {
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/** Clipboard **/
|
||||
.clipboard.clipboard--success:is(:hover, :focus, :active),
|
||||
.clipboard.clipboard--success {
|
||||
background-color: var(--sl-color-success-100);
|
||||
border-color: var(--sl-color-success-600);
|
||||
color: var(--sl-color-success-800);
|
||||
}
|
||||
|
||||
.clipboard {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.clipboard sl-icon {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.clipboard__icon--success, .clipboard__icon--idle {
|
||||
transition: transform .2s ease-in-out;
|
||||
}
|
||||
|
||||
.clipboard .clipboard__icon--idle,
|
||||
.clipboard.clipboard--success .clipboard__icon--success {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.clipboard.clipboard--success .clipboard__icon--idle,
|
||||
.clipboard.clipboard--idle .clipboard__icon--success {
|
||||
height: 0;
|
||||
width: 0;
|
||||
visibility: hidden;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
.contact__title {
|
||||
line-height: 1.3;
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
.footer {
|
||||
width: 100%;
|
||||
margin-top: auto;
|
||||
padding: var(--sl-spacing-large) var(--sl-spacing-2x-small);
|
||||
text-align: center;
|
||||
background-color: var(--sl-color-neutral-50);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
.nav-header {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
padding: 0.5rem;
|
||||
padding-inline-end: 1.5rem;
|
||||
font-size: 1.05em;
|
||||
justify-items: space-between;
|
||||
border-bottom: 1px solid var(--sl-color-neutral-200);
|
||||
background-color: var(--body-color);
|
||||
min-height: var(--header-height);
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
.hero {
|
||||
margin: 0 auto;
|
||||
padding: 16px;
|
||||
max-width: 600px;
|
||||
}
|
||||
|
||||
.hero--mobile {
|
||||
display: flex;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.hero--mobile a {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
width: auto;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.hero--mobile .logo__text{
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
|
||||
.hero__caption {
|
||||
font-size: 0.85em;
|
||||
margin-top: 6px;
|
||||
border-inline-start: 4px solid var(--divider-color);
|
||||
padding-inline-start: 8px;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
.input {
|
||||
font-size: var(--input-font-size);
|
||||
font-family: inherit;
|
||||
padding: var(--input-padding);
|
||||
background-color: var(--input-bg-color);
|
||||
border: var(--input-border-width) var(--input-border-style) var(--input-border-color);
|
||||
border-radius: var(--input-border-radius);
|
||||
height: var(--sl-spacing-2x-large);
|
||||
color: var(--sl-color-neutral-700);
|
||||
}
|
||||
|
||||
.input {
|
||||
transition: 150ms box-shadow ease-in-out;
|
||||
}
|
||||
|
||||
.input:focus,
|
||||
.input:hover {
|
||||
border-color: var(--sl-color-primary-500);
|
||||
}
|
||||
|
||||
.input:focus {
|
||||
box-shadow: 0 0 0 var(--input-focus-ring-width)
|
||||
hsla(198.6 88.7% 48.4% / 0.4);
|
||||
|
||||
/* for users who may have shadows and other colors turned off */
|
||||
outline: var(--input-focus-ring-width) solid transparent;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
:is(.index, .doc, .page, .post) kr-layout {
|
||||
background-color: var(--sl-color-neutral-50);
|
||||
}
|
||||
|
||||
/* .documentation-content {} */
|
||||
|
||||
body:is(.index, .doc, .page, .post) kr-layout::part(main-content) {
|
||||
background: var(--body-color);
|
||||
}
|
||||
|
||||
kr-layout > [slot='aside'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Janky hack for iOS mobile */
|
||||
.fixed-body {
|
||||
position: fixed;
|
||||
height: var(--viewport-height, 100%);
|
||||
width: 100%;
|
||||
/* Allow the main content to be scrolled,
|
||||
so we can adjust the scroll position with JS. */
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
body:is(.default, .home) kr-layout {
|
||||
--menu-width: 0px;
|
||||
--main-width: 1fr;
|
||||
--aside-width: 0px;
|
||||
}
|
||||
|
||||
kr-layout {
|
||||
--menu-width: auto;
|
||||
--main-width: 105ch;
|
||||
--aside-width: auto;
|
||||
}
|
||||
|
||||
kr-layout,
|
||||
kr-layout::part(skip-links) {
|
||||
background-color: var(--body-color);
|
||||
}
|
||||
|
||||
kr-layout::part(body) {
|
||||
max-width: 100%;
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
kr-layout::part(main) {
|
||||
background-color: var(--body-color);
|
||||
}
|
||||
|
||||
main {
|
||||
max-width: 100%;
|
||||
padding: 0 var(--main-padding-x) 2rem;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
background-color: var(--body-color);
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
:is(.default, .home) main {
|
||||
max-width: var(--main-width);
|
||||
}
|
||||
|
||||
:is(.default, .home) .footer {
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
:is(.doc, .index, .page, .post) main {
|
||||
background-color: var(--body-color);
|
||||
}
|
||||
|
||||
|
||||
@media screen and (min-width: 1360px) {
|
||||
kr-layout > [slot='aside'] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
body:is(.index, .doc, .page, .post) kr-layout::part(main),
|
||||
body:is(.index, .doc, .page, .post) kr-layout::part(menu),
|
||||
body:is(.index, .doc, .page, .post) kr-layout::part(aside) {
|
||||
padding-top: 2rem;
|
||||
}
|
||||
|
||||
.documentation-content {
|
||||
border-radius: 32px;
|
||||
}
|
||||
|
||||
body:is(.index, .doc, .page, .post) kr-layout::part(main) {
|
||||
background-color: transparent;
|
||||
margin-inline-end: 16px;
|
||||
margin-inline-start: 16px;
|
||||
|
||||
}
|
||||
|
||||
body:is(.index, .doc, .page, .post) kr-layout::part(main-content) {
|
||||
box-shadow: 0 0 5px 0 rgb(0 0 0 / 10%);
|
||||
background: var(--body-color);
|
||||
border-radius: 32px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
.logo__link {
|
||||
display: flex;
|
||||
flex: 1 0 auto;
|
||||
width: auto;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.logo__link:is(:focus, :hover) {
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: solid;
|
||||
text-decoration-color: var(--link-color);
|
||||
color: var(--link-color-focus);
|
||||
}
|
||||
|
||||
.logo__link:is(:focus, :hover) * {
|
||||
color: var(--link-color-focus);
|
||||
}
|
||||
|
||||
.blog-link__header,
|
||||
.contact__link,
|
||||
.main-list__link,
|
||||
.side-nav__link,
|
||||
.nav-link {
|
||||
font-weight: bold;
|
||||
color: var(--sl-color-neutral-800);
|
||||
text-decoration-line: underline;
|
||||
text-decoration-style: solid;
|
||||
text-decoration-color: var(--sl-color-primary-500);
|
||||
text-underline-offset: 0.3em;
|
||||
}
|
||||
|
||||
.link__flex {
|
||||
display: inline-flex;
|
||||
gap: 0.25em;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
max-width: max-content;
|
||||
}
|
||||
|
||||
.link--small {
|
||||
font-size: 0.85em;
|
||||
}
|
||||
|
||||
.link--large {
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
ul.list li {
|
||||
line-height: 2.5;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
.main-list {
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.main-list__item {
|
||||
padding: 8px;
|
||||
max-width: 100%;
|
||||
line-height: 1.3;
|
||||
font-size: 1.25rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 400px) {
|
||||
.main-list {
|
||||
grid-auto-flow: column;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/** Pagination */
|
||||
sl-button:is(.previous-page, .next-page) {
|
||||
transition: transform 0.15s;
|
||||
}
|
||||
|
||||
sl-button:is(.previous-page, .next-page)::part(label) {
|
||||
max-width: calc(100% - 24px);
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
sl-button:is(.next-page)::part(base) {
|
||||
justify-content: start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
sl-button:is(.previous-page)::part(base) {
|
||||
justify-content: end;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
sl-button:is(.next-page, .previous-page):is(:hover, :focus) {
|
||||
box-shadow: var(--sl-color-neutral-50) 0px 12px 13px;
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.pagination-footer {
|
||||
padding-top: 2rem;
|
||||
margin-top: auto;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
|
||||
justify-content: space-between;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
pagination-title {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
font-size: 1.15rem;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
.side-nav ul {
|
||||
list-style-type: " ";
|
||||
}
|
||||
|
||||
.side-nav__menu {
|
||||
margin: 0;
|
||||
padding-inline-start: 0;
|
||||
min-width: 250px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
ul.side-nav__menu li::marker {
|
||||
content: ""
|
||||
}
|
||||
|
||||
.side-nav__item {
|
||||
padding: 8px;
|
||||
max-width: 100%;
|
||||
line-height: 1.3;
|
||||
font-size: 1rem;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.side-nav__link {
|
||||
font-weight: normal;
|
||||
text-decoration: none;
|
||||
color: var(--sl-color-neutral-700);
|
||||
}
|
||||
|
||||
.side-nav__link:is(:hover, :focus) {
|
||||
color: var(--link-color);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.side-nav--desktop {
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
max-width: 275px;
|
||||
max-height: 100%;
|
||||
padding-bottom: 1rem;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.side-nav__menu {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
.side-nav__drawer__header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
border-bottom: 1px solid var(--sl-color-neutral-200);
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
|
||||
.side-nav__item.is-active {
|
||||
font-weight: normal;
|
||||
border-inline-start: 4px solid var(--sl-color-primary-600);
|
||||
background-color: var(--sl-color-primary-100);
|
||||
}
|
||||
|
||||
.side-nav__item.is-active,
|
||||
.side-nav__item.is-active a {
|
||||
color: var(--sl-color-primary-700);
|
||||
}
|
||||
|
||||
.side-nav__category-header {
|
||||
font-size: 1.25rem;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.side-nav__category-menu:not(:first-child) {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
.side-nav--desktop {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.side-nav__category-menu {
|
||||
padding-inline-start: 40px;
|
||||
}
|
||||
|
||||
.side-nav__category-menu:first-of-type {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.side-nav__drawer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
.syntax-block {
|
||||
position: relative;
|
||||
margin-block-end: 1rem;
|
||||
margin-block-start: 1rem;
|
||||
}
|
||||
|
||||
.syntax-block {
|
||||
border: 1px solid var(--divider-color);
|
||||
border-radius: var(--sl-border-radius-large);
|
||||
}
|
||||
|
||||
.syntax-block pre {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.syntax-block__actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 4px 8px;
|
||||
}
|
||||
|
||||
.syntax-block .highlight {
|
||||
border-top-right-radius: 0px;
|
||||
border-top-left-radius: 0px;
|
||||
}
|
||||
|
||||
.syntax-block__badge {
|
||||
font-size: 0.85em;
|
||||
color: var(--sl-color-neutral-700);
|
||||
}
|
||||
|
||||
:is(.language-bash, .language-shell, .language-zsh, .language-sh).highlighter-rouge pre.highlight::before {
|
||||
content: "$";
|
||||
user-select: none;
|
||||
padding-inline-end: 0.45em;
|
||||
color: gray;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
.table-of-contents {
|
||||
margin-inline-start: 1rem;
|
||||
min-width: 275px;
|
||||
max-width: 275px;
|
||||
}
|
||||
|
||||
.table-of-contents * {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.table-of-contents__header {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding-top: 1rem;
|
||||
font-weight: normal;
|
||||
color: var(--sl-color-neutral-800);
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.table-of-contents__list {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-top: 1rem;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.table-of-contents__list a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.table-of-contents__list li {
|
||||
border-inline-start: 4px solid var(--sl-color-neutral-400);
|
||||
padding-inline-start: 1rem;
|
||||
}
|
||||
|
||||
.table-of-contents__list li {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
.table-container {
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
min-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: start;
|
||||
font-weight: 500;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
tr {
|
||||
border-bottom: 1px solid var(--divider-color);
|
||||
}
|
||||
|
||||
tbody > tr:nth-of-type(2n) {
|
||||
background-color: rgba(0,0,0,0.02);
|
||||
}
|
||||
|
||||
tbody > tr code {
|
||||
border: 1px solid rgba(0,0,0,0.2);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
.logo__text {
|
||||
color: var(--text-color-primary);
|
||||
font-size: var(--sl-font-size-x-large);
|
||||
padding-bottom: var(--sl-spacing-x-small);
|
||||
margin-bottom: calc(var(--sl-spacing-x-small) - (var(--sl-spacing-x-small) * 2));
|
||||
margin-inline-start: var(--sl-spacing-2x-small);
|
||||
}
|
||||
|
||||
.site-title,
|
||||
.slogan {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.slogan {
|
||||
max-width: max(75%, 600px);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.site-title {
|
||||
margin-top: 0;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Themes */
|
||||
.theme-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
[data-controller~='theme-switcher'],
|
||||
[data-controller~='theme-switcher']:not(:defined) {
|
||||
height: 0;
|
||||
width: 0;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
[data-controller~='theme-switcher']:defined {
|
||||
height: unset;
|
||||
width: unset;
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
animation: fadeInAnimation ease 500ms;
|
||||
animation-iteration-count: 1;
|
||||
animation-fill-mode: forwards;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
.top-nav {
|
||||
display: flex;
|
||||
max-width: var(--top-nav-max-width);
|
||||
justify-content: center;
|
||||
margin: 0 auto;
|
||||
background-color: var(--body-color);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.top-nav__search,
|
||||
.top-nav__go-home,
|
||||
.top-nav__categories {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.top-nav__go-home {
|
||||
min-width: 100px;
|
||||
}
|
||||
|
||||
.top-nav__hamburger__button {
|
||||
font-size: 1.75em;
|
||||
}
|
||||
|
||||
.top-nav__hamburger__button::part(base),
|
||||
.top-nav__search__button::part(base) {
|
||||
color: var(--sl-color-gray-600);
|
||||
font-size: var(--sl-font-size-x-large);
|
||||
}
|
||||
|
||||
.top-nav__hamburger__button::part(base):is(:hover, :focus),
|
||||
.top-nav__search__button::part(base):is(:hover, :focus) {
|
||||
color: var(--link-color-focus);
|
||||
}
|
||||
|
||||
.top-nav__hamburger__button::part(base):focus,
|
||||
.top-nav__search__button::part(base):focus {
|
||||
border-color: var(--link-color-focus);
|
||||
box-shadow: 0 0 6px var(--link-color-focus);
|
||||
}
|
||||
|
||||
.top-nav__search {
|
||||
margin: 0;
|
||||
margin-inline-start: auto;
|
||||
}
|
||||
|
||||
.top-nav__github sl-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.top-nav__github {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.top-nav__links {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
flex: 0 1 auto;
|
||||
}
|
||||
|
||||
.top-nav__categories {
|
||||
display: none;
|
||||
font-family: var(--sl-font-sans);
|
||||
font-weight: bold;
|
||||
min-width: fit-content;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.top-nav__categories > * {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.top-nav__github {
|
||||
padding-top: var(--sl-spacing-2x-small);
|
||||
margin-inline-start: var(--sl-spacing-medium);
|
||||
margin-inline-end: 2px;
|
||||
}
|
||||
|
||||
.top-nav__go-home,
|
||||
.top-nav__command-palette-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
/* .hero--mobile, */
|
||||
.top-nav__hamburger__button,
|
||||
.top-nav__search__button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.top-nav__go-home,
|
||||
.top-nav__command-palette-button {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.top-nav__search {
|
||||
margin: 0 auto 0 auto;
|
||||
order: unset;
|
||||
}
|
||||
|
||||
.top-nav__categories {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
10
docs/assets/scripts/light-pen/docs/frontend/styles/defer.css
Normal file
10
docs/assets/scripts/light-pen/docs/frontend/styles/defer.css
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Anything that can be deferred and not cause layout shift.
|
||||
* IE: colors, fonts, syntax highlighting, etc.
|
||||
*/
|
||||
|
||||
@import "@shoelace-style/shoelace/dist/themes/light.css";
|
||||
@import "@shoelace-style/shoelace/dist/themes/dark.css";
|
||||
@import "./tokens/_colors.css";
|
||||
@import "./defer/_syntax.css";
|
||||
@import "./defer/_fonts.css";
|
||||
@@ -0,0 +1,17 @@
|
||||
@keyframes fadeInAnimation {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fadeOutAnimation {
|
||||
0% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
/** Nothing here...yet */
|
||||
/* @font-face { */
|
||||
/* font-family: 'VT323'; */
|
||||
/* src: */
|
||||
/* url('/assets/fonts/VT323.ttf') format('truetype'); */
|
||||
/* font-display: swap; */
|
||||
/* font-weight: 400; */
|
||||
/* font-style: normal; */
|
||||
/* font-stretch: 100; */
|
||||
/* } */
|
||||
@@ -0,0 +1,67 @@
|
||||
/** Syntax highlighting only */
|
||||
.highlight { color: black; background-color: #f8f8f8; font-family: var(--sl-font-mono); }
|
||||
.highlight * { font-family: var(--sl-font-mono); }
|
||||
.highlight .hll { background-color: #ffffcc }
|
||||
.highlight .c { color: #999988; font-style: italic } /* Comment */
|
||||
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
|
||||
.highlight .k { color: #000000; font-weight: bold } /* Keyword */
|
||||
.highlight .o { color: #000000; font-weight: bold } /* Operator */
|
||||
.highlight .ch { color: #999988; font-style: italic } /* Comment.Hashbang */
|
||||
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
|
||||
.highlight .cp { color: #999999; font-weight: bold; font-style: italic } /* Comment.Preproc */
|
||||
.highlight .cpf { color: #999988; font-style: italic } /* Comment.PreprocFile */
|
||||
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
|
||||
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
|
||||
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
|
||||
.highlight .ge { color: #000000; font-style: italic } /* Generic.Emph */
|
||||
.highlight .gr { color: #aa0000 } /* Generic.Error */
|
||||
.highlight .gh { color: #999999 } /* Generic.Heading */
|
||||
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
|
||||
.highlight .go { color: #888888 } /* Generic.Output */
|
||||
.highlight .gp { color: #555555 } /* Generic.Prompt */
|
||||
.highlight .gs { font-weight: bold } /* Generic.Strong */
|
||||
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
|
||||
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
|
||||
.highlight .kc { color: #000000; font-weight: bold } /* Keyword.Constant */
|
||||
.highlight .kd { color: #000000; font-weight: bold } /* Keyword.Declaration */
|
||||
.highlight .kn { color: #000000; font-weight: bold } /* Keyword.Namespace */
|
||||
.highlight .kp { color: #000000; font-weight: bold } /* Keyword.Pseudo */
|
||||
.highlight .kr { color: #000000; font-weight: bold } /* Keyword.Reserved */
|
||||
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
|
||||
.highlight .m { color: #009999 } /* Literal.Number */
|
||||
.highlight .s { color: #dd1144 } /* Literal.String */
|
||||
.highlight .na { color: #008080 } /* Name.Attribute */
|
||||
.highlight .nb { color: #0086B3 } /* Name.Builtin */
|
||||
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
|
||||
.highlight .no { color: #008080 } /* Name.Constant */
|
||||
.highlight .nd { color: #3c5d5d; font-weight: bold } /* Name.Decorator */
|
||||
.highlight .ni { color: #800080 } /* Name.Entity */
|
||||
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
|
||||
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
|
||||
.highlight .nl { color: #990000; font-weight: bold } /* Name.Label */
|
||||
.highlight .nn { color: #555555 } /* Name.Namespace */
|
||||
.highlight .nt { color: #000080 } /* Name.Tag */
|
||||
.highlight .nv { color: #008080 } /* Name.Variable */
|
||||
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
|
||||
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.highlight .mb { color: #009999 } /* Literal.Number.Bin */
|
||||
.highlight .mf { color: #009999 } /* Literal.Number.Float */
|
||||
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
|
||||
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
|
||||
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
|
||||
.highlight .sb { color: #dd1144 } /* Literal.String.Backtick */
|
||||
.highlight .sc { color: #dd1144 } /* Literal.String.Char */
|
||||
.highlight .sd { color: #dd1144 } /* Literal.String.Doc */
|
||||
.highlight .s2 { color: #dd1144 } /* Literal.String.Double */
|
||||
.highlight .se { color: #dd1144 } /* Literal.String.Escape */
|
||||
.highlight .sh { color: #dd1144 } /* Literal.String.Heredoc */
|
||||
.highlight .si { color: #dd1144 } /* Literal.String.Interpol */
|
||||
.highlight .sx { color: #dd1144 } /* Literal.String.Other */
|
||||
.highlight .sr { color: #009926 } /* Literal.String.Regex */
|
||||
.highlight .s1 { color: #dd1144 } /* Literal.String.Single */
|
||||
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
|
||||
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
|
||||
.highlight .vc { color: #008080 } /* Name.Variable.Class */
|
||||
.highlight .vg { color: #008080 } /* Name.Variable.Global */
|
||||
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
|
||||
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
|
||||
@@ -0,0 +1,9 @@
|
||||
/* Tokens */
|
||||
@import "./tokens/_layout.css";
|
||||
@import "./tokens/_typography.css";
|
||||
|
||||
@import "./_normalize.css";
|
||||
@import "./_components.css";
|
||||
@import "./_content.css";
|
||||
@import "./_layout.css";
|
||||
@import "./_overrides.css";
|
||||
@@ -0,0 +1,30 @@
|
||||
bridgetown-ninja-keys {
|
||||
/* This is a hacky media query. We do this so that we can guess for mobile devices we should
|
||||
be full height / width so we don't need to deal with dialog scrolling bullshit. */
|
||||
--ninja-top: 0px;
|
||||
--ninja-width: clamp(200px, 100vw, 100ch);
|
||||
--ninja-accent-color: var(--sl-color-primary-600);
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
bridgetown-ninja-keys::part(modal-content) {
|
||||
height: 100%;
|
||||
--ninja-actions-height: 100%;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
bridgetown-ninja-keys::part(modal-content) {
|
||||
height: unset;
|
||||
|
||||
--ninja-top: 10vh;
|
||||
--ninja-actions-height: 60vh;
|
||||
--ninja-width: clamp(200px, 90vw, 100ch);
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
bridgetown-ninja-keys.dark {
|
||||
--ninja-modal-background: rgba(35, 35, 35, 1);
|
||||
--ninja-text-color: gray;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
:where(sl-visually-hidden:not(:defined)) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/** Bypass a11y checker. */
|
||||
sl-visually-hidden {
|
||||
background-color: var(--sl-color-neutral-0);
|
||||
background-color: var(--sl-color-neutral-1000);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
:root,
|
||||
html.sl-theme-light,
|
||||
html.sl-theme-dark {
|
||||
/** Colors */
|
||||
--text-color: var(--sl-color-neutral-1000);
|
||||
--light-text-color: var(--sl-color-neutral-700);
|
||||
--body-color: var(--sl-color-neutral-0);
|
||||
|
||||
--logo-color: var(--sl-color-neutral-1000);
|
||||
|
||||
--input-border-color: var(--divider-color);
|
||||
--input-bg-color: var(--sl-color-neutral-0);
|
||||
--input-transition: 100ms box-shadow ease-in-out;
|
||||
|
||||
--color-primary: var(--sl-color-primary-600);
|
||||
--text-color-primary: var(--sl-color-primary-700);
|
||||
--link-color: var(--sl-color-primary-700);
|
||||
--link-color-focus: var(--sl-color-primary-500);
|
||||
--divider-color: var(--sl-color-neutral-300);
|
||||
--code-color: hsl(209, 27%, 26%);
|
||||
--code-background-color: hsl(210, 29%, 97%);
|
||||
|
||||
/** Shoelace overrides */
|
||||
/* --sl-color-primary-50: var(--sl-color-emerald-50); */
|
||||
/* --sl-color-primary-100: var(--sl-color-emerald-100); */
|
||||
/* --sl-color-primary-200: var(--sl-color-emerald-200); */
|
||||
/* --sl-color-primary-300: var(--sl-color-emerald-300); */
|
||||
/* --sl-color-primary-400: var(--sl-color-emerald-400); */
|
||||
/* --sl-color-primary-500: var(--sl-color-emerald-500); */
|
||||
/* --sl-color-primary-600: var(--sl-color-emerald-600); */
|
||||
/* --sl-color-primary-700: var(--sl-color-emerald-700); */
|
||||
/* --sl-color-primary-800: var(--sl-color-emerald-800); */
|
||||
/* --sl-color-primary-900: var(--sl-color-emerald-900); */
|
||||
/* --sl-color-primary-950: var(--sl-color-emerald-950); */
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
:root,
|
||||
html.sl-theme-light,
|
||||
html.sl-theme-dark {
|
||||
/* Layout related tokens (anything that affects layout shift) */
|
||||
--z-header: 2;
|
||||
--z-search: 3;
|
||||
|
||||
--top-nav-max-width: 1650px;
|
||||
--body-max-width: 1800px;
|
||||
--side-nav-width: 300px;
|
||||
--main-width: clamp(75ch, 70vw, 100ch);
|
||||
--main-padding-x: 2rem;
|
||||
--input-focus-ring-width: 3px;
|
||||
--input-font-size: var(--sl-font-size-size-medium);
|
||||
|
||||
--input-sm-padding: var(--sl-spacing-2x-small) var(--sl-spacing-x-small);
|
||||
--input-padding: var(--sl-spacing-medium) var(--sl-spacing-large);
|
||||
|
||||
--input-border-width: 1px;
|
||||
--input-border-style: solid;
|
||||
--input-border-radius: 4px;
|
||||
|
||||
--header-height: 58px;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
:root,
|
||||
html.sl-theme-dark,
|
||||
html.sl-theme-light {
|
||||
--sl-font-sans:
|
||||
-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
|
||||
--sl-font-serif: Georgia, 'Times New Roman', serif;
|
||||
--sl-font-mono: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, monospace;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class Builders::ChangelogGenerator < SiteBuilder
|
||||
def build
|
||||
# changelog_file = File.expand_path("../../../CHANGELOG.md", __dir__)
|
||||
# add_resource :documentation, "references/00-changelog.md" do
|
||||
# title "Changelog"
|
||||
# permalink "/references/changelog"
|
||||
# category "references"
|
||||
# content File.read(changelog_file)
|
||||
# end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,275 @@
|
||||
require "cgi"
|
||||
require "custom_elements_manifest_parser"
|
||||
|
||||
class Builders::ComponentGenerator < SiteBuilder
|
||||
def build
|
||||
generator do
|
||||
custom_elements_manifest_path = File.read(File.expand_path("../../../custom-elements.json", __dir__))
|
||||
manifest = JSON.parse(custom_elements_manifest_path)
|
||||
|
||||
# @return [::CustomElementsManifestParser::Parser]
|
||||
parser = ::CustomElementsManifestParser.parse(manifest)
|
||||
elements = parser.find_all_tag_names
|
||||
|
||||
resources = site.collections.documentation.resources
|
||||
|
||||
resources.each do |resource|
|
||||
component_name = File.basename(resource.relative_path.basename, ".md").to_s
|
||||
|
||||
metadata = elements[component_name]
|
||||
next if metadata.nil?
|
||||
|
||||
resource.data.merge!({
|
||||
"description" => metadata.description
|
||||
})
|
||||
|
||||
slots = metadata.slots
|
||||
attributes = metadata.members.select { |member| member.attributes[:attribute] }
|
||||
events = metadata.events
|
||||
|
||||
# Use functions instead of methods so we don't clobber built-in #methods method.
|
||||
functions = metadata.members.select { |member| member.kind == "method" }
|
||||
|
||||
parts = metadata.cssParts
|
||||
|
||||
resource.content += [
|
||||
slots_table(slots).html_safe,
|
||||
attributes_table(attributes).html_safe,
|
||||
events_table(events).html_safe,
|
||||
functions_table(functions).html_safe,
|
||||
parts_table(parts).html_safe
|
||||
].join("\n\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def escape(html)
|
||||
CGI.escape_html(html || "")
|
||||
end
|
||||
|
||||
def slots_table(slots)
|
||||
return "" if slots.nil? || slots.empty?
|
||||
|
||||
tbody = slots.map do |slot|
|
||||
<<~HTML
|
||||
<tr>
|
||||
<td>
|
||||
<code>#{slot.name}</code>
|
||||
</td>
|
||||
<td>
|
||||
#{slot.description.to_s.empty? ? "-" : escape(slot.description)}
|
||||
</td>
|
||||
</tr>
|
||||
HTML
|
||||
end.join("\n")
|
||||
|
||||
<<~HTML
|
||||
## Slots
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#{tbody}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
HTML
|
||||
end
|
||||
|
||||
def attributes_table(members)
|
||||
return "" if members.nil? || members.empty?
|
||||
|
||||
tbody = members.map do |member|
|
||||
type_text = ""
|
||||
|
||||
type_text = member.type.text if member.type && member.type.text
|
||||
|
||||
<<~HTML
|
||||
<tr>
|
||||
<td>
|
||||
<% if "#{member.attribute}" != "#{member.name}" %>
|
||||
<small>[Attribute]</small>
|
||||
<br>
|
||||
<code>#{member.attribute}</code>
|
||||
<br><br>
|
||||
<small>[Property]</small>
|
||||
<br>
|
||||
<code>#{member.name}</code>
|
||||
<% elsif not("#{member.attribute}".blank?) %>
|
||||
<small>[Attribute + Property]</small>
|
||||
<br>
|
||||
<code>#{member.attribute}</code>
|
||||
<% else %>
|
||||
<small>[Property Only]</small>
|
||||
<br>
|
||||
<code>#{member.name}</code>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
#{member.description.to_s.empty? ? "-" : escape(member.description)}
|
||||
</td>
|
||||
<td>
|
||||
#{member.reflects ? "<sl-icon name='check-lg'></sl-icon>" : "-"}
|
||||
</td>
|
||||
<td>
|
||||
#{type_text.blank? ? "-" : "<code>#{escape(type_text)}</code>"}
|
||||
</td>
|
||||
<td>
|
||||
#{member.default.nil? ? "-" : "<code>#{escape(member.default)}</code>"}
|
||||
</td>
|
||||
</tr>
|
||||
HTML
|
||||
end.join("\n")
|
||||
|
||||
<<~HTML
|
||||
## Attributes
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Reflects</th>
|
||||
<th>Type</th>
|
||||
<th>Default</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#{tbody}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
HTML
|
||||
end
|
||||
|
||||
def events_table(events)
|
||||
return "" if events.nil? || events.empty?
|
||||
|
||||
|
||||
tbody = events.map do |event|
|
||||
<<~HTML
|
||||
<tr>
|
||||
<td>
|
||||
#{event.name}
|
||||
</td>
|
||||
<td>
|
||||
</td>
|
||||
</tr>
|
||||
HTML
|
||||
end
|
||||
|
||||
<<~HTML
|
||||
## Events
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#{tbody}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
HTML
|
||||
end
|
||||
|
||||
def parameter_string(parameter)
|
||||
rest = parameter.rest ? "..." : ""
|
||||
# optional = parameter.optional ? "?" : ""
|
||||
type_text = ""
|
||||
type_text = ": " + parameter.type.text if parameter.type && parameter.type.text
|
||||
|
||||
rest + parameter.name + type_text
|
||||
end
|
||||
|
||||
def functions_table(functions)
|
||||
return "" if functions.nil? || functions.empty?
|
||||
|
||||
tbody = functions.map do |function|
|
||||
parameters = "-"
|
||||
if not(function.parameters.to_s.empty?)
|
||||
parameters = "<code>" + escape(function.parameters.map { |parameter| parameter_string(parameter) }.join(", ")) + "</code>"
|
||||
end
|
||||
|
||||
<<~HTML
|
||||
<tr>
|
||||
<td>
|
||||
<code>#{function.name}()</code>
|
||||
</td>
|
||||
<td>
|
||||
#{function.description.to_s.empty? ? "-" : escape(function.description.to_s)}
|
||||
</td>
|
||||
<td>
|
||||
#{parameters}
|
||||
</td>
|
||||
</tr>
|
||||
HTML
|
||||
end.join("\n")
|
||||
|
||||
<<~HTML
|
||||
## Functions
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
<th>Parameters</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#{tbody}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
HTML
|
||||
end
|
||||
|
||||
def parts_table(parts)
|
||||
return "" if parts.nil? || parts.empty?
|
||||
|
||||
tbody = parts.map do |part|
|
||||
<<~HTML
|
||||
<tr>
|
||||
<td>
|
||||
<code>#{part.name}</code>
|
||||
</td>
|
||||
<td>
|
||||
#{part.description.to_s.empty? ? "-" : escape(part.description)}
|
||||
</td>
|
||||
</tr>
|
||||
HTML
|
||||
end.join("\n")
|
||||
|
||||
<<~HTML
|
||||
## Parts
|
||||
|
||||
<div class="table-container">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
#{tbody}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
HTML
|
||||
end
|
||||
|
||||
end
|
||||
138
docs/assets/scripts/light-pen/docs/plugins/builders/helpers.rb
Normal file
138
docs/assets/scripts/light-pen/docs/plugins/builders/helpers.rb
Normal file
@@ -0,0 +1,138 @@
|
||||
require 'json'
|
||||
require "nokogiri"
|
||||
require "asset_mapper"
|
||||
|
||||
class Builders::Helpers < SiteBuilder
|
||||
def build
|
||||
# Create an AssetMapper::Configuration instance
|
||||
@asset_mapper = AssetMapper.new.configure do |config|
|
||||
# Where the manifest files can be found on the host machine
|
||||
config.manifest_files = [".bridgetown-cache/asset-mapper-manifest.json"]
|
||||
|
||||
# The URL or path prefix for the files.
|
||||
config.asset_host = ENV["BASE_PATH"] + "/bridgetown/static"
|
||||
|
||||
# Do not cache the manifest in testing or in development.
|
||||
config.cache_manifest = false
|
||||
end
|
||||
|
||||
helper "find_asset", :find_asset
|
||||
helper "find_asset_file_path", :find_asset_file_path
|
||||
helper "version_number", :version_number
|
||||
helper "render_svg", :render_svg
|
||||
# All pages in "_documentation"
|
||||
helper "doc_collection", :doc_collection
|
||||
|
||||
# Categories are top level in "_documentation"
|
||||
# "_documentation/how_tos", "how_tos" is a category
|
||||
helper "ordered_categories", :ordered_categories
|
||||
helper "ordered_categories_hash_map", :ordered_categories_hash_map
|
||||
|
||||
helper "docs_without_indexes", :docs_without_indexes
|
||||
helper "docs_in_category", :docs_in_category
|
||||
helper "indexed_docs_by_category", :indexed_docs_by_category
|
||||
|
||||
helper "on_github", :on_github
|
||||
|
||||
helper "next_page_in_category", :next_page_in_category
|
||||
helper "previous_page_in_category", :previous_page_in_category
|
||||
helper "current_page_in_category_index", :current_page_in_category_index
|
||||
end
|
||||
|
||||
def find_asset(file_name)
|
||||
@asset_mapper.manifest.find(file_name)
|
||||
end
|
||||
|
||||
def find_asset_file_path(file_name)
|
||||
@asset_mapper.manifest.manifest_files[file_name]["file_path"]
|
||||
end
|
||||
|
||||
def render_svg(filename, options = {})
|
||||
image = site.static_files.find { |f| f.relative_path == "/#{filename}.svg" }
|
||||
|
||||
return unless image
|
||||
|
||||
file = File.read(image.path)
|
||||
doc = ::Nokogiri::HTML::DocumentFragment.parse file
|
||||
svg = doc.at_css 'svg'
|
||||
|
||||
options.each { |attr, value| svg[attr.to_s] = value }
|
||||
|
||||
doc.to_html.html_safe
|
||||
end
|
||||
|
||||
def doc_collection
|
||||
site.collections[:documentation].resources
|
||||
end
|
||||
|
||||
def ordered_categories
|
||||
doc_collection.uniq { |c| c.data[:category] }.sort_by { |c| c.data[:category_order] }
|
||||
end
|
||||
|
||||
def ordered_categories_hash_map
|
||||
ordered_categories.map do |c|
|
||||
{
|
||||
category: c.data[:category],
|
||||
url: site.config.base_path.to_s + "/" + ::Bridgetown::Utils.slugify(c.data[:category]),
|
||||
text: c.data[:category].split("_").map(&:capitalize).join(" ")
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def docs_without_indexes
|
||||
doc_collection.reject { |doc| doc.data.layout == "index" }
|
||||
end
|
||||
|
||||
def docs_in_category(category)
|
||||
docs_without_indexes.select { |doc| doc.data.categories.include?(category) }
|
||||
end
|
||||
|
||||
def indexed_docs_by_category(category)
|
||||
docs_in_category(category).sort_by { |doc| doc.data.slug }
|
||||
end
|
||||
|
||||
def on_github(resource)
|
||||
branch = ENV["GITHUB_REF_NAME"] || site.metadata.default_branch
|
||||
site.metadata.github_url + "/tree/#{branch}/#{site.metadata.doc_location}/#{resource.relative_path}"
|
||||
end
|
||||
|
||||
def version_number
|
||||
is_ci = ENV["GITHUB_REF_NAME"] != ""
|
||||
|
||||
if is_ci && ENV["GITHUB_REF_NAME"] == "main"
|
||||
return "main"
|
||||
end
|
||||
|
||||
if !is_ci && `git rev-parse --abbrev-ref HEAD`.chomp == "main"
|
||||
return "main"
|
||||
end
|
||||
|
||||
package_json_file = File.join(File.expand_path("../../../", __dir__), "package.json")
|
||||
|
||||
return unless File.exist?(package_json_file)
|
||||
|
||||
package_json = File.read(package_json_file)
|
||||
JSON.parse(package_json)["version"].to_s
|
||||
end
|
||||
|
||||
def next_page_in_category(resource, category = resource.data[:category])
|
||||
current_page_index = current_page_in_category_index(resource)
|
||||
|
||||
return nil if current_page_index.nil?
|
||||
|
||||
indexed_docs_by_category(category)[current_page_index + 1]
|
||||
end
|
||||
|
||||
def previous_page_in_category(resource, category = resource.data[:category])
|
||||
current_page_index = current_page_in_category_index(resource)
|
||||
|
||||
return nil if current_page_index.nil? || current_page_index == 0
|
||||
|
||||
indexed_docs_by_category(category)[current_page_index - 1]
|
||||
end
|
||||
|
||||
def current_page_in_category_index(resource, category = resource.data[:category])
|
||||
indexed_docs_by_category(category).index(resource)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
class Builders::Inspectors < SiteBuilder
|
||||
def build
|
||||
inspect_html do |document|
|
||||
grab_headers(document)
|
||||
mark_external(document)
|
||||
syntax_highlight(document)
|
||||
end
|
||||
end
|
||||
|
||||
def mark_external(document)
|
||||
document.css("a[href^='http']").each do |anchor|
|
||||
next unless anchor[:href]&.starts_with?("http") && !anchor[:href]&.include?(site.config.url)
|
||||
|
||||
anchor[:target] = "_blank"
|
||||
anchor[:rel] = "nofollow noopener noreferrer"
|
||||
|
||||
next if anchor.css("external-icon")[0]
|
||||
next if anchor[:"no-external-icon"]
|
||||
|
||||
anchor << " <external-icon></external-icon>"
|
||||
end
|
||||
end
|
||||
|
||||
def syntax_highlight(document)
|
||||
document.css(":not(.syntax-block) > div.highlighter-rouge").each do |el|
|
||||
text = el.inner_text
|
||||
lang = el["class"].scan(/\s?language-.*\s/).last
|
||||
|
||||
lang = lang.strip.split("-")[1] if lang
|
||||
|
||||
lang = Syntax.full_language(lang)
|
||||
id = SecureRandom.uuid
|
||||
|
||||
el.wrap("<div class='syntax-block'></div>")
|
||||
|
||||
actions = <<-HTML
|
||||
<div class='syntax-block__actions'>
|
||||
<div class='syntax-block__badge'>
|
||||
#{lang}
|
||||
</div>
|
||||
|
||||
<clipboard-copy
|
||||
for='#{id}'
|
||||
class='button clipboard clipboard--idle syntax-block__clipboard'
|
||||
aria-label='Copy to clipboard'
|
||||
data-controller='clipboard'
|
||||
>
|
||||
<sl-icon class='clipboard__icon--success' name='clipboard-check'></sl-icon>
|
||||
<sl-icon class='clipboard__icon--idle' name='clipboard'></sl-icon>
|
||||
</clipboard-copy>
|
||||
|
||||
<textarea id='#{id}' hidden>#{text}</textarea>
|
||||
</div>
|
||||
HTML
|
||||
|
||||
el.add_previous_sibling(actions)
|
||||
end
|
||||
end
|
||||
|
||||
def grab_headers(document)
|
||||
table_of_contents = document.css(".doc #table-of-contents ol")[0]
|
||||
mobile_menu = document.css(".side-nav--mobile .side-nav__menu")[0]
|
||||
|
||||
# This isn't great. but works for my case :shrug:
|
||||
document.css("main").css("h2[id],h3[id],h4[id],h5[id],h6[id]").each do |heading|
|
||||
text = heading.inner_text
|
||||
|
||||
unless heading.css("a")[0]
|
||||
heading.content = ""
|
||||
anchor = %(
|
||||
<a href='##{heading[:id]}'>#{text}</a>
|
||||
)
|
||||
|
||||
heading << anchor
|
||||
end
|
||||
|
||||
|
||||
side_anchor = %(
|
||||
<a href='##{heading[:id]}' class='side-nav__link'>#{text}</a>
|
||||
)
|
||||
|
||||
item = document.create_element("li", "", class: "side-nav__item")
|
||||
item << side_anchor
|
||||
|
||||
table_of_contents << item
|
||||
|
||||
# we'll get here.
|
||||
# list = document.create_element("ul", "", class: "side-nav__category-menu")
|
||||
# list << item
|
||||
# mobile_menu.before list
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
class SiteBuilder < Bridgetown::Builder
|
||||
# write builders which subclass SiteBuilder in plugins/builders
|
||||
end
|
||||
|
||||
1520
docs/assets/scripts/light-pen/docs/pnpm-lock.yaml
generated
Normal file
1520
docs/assets/scripts/light-pen/docs/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
11
docs/assets/scripts/light-pen/docs/postcss.config.js
Normal file
11
docs/assets/scripts/light-pen/docs/postcss.config.js
Normal file
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
'postcss-flexbugs-fixes': {},
|
||||
'postcss-preset-env': {
|
||||
autoprefixer: {
|
||||
flexbox: 'no-2009'
|
||||
},
|
||||
stage: 3
|
||||
}
|
||||
}
|
||||
}
|
||||
32
docs/assets/scripts/light-pen/docs/server/roda_app.rb
Normal file
32
docs/assets/scripts/light-pen/docs/server/roda_app.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
# Roda is a simple Rack-based framework with a flexible architecture based
|
||||
# on the concept of a routing tree. Bridgetown uses it for its development
|
||||
# server, but you can also run it in production for fast, dynamic applications.
|
||||
#
|
||||
# Learn more at: http://roda.jeremyevans.net
|
||||
|
||||
class RodaApp < Roda
|
||||
# Add additional Roda configuration here if needed
|
||||
plugin :bridgetown_server
|
||||
|
||||
# Uncomment to use Bridgetown SSR:
|
||||
# plugin :bridgetown_ssr
|
||||
|
||||
# Uncomment to use file-based dynamic routing in your project (make sure you
|
||||
# uncomment the gem dependency in your `Gemfile` as well):
|
||||
# plugin :bridgetown_routes
|
||||
|
||||
# plugin :default_headers,
|
||||
# {
|
||||
# 'Content-Type'=>'text/html',
|
||||
# 'Strict-Transport-Security'=>'max-age=16070400;',
|
||||
# 'X-Content-Type-Options'=>'nosniff',
|
||||
# 'X-Frame-Options'=>'deny',
|
||||
# 'X-XSS-Protection'=>'1; mode=block',
|
||||
# 'Access-Control-Allow-Origin'=>"*"
|
||||
# }
|
||||
#
|
||||
route do |r|
|
||||
# Load Roda routes in server/routes (and src/_routes via `bridgetown-routes`)
|
||||
r.bridgetown
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
# Rename this file to hello.rb to try it out
|
||||
|
||||
class Routes::Hello < Bridgetown::Rack::Routes
|
||||
route do |r|
|
||||
# route: GET /hello/:name
|
||||
r.get "hello", String do |name|
|
||||
{ hello: "friend #{name}" }
|
||||
end
|
||||
end
|
||||
end
|
||||
18
docs/assets/scripts/light-pen/docs/src/404.html
Normal file
18
docs/assets/scripts/light-pen/docs/src/404.html
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
permalink: /404.html
|
||||
layout: default
|
||||
exclude_from_search: true
|
||||
---
|
||||
|
||||
<main style="margin: 0 auto; display: grid; place-content: center;">
|
||||
<h1>404 Page Not Found</h1>
|
||||
<p>
|
||||
Huh...Strange. That page doesnt appear to exist. Must've gotten lost in the
|
||||
<br>
|
||||
Space Time Continuum...
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<a href="/">There's no place like home...</a>
|
||||
</p>
|
||||
</main>
|
||||
11
docs/assets/scripts/light-pen/docs/src/500.html
Normal file
11
docs/assets/scripts/light-pen/docs/src/500.html
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
permalink: /500.html
|
||||
layout: default
|
||||
exclude_from_search: true
|
||||
---
|
||||
|
||||
<h1>500</h1>
|
||||
|
||||
<h2>Internal Server Error :(</h2>
|
||||
|
||||
<p>The requested page could not be delivered.</p>
|
||||
@@ -0,0 +1,5 @@
|
||||
<sl-alert variant="<%= @type.to_s %>" open>
|
||||
<sl-icon slot="icon" name="<%= @icon %>"></sl-icon>
|
||||
<%= markdownify(title) %>
|
||||
<%= markdownify(content) %>
|
||||
</sl-alert>
|
||||
24
docs/assets/scripts/light-pen/docs/src/_components/alert.rb
Normal file
24
docs/assets/scripts/light-pen/docs/src/_components/alert.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
# @example
|
||||
# <%= render Alert.new(type: "warning", title:) %>
|
||||
class Alert < Bridgetown::Component
|
||||
ICONS = {
|
||||
primary: "info-circle",
|
||||
success: "check2-circle",
|
||||
info: "gear",
|
||||
warning: "exclamation-triangle",
|
||||
danger: "exclamation-octagon"
|
||||
}.freeze
|
||||
|
||||
def initialize(type: :info, title: nil, icon: nil)
|
||||
@type = type.to_sym
|
||||
@title = title
|
||||
|
||||
@icon = icon || ICONS[@type]
|
||||
end
|
||||
|
||||
def title
|
||||
return if @title.nil?
|
||||
|
||||
"<strong>#{@title}</strong><br>".html_safe
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,3 @@
|
||||
<%= render Alert.new(type: "warning", icon: "cone-striped") do %>
|
||||
Coming Soon...
|
||||
<% end %>
|
||||
@@ -0,0 +1,2 @@
|
||||
class ComingSoon < Bridgetown::Component
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
<% indexed_docs_by_category(@category).each do |doc| %>
|
||||
<li class="<%= @list_classes %> <%= 'is-active' if doc == @resource %>">
|
||||
<a class="<%= @link_classes %>" href="<%= doc.relative_url %>"><%= doc.data.title %></a>
|
||||
</li>
|
||||
<% end %>
|
||||
@@ -0,0 +1,12 @@
|
||||
class DocLinks < Bridgetown::Component
|
||||
def initialize(category:, resource:, link_classes: nil, list_classes: nil)
|
||||
@category = category
|
||||
@list_classes = list_classes
|
||||
@link_classes = link_classes
|
||||
@resource = resource
|
||||
end
|
||||
|
||||
def collection
|
||||
sorted_collection.select { |doc| doc.data[:categories].include?(@category) }
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
<div class="syntax-block">
|
||||
<div class="syntax-block__actions">
|
||||
<div class="syntax-block__badge">
|
||||
<%= filename_or_language %>
|
||||
</div>
|
||||
|
||||
<clipboard-copy
|
||||
for="<%= id %>"
|
||||
class="button clipboard clipboard--idle syntax-block__clipboard"
|
||||
aria-label="Copy to clipboard"
|
||||
data-controller="clipboard"
|
||||
>
|
||||
<sl-icon class="clipboard__icon--success" name="clipboard-check"></sl-icon>
|
||||
<sl-icon class="clipboard__icon--idle" name="clipboard"></sl-icon>
|
||||
</clipboard-copy>
|
||||
|
||||
<textarea id="<%= id %>" hidden><%= content %></textarea>
|
||||
|
||||
</div>
|
||||
<%= markdownify("```#{language}" + content + "```") %>
|
||||
</div>
|
||||
|
||||
30
docs/assets/scripts/light-pen/docs/src/_components/syntax.rb
Normal file
30
docs/assets/scripts/light-pen/docs/src/_components/syntax.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
require "securerandom"
|
||||
|
||||
class Syntax < Bridgetown::Component
|
||||
def self.full_language(language)
|
||||
return "" if language.nil?
|
||||
|
||||
Rouge::Lexer.find(language).title || language.titleize
|
||||
end
|
||||
|
||||
attr_accessor :language, :filename
|
||||
|
||||
def initialize(language = "markup", filename = nil)
|
||||
super()
|
||||
@language = language
|
||||
@filename = filename
|
||||
end
|
||||
|
||||
def filename_or_language
|
||||
filename || full_language
|
||||
end
|
||||
|
||||
def full_language
|
||||
Syntax.full_language(@language)
|
||||
end
|
||||
|
||||
def id
|
||||
@id ||= "syntax-#{SecureRandom.uuid}"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Site settings
|
||||
# These are used to personalize your new site. If you look in the HTML files,
|
||||
# you will see them accessed via {{ site.metadata.title }}, {{ site.metadata.email }}, and so on.
|
||||
# You can create any custom variable you would like, and they will be accessible
|
||||
# in the templates via {{ site.metadata.myvariable }}.
|
||||
|
||||
title: Lightweight Components for doing complex things.
|
||||
logo: "Light Pen"
|
||||
slogan: Lightweight components for doing complex things.
|
||||
email: konnor5456@gmail.com
|
||||
description: >- # this means to ignore newlines until "baseurl:"
|
||||
A collection of components that don't generally fit a design system, but that I wanted to build.
|
||||
github_url: https://github.com/konnorrogers/light-pen
|
||||
default_branch: main
|
||||
doc_location: docs/src
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: Components
|
||||
permalink: /components/
|
||||
layout: index
|
||||
---
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
title: <light-pen>
|
||||
permalink: /components/light-pen/
|
||||
component: light-pen
|
||||
---
|
||||
|
||||
## Typical Usage
|
||||
|
||||
<light-pen style="padding: 8px; height: 100%;" resize-position="30" open-languages="js,html,css">
|
||||
<template slot="html">
|
||||
<light-pen>
|
||||
<template slot="html">
|
||||
<div>
|
||||
This is kind of wild huh? We have a <code><light-pen></code>
|
||||
component running inside of a <code><light-pen></code> component!!
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template slot="css">
|
||||
code {
|
||||
padding: 2px 6px;
|
||||
display: inline-block;
|
||||
font-size: 0.9em;
|
||||
background-color: rgba(0,0,0,0.05);
|
||||
border-radius: 4px;
|
||||
}
|
||||
</template>
|
||||
</light-pen>
|
||||
</template>
|
||||
|
||||
<template slot="css">
|
||||
html, body {
|
||||
height: 100%;
|
||||
min-height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
light-pen {
|
||||
height: 100%;
|
||||
}
|
||||
</template>
|
||||
|
||||
<template slot="js">
|
||||
import LightPen from "<%= find_asset "../exports/light-pen.js" %>";
|
||||
LightPen.define()
|
||||
</template>
|
||||
</light-pen>
|
||||
@@ -0,0 +1,194 @@
|
||||
---
|
||||
title: <light-preview>
|
||||
permalink: /components/light-preview/
|
||||
---
|
||||
|
||||
## Typical Usage
|
||||
|
||||
<light-preview>
|
||||
<template slot="preview-code">
|
||||
<button>Displaying a super cool button</button>
|
||||
</template>
|
||||
<template slot="code">
|
||||
<style>
|
||||
light-preview::part(iframe) {
|
||||
height: 80px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<light-preview>
|
||||
<template slot="code">
|
||||
<button>Displaying a super cool button</button>
|
||||
</template>
|
||||
</light-preview>
|
||||
|
||||
<script type="module">
|
||||
import LightPreview from "./exports/light-preview.js";
|
||||
LightPreview.define()
|
||||
</script>
|
||||
</template>
|
||||
</light-preview>
|
||||
|
||||
## Nesting a light-pen inside of a light-pen
|
||||
|
||||
<light-preview>
|
||||
<template slot="code">
|
||||
<style>
|
||||
light-preview::part(iframe) {
|
||||
height: 80px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<light-preview>
|
||||
<template slot="code">
|
||||
<button>Displaying a super cool button</button>
|
||||
</template>
|
||||
</light-preview>
|
||||
|
||||
<script type="module">
|
||||
import LightPreview from "light-pen/exports/light-preview.js"
|
||||
LightPreview.define()
|
||||
</script>
|
||||
</template>
|
||||
|
||||
<template slot="preview-code">
|
||||
<style>
|
||||
light-preview::part(iframe) {
|
||||
height: 80px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<light-preview>
|
||||
<template slot="code">
|
||||
<button>Displaying a super cool button</button>
|
||||
</template>
|
||||
</light-preview>
|
||||
|
||||
<script type="module">
|
||||
import LightPreview from "<%= find_asset "../exports/light-preview.js" %>"
|
||||
LightPreview.define()
|
||||
</script>
|
||||
</template>
|
||||
</light-preview>
|
||||
|
||||
|
||||
## Loading inline
|
||||
|
||||
<light-preview inline-preview>
|
||||
<template slot="code">
|
||||
<light-preview inline-preview>
|
||||
<template slot="code">
|
||||
<style>
|
||||
button.button {
|
||||
border-color: gray;
|
||||
}
|
||||
</style>
|
||||
|
||||
<button class="button">Displaying a super cool button not inside an iframe</button>
|
||||
|
||||
<br>
|
||||
<p>
|
||||
Notice how the button has the same styling as the toggle! That's because its not scoped into an iFrame!
|
||||
</p>
|
||||
</template>
|
||||
</light-preview>
|
||||
|
||||
<script type="module">
|
||||
import LightPreview from "<%= find_asset "../exports/light-preview.js" %>"
|
||||
LightPreview.define()
|
||||
</script>
|
||||
</template>
|
||||
</light-preview>
|
||||
|
||||
|
||||
## Additional buttons
|
||||
|
||||
|
||||
<style>
|
||||
#additional-buttons button {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
background-color: inherit;
|
||||
padding: 0.4em 0.6em;
|
||||
color: inherit;
|
||||
border: 1px solid lightgray;
|
||||
border-bottom-color: transparent;
|
||||
border-right-color: transparent;
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
|
||||
#additional-buttons button:focus-visible {
|
||||
outline: 2px solid hsl(203, 77%, 43%);
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
#additional-buttons button:focus-within {
|
||||
outline: 2px solid hsl(203, 77%, 43%);
|
||||
}
|
||||
}
|
||||
|
||||
#additional-buttons button:hover {
|
||||
cursor: pointer;
|
||||
color: hsla(203, 77%, 43%);
|
||||
background-color: hsla(203, 77%, 43%, 0.1);
|
||||
}
|
||||
</style>
|
||||
|
||||
<light-preview id="additional-buttons">
|
||||
<template slot="code">
|
||||
<style>
|
||||
#additional-buttons button {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
background-color: inherit;
|
||||
padding: 0.4em 0.6em;
|
||||
color: inherit;
|
||||
border: 1px solid lightgray;
|
||||
border-bottom-color: transparent;
|
||||
border-right-color: transparent;
|
||||
height: 100%;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#additional-buttons button:focus-visible {
|
||||
outline: 2px solid hsl(203, 77%, 43%);
|
||||
}
|
||||
|
||||
@supports not selector(:focus-visible) {
|
||||
#additional-buttons button:focus-within {
|
||||
outline: 2px solid hsl(203, 77%, 43%);
|
||||
}
|
||||
}
|
||||
|
||||
#additional-buttons button:hover {
|
||||
cursor: pointer;
|
||||
color: hsla(203, 77%, 43%);
|
||||
background-color: hsla(203, 77%, 43%, 0.1);
|
||||
}
|
||||
|
||||
light-preview::part(iframe) {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<light-preview id="additional-buttons">
|
||||
<template slot="code">
|
||||
<div>Showing off more buttons</div>
|
||||
</template>
|
||||
|
||||
<button slot="actions">HTML</button>
|
||||
<button slot="actions">Codepen</button>
|
||||
</light-preview>
|
||||
|
||||
<script type="module">
|
||||
import LightPreview from "<%= find_asset "../exports/light-preview.js" %>"
|
||||
LightPreview.define()
|
||||
</script>
|
||||
</template>
|
||||
|
||||
<button slot="actions">HTML</button>
|
||||
<button slot="actions">Codepen</button>
|
||||
</light-preview>
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: Guides
|
||||
permalink: /guides/
|
||||
layout: index
|
||||
---
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
title: References
|
||||
permalink: /references/
|
||||
layout: index
|
||||
---
|
||||
19
docs/assets/scripts/light-pen/docs/src/_layouts/default.erb
Normal file
19
docs/assets/scripts/light-pen/docs/src/_layouts/default.erb
Normal file
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html class="sl-theme-light" lang="<%= site.locale %>">
|
||||
<head>
|
||||
<%= render "head", metadata: site.metadata, title: resource.data.title %>
|
||||
</head>
|
||||
<body class='<%= "#{resource.data.layout} #{resource.data.page_class}" %>' data-controller="search">
|
||||
<kr-layout main-id="main">
|
||||
<%= render "top_nav", metadata: site.metadata %>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
<%= render "footer", metadata: site.metadata %>
|
||||
|
||||
</kr-layout>
|
||||
|
||||
<%= render "side_nav_mobile" %>
|
||||
<bridgetown-ninja-keys endpoint="<%= site.base_path %>/bridgetown_quick_search/index.json"></bridgetown-ninja-keys>
|
||||
</body>
|
||||
</html>
|
||||
19
docs/assets/scripts/light-pen/docs/src/_layouts/doc.erb
Normal file
19
docs/assets/scripts/light-pen/docs/src/_layouts/doc.erb
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
<%= render "side_nav" %>
|
||||
|
||||
<main id="main" class="documentation-content">
|
||||
<% title_id = resource.data.title.downcase.split(" ").join("-").gsub(/[\?!]/, "") %>
|
||||
<h1 id="<%= title_id %>">
|
||||
<a href="<%= "##{title_id}" %>">
|
||||
<%= resource.data.title.titleize %>
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<%= yield %>
|
||||
|
||||
<%= render "pagination" %>
|
||||
</main>
|
||||
|
||||
<%= render "table_of_contents" %>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user