diff --git a/package.json b/package.json index c6bf365..a6cc51c 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "@myst-theme/diagrams": "^0.3.2", "@myst-theme/frontmatter": "^0.3.2", "@myst-theme/providers": "^0.3.2", + "citation-js-utils": "^1.0.0", "katex": "^0.15.2", "myst-ext-card": "^1.0.0", "myst-ext-exercise": "^1.0.0", diff --git a/src/bibliography.ts b/src/bibliography.ts new file mode 100644 index 0000000..ce57680 --- /dev/null +++ b/src/bibliography.ts @@ -0,0 +1,89 @@ +import { Token } from '@lumino/coreutils'; +import { getCitations, CitationRenderer } from 'citation-js-utils'; +import { Contents, ContentsManager } from '@jupyterlab/services'; +import { ISignal, Signal } from '@lumino/signaling'; + +export interface IBibliographyManager { + getBibliography(): CitationRenderer | null; + + changed: ISignal; +} + +export const IBibliographyManager = new Token( + 'jupyterlab-myst:IBibliographyManager' +); + +export class BibliographyManager implements IBibliographyManager { + private _renderer: CitationRenderer | null; + private _changed = new Signal(this); + + get changed(): ISignal { + return this._changed; + } + + getBibliography(): CitationRenderer | null { + return this._renderer; + } + + constructor(contents: Contents.IManager, bibFile: string) { + this._renderer = null; + + contents + .get(bibFile) + .then(async model => { + this._renderer = await getCitations(model.content); + this._changed.emit(this._renderer); + }) + .catch(); + + // Handle changes + contents.fileChanged.connect(async (_, change) => { + // On create + if (change.type === 'new') { + const path = (change.newValue as Contents.IModel).path; + // Add model to record registry + if (path === bibFile) { + const model = await contents.get(path); + this._renderer = await getCitations(model.content); + this._changed.emit(this._renderer); + } + } + // On rename + else if (change.type === 'rename') { + // Remove by path + const oldPath = (change.oldValue as Contents.IModel).path; + // Add under new path! + const newPath = (change.newValue as Contents.IModel).path; + // Add model to record registry + if (newPath === bibFile) { + const model = await contents.get(newPath); + this._renderer = await getCitations(model.content); + this._changed.emit(this._renderer); + } else if (oldPath === bibFile) { + this._renderer = null; + this._changed.emit(this._renderer); + } + } + // On delete + else if (change.type === 'delete') { + const path = (change.oldValue as Contents.IModel).path; + // Add model to record registry + if (path === bibFile) { + this._renderer = null; + this._changed.emit(this._renderer); + } + } + // On save + else { + const path = (change.newValue as Contents.IModel).path; + // Add model to record registry + // Add model to record registry + if (path === bibFile) { + const model = await contents.get(path); + this._renderer = await getCitations(model.content); + this._changed.emit(this._renderer); + } + } + }); + } +} diff --git a/src/index.ts b/src/index.ts index aa1020a..341719e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,6 +14,8 @@ import { } from '@jupyterlab/notebook'; import { Cell } from '@jupyterlab/cells'; import { MySTContentFactory } from './MySTContentFactory'; +import { IBibliographyManager, BibliographyManager } from './bibliography'; + import { IRenderMimeRegistry } from '@jupyterlab/rendermime'; import { notebookCellExecuted } from './actions'; @@ -73,4 +75,23 @@ const mimeRendererPlugin: JupyterFrontEndPlugin = { } }; -export default [plugin, executorPlugin, mimeRendererPlugin]; +const bibPlugin: JupyterFrontEndPlugin = { + id: 'jupyterlab-myst:bibliography', + requires: [], + provides: IBibliographyManager, + autoStart: true, + activate: (app: JupyterFrontEnd) => { + console.log('Using jupyterlab-myst:bibliography'); + + const manager = new BibliographyManager( + app.serviceManager.contents, + 'bibliography.bib' + ); + manager.changed.connect((manager, renderer) => { + console.log(renderer, 'CHANGE'); + }); + return manager; + } +}; + +export default [plugin, executorPlugin, mimeRendererPlugin, bibPlugin]; diff --git a/yarn.lock b/yarn.lock index b154706..6692d65 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1321,6 +1321,123 @@ __metadata: languageName: node linkType: hard +"@citation-js/cli@npm:0.6.8": + version: 0.6.8 + resolution: "@citation-js/cli@npm:0.6.8" + dependencies: + "@citation-js/core": ^0.6.8 + "@citation-js/plugin-bibjson": ^0.6.8 + "@citation-js/plugin-bibtex": ^0.6.8 + "@citation-js/plugin-csl": ^0.6.8 + "@citation-js/plugin-doi": ^0.6.8 + "@citation-js/plugin-ris": ^0.6.8 + "@citation-js/plugin-wikidata": ^0.6.8 + commander: ^10.0.1 + bin: + citation-js: lib/index.js + checksum: 507e95b68a41321aade3cf968a2686e55aab0f07c8780b3a23687425628158b0bd300ef122a0f7c1c5afced631b12a117c7a87b1c9c993c5abdeadd79556dff9 + languageName: node + linkType: hard + +"@citation-js/core@npm:0.6.8, @citation-js/core@npm:^0.6.8": + version: 0.6.8 + resolution: "@citation-js/core@npm:0.6.8" + dependencies: + "@citation-js/date": ^0.5.0 + "@citation-js/name": ^0.4.2 + fetch-ponyfill: ^7.1.0 + sync-fetch: ^0.4.1 + checksum: 81916f7f30e2902a860bddd0ef07c7130c4c6b7f97791e031d9cc148236528996f6df5237f2fcdd949352ba3cd46a16f701ec8ebc760d6966577bb73e8e98ac9 + languageName: node + linkType: hard + +"@citation-js/date@npm:0.5.1, @citation-js/date@npm:^0.5.0": + version: 0.5.1 + resolution: "@citation-js/date@npm:0.5.1" + checksum: d3f71fd8cc933d7b51f3aec3a529729a13617680b310aba72c1adb3c0b9756c418219d30a85e9a495b1f8202fd6c751ade117b64e5a95ac95a3c94014448e56f + languageName: node + linkType: hard + +"@citation-js/name@npm:0.4.2, @citation-js/name@npm:^0.4.2": + version: 0.4.2 + resolution: "@citation-js/name@npm:0.4.2" + checksum: 35556499a6a8a77189ee29b2ec15ee06366d0d0d79b5a896dfb617b94c1f4cf8423a0db022c294ee144a5a0f382fec6cce7b8064b71aaf001574095064b1586b + languageName: node + linkType: hard + +"@citation-js/plugin-bibjson@npm:0.6.8, @citation-js/plugin-bibjson@npm:^0.6.8": + version: 0.6.8 + resolution: "@citation-js/plugin-bibjson@npm:0.6.8" + dependencies: + "@citation-js/date": ^0.5.0 + "@citation-js/name": ^0.4.2 + peerDependencies: + "@citation-js/core": ^0.6.0 + checksum: 193be691f1ca8b7dcc74738ffb32529983eb8d586d9319ca3ba8b2d7f2fd8be010d00c2123b03f3d1d5e3305a728223c5fae69e6862d4061f49d60a6aefb6a38 + languageName: node + linkType: hard + +"@citation-js/plugin-bibtex@npm:0.6.8, @citation-js/plugin-bibtex@npm:^0.6.8": + version: 0.6.8 + resolution: "@citation-js/plugin-bibtex@npm:0.6.8" + dependencies: + "@citation-js/date": ^0.5.0 + "@citation-js/name": ^0.4.2 + moo: ^0.5.1 + peerDependencies: + "@citation-js/core": ^0.6.0 + checksum: 1b81d97d12d638e7d86d738eeff56ed72cc51c28f536e83ee552616cfc4ab088017d09de7404d74d36e73ffeb1a12068f112ada830f6b0cd890d8841ae3e5512 + languageName: node + linkType: hard + +"@citation-js/plugin-csl@npm:0.6.8, @citation-js/plugin-csl@npm:^0.6.8": + version: 0.6.8 + resolution: "@citation-js/plugin-csl@npm:0.6.8" + dependencies: + "@citation-js/date": ^0.5.0 + citeproc: ^2.4.6 + peerDependencies: + "@citation-js/core": ^0.6.0 + checksum: 51af2b8d4dfc2fda81bf363062851de02d393db184dbf3368dbb7b14b27523eef643bccfc02857f592a696d0a29fff7c053ee4c7c413835141d1f9bc1ee645ea + languageName: node + linkType: hard + +"@citation-js/plugin-doi@npm:0.6.8, @citation-js/plugin-doi@npm:^0.6.8": + version: 0.6.8 + resolution: "@citation-js/plugin-doi@npm:0.6.8" + dependencies: + "@citation-js/date": ^0.5.0 + peerDependencies: + "@citation-js/core": ^0.6.0 + checksum: 0fac8eb94e80cfeb1275bd8164fce53a09affd2652cca03e9903ec0e8918b4f26907325e9531bc37b7b74bee1fab98f3361ac59f27426fcae7c9189fd18ec3f3 + languageName: node + linkType: hard + +"@citation-js/plugin-ris@npm:0.6.8, @citation-js/plugin-ris@npm:^0.6.8": + version: 0.6.8 + resolution: "@citation-js/plugin-ris@npm:0.6.8" + dependencies: + "@citation-js/date": ^0.5.0 + "@citation-js/name": ^0.4.2 + peerDependencies: + "@citation-js/core": ^0.6.0 + checksum: 16e25b39f8faba3239ee37c240ffa8c5d95cd1fae98dc5a79e416f51492f4e4543d4dc2222b642fde312ef26d0ea4bb7adb4361d8e8a241472ebef00d7f094e3 + languageName: node + linkType: hard + +"@citation-js/plugin-wikidata@npm:0.6.8, @citation-js/plugin-wikidata@npm:^0.6.8": + version: 0.6.8 + resolution: "@citation-js/plugin-wikidata@npm:0.6.8" + dependencies: + "@citation-js/date": ^0.5.0 + "@citation-js/name": ^0.4.2 + wikidata-sdk: ^8.0.0 + peerDependencies: + "@citation-js/core": ^0.6.0 + checksum: 6f05ccafb82c30a31d3ddc096a08f385a40b7fbe3e7a149d7df2c5eecb944dd2eecbf4ec5b472e3de9096750af924f0b730b5b4db2cccf81772ccbe0c6e370f1 + languageName: node + linkType: hard + "@codemirror/autocomplete@npm:^6.0.0, @codemirror/autocomplete@npm:^6.3.2, @codemirror/autocomplete@npm:^6.5.1": version: 6.7.1 resolution: "@codemirror/autocomplete@npm:6.7.1" @@ -4911,6 +5028,16 @@ __metadata: languageName: node linkType: hard +"buffer@npm:^5.7.1": + version: 5.7.1 + resolution: "buffer@npm:5.7.1" + dependencies: + base64-js: ^1.3.1 + ieee754: ^1.1.13 + checksum: e2cf8429e1c4c7b8cbd30834ac09bd61da46ce35f5c22a78e6c2f04497d6d25541b16881e30a019c6fd3154150650ccee27a308eff3e26229d788bbdeb08ab84 + languageName: node + linkType: hard + "buffer@npm:^6.0.3": version: 6.0.3 resolution: "buffer@npm:6.0.3" @@ -5106,6 +5233,44 @@ __metadata: languageName: node linkType: hard +"citation-js-utils@npm:^1.0.0": + version: 1.0.0 + resolution: "citation-js-utils@npm:1.0.0" + dependencies: + citation-js: ^0.6.3 + sanitize-html: ^2.7.0 + checksum: a39846e17a42ded7f22f3c97be06d3a115fdd70e6208e30a840f459a6569fbe383bc4742f2749349963b6df0c4716a8614f2ec699718891110bf0378067882b2 + languageName: node + linkType: hard + +"citation-js@npm:^0.6.3": + version: 0.6.8 + resolution: "citation-js@npm:0.6.8" + dependencies: + "@citation-js/cli": 0.6.8 + "@citation-js/core": 0.6.8 + "@citation-js/date": 0.5.1 + "@citation-js/name": 0.4.2 + "@citation-js/plugin-bibjson": 0.6.8 + "@citation-js/plugin-bibtex": 0.6.8 + "@citation-js/plugin-csl": 0.6.8 + "@citation-js/plugin-doi": 0.6.8 + "@citation-js/plugin-ris": 0.6.8 + "@citation-js/plugin-wikidata": 0.6.8 + citeproc: ^2.4.59 + bin: + citation-js: bin/cmd.js + checksum: 9a119fa3b5a059f91804e67a7a3b8fa57666ddf5584d132d27c4763a358cd4f588e94a2c37fbcb650b59bdda9665162c1539f95f7fd0373e8ecec4ec27454fa4 + languageName: node + linkType: hard + +"citeproc@npm:^2.4.59, citeproc@npm:^2.4.6": + version: 2.4.63 + resolution: "citeproc@npm:2.4.63" + checksum: 15a22d857cabca6e28b79d52cff094949031145b3ff223ec17cb1b7f1be68b9ad63e8fcaa8621685f10c3c09daf72be58f9e9d20ef322e70e2b60dfbade27dc7 + languageName: node + linkType: hard + "cjs-module-lexer@npm:^1.0.0": version: 1.2.2 resolution: "cjs-module-lexer@npm:1.2.2" @@ -6054,7 +6219,18 @@ __metadata: languageName: node linkType: hard -"domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0": +"dom-serializer@npm:^2.0.0": + version: 2.0.0 + resolution: "dom-serializer@npm:2.0.0" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.2 + entities: ^4.2.0 + checksum: cd1810544fd8cdfbd51fa2c0c1128ec3a13ba92f14e61b7650b5de421b88205fd2e3f0cc6ace82f13334114addb90ed1c2f23074a51770a8e9c1273acbc7f3e6 + languageName: node + linkType: hard + +"domelementtype@npm:^2.0.1, domelementtype@npm:^2.2.0, domelementtype@npm:^2.3.0": version: 2.3.0 resolution: "domelementtype@npm:2.3.0" checksum: ee837a318ff702622f383409d1f5b25dd1024b692ef64d3096ff702e26339f8e345820f29a68bcdcea8cfee3531776b3382651232fbeae95612d6f0a75efb4f6 @@ -6079,6 +6255,15 @@ __metadata: languageName: node linkType: hard +"domhandler@npm:^5.0.2, domhandler@npm:^5.0.3": + version: 5.0.3 + resolution: "domhandler@npm:5.0.3" + dependencies: + domelementtype: ^2.3.0 + checksum: 0f58f4a6af63e6f3a4320aa446d28b5790a009018707bce2859dcb1d21144c7876482b5188395a188dfa974238c019e0a1e610d2fc269a12b2c192ea2b0b131c + languageName: node + linkType: hard + "dompurify@npm:2.4.3": version: 2.4.3 resolution: "dompurify@npm:2.4.3" @@ -6097,6 +6282,17 @@ __metadata: languageName: node linkType: hard +"domutils@npm:^3.0.1": + version: 3.1.0 + resolution: "domutils@npm:3.1.0" + dependencies: + dom-serializer: ^2.0.0 + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + checksum: e5757456ddd173caa411cfc02c2bb64133c65546d2c4081381a3bafc8a57411a41eed70494551aa58030be9e58574fcc489828bebd673863d39924fb4878f416 + languageName: node + linkType: hard + "duplicate-package-checker-webpack-plugin@npm:^3.0.0": version: 3.0.0 resolution: "duplicate-package-checker-webpack-plugin@npm:3.0.0" @@ -6170,7 +6366,7 @@ __metadata: languageName: node linkType: hard -"entities@npm:^4.4.0": +"entities@npm:^4.2.0, entities@npm:^4.4.0": version: 4.5.0 resolution: "entities@npm:4.5.0" checksum: 853f8ebd5b425d350bffa97dd6958143179a5938352ccae092c62d1267c4e392a039be1bae7d51b6e4ffad25f51f9617531fedf5237f15df302ccfb452cbf2d7 @@ -6647,6 +6843,15 @@ __metadata: languageName: node linkType: hard +"fetch-ponyfill@npm:^7.1.0": + version: 7.1.0 + resolution: "fetch-ponyfill@npm:7.1.0" + dependencies: + node-fetch: ~2.6.1 + checksum: 7fd497dd5f7db890e80193de5bc1cd0115a62400272cd9a992849288e66886fcdb0724ea1ed161be7b8db2daeafda8c58d0259acdda42d6561155dbcdbb0720a + languageName: node + linkType: hard + "file-entry-cache@npm:^6.0.1": version: 6.0.1 resolution: "file-entry-cache@npm:6.0.1" @@ -7377,6 +7582,18 @@ __metadata: languageName: node linkType: hard +"htmlparser2@npm:^8.0.0": + version: 8.0.2 + resolution: "htmlparser2@npm:8.0.2" + dependencies: + domelementtype: ^2.3.0 + domhandler: ^5.0.3 + domutils: ^3.0.1 + entities: ^4.4.0 + checksum: 29167a0f9282f181da8a6d0311b76820c8a59bc9e3c87009e21968264c2987d2723d6fde5a964d4b7b6cba663fca96ffb373c06d8223a85f52a6089ced942700 + languageName: node + linkType: hard + "http-cache-semantics@npm:^4.1.0": version: 4.1.1 resolution: "http-cache-semantics@npm:4.1.1" @@ -7448,7 +7665,7 @@ __metadata: languageName: node linkType: hard -"ieee754@npm:^1.2.1": +"ieee754@npm:^1.1.13, ieee754@npm:^1.2.1": version: 1.2.1 resolution: "ieee754@npm:1.2.1" checksum: 5144c0c9815e54ada181d80a0b810221a253562422e7c6c3a60b1901154184f49326ec239d618c416c1c5945a2e197107aee8d986a3dd836b53dffefd99b5e7e @@ -8634,6 +8851,7 @@ __metadata: "@types/react-dom": ^18.0.9 "@typescript-eslint/eslint-plugin": ^5.55.0 "@typescript-eslint/parser": ^5.55.0 + citation-js-utils: ^1.0.0 css-loader: ^6.7.1 eslint: ^8.36.0 eslint-config-prettier: ^8.7.0 @@ -9465,6 +9683,13 @@ __metadata: languageName: node linkType: hard +"moo@npm:^0.5.1": + version: 0.5.2 + resolution: "moo@npm:0.5.2" + checksum: 5a41ddf1059fd0feb674d917c4774e41c877f1ca980253be4d3aae1a37f4bc513f88815041243f36f5cf67a62fb39324f3f997cf7fb17b6cb00767c165e7c499 + languageName: node + linkType: hard + "ms@npm:2.1.2": version: 2.1.2 resolution: "ms@npm:2.1.2" @@ -9772,7 +9997,7 @@ __metadata: languageName: node linkType: hard -"node-fetch@npm:^2.6.0": +"node-fetch@npm:^2.6.0, node-fetch@npm:^2.6.1, node-fetch@npm:~2.6.1": version: 2.6.11 resolution: "node-fetch@npm:2.6.11" dependencies: @@ -11018,6 +11243,20 @@ __metadata: languageName: node linkType: hard +"sanitize-html@npm:^2.7.0": + version: 2.11.0 + resolution: "sanitize-html@npm:2.11.0" + dependencies: + deepmerge: ^4.2.2 + escape-string-regexp: ^4.0.0 + htmlparser2: ^8.0.0 + is-plain-object: ^5.0.0 + parse-srcset: ^1.0.2 + postcss: ^8.3.11 + checksum: 44807f22b0feb5a6a883b4bc04bcd8690ec3bbd6dacb24d6e52226ffe0c0e4fad43d6a882ce60e3884a327fae2de01e67e566e3a211491add50ff0160be2e98a + languageName: node + linkType: hard + "sanitize-html@npm:~2.7.3": version: 2.7.3 resolution: "sanitize-html@npm:2.7.3" @@ -11735,6 +11974,16 @@ __metadata: languageName: node linkType: hard +"sync-fetch@npm:^0.4.1": + version: 0.4.5 + resolution: "sync-fetch@npm:0.4.5" + dependencies: + buffer: ^5.7.1 + node-fetch: ^2.6.1 + checksum: 84aa2bf85b1a6558b7c75716d7b7c3bd787f02602993a08bdfdd69384afa7d6dc54e94b006a6362277334edf92940e0f4de57801166c52854912443fbbe78e00 + languageName: node + linkType: hard + "table@npm:^6.8.1": version: 6.8.1 resolution: "table@npm:6.8.1" @@ -12811,6 +13060,22 @@ __metadata: languageName: node linkType: hard +"wikibase-sdk@npm:^8.1.1": + version: 8.1.1 + resolution: "wikibase-sdk@npm:8.1.1" + checksum: 860147cf9e19d9f331d5be473bed0011456c8163424d1485e67293b9d528b3bb924b262abacf869fc730c6477d6e5ca2648823bf28c3bffc67ae418fc871134c + languageName: node + linkType: hard + +"wikidata-sdk@npm:^8.0.0": + version: 8.1.1 + resolution: "wikidata-sdk@npm:8.1.1" + dependencies: + wikibase-sdk: ^8.1.1 + checksum: e52874f637cd6f15024422e9bd977ecd73e8c0f1f9953f50023c2a1dd823a3f0e7a3284ab96253706a0fa33850f84e5d880f4c7f66a0e87d8363ec3d6a681ce4 + languageName: node + linkType: hard + "wildcard@npm:^2.0.0": version: 2.0.1 resolution: "wildcard@npm:2.0.1"