Navigation Menu

Skip to content
This repository has been archived by the owner on Dec 27, 2022. It is now read-only.

Commit

Permalink
Move site build-scripts into in-browser tools
Browse files Browse the repository at this point in the history
  • Loading branch information
pfrazee committed May 24, 2019
1 parent e5abf15 commit f9b17b2
Show file tree
Hide file tree
Showing 25 changed files with 191 additions and 115 deletions.
2 changes: 1 addition & 1 deletion _md/docs/how-does-it-work.md
@@ -1,4 +1,4 @@
## How does Unwalled.Garden work?
## How does Unwalled.Garden work!?

### Souped-up RSS

Expand Down
Binary file added assets/.DS_Store
Binary file not shown.
167 changes: 167 additions & 0 deletions assets/admin.js
@@ -0,0 +1,167 @@
const ASSETS_DIRECTORY_PATH = '/assets'
const MARKDOWN_DIRECTORY_PATH = '/_md'
const OUTPUT_DIRECTORY_PATH = '/'
const SITEWIDE_NOTICE = `Status: DRAFT. Part of the upcoming <a href="https://beakerbrowser.com">Beaker Browser</a> 0.9 release.`

const self = new DatArchive(window.location)
var watchStream

adminMain()

async function adminMain () {
let info = await self.getInfo()
if (!info.isOwner) return console.debug('Admin disabled: not owner')
if (!location.hostname.endsWith('+preview')) return console.debug('Admin disabled: not preview mode')
console.debug('Admin enabled')

addUI()
if (isWatching()) {
startWatcher()
}
}

function isWatching () {
return (sessionStorage.watchEnabled == 1)
}

function setWatching (v) {
sessionStorage.watchEnabled = v ? '1' : '0'
document.querySelector('.admin-watch').textContent = v ? 'Stop watching' : 'Start watching'
}

function addUI () {
// UI elements
var el = document.createElement('div')
el.className = 'admin-controls'
el.innerHTML = `
<a href="#" class="admin-build">Build</a>
|
<a href="#" class="admin-watch">Start watching</a>
`
el.querySelector('.admin-build').addEventListener('click', onClickBuild)
el.querySelector('.admin-watch').addEventListener('click', onClickWatchToggle)
document.body.append(el)

// needed scripts
var script1 = document.createElement('script')
script1.setAttribute('src', '/assets/vendor/markdown-it.min.js')
document.body.append(script1)
var script2 = document.createElement('script')
script2.setAttribute('src', '/assets/vendor/highlight.pack.js')
document.body.append(script2)
}

function onClickBuild (e) {
e.preventDefault()
build()
}

function onClickWatchToggle (e) {
e.preventDefault()
if (isWatching()) {
stopWatcher()
} else {
startWatcher()
}
}

var to
function onChange (e) {
if (to) clearTimeout(to)
to = setTimeout(build, 100)
}

async function startWatcher () {
setWatching(true)
watchStream = self.watch()
watchStream.addEventListener('changed', onChange)
}

async function stopWatcher () {
setWatching(false)
watchStream.close()
}

async function build () {
console.debug('Building')
if (watchStream) watchStream.close()
var layoutHtml = await self.readFile(joinPath(ASSETS_DIRECTORY_PATH, 'layout.html'), 'utf8')
var navHtml = await self.readFile(joinPath(ASSETS_DIRECTORY_PATH, 'nav.html'), 'utf8')
layoutHtml = layoutHtml.replace('$NAV', navHtml)

const md = markdownit({
html: true, // Enable HTML tags in source
xhtmlOut: false, // Use '/' to close single tags (<br />)
breaks: true, // Convert '\n' in paragraphs into <br>
langPrefix: 'language-', // CSS language prefix for fenced blocks
linkify: true, // Autoconvert URL-like text to links

// Enable some language-neutral replacement + quotes beautification
typographer: true,

// Double + single quotes replacement pairs, when typographer enabled,
// and smartquotes on. Set doubles to '«»' for Russian, '„“' for German.
quotes: '“”‘’',

// Highlighter function. Should return escaped HTML,
// or '' if the source string is not changed
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (__) {}
}

return ''; // use external default escaping
}
})

// index.html
console.debug('Writing index.html')
var indexHtml = await self.readFile(joinPath(ASSETS_DIRECTORY_PATH, 'index.html'), 'utf8')
await self.writeFile(joinPath(OUTPUT_DIRECTORY_PATH, 'index.html'), indexHtml.replace('$NAV', navHtml))

// markdown pages
let markdownPaths = await listMarkdownPaths(MARKDOWN_DIRECTORY_PATH)
for (let p of markdownPaths) {
await generateHTML(md, toInputPath(p), toOutputPath(p), layoutHtml)
}

window.location.reload()
}

async function listMarkdownPaths (p) {
let results = []
let paths = await self.readdir(p, {recursive: true})
return paths.filter(p => p.endsWith('.md'))
}

function toInputPath (p) {
return joinPath(MARKDOWN_DIRECTORY_PATH, p)
}

function toOutputPath (p) {
return joinPath(OUTPUT_DIRECTORY_PATH, p).replace(/\.md$/, '.html')
}

async function generateHTML (md, mdPath, htmlPath, layoutHtml) {
console.debug('Writing', htmlPath)
let mdfile = await self.readFile(mdPath, 'utf8')
let html = layoutHtml
.replace('$CONTENT', md.render(mdfile))
.replace('</h2>', `</h2><div class="notice">${SITEWIDE_NOTICE}</div>`)
await self.writeFile(htmlPath, html)
}

function joinPath (...args) {
var str = args[0]
for (let v of args.slice(1)) {
v = v && typeof v === 'string' ? v : ''
let left = str.endsWith('/')
let right = v.startsWith('/')
if (left !== right) str += v
else if (left) str += v.slice(1)
else str += '/' + v
}
return str
}
1 change: 1 addition & 0 deletions assets/index.html
Expand Up @@ -77,4 +77,5 @@ <h3>Who decides which schemas are included?</h3>
</div>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions assets/layout.html
Expand Up @@ -21,4 +21,5 @@ <h1><a href="/">Unwalled.Garden</a></h1>
</nav>
<main>$CONTENT</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
6 changes: 3 additions & 3 deletions assets/styles.css
Expand Up @@ -60,11 +60,11 @@ var {
}

aside {
background: #CDDC39;
background: #efd7f3;
padding: 1rem;
border-left: 1rem solid #94a01c;
border-left: 1rem solid #CE93D8;
border-radius: 4px;
color: rgba(0, 0, 0, 0.74);
color: #510b5d;
}

aside > :last-child {
Expand Down
2 changes: 2 additions & 0 deletions assets/vendor/highlight.pack.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

File renamed without changes.
1 change: 1 addition & 0 deletions bookmark.html
Expand Up @@ -93,4 +93,5 @@ <h1><a href="/">Unwalled.Garden</a></h1>
</ul>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions comment.html
Expand Up @@ -91,4 +91,5 @@ <h1><a href="/">Unwalled.Garden</a></h1>
</code></pre>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions docs/api/bookmarks.html
Expand Up @@ -89,4 +89,5 @@ <h1><a href="/">Unwalled.Garden</a></h1>
<p>TODO</p>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions docs/api/graph.html
Expand Up @@ -150,4 +150,5 @@ <h3><code>graph.unfollow(siteUrl)</code></h3>
</ul>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions docs/api/posts.html
Expand Up @@ -159,4 +159,5 @@ <h3><code>posts.delete(postUrl)</code></h3>
<hr>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions docs/api/profiles.html
Expand Up @@ -77,4 +77,5 @@ <h1><a href="/">Unwalled.Garden</a></h1>
<p>TODO</p>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions docs/api/reactions.html
Expand Up @@ -83,4 +83,5 @@ <h1><a href="/">Unwalled.Garden</a></h1>
<p>TODO</p>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions docs/api/search.html
Expand Up @@ -79,4 +79,5 @@ <h1><a href="/">Unwalled.Garden</a></h1>
<p>TODO</p>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>
1 change: 1 addition & 0 deletions docs/dat-primer.html
Expand Up @@ -78,4 +78,5 @@ <h3>How unwalled.garden uses Dat</h3>
<p>The hyperdrives act as a shared global filesystem for the Dat Web. By reading &amp; writing files with these schemas, applications are able to integrate with each other on the Dat Web.</p>
</main>
</body>
<script type="module" src="/assets/admin.js"></script>
</html>

0 comments on commit f9b17b2

Please sign in to comment.