WIP: nearly working, just need to figure out why the comments link in gemini is broken

This commit is contained in:
Joe Mulvaney 2023-07-20 04:07:54 +00:00
parent a12f6c0e20
commit fc66e72d2f
10 changed files with 214 additions and 8 deletions

19
assets/cgi-bin/comments.gmi.cgi Executable file
View File

@ -0,0 +1,19 @@
#!/usr/bin/env node
const defaults = {
rootToot: '109574160582937075',
tootSource: 'fosstodon.org',
fragment: 'false',
}
const { execSync } = require('node:child_process')
const queryparser = require('node:querystring')
console.log('20 text/gemini\r\n')
const query = queryparser.parse(process.env.QUERY_STRING)
const args = { ...defaults, ...query }
const commentsHtml = execSync(`node /home/mycrobe/cms/src/mastodonComments.js --fragment ${args.fragment} --rootToot ${args.rootToot} --tootSource ${args.tootSource} --title "${args.title}" --backlink "${args.backlink}" --format gemini`).toString()
console.log(commentsHtml)

View File

@ -21,7 +21,7 @@ window.MYCROBE = {
queryString = 'fragment=true&rootToot=' + rootToot + '&tootSource=' + tootSource + "&title" + title + "&ts=" + new Date().getTime();
req = new XMLHttpRequest();
req.addEventListener("load", callback);
req.open("GET", "../cgi-bin/comments.cgi?" + queryString);
req.open("GET", "../cgi-bin/comments.html.cgi?" + queryString);
req.send();
}
}

144
package-lock.json generated
View File

@ -11,6 +11,7 @@
"dependencies": {
"@github-docs/frontmatter": "^1.3.1",
"dompurify": "^3.0.5",
"html-to-text": "^9.0.5",
"jsdom": "^22.1.0",
"luxon": "^3.3.0",
"minimist": "^1.2.8",
@ -27,6 +28,18 @@
"revalidator": "^0.3.1"
}
},
"node_modules/@selderee/plugin-htmlparser2": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz",
"integrity": "sha512-P33hHGdldxGabLFjPPpaTxVolMrzrcegejx+0GxjrIb9Zv48D8yAIA/QTDR2dFl7Uz7urX8aX6+5bCZslr+gWQ==",
"dependencies": {
"domhandler": "^5.0.3",
"selderee": "^0.11.0"
},
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/@tootallnate/once": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz",
@ -120,6 +133,14 @@
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
@ -128,6 +149,30 @@
"node": ">=0.4.0"
}
},
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
]
},
"node_modules/domexception": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/domexception/-/domexception-4.0.0.tgz",
@ -139,11 +184,38 @@
"node": ">=12"
}
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/dompurify": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.5.tgz",
"integrity": "sha512-F9e6wPGtY+8KNMRAVfxeCOHU0/NPWMSENNq4pQctuXRqqdEPW7q3CrLbR5Nse044WwacyjHGOMlvNsBe1y6z9A=="
},
"node_modules/domutils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@ -216,6 +288,39 @@
"node": ">=12"
}
},
"node_modules/html-to-text": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz",
"integrity": "sha512-qY60FjREgVZL03vJU6IfMV4GDjGBIoOyvuFdpBDIX9yTlDw0TjxVBQp+P8NvpdIXNJvfWBTNul7fsAQJq2FNpg==",
"dependencies": {
"@selderee/plugin-htmlparser2": "^0.11.0",
"deepmerge": "^4.3.1",
"dom-serializer": "^2.0.0",
"htmlparser2": "^8.0.2",
"selderee": "^0.11.0"
},
"engines": {
"node": ">=14"
}
},
"node_modules/htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"node_modules/http-proxy-agent": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz",
@ -326,6 +431,14 @@
"node": ">=0.10.0"
}
},
"node_modules/leac": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/leac/-/leac-0.6.0.tgz",
"integrity": "sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==",
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
@ -387,6 +500,26 @@
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parseley": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/parseley/-/parseley-0.12.1.tgz",
"integrity": "sha512-e6qHKe3a9HWr0oMRVDTRhKce+bRO8VGQR3NyVwcjwrbhMmFCX9KszEV35+rn4AdilFAq9VPxP/Fe1wC9Qjd2lw==",
"dependencies": {
"leac": "^0.6.0",
"peberminta": "^0.9.0"
},
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/peberminta": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/peberminta/-/peberminta-0.9.0.tgz",
"integrity": "sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==",
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/psl": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz",
@ -460,6 +593,17 @@
"node": ">=4"
}
},
"node_modules/selderee": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/selderee/-/selderee-0.11.0.tgz",
"integrity": "sha512-5TF+l7p4+OsnP8BCCvSyZiSPc4x4//p5uPwK8TCnVPJYRmU2aYKMpOXvw8zM5a5JvuuCGN1jmsMwuU2W02ukfA==",
"dependencies": {
"parseley": "^0.12.0"
},
"funding": {
"url": "https://ko-fi.com/killymxi"
}
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",

View File

@ -11,6 +11,7 @@
"dependencies": {
"@github-docs/frontmatter": "^1.3.1",
"dompurify": "^3.0.5",
"html-to-text": "^9.0.5",
"jsdom": "^22.1.0",
"luxon": "^3.3.0",
"minimist": "^1.2.8",

12
src/gemini/comment.js Normal file
View File

@ -0,0 +1,12 @@
const { convert } = require('html-to-text');
const options = { wordwrap: 65 }
module.exports = (data) => `
> ${convert(data.content, options).replace(/\n/gm, '\n> ')}
=> ${data.url} ${data.date} ${data.attachments && `-- ${data.attachments.length} attachment(s)`}
=> ${data.account.url} ${data.account.displayName} ${data.account.user}
${data.counts.replies && `💬 ${data.counts.replies}`} ${data.counts.reblogs && `♻️ ${data.counts.reblogs}`} ${data.counts.favourites && `❤️${data.counts.favourites}`}
`

View File

@ -0,0 +1,9 @@
module.exports = (toots, title, backlink) =>
`# Comments for “${title}
${toots}
### Nav
=> .. 🏠 Journal home
${backlink && '=> ' + backlink + ' ⬅️ Back to enty'}
`

View File

@ -4,6 +4,9 @@ ${data.date} - ${data.location}
${content}
${data.metadata && `
=> ../cgi-bin/comments.gmi.cgi?rootToot=${data.metadata.rootToot}&tootSource=${data.metadata.tootSource}&title=${encodeURIComponent(title)}&backlink=${encodeURIComponent(data.entryRelativeUrl)} Comments
`}
### Nav
=> .. 🏠 Journal home
${data.next ? '=> ' + data.next + ' ➡️ Next' : ''}

View File

@ -9,7 +9,7 @@ if (data.metadata) {
const meta = data.metadata
const commentOptions = JSON.stringify(meta)
commentScript = ` <div class="footer" id="comments">
<a href="../cgi-bin/comments.cgi?rootToot=${meta.rootToot}&tootSource=${meta.tootSource}&title=${encodedTitle}&backlink=${data.entryRelativeUrl}">Comments</a></p>
<a href="../cgi-bin/comments.html.cgi?rootToot=${meta.rootToot}&tootSource=${meta.tootSource}&title=${encodedTitle}&backlink=${data.entryRelativeUrl}">Comments</a></p>
</div>
<script src="../comments.js"></script>
<script>

View File

@ -1,7 +1,10 @@
const args = require('minimist')(process.argv.slice(2), {string: 'rootToot', boolean: 'fragment'})
const htmlComment = require('./html/comment.js')
const htmlCommentsPageTempate = require('./html/commentsPageTemplate.js')
// const htmlComment = require('./html/comment.js')
// const htmlCommentsPageTempate = require('./html/commentsPageTemplate.js')
// const geminiComment = require('./gemini/comment.js')
// const geminiCommentsPageTempate = require('./gemini/commentsTemplate.js')
const defaultArgs = {
rootToot: '109574160582937075',
@ -9,21 +12,36 @@ const defaultArgs = {
fragment: false,
title: '',
backlink: '..',
format: 'html'
}
// const defaultArgs = {
// rootToot: '109309280260024223',
// tootSource: 'curious.simio.us'
// }
let { rootToot, tootSource, fragment, title, backlink } = { ...defaultArgs, ...args }
let { rootToot, tootSource, fragment, title, backlink, format } = { ...defaultArgs, ...args }
rootToot = String(rootToot)
let commentTpl
let commentPageTpl
switch(args.format) {
case 'gemini':
commentTpl = require('./gemini/comment.js')
commentPageTpl = require('./gemini/commentsTemplate.js')
break
case 'html':
default:
commentTpl = require('./html/comment.js')
commentPageTpl = require('./html/commentsPageTemplate.js')
break
}
const getMastodonComments = async (id) => {
const apiUrl = `https://${tootSource}/api/v1/statuses/${id}/context`
const response = await fetch(apiUrl)
const { descendants } = await response.json()
const tootHtml = renderToots(descendants, id, 0).join('\n')
return fragment ? tootHtml : htmlCommentsPageTempate(tootHtml, title, backlink)
const tootString = renderToots(descendants, id, 0).join('\n')
return fragment ? tootString : commentPageTpl(tootString, title, backlink)
}
getMastodonComments(rootToot).then(console.log)
@ -49,7 +67,7 @@ function renderToots(toots, in_reply_to, depth) {
function renderToot(toots, toot, depth) {
const data = prepTootData(toot, depth)
const mastodonComment = htmlComment(data)
const mastodonComment = commentTpl(data)
return [mastodonComment, ...renderToots(toots, toot.id, depth + 1)]
}