{"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753218817", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753218817, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxODgxNw==", "user": {"value": 173848, "label": "yozlet"}, "created_at": "2020-12-31T22:32:25Z", "updated_at": "2020-12-31T22:32:25Z", "author_association": "NONE", "body": "Amazing work! And you've put in far more work than I'd expect to reduce the payload (which is admirable).\r\n\r\nSo, to add a plugin with the current design, it goes in (a) the template or (b) a bookmarklet, right?", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753217714", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753217714, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxNzcxNA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:21:33Z", "updated_at": "2020-12-31T22:21:33Z", "author_association": "OWNER", "body": "Eventually I'd like to provide a whole bunch of other `datasette.X` utility functions that plugins can use - things like `datasette.addTabbedContentPane()` or similar.\r\n\r\nBut I don't want to inline those into the page.\r\n\r\nSo... I think the basic plugin system remains inline - maybe from an inlined file called `plugins-bootstrap.js`. Then a separate `plugins.js` contains the rest of the API functionality.\r\n\r\nIf a plugin wants to take advantage of those APIs, maybe it registers itself using `datasette.plugins.register('load', () => ...)` - that `load` hook can then be fired once the bulkier plugin code has been loaded.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753219521", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753219521, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxOTUyMQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:39:52Z", "updated_at": "2020-12-31T22:39:52Z", "author_association": "OWNER", "body": "For inlining the `plugins.min.js` file into the Jinja templates I could use the trick described here: https://stackoverflow.com/a/41404611 - which adds a `{{ include_file('file.txt') }}` function to Jinja.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1165#issuecomment-752828851", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1165", "id": 752828851, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MjgyODg1MQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T03:19:38Z", "updated_at": "2020-12-31T03:19:38Z", "author_association": "OWNER", "body": "I got Cypress working! I added the `datasette.plugins` code to the table template and ran a test called `plugins.spec.js` using the following:\r\n```javascript\r\ncontext('datasette.plugins API', () => {\r\n beforeEach(() => {\r\n cy.visit('/fixtures/compound_three_primary_keys')\r\n });\r\n it('should exist', () => {\r\n let datasette;\r\n cy.window().then(win => {\r\n datasette = win.datasette;\r\n }).then(() => {\r\n expect(datasette).to.exist;\r\n expect(datasette.plugins).to.exist;\r\n });\r\n });\r\n it('should register and execute plugins', () => {\r\n let datasette;\r\n cy.window().then(win => {\r\n datasette = win.datasette;\r\n }).then(() => {\r\n expect(datasette.plugins.call('numbers')).to.deep.equal([]);\r\n // Register a plugin\r\n datasette.plugins.register(\"numbers\", (a, b) => a + b, ['a', 'b']);\r\n var result = datasette.plugins.call(\"numbers\", {a: 1, b: 2});\r\n expect(result).to.deep.equal([3]);\r\n // Second plugin\r\n datasette.plugins.register(\"numbers\", (a, b) => a * b, ['a', 'b']);\r\n var result2 = datasette.plugins.call(\"numbers\", {a: 1, b: 2});\r\n expect(result2).to.deep.equal([3, 2]);\r\n });\r\n });\r\n});\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 776635426, "label": "Mechanism for executing JavaScript unit tests"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1164#issuecomment-753221362", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1164", "id": 753221362, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIyMTM2Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:55:57Z", "updated_at": "2020-12-31T22:55:57Z", "author_association": "OWNER", "body": "I had to add this as the first line in `table.min.js` for the source mapping to work:\r\n```\r\n//# sourceMappingURL=/-/static/table.min.js.map\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 776634318, "label": "Mechanism for minifying JavaScript that ships with Datasette"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753224999", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753224999, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIyNDk5OQ==", "user": {"value": 11941245, "label": "jussiarpalahti"}, "created_at": "2020-12-31T23:29:36Z", "updated_at": "2020-12-31T23:29:36Z", "author_association": "NONE", "body": "I have yet to build Datasette plugin and am unfamiliar with Pluggy. Since browsers have event handling builtin Datasette could communicate with plugins through it. Handlers register as listeners for custom Datasette events and Datasette's JS can then trigger said events.\r\n\r\nI was also wondering if you had looked at Javascript Modules for JS plugins? With services like Skypack (https://www.skypack.dev) NPM libraries can be loaded directly into browser, no build step needed. Same goes for local JS if you adhere to ES Module spec. \r\n\r\nIf minification is required then tools such as Snowpack (https://www.snowpack.dev) could fit better. It uses https://github.com/evanw/esbuild for bundling and minification.\r\n\r\nOn plugins you'd simply:\r\n\r\n```javascript\r\nimport {register} from '/assets/js/datasette'\r\nregister.on({'click' : my_func})\r\n```\r\n\r\nIn Datasette HTML pages' head you'd merely import these files as modules one by one.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753224351", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753224351, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIyNDM1MQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T23:23:29Z", "updated_at": "2020-12-31T23:23:29Z", "author_association": "OWNER", "body": "I should configure the action to only run if changes have been made within the `datasette/static` directory.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1164#issuecomment-753220665", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1164", "id": 753220665, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIyMDY2NQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:49:36Z", "updated_at": "2020-12-31T22:49:36Z", "author_association": "OWNER", "body": "I started with a 7K `table.js` file.\r\n\r\n`npx uglifyjs table.js --source-map -o table.min.js` gave me a 5.6K `table.min.js` file. \r\n\r\n`npx uglifyjs table.js --source-map -o table.min.js --compress --mangle` gave me 4.5K.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 776634318, "label": "Mechanism for minifying JavaScript that ships with Datasette"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753215761", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753215761, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxNTc2MQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:07:31Z", "updated_at": "2020-12-31T22:07:31Z", "author_association": "OWNER", "body": "I think I need to keep the mechanism whereby a plugin can return `undefined` in order to indicate that it has nothing to say for that specific item - that's borrowed from Pluggy and I've used it a bunch in my Python plugins. That makes the code a bit longer.\r\n\r\nI'll write some example plugins to help me decide if the filtering-out-of-undefined mechanism is needed or not.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753200580", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753200580, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIwMDU4MA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T21:38:06Z", "updated_at": "2020-12-31T21:38:06Z", "author_association": "OWNER", "body": "I think this should work:\r\n```\r\n- uses: actions/cache@v2\r\n with:\r\n path: ~/.npm\r\n key: ${{ runner.os }}-node-${{ hashFiles('**/prettier.yml' }}\r\n```\r\nI'll use the `prettier.yml` workflow that I'm about to create as the cache key for the NPM cache.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753193475", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753193475, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzE5MzQ3NQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T21:33:00Z", "updated_at": "2020-12-31T21:33:00Z", "author_association": "OWNER", "body": "I want a CI check that confirms that files conform to prettier - but only `datasette/static/*.js` files that are not already minified.\r\n\r\nThis seems to do the job:\r\n\r\n npx prettier --check 'datasette/static/*[!.min].js'\r\n", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/987#issuecomment-753217127", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/987", "id": 753217127, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxNzEyNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:16:46Z", "updated_at": "2020-12-31T22:16:46Z", "author_association": "OWNER", "body": "I'm going to use `class=\"plugin-content-pre-table\"` rather than `id=` - just because I still want to be able to display all of this stuff on the single https://latest.datasette.io/-/patterns page so duplicate IDs are best avoided.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712984738, "label": "Documented HTML hooks for JavaScript plugin authors"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1164#issuecomment-753220412", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1164", "id": 753220412, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIyMDQxMg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:47:36Z", "updated_at": "2020-12-31T22:47:36Z", "author_association": "OWNER", "body": "I'm trying to minify `table.js` and I ran into a problem:\r\n\r\n Uglification failed. Unexpected character '`'\r\n\r\nIt turns out `uglify-js` doesn't support ES6 syntax!\r\n\r\nBut `uglify-es` does:\r\n\r\n npm install uglify-es\r\n\r\nAnnoyingly it looks like `uglify-es` uses the same CLI command, `uglifyjs`. So after installing it this seemed to work:\r\n\r\n npx uglifyjs table.js --source-map -o table.min.js\r\n\r\nI really don't like how `npx uglifyjs` could mean different things depending on which package was installed.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 776634318, "label": "Mechanism for minifying JavaScript that ships with Datasette"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753217917", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753217917, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxNzkxNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:23:29Z", "updated_at": "2020-12-31T22:23:36Z", "author_association": "OWNER", "body": "If I'm going to do that, it would be good if subsequent plugins that register against the `load` event are executed straight away. That's a bit of a weird edge-case in plugin world - it would involve the bulkier code that gets loaded redefining how `datasette.plugins.register` works to special-case the `'load'` hook.\r\n\r\nMaybe the tiny bootstrap code could define a `datasette.plugins.onload(callbackFunction)` method which gets upgraded later into something that fires straight away? Would add more bytes though.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-752888552", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 752888552, "node_id": "MDEyOklzc3VlQ29tbWVudDc1Mjg4ODU1Mg==", "user": {"value": 154364, "label": "dracos"}, "created_at": "2020-12-31T08:33:11Z", "updated_at": "2020-12-31T08:34:27Z", "author_association": "NONE", "body": "If you could say that all hook functions had to accept one options parameter (and could use object destructuring if they wished to only see a subset), you could have this, which minifies (to all-browser-JS) to 200 bytes, gzips to 146, and works practically the same:\r\n\r\n```js\r\nvar datasette = datasette || {};\r\ndatasette.plugins = (() => {\r\n var registry = {};\r\n return {\r\n register: (hook, fn) => {\r\n registry[hook] = registry[hook] || [];\r\n registry[hook].push(fn);\r\n },\r\n call: (hook, args) => {\r\n var results = (registry[hook] || []).map(fn => fn(args||{}));\r\n return results;\r\n }\r\n };\r\n})();\r\n```\r\n\r\n`var datasette=datasette||{};datasette.plugins=function(){var b={};return{register:function(a,c){b[a]=b[a]||[];b[a].push(c)},call:function(a,c){return(b[a]||[]).map(function(a){return a(c||{})})}}}();`\r\n\r\nCalled the same, definitions tiny bit different:\r\n\r\n```js\r\ndatasette.plugins.register('numbers', ({a, b}) => a + b)\r\ndatasette.plugins.register('numbers', o => o.a * o.b)\r\ndatasette.plugins.call('numbers', {a: 4, b: 6})\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-752882797", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 752882797, "node_id": "MDEyOklzc3VlQ29tbWVudDc1Mjg4Mjc5Nw==", "user": {"value": 154364, "label": "dracos"}, "created_at": "2020-12-31T08:07:59Z", "updated_at": "2020-12-31T15:04:32Z", "author_association": "NONE", "body": "If you're using arrow functions, you can presumably use default parameters, not much difference in support. That would save you 9 bytes. But OTOH you need `\"use strict\";` to use arrow functions etc, and that's 13 bytes.\r\n\r\nYour latest 250-byte one, with use strict, gzips to 199 bytes. The following might be 292 bytes, but compresses to 204, basically the same, and works in any browser (well, IE9+) at all:\r\n\r\n`var datasette=datasette||{};datasette.plugins=function(){var d={};return{register:function(b,c,e){d[b]||(d[b]=[]);d[b].push([c,e])},call:function(b,c){c=c||{};var e=[];(d[b]||[]).forEach(function(a){a=a[0].apply(a[0],a[1].map(function(a){return c[a]}));void 0!==a&&e.push(a)});return e}}}();`\r\n\r\nSource for that is below; I replaced the [fn,parameters] because closure-compiler includes a polyfill for that, and I ran `closure-compiler --language_out ECMASCRIPT3`:\r\n\r\n```js\r\nvar datasette = datasette || {};\r\ndatasette.plugins = (() => {\r\n var registry = {};\r\n return {\r\n register: (hook, fn, parameters) => {\r\n if (!registry[hook]) {\r\n registry[hook] = [];\r\n }\r\n registry[hook].push([fn, parameters]);\r\n },\r\n call: (hook, args) => {\r\n args = args || {};\r\n var results = [];\r\n (registry[hook] || []).forEach((data) => {\r\n /* Call with the correct arguments */\r\n var result = data[0].apply(data[0], data[1].map(parameter => args[parameter]));\r\n if (result !== undefined) {\r\n results.push(result);\r\n }\r\n });\r\n return results;\r\n }\r\n };\r\n})();\r\n```", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1165#issuecomment-752839433", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1165", "id": 752839433, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MjgzOTQzMw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T04:29:40Z", "updated_at": "2020-12-31T04:29:40Z", "author_association": "OWNER", "body": "Important to absorb the slightly bizarre assertion syntax from Chai - docs here https://www.chaijs.com/api/bdd/", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 776635426, "label": "Mechanism for executing JavaScript unit tests"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753197957", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753197957, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzE5Nzk1Nw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T21:36:14Z", "updated_at": "2020-12-31T21:36:14Z", "author_association": "OWNER", "body": "Maybe not that action actually - I wanted to use a pre-built action to avoid installing Prettier every time, but that's what it seems to do: https://github.com/creyD/prettier_action/blob/bb361e2979cff283ca7684908deac8f95400e779/entrypoint.sh#L28-L37", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753210536", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753210536, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxMDUzNg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T21:45:19Z", "updated_at": "2020-12-31T21:45:19Z", "author_association": "OWNER", "body": "Oops, committed that bad formatting test to `main` instead of a branch!", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1165#issuecomment-753033121", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1165", "id": 753033121, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzAzMzEyMQ==", "user": {"value": 154364, "label": "dracos"}, "created_at": "2020-12-31T19:33:47Z", "updated_at": "2020-12-31T19:33:47Z", "author_association": "NONE", "body": "Sorry to go on about it, but it's my only example ;) And thought it might be of interest/use. Here is FixMyStreet's Cypress workflow https://github.com/mysociety/fixmystreet/blob/master/.github/workflows/cypress.yml with the master script that sets up server etc at https://github.com/mysociety/fixmystreet/blob/master/bin/browser-tests (that has features such as working inside/outside Vagrant, and can do JS code coverage) and then the tests are at https://github.com/mysociety/fixmystreet/tree/master/.cypress/cypress/integration", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 776635426, "label": "Mechanism for executing JavaScript unit tests"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753209192", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753209192, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIwOTE5Mg==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T21:44:22Z", "updated_at": "2020-12-31T21:44:22Z", "author_association": "OWNER", "body": "Tests passed in https://github.com/simonw/datasette/runs/1631677726?check_suite_focus=true\r\n\r\nI'm going to try submitting a pull request with badly formatted JavaScript to see if it gets caught.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753195905", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753195905, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzE5NTkwNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T21:34:46Z", "updated_at": "2020-12-31T21:34:46Z", "author_association": "OWNER", "body": "This action looks good - tag 3.2 is equivalent to this commit hash: https://github.com/creyD/prettier_action/tree/bb361e2979cff283ca7684908deac8f95400e779", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753215545", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753215545, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxNTU0NQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:05:41Z", "updated_at": "2020-12-31T22:05:41Z", "author_association": "OWNER", "body": "Using object destructuring like that is a great idea. I'm going to play with your version - it's delightfully succinct.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 712260429, "label": "JavaScript plugin hooks mechanism similar to pluggy"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/1166#issuecomment-753214664", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/1166", "id": 753214664, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxNDY2NA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T21:58:04Z", "updated_at": "2020-12-31T21:58:04Z", "author_association": "OWNER", "body": "Wrote a TIL about this: https://til.simonwillison.net/github-actions/prettier-github-actions", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 777140799, "label": "Adopt Prettier for JavaScript code formatting"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/983#issuecomment-753219407", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/983", "id": 753219407, "node_id": "MDEyOklzc3VlQ29tbWVudDc1MzIxOTQwNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-12-31T22:38:45Z", "updated_at": "2020-12-31T22:39:10Z", "author_association": "OWNER", "body": "You'll be able to add JavaScript plugins using a bunch of different mechanisms:\r\n\r\n- In a custom template, dropping the code in to a `