This commit is contained in:
dmc
2024-01-09 12:47:13 +01:00
parent 8c1dfc51ce
commit af5ec98a44
4 changed files with 392 additions and 0 deletions

131
.gitignore vendored Normal file
View File

@@ -0,0 +1,131 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
package-lock.json

83
lib/docs-viewer.js Normal file
View File

@@ -0,0 +1,83 @@
/* eslint-env browser */
import { marked } from 'marked'
customElements.define('docs-viewer', class extends HTMLElement {
static get observedAttributes () { return ['data-load'] }
attributeChangedCallback (name, _, page) { if (name === 'data-load') this.load(page).catch((err) => this.#error(err)) }
constructor () {
super()
this.template = document.createElement('template')
this.template.innerHTML = `
<div>
<style>
ul { list-style-type: none; }
ul li::before { content: '❥ '; margin-right: 0.5em; }
a:visited, a:active, a { color: #B0D944; outline: none; text-decoration: none }
h1 { padding: .5rem; border-right: 1px solid #B0D944; border-bottom: 1px solid #B0D944; display: inline-block; padding-right: 0.75em; padding-left: 0.5em; }
code { background: #333; color: #eee; padding: .25rem; }
pre > code { display: block; line-height: 1.025rem; padding-left: 1em; }
h1, h2, h3, h4, h5, h6 { font-weight: bold; }
h1 { font-size: 1.6rem; }
h2 { font-size: 1.4rem; }
h3 { font-size: 1.2rem; }
h4 { font-size: 1rem; }
h5 { font-size: .8rem; }
h6 { font-size: .7rem; }
blockquote { outline: 1px solid #323532; margin-inline-start: 0; margin-inline-end: 0; display: block; margin-block-start: 1rem; margin-block-end: 0; padding: 1px; font-size: .825rem }
blockquote::before { content: ""; float: left; font-size: 1.625rem; margin-left: 1rem; margin-right: 0.625rem; }
img { display: block; max-width: 63em; margin: 0 auto; margin-block-start: 1.625rem; margin-block-end: 1.625rem; box-shadow: rgb(123 115 168 / 15%) 0px 13px 24px 0px; }
#panel { margin-top: 4px; }
</style>
<div id="panel"><slot></slot></div>
</div>
`
this.root = this.attachShadow({ mode: 'open' })
this.root.appendChild(this.template.content.cloneNode(true))
this.panel = this.root.querySelector('#panel')
this.header = this.root.querySelector('header')
this.panel.addEventListener('click', (evt) => {
if (evt.target?.tagName !== 'A') return
const href = evt.target.getAttribute('href')
const { origin } = new URL(location.href)
const url = new URL(href, location.href)
if (url.origin !== origin) return window.open(href)
evt.preventDefault()
document.documentElement.scrollTo(0, 0)
this.load(url.pathname).catch((err) => this.#error(err)).finally(() => {
this.header.querySelector('a').style.display = 'inline-block'
})
})
window.addEventListener('popstate', (evt) => {
document.documentElement.scrollTo(0, 0)
if (evt.state?.page === 'readme.md') this.header.querySelector('a').style.display = 'none'
evt.preventDefault()
this.load(evt.state?.page || this.page, true).catch((err) => this.#error(err))
})
window.onbeforeunload = (e) => {
this.#load()
e.returnValue = false
}
this.page = this.dataset.load
this.load(this.page).catch((err) => this.#error(err))
}
#error (err) {
try { this.panel.querySelector('slot').innerHTML = err.stack } catch (e) { console.error(err, e) }
}
load (page = 'readme.md', replace) {
if (replace) history.replaceState({ page }, page, page)
else history.pushState({ page }, page, page)
this.page = page
return this.#load()
}
async #load () {
this.panel.querySelector('slot').innerHTML = marked.parse(await (await fetch(this.page)).text(), {headerIds: false, mangle: false})
}
})

16
package.json Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "pear",
"main": "pulse.html",
"type": "module",
"pear": {
"gui": {
"backgroundColor": "#151517",
"height": 780,
"width": 1120
}
},
"dependencies": {
"marked": "^5.1.0",
"overpass": "github:RedHatOfficial/Overpass#71f18db"
}
}

162
pulse.html Normal file
View File

@@ -0,0 +1,162 @@
<!DOCTYPE html>
<body onload="location.hash = location.hash || '#status'">
<script> addEventListener('hashchange', () => { document.documentElement.scrollTop = 0 }) </script>
<style>
@font-face {
font-family: 'overpass-mono';
src: url('~overpass/webfonts/overpass-mono-webfont/overpass-mono-regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
}
@font-face {
font-family: 'overpass-mono';
src: url('~overpass/webfonts/overpass-mono-webfont/overpass-mono-bold.woff2') format('woff2');
font-weight: 600;
font-style: normal;
}
body {
background: #151517;
box-sizing: border-box;
border-radius: 8px;
font-family:'overpass-mono';
-webkit-font-smoothing: antialiased;
color: #eee;
transition: background-color .4s, color .4s;
}
html, body { overflow: scroll; }
html.light body {
background: hsl(0deg, 1.59%, 52.42%);
color: #151517;
}
a:visited, a:active, a { color: #B0D944; outline: none; text-decoration: none }
#logo {
float: left;
margin-right: 2rem;
margin-left: 0.65rem;
margin-top: 0.45rem;
}
nav {
height: 146px;
float: left;
padding-left: 2em;
padding-top: 2em;
margin-right: 30rem;
}
nav > a {
display: block;
}
section {
display: none;
}
section:target {
display: block;
padding-top: 156px;
}
pre {
background: none;
color: #B0D944;
font-family: overpass-mono;
border: none;
height: 146px;
user-select: none;
}
header {
top: 0;
left:0;
height: 170px;
z-index:10;
background: rgba(21, 21, 23, 0.9);
width: 100%;
transition: background-color .4s, color .4s;
position: fixed;
}
#headin {
transform: scale(0.92);
width: 72rem;
margin: 0 auto;
}
html.light header {
background: hsla(0deg, 1.59%, 52.42%, 0.9)
}
h1 { padding: .5rem; border-right: 1px solid #B0D944; border-bottom: 1px solid #B0D944; display: inline-block; padding-right: 0.75em; padding-left: 0.5em; font-weight: bold; font-size: 1.6rem; }
blockquote { outline: 1px solid #323532; margin-inline-start: 0; margin-inline-end: 0; display: block; margin-block-start: 1rem; margin-block-end: 0; padding: 1px; font-size: .825rem }
blockquote::before { content: ""; float: left; font-size: 1.625rem; margin-left: 1rem; margin-right: 0.625rem; }
.col { max-width: 63rem; margin: 0 auto; }
#mode {
position: absolute;
font-size: 2rem;
right: 0.4rem;
top: -0.4rem;
cursor: pointer;
opacity: .65;
color: #B0D944;
}
#mode::after { content: "☀"; }
html.light #mode::after { content: "☾"; }
</style>
<header>
<div id="headin">
<svg id="logo" width="102" height="146" viewBox="0 0 102 146" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_8912_10861)">
<path d="M47.4056 0.838379H54.5943V15.0361H47.4056V0.838379Z" fill="#B0D944"/>
<path d="M43.8113 19.5305V22.406H36.6226V26.0004H65.3774V22.406H58.1887V16.8347H51V19.5305H43.8113Z" fill="#B0D944"/>
<path d="M72.5662 27.7974H51V30.4931H29.4339V36.963H72.5662V27.7974Z" fill="#B0D944"/>
<path d="M79.7548 38.7593H51V41.455H22.2451V47.9249H79.7548V38.7593Z" fill="#B0D944"/>
<path d="M79.7548 49.7219H51V52.4177H22.2451V58.8875H79.7548V49.7219Z" fill="#B0D944"/>
<path d="M86.9436 60.6846H51V63.3803H15.0565V69.8502H86.9436V60.6846Z" fill="#B0D944"/>
<path d="M86.9436 71.6481H51V74.3438H15.0565V80.8137H86.9436V71.6481Z" fill="#B0D944"/>
<path d="M94.1323 82.61H51V85.3058H7.86774V91.7756H94.1323V82.61Z" fill="#B0D944"/>
<path d="M101.321 93.5726H51V96.2684H0.679016V102.738H101.321V93.5726Z" fill="#B0D944"/>
<path d="M101.321 104.536H51V107.232H0.679016V113.702H101.321V104.536Z" fill="#B0D944"/>
<path d="M101.321 115.499H51V118.195H0.679016V124.664H101.321V115.499Z" fill="#B0D944"/>
<path d="M86.9436 126.461H51V129.156H15.0565V135.626H86.9436V126.461Z" fill="#B0D944"/>
<path d="M72.5662 137.424H51V140.12H29.4339V144.613H72.5662V137.424Z" fill="#B0D944"/>
</g>
<defs>
<clipPath id="clip0_8912_10861">
<rect width="100.642" height="145.571" fill="white" transform="translate(0.679016 0.214233)"/>
</clipPath>
</defs>
</svg>
<span id="mode" onclick="document.documentElement.classList[document.documentElement.classList.contains('light') ? 'remove' : 'add']('light');"></span>
<nav>
<a href="#status" style="text-indent: -1rem">System Status</a>
<a href="#documentation">Documentation</a>
</nav>
<pre>
__ \ _ \ _` | __|
| | __/ ( | |
.__/ \___| \__,_| _|
_|
</pre>
</div>
</header>
<section id="status">
<div class="col">
<h1>Pear by Holepunch</h1>
<blockquote><p>Welcome to the Internet of Peers</p></blockquote>
<p>Pear is ready to go.</p>
</div>
</section>
<section id="documentation">
<div class="col">
<docs-viewer data-page="readme.md"></docs-viewer>
</div>
</section>
<script type='module' src='./lib/docs-viewer.js'></script>
</body>