Merge branch 'master' of github.com:fraction/oasis into type-defs

This commit is contained in:
Christian Bundy 2020-03-27 08:02:44 -07:00
commit defb57321e
14 changed files with 642 additions and 491 deletions

View File

@ -47,6 +47,7 @@
"socio",
"ssbc",
"summerfruit",
"sulphurpool",
"systemctl",
"systemd",
"unfollow",

View File

@ -1,5 +1,3 @@
## What's the problem you want solved?
## Is there a solution you'd like to recommend?
## What version or commit of Oasis are you using?

View File

@ -1,5 +0,0 @@
{
"hooks": {
"pre-commit": "npm test"
}
}

450
package-lock.json generated
View File

@ -297,10 +297,30 @@
"urijs": "^1.19.2"
},
"dependencies": {
"koa-compose": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
"http-errors": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
},
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
}
}
}
},
@ -975,34 +995,6 @@
"requires": {
"ms": "2.0.0"
}
},
"http-errors": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
},
"raw-body": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
"requires": {
"bytes": "3.1.0",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
}
}
},
@ -1254,7 +1246,6 @@
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
@ -1269,9 +1260,9 @@
"optional": true
},
"ci-info": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz",
"integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
"integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
"dev": true
},
"class-list": {
@ -1489,12 +1480,6 @@
"typewiselite": "^1.0.0"
}
},
"compare-versions": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
"integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
"dev": true
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
@ -2042,6 +2027,11 @@
"type": "^1.0.1"
}
},
"dash-ast": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dash-ast/-/dash-ast-1.0.0.tgz",
"integrity": "sha512-Vy4dx7gquTeMcQR/hDkYLGUnwVil6vk4FOOct+djUnHOUWt+zJPJAaRIXaAFkPXtJjvlY7o3rfRu0/3hpnwoUA=="
},
"debug": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
@ -2818,11 +2808,6 @@
"ms": "2.0.0"
}
},
"path-to-regexp": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
@ -2962,15 +2947,6 @@
"locate-path": "^3.0.0"
}
},
"find-versions": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz",
"integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==",
"dev": true,
"requires": {
"semver-regex": "^2.0.0"
}
},
"flat-cache": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
@ -3137,9 +3113,9 @@
}
},
"formidable": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz",
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg=="
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
"integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
},
"forwarded": {
"version": "0.1.2",
@ -3199,13 +3175,6 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
"integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
@ -3532,9 +3501,9 @@
"integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ=="
},
"html-element": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/html-element/-/html-element-2.3.0.tgz",
"integrity": "sha512-axsAv89JAxk/zSSOn+jK5dJ1eAUVSkienyIcruAe/kD5skC/E/HxjFfCfNYv8+A9m7BXR9kfL4ZD1ZobUfUWzQ==",
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/html-element/-/html-element-2.3.1.tgz",
"integrity": "sha512-xnFt2ZkbFcjc+JoAtg3Hl89VeEZDjododu4VCPkRvFmBTHHA9U1Nt6hLUWfW2O+6Sl/rT1hHK/PivleX3PdBJQ==",
"requires": {
"class-list": "~0.1.1"
}
@ -3588,78 +3557,21 @@
}
},
"http-errors": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz",
"integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==",
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
"requires": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"inherits": "2.0.3",
"setprototypeof": "1.1.1",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.0"
}
},
"husky": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/husky/-/husky-4.2.3.tgz",
"integrity": "sha512-VxTsSTRwYveKXN4SaH1/FefRJYCtx+wx04sSVcOpD7N2zjoHxa+cEJ07Qg5NmV3HAK+IRKOyNVpi2YBIVccIfQ==",
"dev": true,
"requires": {
"chalk": "^3.0.0",
"ci-info": "^2.0.0",
"compare-versions": "^3.5.1",
"cosmiconfig": "^6.0.0",
"find-versions": "^3.2.0",
"opencollective-postinstall": "^2.0.2",
"pkg-dir": "^4.2.0",
"please-upgrade-node": "^3.2.0",
"slash": "^3.0.0",
"which-pm-runs": "^1.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
"dev": true,
"requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
"integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
"requires": {
"color-name": "~1.1.4"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
"inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
}
}
},
@ -3948,14 +3860,6 @@
"dev": true,
"requires": {
"ci-info": "^1.5.0"
},
"dependencies": {
"ci-info": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
"integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
"dev": true
}
}
},
"is-date-object": {
@ -4153,9 +4057,9 @@
}
},
"is-valid-domain": {
"version": "0.0.11",
"resolved": "https://registry.npmjs.org/is-valid-domain/-/is-valid-domain-0.0.11.tgz",
"integrity": "sha512-N+XmAifLwbpAf6d5GM5DliNOZZrq2wnmdsAuhM2gyVaKAoJQIBz4emiPC4cnh4cIGiIqg0QvAa7sCpvGkN4WCg=="
"version": "0.0.14",
"resolved": "https://registry.npmjs.org/is-valid-domain/-/is-valid-domain-0.0.14.tgz",
"integrity": "sha512-MTUz/3y25zTtutAfwrLyFK+1l2IL4bcq2iHVdYHIPQbvBJLunlYu9dsQdtLwD9HKPDyxCDlKnSbGcRwvjVeCxA=="
},
"is-whitespace-character": {
"version": "1.0.4",
@ -4346,11 +4250,6 @@
"requires": {
"ms": "2.0.0"
}
},
"koa-compose": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
}
}
},
@ -4365,12 +4264,9 @@
}
},
"koa-compose": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
"integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
"requires": {
"any-promise": "^1.1.0"
}
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
},
"koa-convert": {
"version": "1.2.0",
@ -4379,6 +4275,16 @@
"requires": {
"co": "^4.6.0",
"koa-compose": "^3.0.0"
},
"dependencies": {
"koa-compose": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-3.2.1.tgz",
"integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
"requires": {
"any-promise": "^1.1.0"
}
}
}
},
"koa-mount": {
@ -4388,18 +4294,6 @@
"requires": {
"debug": "^4.0.1",
"koa-compose": "^4.1.0"
},
"dependencies": {
"koa-compose": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
}
},
"koa-send": {
@ -4802,9 +4696,9 @@
"dev": true
},
"looper": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz",
"integrity": "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew="
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz",
"integrity": "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k="
},
"lossy-store": {
"version": "1.2.4",
@ -5182,13 +5076,6 @@
"separator-escape": "0.0.0",
"socks": "^2.2.3",
"stream-to-pull-stream": "^1.7.2"
},
"dependencies": {
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}
}
},
"multiserver-address": {
@ -5357,9 +5244,9 @@
}
},
"node-gyp-build": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.0.tgz",
"integrity": "sha512-4oiumOLhCDU9Rronz8PZ5S4IvT39H5+JEv/hps9V8s7RSLhsac0TCP78ulnHXOo8X1wdpPiTayGlM1jr4IbnaQ==",
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.1.tgz",
"integrity": "sha512-XyCKXsqZfLqHep1hhsMncoXuUNt/cXCjg1+8CLbu69V1TKuPiOeSGbL9n+k/ByKH8UT0p4rdIX8XkTRZV0i7Sw==",
"optional": true
},
"node-releases": {
@ -5773,19 +5660,9 @@
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw=="
},
"path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"requires": {
"isarray": "0.0.1"
},
"dependencies": {
"isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8="
}
}
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
},
"path-type": {
"version": "4.0.0",
@ -5805,51 +5682,6 @@
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
"dev": true
},
"pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
"dev": true,
"requires": {
"find-up": "^4.0.0"
},
"dependencies": {
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": {
"p-locate": "^4.1.0"
}
},
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": {
"p-limit": "^2.2.0"
}
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
}
}
},
"pkg-up": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
@ -5859,15 +5691,6 @@
"find-up": "^3.0.0"
}
},
"please-upgrade-node": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
"integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
"dev": true,
"requires": {
"semver-compare": "^1.0.0"
}
},
"postcss": {
"version": "7.0.27",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.27.tgz",
@ -6409,13 +6232,6 @@
"integrity": "sha1-jdYjFCY+Wc9Qlur7sSeitu8xBzU=",
"requires": {
"looper": "~3.0.0"
},
"dependencies": {
"looper": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz",
"integrity": "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k="
}
}
},
"pull-traverse": {
@ -6434,6 +6250,13 @@
"integrity": "sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA=",
"requires": {
"looper": "^2.0.0"
},
"dependencies": {
"looper": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/looper/-/looper-2.0.0.tgz",
"integrity": "sha1-Zs0Md0rz1P7axTeU90LbVtqPCew="
}
}
},
"pull-write": {
@ -6544,12 +6367,12 @@
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
},
"raw-body": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.1.tgz",
"integrity": "sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==",
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
"requires": {
"bytes": "3.1.0",
"http-errors": "1.7.3",
"http-errors": "1.7.2",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
}
@ -6988,11 +6811,12 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"scope-analyzer": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.0.5.tgz",
"integrity": "sha512-+U5H0417mnTEstCD5VwOYO7V4vYuSqwqjFap40ythe67bhMFL5C3UgPwyBv7KDJsqUBIKafOD57xMlh1rN7eaw==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/scope-analyzer/-/scope-analyzer-2.1.1.tgz",
"integrity": "sha512-azEAihtQ9mEyZGhfgTJy3IbOWEzeOrYbg7NcYEshPKnKd+LZmC3TNd5dmDxbLBsTG/JVWmCp+vDJ03vJjeXMHg==",
"requires": {
"array-from": "^2.1.1",
"dash-ast": "^1.0.0",
"es6-map": "^0.1.5",
"es6-set": "^0.1.5",
"es6-symbol": "^3.1.1",
@ -7041,12 +6865,6 @@
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
},
"semver-compare": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
"integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=",
"dev": true
},
"semver-diff": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-2.1.0.tgz",
@ -7056,12 +6874,6 @@
"semver": "^5.0.3"
}
},
"semver-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz",
"integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==",
"dev": true
},
"send": {
"version": "0.17.1",
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
@ -7284,9 +7096,9 @@
}
},
"tweetnacl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.1.tgz",
"integrity": "sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A=="
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz",
"integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw=="
}
}
},
@ -7296,9 +7108,9 @@
"integrity": "sha512-8AVzr9VHueXqfzfkzUA0aXe/Q4XG3UTmhlP6Pt+HQc5bbAPIJFo7ZIMh9tvn+99QuiMcyDJdYumegGAczl0N+g=="
},
"sodium-native": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-2.4.6.tgz",
"integrity": "sha512-Ro9lhTjot8M01nwKLXiqLSmjR7B8o+Wg4HmJUjEShw/q6XPlNMzjPkA1VJKaMH8SO8fJ/sggAKVwreTaFszS2Q==",
"version": "2.4.9",
"resolved": "https://registry.npmjs.org/sodium-native/-/sodium-native-2.4.9.tgz",
"integrity": "sha512-mbkiyA2clyfwAyOFIzMvsV6ny2KrKEIhFVASJxWfsmgfUEymgLIS2MLHHcGIQMkrcKhPErRaMR5Dzv0EEn+BWg==",
"optional": true,
"requires": {
"ini": "^1.3.5",
@ -7412,26 +7224,6 @@
"pull-stream": "^3.6.0",
"ssb-config": "^3.4.4",
"ssb-keys": "^7.2.1"
},
"dependencies": {
"mkdirp": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
"requires": {
"minimist": "^1.2.5"
}
},
"ssb-keys": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/ssb-keys/-/ssb-keys-7.2.2.tgz",
"integrity": "sha512-FPeyYU/3LpxcagnbmVWE+Q/qzg6keqeOBPbD7sEH9UKixUASeufPKiORDgh8nVX7J9Z+0vUaHt/WG999kGjvVQ==",
"requires": {
"chloride": "^2.2.8",
"mkdirp": "~0.5.0",
"private-box": "^0.3.0"
}
}
}
},
"ssb-config": {
@ -7609,33 +7401,21 @@
}
},
"ssb-keys": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/ssb-keys/-/ssb-keys-7.2.0.tgz",
"integrity": "sha512-qxbVBYB5CsxWPEFg6qe+98hL6Jbs0rztA5zYsoQmYqz2+j3EhhIuXMTki92K4xREOCA2x45FFdOjDFy7ReDpBA==",
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/ssb-keys/-/ssb-keys-7.2.2.tgz",
"integrity": "sha512-FPeyYU/3LpxcagnbmVWE+Q/qzg6keqeOBPbD7sEH9UKixUASeufPKiORDgh8nVX7J9Z+0vUaHt/WG999kGjvVQ==",
"requires": {
"chloride": "^2.2.8",
"mkdirp": "~0.5.0",
"private-box": "^0.3.0"
},
"dependencies": {
"minimist": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
"integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
},
"mkdirp": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.4.tgz",
"integrity": "sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw==",
"requires": {
"minimist": "^1.2.5"
},
"dependencies": {
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw=="
}
}
}
}
@ -7662,9 +7442,9 @@
}
},
"ssb-markdown": {
"version": "6.0.5",
"resolved": "https://registry.npmjs.org/ssb-markdown/-/ssb-markdown-6.0.5.tgz",
"integrity": "sha512-isJeAb7KgVXD1e+uNoF9dHYaD167Aew/VsofZJC1DDfL8tPG7xtjGuB+QRluE2/5ilLej2hE8mq27DcFT2a8Ww==",
"version": "6.0.6",
"resolved": "https://registry.npmjs.org/ssb-markdown/-/ssb-markdown-6.0.6.tgz",
"integrity": "sha512-rPJryeplNPAfJHBTqtg/GQVggjepFTgzPzmgnwD28MFHb2kAnbGo+M+oLsUb8UGkqE2jmV8fdmtiajYJYLOB5g==",
"requires": {
"emoji-regex": "^8.0.0",
"hashtag-regex": "^2.1.0",
@ -8024,24 +7804,29 @@
"dev": true
},
"static-eval": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.3.tgz",
"integrity": "sha512-zsxDGucfAh8T339sSKgpFbvg15Fms2IVaJGC+jqp0bVsxhcpM+iMeAI8weNo8dmf4OblgifTBUoyk1vGVtYw2w==",
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.5.tgz",
"integrity": "sha512-nNbV6LbGtMBgv7e9LFkt5JV8RVlRsyJrphfAt9tOtBBW/SfnzZDf2KnS72an8e434A+9e/BmJuTxeGPvrAK7KA==",
"requires": {
"escodegen": "^1.11.1"
},
"dependencies": {
"escodegen": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz",
"integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==",
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.1.tgz",
"integrity": "sha512-Bmt7NcRySdIfNPfU2ZoXDrrXsG9ZjvDxcAlMfDUgRBjLOWTuIACXPBFJH7Z+cLb40JeQco5toikyc9t9P8E9SQ==",
"requires": {
"esprima": "^3.1.3",
"esprima": "^4.0.1",
"estraverse": "^4.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1",
"source-map": "~0.6.1"
}
},
"esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
}
}
},
@ -8090,13 +7875,6 @@
"requires": {
"looper": "^3.0.0",
"pull-stream": "^3.2.3"
},
"dependencies": {
"looper": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/looper/-/looper-3.0.0.tgz",
"integrity": "sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k="
}
}
},
"string-width": {
@ -9183,7 +8961,8 @@
"which-pm-runs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz",
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs="
"integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=",
"optional": true
},
"wide-align": {
"version": "1.1.3",
@ -9353,11 +9132,6 @@
"yargs-parser": "^18.1.1"
},
"dependencies": {
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",

View File

@ -16,13 +16,13 @@
"dev": "nodemon --inspect src/index.js --debug --no-open",
"fix": "common-good fix",
"start": "node src/index.js",
"test": "common-good check --dependency-check-suffix '-i husky -i changelog-version -i mkdirp -i nodemon -i stylelint-config-recommended'",
"test": "common-good check --dependency-check-suffix '-i changelog-version -i mkdirp -i nodemon -i stylelint-config-recommended'",
"preversion": "npm test",
"version": "changelog-version && git add CHANGELOG.md"
},
"dependencies": {
"@fraction/base16-css": "^1.1.0",
"@fraction/flotilla": "^4.0.0",
"@fraction/flotilla": "^4.0.1",
"@koa/router": "^8.0.0",
"debug": "^4.1.1",
"env-paths": "^2.2.0",
@ -44,7 +44,7 @@
"sharp": "^0.23.0",
"ssb-client": "^4.9.0",
"ssb-config": "^3.4.4",
"ssb-markdown": "^6.0.5",
"ssb-markdown": "^6.0.6",
"ssb-mentions": "^0.5.2",
"ssb-msgs": "^5.2.0",
"ssb-ref": "^2.13.9",
@ -68,7 +68,6 @@
"@types/yargs": "^15.0.4",
"changelog-version": "^1.0.1",
"common-good": "^2.0.3",
"husky": "^4.0.0",
"mkdirp": "^1.0.0",
"nodemon": "^2.0.2",
"stylelint-config-recommended": "^3.0.0"

77
scripts/build.sh Executable file
View File

@ -0,0 +1,77 @@
#!/bin/sh
set -ex
BASEDIR="$(dirname "$0")"
TARGET_VERSION="12.16.1"
cd "$BASEDIR/.."
git clean -fdx
mkdir -p vendor
cd vendor
get_tgz () {
TARGET_PLATFORM="$1"
TARGET="node-v$TARGET_VERSION-$TARGET_PLATFORM-x64"
ARCHIVE="$TARGET.tar.gz"
URL="https://nodejs.org/dist/v$TARGET_VERSION/$ARCHIVE"
TARGET_NODE="$TARGET/bin/node"
wget "$URL"
tar -xvf "$ARCHIVE" "$TARGET_NODE"
rm -f "$ARCHIVE"
}
get_zip () {
TARGET_PLATFORM="$1"
TARGET="node-v$TARGET_VERSION-$TARGET_PLATFORM-x64"
ARCHIVE="$TARGET.zip"
URL="https://nodejs.org/dist/v$TARGET_VERSION/$ARCHIVE"
TARGET_NODE="$TARGET/node.exe"
wget "$URL"
unzip "$ARCHIVE" "$TARGET_NODE"
rm -f "$ARCHIVE"
}
get_tgz darwin
get_tgz linux
get_zip win
cd ..
# Avoid building anything from source.
npm ci --only=prod --ignore-scripts --no-audit --no-fund
# More trouble than it's worth :)
rm -rf ./node_modules/sharp
export GOARCH="amd64"
# Darwin (shell script)
export GOOS="darwin"
OUTFILE="oasis-$GOOS-$GOARCH"
go build -ldflags "-X main.node=vendor/node-v$TARGET_VERSION-darwin-x64/bin/node" -o "$OUTFILE" scripts/oasis.go
chmod +x "$OUTFILE"
# Linux (ELF executable)
export GOOS="linux"
OUTFILE="oasis-$GOOS-$GOARCH"
go build -ldflags "-X main.node=vendor/node-v$TARGET_VERSION-linux-x64/bin/node" -o "$OUTFILE" scripts/oasis.go
chmod +x "$OUTFILE"
# Windows (batch file)
export GOOS="windows"
OUTFILE="oasis-$GOOS-$GOARCH.exe"
go build -ldflags "-X main.node=vendor\\node-v$TARGET_VERSION-win-x64\\bin\\node" -o "$OUTFILE" scripts/oasis.go
chmod +x "$OUTFILE"
# I think if the zip already exists it's adding files to the existing archive?
ZIP_PATH="/tmp/oasis-x64.zip"
rm -f "$ZIP_PATH"
zip -r "$ZIP_PATH" . -x ".git/**"
git clean -fdx

57
scripts/oasis.go Normal file
View File

@ -0,0 +1,57 @@
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
)
// The relative path to the `node` binary depends on the platform, so we
// pass this via an `-ldflags` hack I don't completely understand. In my
// head this is similar to how GCC lets you use `-D` to define a macro to
// be inserted by the preprocessor.
var node string
func main() {
// The problem with relative paths is that they only work when
// you run `./oasis-platform-x64`, but not when you run a command
// like `./path/to/oasis-platform-x64`. To resolve this problem
// we need to put together an absolute path, which we can build
// with the first argument (the relative path of this executable)
// and the relative path of either the `node` binary or the
// source code directory so that we can run `node src`.
node := filepath.Join(filepath.Dir(os.Args[0]), node)
src := filepath.Join(filepath.Dir(os.Args[0]), "src")
// We know that the command will be the absolute path to `node`
// and the first argument will be the absolute path to the `src`
// directory, but we need to get collect the rest of the arguments
// programatically by pulling them out of the `os.Args` slice and
// putting them in a new slice called `args`.
args := []string{src}
for i := 1; i < len(os.Args); i++ {
args = append(args, os.Args[i])
}
// This seems to execute the script and pass-through all of the
// arguments we want, *plus* it hooks up stdout and stderr, but
// the exit code of Oasis doesn't seem to be passed through. This
// is easy to test with a command like:
//
// ./oasis-platform-x64 --port -1
//
// This should give an exit code of 1, but it seems to exit 0. :/
cmd := exec.Command(node, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
// This catches problems like "no such file or directory" if the
// `node` variable points to a path where there isn't a binary.
//
// TODO: I think we're supposed to handle the exit code here.
err := cmd.Run()
if err != nil {
fmt.Println(err)
}
}

View File

@ -109,6 +109,7 @@ h6 {
ul,
ol {
padding-left: var(--whole);
margin-left: var(--nano);
}
a {
@ -124,13 +125,22 @@ button {
border-radius: var(--common-radius);
}
section > footer > a,
section > footer > form > button {
section header a {
display: flex;
color: var(--fg-status);
text-decoration: none;
font-weight: bold;
margin-right: var(--micro);
margin-left: var(--micro);
}
section > footer > div > a,
section > footer > div > form > button {
color: var(--fg-status);
font-weight: bold;
}
section > footer > form > button {
section > footer > div > form > button {
display: inline-block;
border: 0;
background: transparent;
@ -186,13 +196,14 @@ textarea:focus {
border-color: var(--blue);
}
/* Prevent button styles being applied to heart button */
button:focus,
button:hover {
background-color: var(--fg-light);
}
section > footer > form > button:hover,
section > footer > form > button:focus {
section > div > footer > form > button:hover,
section > div > footer > form > button:focus {
background-color: transparent;
}
@ -240,6 +251,11 @@ section video {
box-sizing: border-box;
}
section > h1 {
margin-top: 0;
padding-top: 0;
}
.profile > img,
.profile > h1 {
display: inline-block;
@ -278,15 +294,6 @@ section audio {
width: 100%;
}
section > :first-child {
margin-top: 0;
padding-top: 0;
}
.content > :last-child {
margin-bottom: 0;
}
@media screen {
html {
min-height: 100%;
@ -305,15 +312,6 @@ nav {
margin: var(--whole) 0;
}
section header a {
display: flex;
color: var(--fg-status);
text-decoration: none;
font-weight: bold;
margin-right: var(--micro);
margin-left: var(--micro);
}
nav > ul > li > a {
color: var(--fg);
text-decoration: none;
@ -335,11 +333,20 @@ section {
}
section > header {
height: var(--line);
display: flex;
margin-bottom: var(--whole);
justify-content: space-between;
background: var(--bg);
color: var(--fg-status);
height: var(--line);
margin-bottom: calc(-1 * var(--milli));
margin-top: calc(-1 * var(--milli));
padding-bottom: var(--milli);
padding-top: var(--milli);
position: sticky;
top: 0;
}
section > header > div {
display: flex;
justify-content: space-between;
}
section header a > .avatar {
@ -350,9 +357,8 @@ section header a > .avatar {
}
section header span {
display: flex;
display: inline-flex;
}
section header .author > a:first-child {
margin-left: 0;
color: var(--fg-light);
@ -384,17 +390,23 @@ section > .centered-footer {
}
section > footer {
display: flex;
justify-content: space-between;
margin-top: var(--whole);
color: var(--fg-status);
}
section > footer > * {
section > footer br {
display: none;
}
section > footer > div {
display: flex;
justify-content: space-between;
}
section > footer > div > * {
text-decoration: none;
}
section > footer > form > button.liked {
section > footer > div > form > button.liked {
color: var(--red);
}
@ -417,7 +429,6 @@ nav > ul > li {
}
.profile {
margin-top: var(--whole);
display: flex;
margin-bottom: var(--whole);
}
@ -434,12 +445,17 @@ progress {
border-color: var(--blue);
}
/* content warning! */
summary {
padding: var(--milli);
margin: 0;
margin-top: var(--whole);
cursor: pointer;
border: var(--pico) solid var(--bg-selection);
background: var(--bg);
border-radius: var(--common-radius);
list-style-type: "+ ";
}
details[open] > summary {
list-style-type: " ";
}
.md-mention {
@ -517,6 +533,63 @@ hr {
* be wise to nest these recursively on the thread view, which would make it so
* that we don't need any inline CSS anymore.
*/
.indent > section {
margin-left: 2rem;
.indent {
padding-left: 1rem;
border-left: var(--micro) solid var(--bg-selection);
}
.theme-preview {
width: calc(100% / 15);
height: var(--whole);
margin-top: var(--whole);
display: inline-block;
}
.theme-preview-00 {
background-color: var(--base00);
}
.theme-preview-01 {
background-color: var(--base01);
}
.theme-preview-02 {
background-color: var(--base02);
}
.theme-preview-03 {
background-color: var(--base03);
}
.theme-preview-04 {
background-color: var(--base04);
}
.theme-preview-05 {
background-color: var(--base05);
}
.theme-preview-06 {
background-color: var(--base06);
}
.theme-preview-07 {
background-color: var(--base07);
}
.theme-preview-08 {
background-color: var(--base08);
}
.theme-preview-09 {
background-color: var(--base09);
}
.theme-preview-0A {
background-color: var(--base0A);
}
.theme-preview-0B {
background-color: var(--base0B);
}
.theme-preview-0C {
background-color: var(--base0C);
}
.theme-preview-0D {
background-color: var(--base0D);
}
.theme-preview-0E {
background-color: var(--base0E);
}
.theme-preview-0F {
background-color: var(--base0F);
}

View File

@ -43,4 +43,9 @@ module.exports = (presets, defaultConfigFile) =>
default: _.get(presets, "debug", false),
type: "boolean",
})
.options("theme", {
describe: "The theme to use, if a theme hasn't been set in the cookies",
default: _.get(presets, "theme", "atelier-sulphurpool-light"),
type: "string",
})
.epilog(`The defaults can be configured in ${defaultConfigFile}.`).argv;

View File

@ -33,7 +33,7 @@ const http = ({ host, port, middleware }) => {
"img-src 'self'",
"form-action 'self'",
"media-src 'self'",
"style-src 'self' 'unsafe-inline'",
"style-src 'self'",
].join("; ");
// Disallow scripts.

View File

@ -165,6 +165,7 @@ const {
settingsView,
topicsView,
summaryView,
threadsView,
} = require("./views");
let sharp;
@ -175,8 +176,6 @@ try {
// Optional dependency
}
const defaultTheme = "atelier-sulphurPool-light".toLowerCase();
const readmePath = path.join(__dirname, "..", "README.md");
const packagePath = path.join(__dirname, "..", "package.json");
@ -263,6 +262,10 @@ router
const messages = await post.latestSummaries();
ctx.body = await summaryView({ messages });
})
.get("/public/latest/threads", async (ctx) => {
const messages = await post.latestThreads();
ctx.body = await threadsView({ messages });
})
.get("/author/:feed", async (ctx) => {
const { feed } = ctx.params;
const author = async (feedId) => {
@ -326,7 +329,7 @@ router
ctx.body = await hashtagView({ hashtag, messages });
})
.get("/theme.css", (ctx) => {
const theme = ctx.cookies.get("theme") || defaultTheme;
const theme = ctx.cookies.get("theme") || config.theme;
const packageName = "@fraction/base16-css";
const filePath = `${packageName}/src/base16-${theme}.css`;
@ -511,7 +514,7 @@ router
ctx.body = await image({ blobId, imageSize: Number(imageSize) });
})
.get("/settings/", async (ctx) => {
const theme = ctx.cookies.get("theme") || defaultTheme;
const theme = ctx.cookies.get("theme") || config.theme;
const getMeta = async ({ theme }) => {
const status = await meta.status();
const peers = await meta.peers();

View File

@ -899,6 +899,50 @@ module.exports = ({ cooler, isPublic }) => {
return messages;
},
latestThreads: async () => {
const ssb = await cooler.open();
const myFeedId = ssb.id;
const options = configure({
type: "post",
private: false,
});
const source = ssb.messagesByType(options);
const messages = await new Promise((resolve, reject) => {
pull(
source,
pull.filter(
(message) =>
typeof message.value.content !== "string" &&
message.value.content.root == null
),
pull.take(maxMessages),
pullParallelMap(async (message, cb) => {
// Retrieve a preview of this post's comments / thread
const thread = await post.fromThread(message.key);
lodash.set(
message,
"value.meta.thread",
await transform(ssb, thread, myFeedId)
);
cb(null, message);
}),
pull.filter((message) => message.value.meta.thread.length > 1),
pull.collect((err, collectedMessages) => {
if (err) {
reject(err);
} else {
resolve(transform(ssb, collectedMessages, myFeedId));
}
})
);
});
return messages;
},
popular: async ({ period }) => {
const ssb = await cooler.open();
@ -1056,17 +1100,22 @@ module.exports = ({ cooler, isPublic }) => {
debug("getting root ancestor of %s", msg.key);
if (typeof msg.value.content === "string") {
debug("private message");
// Private message we can't decrypt, stop looking for parents.
resolve(parents);
}
if (msg.value.content.type !== "post") {
debug("private message");
if (parents.length > 0) {
// If we already have some parents, return those.
resolve(parents);
} else {
// If we don't know of any parents, resolve this message.
resolve(msg);
}
} else if (msg.value.content.type !== "post") {
debug("not a post");
resolve(msg);
}
if (isLooseReply(msg) && ssbRef.isMsg(msg.value.content.fork)) {
} else if (
isLooseReply(msg) &&
ssbRef.isMsg(msg.value.content.fork)
) {
debug("reply, get the parent");
try {
// It's a message reply, get the parent!

View File

@ -30,6 +30,11 @@ const i18n = {
strong("Topics and some comments"),
" from yourself and people you follow, sorted by recency. Select the timestamp of any post to see the rest of the thread.",
],
threads: "Threads",
threadsDescription: [
strong("Posts that have comments"),
" from people you follow and your extended network, sorted by recency. Select the timestamp of any post to see the rest of the thread.",
],
profile: "Profile",
manualMode: "Manual Mode",
mentions: "Mentions",
@ -125,7 +130,7 @@ const i18n = {
],
theme: "Theme",
themeIntro:
"Choose from any theme you'd like. The default theme is Atelier-SulphurPool-Light.",
"Choose from any theme you'd like. The default theme is Atelier-SulphurPool-Light. You can also set your theme in the default configuration file.",
setTheme: "Set theme",
language: "Language",
languageDescription:
@ -151,11 +156,11 @@ const i18n = {
searchLabel: "Add word(s) to look for in downloaded messages.",
// posts and comments
commentDescription: ({ parentUrl }) => [
"commented on ",
" commented on ",
a({ href: parentUrl }, " thread"),
],
replyDescription: ({ parentUrl }) => [
"replied to ",
" replied to ",
a({ href: parentUrl }, " message"),
],
mysteryDescription: "posted a mysterious message",
@ -322,11 +327,11 @@ const i18n = {
"Buscá las siguientes palabras por los mensajes que tenés descargados.",
// posts and comments
commentDescription: ({ parentUrl }) => [
"comentado en el hilo ",
" comentado en el hilo ",
a({ href: parentUrl }, ""),
],
replyDescription: ({ parentUrl }) => [
"respondido al mensaje ",
" respondido al mensaje ",
a({ href: parentUrl }, ""),
],
mysteryDescription: "publicó un mensaje misterioso",
@ -490,11 +495,11 @@ const i18n = {
"Füge Wörte hinzu nach denen in heruntergeladenen Nachrichten gesucht werden soll.",
// posts and comments
commentDescription: ({ parentUrl }) => [
"kommentierte auf ",
" kommentierte auf ",
a({ href: parentUrl }, " Thread"),
],
replyDescription: ({ parentUrl }) => [
"antwortete auf ",
" antwortete auf ",
a({ href: parentUrl }, " Nachricht"),
],
mysteryDescription: "veröffentlichte eine mysteriöse Nachricht",

View File

@ -8,6 +8,7 @@ const MarkdownIt = require("markdown-it");
const {
a,
article,
br,
body,
button,
details,
@ -119,6 +120,11 @@ const template = (...elements) => {
emoji: "🗒️",
text: i18n.summaries,
}),
navLink({
href: "/public/latest/threads",
emoji: "🧵",
text: i18n.threads,
}),
navLink({ href: "/profile", emoji: "🐱", text: i18n.profile }),
navLink({ href: "/mentions", emoji: "💬", text: i18n.mentions }),
navLink({ href: "/inbox", emoji: "✉️", text: i18n.private }),
@ -220,42 +226,139 @@ const postInAside = (msg) => {
class: messageClasses.join(" "),
},
header(
span(
{ class: "author" },
a(
{ href: url.author },
img({ class: "avatar", src: url.avatar, alt: "" }),
msg.value.meta.author.name
div(
span(
{ class: "author" },
a(
{ href: url.author },
img({ class: "avatar", src: url.avatar, alt: "" }),
msg.value.meta.author.name
),
postOptions[msg.value.meta.postType]
),
postOptions[msg.value.meta.postType]
),
span(
{ class: "time" },
isPrivate ? "🔒" : null,
a({ href: url.link }, timeAgo)
span(
{ class: "time" },
isPrivate ? "🔒" : null,
a({ href: url.link }, nbsp, timeAgo)
)
)
),
articleContent,
footer(
form(
{ action: url.likeForm, method: "post" },
button(
{
name: "voteValue",
type: "submit",
value: likeButton.value,
class: likeButton.class,
},
`${likeCount}`
)
div(
form(
{ action: url.likeForm, method: "post" },
button(
{
name: "voteValue",
type: "submit",
value: likeButton.value,
class: likeButton.class,
},
`${likeCount}`
)
),
a({ href: url.comment }, i18n.comment),
isPrivate || isRoot || isFork
? null
: a({ href: url.reply }, nbsp, i18n.reply),
a({ href: url.json }, nbsp, i18n.json)
),
a({ href: url.comment }, i18n.comment),
isPrivate || isRoot || isFork ? null : a({ href: url.reply }, i18n.reply),
a({ href: url.json }, i18n.json)
br()
)
);
};
const thread = (messages) => {
// this first loop is preprocessing to enable auto-expansion of forks when a
// message in the fork is linked to
let lookingForTarget = true;
let shallowest = Infinity;
for (let i = messages.length - 1; i >= 0; i--) {
const msg = messages[i];
const depth = lodash.get(msg, "value.meta.thread.depth", 0);
if (lookingForTarget) {
const isThreadTarget = Boolean(
lodash.get(msg, "value.meta.thread.target", false)
);
if (isThreadTarget) {
lookingForTarget = false;
}
} else {
if (depth < shallowest) {
lodash.set(msg, "value.meta.thread.ancestorOfTarget", true);
shallowest = depth;
}
}
}
const msgList = [];
for (let i = 0; i < messages.length; i++) {
const j = i + 1;
const currentMsg = messages[i];
const nextMsg = messages[j];
const depth = (msg) => {
// will be undefined when checking depth(nextMsg) when currentMsg is the
// last message in the thread
if (msg === undefined) return 0;
return lodash.get(msg, "value.meta.thread.depth", 0);
};
msgList.push(post({ msg: currentMsg }).outerHTML);
if (depth(currentMsg) < depth(nextMsg)) {
const isAncestor = Boolean(
lodash.get(currentMsg, "value.meta.thread.ancestorOfTarget", false)
);
msgList.push(`<div class="indent"><details ${isAncestor ? "open" : ""}>`);
const nextAuthor = lodash.get(nextMsg, "value.meta.author.name");
const nextSnippet = postSnippet(
lodash.get(nextMsg, "value.content.text")
);
msgList.push(summary(`${nextAuthor}: ${nextSnippet}`).outerHTML);
} else if (depth(currentMsg) > depth(nextMsg)) {
// getting more shallow
const diffDepth = depth(currentMsg) - depth(nextMsg);
const shallowList = [];
for (let d = 0; d < diffDepth; d++) {
// on the way up it might go several depths at once
shallowList.push("</details></div>");
}
msgList.push(shallowList);
}
}
const htmlStrings = lodash.flatten(msgList);
return div({}, { innerHTML: htmlStrings.join("") });
};
const postSnippet = (text) => {
const max = 40;
text = text.trim().split("\n", 3).join("\n");
// this is taken directly from patchwork. i'm not entirely sure what this
// regex is doing
text = text.replace(/_|`|\*|#|^\[@.*?]|\[|]|\(\S*?\)/g, "").trim();
text = text.replace(/:$/, "");
text = text.trim().split("\n", 1)[0].trim();
if (text.length > max) {
text = text.substring(0, max - 1) + "…";
}
return text;
};
/**
* Render a section containing a link that takes users to the context for a
* thread preview.
@ -316,7 +419,7 @@ const postAside = ({ key, value }) => {
const fragments = postsToShow.map(postInAside);
if (thread.length > THREAD_PREVIEW_LENGTH + 1) {
fragments.push(section(footer(continueThreadComponent(thread, isComment))));
fragments.push(section(continueThreadComponent(thread, isComment)));
}
return div({ class: "indent" }, fragments);
@ -352,8 +455,6 @@ const post = ({ msg, aside = false }) => {
const { name } = msg.value.meta.author;
const timeAgo = msg.value.meta.timestamp.received.since.replace("~", "");
const depth = lodash.get(msg, "value.meta.thread.depth", 0);
const markdownContent = markdown(
msg.value.content.text,
msg.value.content.mentions
@ -415,22 +516,23 @@ const post = ({ msg, aside = false }) => {
{
id: msg.key,
class: messageClasses.join(" "),
style: `margin-left: ${depth}rem;`,
},
header(
span(
{ class: "author" },
a(
{ href: url.author },
img({ class: "avatar", src: url.avatar, alt: "" }),
name
div(
span(
{ class: "author" },
a(
{ href: url.author },
img({ class: "avatar", src: url.avatar, alt: "" }),
name
),
postOptions[msg.value.meta.postType]
),
postOptions[msg.value.meta.postType]
),
span(
{ class: "time" },
isPrivate ? "🔒" : null,
a({ href: url.link }, timeAgo)
span(
{ class: "time" },
isPrivate ? "🔒" : null,
a({ href: url.link }, nbsp, timeAgo)
)
)
),
articleContent,
@ -447,21 +549,26 @@ const post = ({ msg, aside = false }) => {
div({ id: `centered-footer-${encoded.key}`, class: "centered-footer" }),
footer(
form(
{ action: url.likeForm, method: "post" },
button(
{
name: "voteValue",
type: "submit",
value: likeButton.value,
class: likeButton.class,
},
`${likeCount}`
)
div(
form(
{ action: url.likeForm, method: "post" },
button(
{
name: "voteValue",
type: "submit",
value: likeButton.value,
class: likeButton.class,
},
`${likeCount}`
)
),
a({ href: url.comment }, i18n.comment),
isPrivate || isRoot || isFork
? null
: a({ href: url.reply }, nbsp, i18n.reply),
a({ href: url.json }, nbsp, i18n.json)
),
a({ href: url.comment }, i18n.comment),
isPrivate || isRoot || isFork ? null : a({ href: url.reply }, i18n.reply),
a({ href: url.json }, i18n.json)
br()
)
);
@ -524,7 +631,8 @@ exports.authorView = ({
relationship.following === true &&
relationship.blocking === false;
const contactFormType = areFollowing ? i18n.unfollow : i18n.follow;
const contactFormType = areFollowing ? "unfollow" : "follow";
const contactFormTypeLabel = i18n[contactFormType];
const contactForm =
relationship === null
@ -538,7 +646,7 @@ exports.authorView = ({
{
type: "submit",
},
contactFormType
contactFormTypeLabel
)
);
@ -572,7 +680,7 @@ exports.authorView = ({
const prefix = section(
{ class: "message" },
header(
div(
{ class: "profile" },
img({ class: "avatar", src: avatarUrl }),
h1(name)
@ -583,12 +691,15 @@ exports.authorView = ({
}),
description !== "" ? article({ innerHTML: markdown(description) }) : null,
footer(
a({ href: `/likes/${encodeURIComponent(feedId)}` }, i18n.viewLikes),
span(relationshipText),
contactForm,
relationship === null
? a({ href: `/profile/edit` }, i18n.editProfile)
: null
div(
a({ href: `/likes/${encodeURIComponent(feedId)}` }, i18n.viewLikes),
span(nbsp, relationshipText),
contactForm,
relationship === null
? a({ href: `/profile/edit` }, nbsp, i18n.editProfile)
: null
),
br()
)
);
@ -699,8 +810,7 @@ exports.publishCustomView = async () => {
);
};
exports.threadView = ({ messages }) =>
template(messages.map((msg) => post({ msg })));
exports.threadView = ({ messages }) => template(thread(messages));
exports.markdownView = ({ text }) => {
const rawHtml = md.render(text);
@ -766,14 +876,16 @@ exports.settingsView = ({ status, peers, theme, themeNames, version }) => {
stopButton,
]);
const peerList = (peers || []).map(([, data]) => {
return li(
a(
{ href: `/author/${encodeURIComponent(data.key)}` },
data.name || data.host || data.key
)
);
});
const peerList = (peers || [])
.filter(([, data]) => data.state === "connected")
.map(([, data]) => {
return li(
a(
{ href: `/author/${encodeURIComponent(data.key)}` },
data.name || data.host || data.key
)
);
});
const themeElements = themeNames.map((cur) => {
const isCurrentTheme = cur === theme;
@ -805,13 +917,7 @@ exports.settingsView = ({ status, peers, theme, themeNames, version }) => {
const base16Elements = base16.map((base) =>
div({
style: {
"background-color": `var(--base${base})`,
width: `${(1 / base16.length) * 100}%`,
height: "1em",
"margin-top": "1em",
display: "inline-block",
},
class: `theme-preview theme-preview-${base}`,
})
);
@ -944,6 +1050,15 @@ exports.summaryView = ({ messages }) => {
});
};
exports.threadsView = ({ messages }) => {
return messageListView({
messages,
viewTitle: i18n.threads,
viewDescription: i18n.threadsDescription,
aside: true,
});
};
exports.replyView = async ({ messages, myFeedId }) => {
const replyForm = `/reply/${encodeURIComponent(
messages[messages.length - 1].key