Skip to content

Commit

Permalink
WWS version 0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Breck Yunits authored and Breck Yunits committed Jun 14, 2024
1 parent 8942bb0 commit 818ec88
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 4 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "scroll-cli",
"version": "95.0.0",
"version": "95.1.0",
"description": "A language for scientists of all ages. A curated collection of tools for refining and sharing thoughts.",
"main": "scroll.js",
"engines": {
Expand All @@ -17,7 +17,8 @@
"cloc": "cloc --vcs git . --read-lang-def=tests/clocLangs.txt"
},
"bin": {
"scroll": "./scroll.js"
"scroll": "./scroll.js",
"wws": "./wws.js"
},
"files": [
"scroll.js",
Expand Down
3 changes: 3 additions & 0 deletions releaseNotes.scroll
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ releaseParser
crux 📦
extends h1Parser

📦 95.1.0 6/14/2024
🎉 added `wws` command line app.

📦 95.0.0 6/11/2024
🎉 added `downloadUrl` keyword.
⚠️ BREAKING: `canonicalLink` is now `canonicalUrl`.
Expand Down
2 changes: 1 addition & 1 deletion scroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ import footer.scroll
}

helpCommand() {
this.log(`\n📜📜📜 WELCOME TO SCROLL (v${SCROLL_VERSION}) 📜📜📜`)
this.log(`\n📜 WELCOME TO SCROLL (v${SCROLL_VERSION})`)
return this.log(`\nThis is the Scroll help page.\n\nCommands you can run from your Scroll's folder:\n\n${this._allCommands.map(comm => `🖌️ ` + comm.replace(this.CommandFnDecoratorSuffix, "")).join("\n")}\n​​`)
}
}
Expand Down
2 changes: 1 addition & 1 deletion tests/scroll.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ testTree.file = areEqual => {
areEqual(releaseNotesFile.permalink, "releaseNotes.html")
areEqual(releaseNotesFile.html.includes("Scroll the language is now called"), true)
areEqual(releaseNotesFile.description, "A list of what has changed in Scroll releases.", "Meta description auto-generated if not specified.")
areEqual(files[4].permalink, "index.html")
areEqual(files[4].permalink, "roadmap.html")
}

testTree.ensureNoErrorsInGrammar = areEqual => {
Expand Down
159 changes: 159 additions & 0 deletions wws.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#! /usr/bin/env node

// NPM ecosystem includes
const parseArgs = require("minimist")
const path = require("path")
const fs = require("fs")

// Scroll Notation Includes
const { Disk } = require("scrollsdk/products/Disk.node.js")
const { ScrollCli, ScrollFile, ScrollFileSystem } = require("./scroll.js")

const WWS_VERSION = "0.0.1"

const scrollFs = new ScrollFileSystem()
const scrollCli = new ScrollCli().silence()

class WWSCli {
CommandFnDecoratorSuffix = "Command"

executeUsersInstructionsFromShell(args = [], userIsPipingInput = process.platform !== "win32" && fs.fstatSync(0).isFIFO()) {
const command = args[0] // Note: we don't take any parameters on purpose. Simpler UX.
const commandName = `${command}${this.CommandFnDecoratorSuffix}`
if (this[commandName]) return userIsPipingInput ? this._runCommandOnPipedStdIn(commandName) : this[commandName](process.cwd())
else if (command) this.log(`No command '${command}'. Running help command.`)
else this.log(`No command provided. Running help command.`)
return this.helpCommand()
}

_runCommandOnPipedStdIn(commandName) {
let pipedData = ""
process.stdin.on("readable", function () {
pipedData += this.read() // todo: what's the lambda way to do this?
})
process.stdin.on("end", () => {
const folders = pipedData
.trim()
.split("\n")
.map(line => line.trim())
.filter(line => fs.existsSync(line))

folders.forEach(line => this[commandName](line))

if (folders.length === 0)
// Hacky to make sure this at least does something in all environments.
// process.stdin.isTTY is not quite accurate for pipe detection
this[commandName](process.cwd())
})
}

silence() {
this.verbose = false
return this
}

verbose = true

logIndent = 0
log(message) {
const indent = " ".repeat(this.logIndent)
if (this.verbose) console.log(indent + message)
return message
}

get _allCommands() {
return Object.getOwnPropertyNames(Object.getPrototypeOf(this))
.filter(word => word.endsWith(this.CommandFnDecoratorSuffix))
.sort()
}

async initCommand(cwd) {
// Split cwd by dir separator and see if it already contains a "wws" part:
const wwsCache = this._getWWSDir(cwd)
if (wwsCache) return this.log(`\n👍 WWS already initialized: '${wwsCache}'.`)

// If not, create a new folder and initialize it:
const newCwd = path.join(cwd, "wws")
Disk.mkdir(newCwd)
const initFolder = {
"index.scroll": `The World Wide Scroll\n`
}
Disk.writeObjectToDisk(newCwd, initFolder)
return this.log(`\n👍 Initialized new WWS cache in '${newCwd}'.`)
}

async buildIndexPage(cwd) {
const indexFile = path.join(cwd, "index.scroll")
const content = `title The World Wide Scroll
metaTags
gazetteCss
printTitle
thinColumns 1
${this.folders.map(concept => `- ${concept.id}\n link ${concept.id}/index.html`).join("\n")}
`
Disk.write(indexFile, content)
await scrollCli.buildCommand(cwd)
}

_getWWSDir(cwd) {
// first check if this folder contains a folder named "wws":
if (Disk.exists(path.join(cwd, "wws"))) return path.join(cwd, "wws")
const parts = cwd.split(path.sep)
const indexOfWws = parts.indexOf("wws")
if (indexOfWws === -1) return null
return parts.slice(0, indexOfWws + 1).join(path.sep)
}

get folders() {
const wwsFile = path.join(__dirname, "wws.scroll")
const wws = new ScrollFile(Disk.read(wwsFile), wwsFile, scrollFs)
return wws.concepts
}

listCommand() {
this.folders.forEach(concept => this.log(concept.id))
}

fetchScroll(folderName, dir) {
const folder = this.folders.find(concept => concept.id === folderName)
if (!folder) return this.log(`\n👎 No folder '${folderName}' found.`)
// mkdir the folder if it doesn't exist:
const conceptDir = path.join(dir, folder.id)
const gitSource = folder.source
if (!Disk.exists(conceptDir)) {
this.log(`Fetching ${folderName}`)
Disk.mkdir(conceptDir)
// do a shallow clone of the built site (wws branch) into the folder:
require("child_process").execSync(`git clone --depth 1 --branch wws ${gitSource} ${conceptDir}`)
} else {
// update the shallow clone but still keep it shallow
this.log(`Updating ${folderName}`)
require("child_process").execSync(`cd ${conceptDir} && git pull`)
}
}

fetchCommand(cwd) {
const dir = this._getWWSDir(cwd)
if (!dir) return this.log(`\n👎 No WWS cache found in '${cwd}'.`)
this.folders.forEach(concept => this.fetchScroll(concept.id, dir))
this.buildIndexPage(dir)
}

openCommand(cwd) {
// Trigger the terminal to run "open index.html", opening the users web browser:
const dir = this._getWWSDir(cwd)
if (!dir) return this.log(`\n👎 No WWS cache found in '${cwd}'.`)
const indexHtml = path.join(dir, "index.html")
return require("child_process").exec(`open ${indexHtml}`)
}

helpCommand() {
this.log(`\n🌎🌏📜 WELCOME TO THE WWS (v${WWS_VERSION})`)
return this.log(`\nThis is the WWS help page.\n\nCommands you can run:\n\n${this._allCommands.map(comm => `🖌️ ` + comm.replace(this.CommandFnDecoratorSuffix, "")).join("\n")}\n​​`)
}
}

if (module && !module.parent) new WWSCli().executeUsersInstructionsFromShell(parseArgs(process.argv.slice(2))._)

module.exports = { WWSCli }

0 comments on commit 818ec88

Please sign in to comment.