@curvenote/renderers 0.8.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/articles.d.ts.map +1 -1
  2. package/dist/articles.js +2 -11
  3. package/dist/components/admonition.d.ts +18 -0
  4. package/dist/components/admonition.d.ts.map +1 -0
  5. package/dist/components/admonition.js +146 -0
  6. package/dist/components/cite-figurebar.d.ts +5 -0
  7. package/dist/components/cite-figurebar.d.ts.map +1 -0
  8. package/dist/components/cite-figurebar.js +73 -0
  9. package/dist/components/cite-youtube.d.ts +6 -0
  10. package/dist/components/cite-youtube.d.ts.map +1 -0
  11. package/dist/components/cite-youtube.js +45 -0
  12. package/dist/components/cite.d.ts +12 -0
  13. package/dist/components/cite.d.ts.map +1 -0
  14. package/dist/components/cite.js +76 -0
  15. package/dist/components/definition-list.d.ts +3 -0
  16. package/dist/components/definition-list.d.ts.map +1 -0
  17. package/dist/components/definition-list.js +20 -0
  18. package/dist/components/faq.d.ts +5 -0
  19. package/dist/components/faq.d.ts.map +1 -0
  20. package/dist/components/faq.js +34 -0
  21. package/dist/components/hero.css +6 -0
  22. package/dist/components/hero.d.ts +28 -0
  23. package/dist/components/hero.d.ts.map +1 -0
  24. package/dist/components/hero.example.d.ts +3 -0
  25. package/dist/components/hero.example.d.ts.map +1 -0
  26. package/dist/components/hero.example.js +30 -0
  27. package/dist/components/hero.js +89 -0
  28. package/dist/components/images.d.ts +5 -0
  29. package/dist/components/images.d.ts.map +1 -0
  30. package/dist/components/images.js +7 -0
  31. package/dist/components/index.d.ts +7 -0
  32. package/dist/components/index.d.ts.map +1 -0
  33. package/dist/components/index.js +6 -0
  34. package/dist/components/inlineError.d.ts +8 -0
  35. package/dist/components/inlineError.d.ts.map +1 -0
  36. package/dist/components/inlineError.js +6 -0
  37. package/dist/components/mermaid.d.ts +11 -0
  38. package/dist/components/mermaid.d.ts.map +1 -0
  39. package/dist/components/mermaid.js +59 -0
  40. package/dist/components/pdb.d.ts +5 -0
  41. package/dist/components/pdb.d.ts.map +1 -0
  42. package/dist/{pdbLink.js → components/pdb.js} +15 -5
  43. package/dist/hooks/useOpenAlex.d.ts +13 -0
  44. package/dist/hooks/useOpenAlex.d.ts.map +1 -0
  45. package/dist/hooks/useOpenAlex.js +33 -0
  46. package/dist/index.css +1 -0
  47. package/dist/index.d.ts +7 -2
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +29 -18
  50. package/dist/transforms/articles.d.ts +4 -1
  51. package/dist/transforms/articles.d.ts.map +1 -1
  52. package/dist/transforms/articles.js +37 -51
  53. package/dist/transforms/index.d.ts +4 -6
  54. package/dist/transforms/index.d.ts.map +1 -1
  55. package/dist/transforms/index.js +11 -24
  56. package/dist/transforms/{outputs.d.ts → notebooks.d.ts} +1 -1
  57. package/dist/transforms/notebooks.d.ts.map +1 -0
  58. package/dist/transforms/{outputs.js → notebooks.js} +3 -4
  59. package/dist/utils/abstract.d.ts +40 -0
  60. package/dist/utils/abstract.d.ts.map +1 -0
  61. package/dist/utils/abstract.js +76 -0
  62. package/package.json +40 -33
  63. package/README.md +0 -6
  64. package/dist/any/index.d.ts +0 -5
  65. package/dist/any/index.d.ts.map +0 -1
  66. package/dist/any/index.js +0 -8
  67. package/dist/any/models.d.ts +0 -18
  68. package/dist/any/models.d.ts.map +0 -1
  69. package/dist/any/models.js +0 -49
  70. package/dist/any/renderers.d.ts +0 -5
  71. package/dist/any/renderers.d.ts.map +0 -1
  72. package/dist/any/renderers.js +0 -113
  73. package/dist/any/types.d.ts +0 -22
  74. package/dist/any/types.d.ts.map +0 -1
  75. package/dist/any/types.js +0 -1
  76. package/dist/cards.d.ts +0 -8
  77. package/dist/cards.d.ts.map +0 -1
  78. package/dist/cards.js +0 -15
  79. package/dist/cite.d.ts +0 -17
  80. package/dist/cite.d.ts.map +0 -1
  81. package/dist/cite.js +0 -94
  82. package/dist/collections.d.ts +0 -6
  83. package/dist/collections.d.ts.map +0 -1
  84. package/dist/collections.js +0 -12
  85. package/dist/pdbLink.d.ts +0 -6
  86. package/dist/pdbLink.d.ts.map +0 -1
  87. package/dist/transforms/cards.d.ts +0 -52
  88. package/dist/transforms/cards.d.ts.map +0 -1
  89. package/dist/transforms/cards.js +0 -68
  90. package/dist/transforms/collections.d.ts +0 -15
  91. package/dist/transforms/collections.d.ts.map +0 -1
  92. package/dist/transforms/collections.js +0 -44
  93. package/dist/transforms/outputs.d.ts.map +0 -1
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Utility functions for working with OpenAlex abstract data
3
+ */
4
+ export interface OpenAlexAbstractInvertedIndex {
5
+ [word: string]: number[];
6
+ }
7
+ export interface OpenAlexWork {
8
+ id: string;
9
+ doi: string;
10
+ title: string;
11
+ display_name: string;
12
+ publication_year: number;
13
+ publication_date: string;
14
+ abstract_inverted_index?: OpenAlexAbstractInvertedIndex;
15
+ authorships?: Array<{
16
+ author: {
17
+ display_name: string;
18
+ };
19
+ author_position: string;
20
+ }>;
21
+ primary_location?: {
22
+ source: {
23
+ display_name: string;
24
+ };
25
+ };
26
+ }
27
+ /**
28
+ * Reverses an inverted abstract index from OpenAlex API into a readable abstract
29
+ * @param invertedIndex - The inverted index object from OpenAlex API
30
+ * @returns The reconstructed abstract as a string
31
+ */
32
+ export declare function reverseInvertedAbstract(invertedIndex: OpenAlexAbstractInvertedIndex): string;
33
+ /**
34
+ * Formats authors list from OpenAlex authorships data
35
+ * @param authorships - Array of authorship objects from OpenAlex
36
+ * @param maxAuthors - Maximum number of authors to show before truncating
37
+ * @returns Formatted author string
38
+ */
39
+ export declare function formatAuthors(authorships?: OpenAlexWork['authorships'], maxAuthors?: number): string;
40
+ //# sourceMappingURL=abstract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract.d.ts","sourceRoot":"","sources":["../../src/utils/abstract.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,6BAA6B;IAC5C,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,CAAC,EAAE,6BAA6B,CAAC;IACxD,WAAW,CAAC,EAAE,KAAK,CAAC;QAClB,MAAM,EAAE;YACN,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;QACF,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC,CAAC;IACH,gBAAgB,CAAC,EAAE;QACjB,MAAM,EAAE;YACN,YAAY,EAAE,MAAM,CAAC;SACtB,CAAC;KACH,CAAC;CACH;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,aAAa,EAAE,6BAA6B,GAAG,MAAM,CAwD5F;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,WAAW,CAAC,EAAE,YAAY,CAAC,aAAa,CAAC,EACzC,UAAU,GAAE,MAAU,GACrB,MAAM,CAeR"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Utility functions for working with OpenAlex abstract data
3
+ */
4
+ /**
5
+ * Reverses an inverted abstract index from OpenAlex API into a readable abstract
6
+ * @param invertedIndex - The inverted index object from OpenAlex API
7
+ * @returns The reconstructed abstract as a string
8
+ */
9
+ export function reverseInvertedAbstract(invertedIndex) {
10
+ if (!invertedIndex || typeof invertedIndex !== 'object') {
11
+ return '';
12
+ }
13
+ // Create an array to hold words at their correct positions
14
+ const words = [];
15
+ // Find the maximum position to determine array length
16
+ let maxPosition = -1;
17
+ for (const positions of Object.values(invertedIndex)) {
18
+ for (const position of positions) {
19
+ maxPosition = Math.max(maxPosition, position);
20
+ }
21
+ }
22
+ // Initialize array with empty strings
23
+ for (let i = 0; i <= maxPosition; i++) {
24
+ words[i] = '';
25
+ }
26
+ // Place each word at its correct position(s)
27
+ for (const [word, positions] of Object.entries(invertedIndex)) {
28
+ for (const position of positions) {
29
+ if (position >= 0 && position <= maxPosition) {
30
+ words[position] = word;
31
+ }
32
+ }
33
+ }
34
+ // Join words with spaces, filtering out any empty slots
35
+ return (words
36
+ .filter((word) => word !== '')
37
+ .join(' ')
38
+ .replace(/^Abstract:? /i, '')
39
+ .replace(/ ([.,;:!?]) /g, '$1 ')
40
+ // Remove spaces around brackets
41
+ .replace(/([[({]) /g, '$1')
42
+ .replace(/ ([\])}])/g, '$1')
43
+ .replace(/\\n/g, ' ')
44
+ // Replace common HTML-encoded characters
45
+ .replace(/&amp;/g, '&')
46
+ .replace(/&gt;/g, '>')
47
+ .replace(/&lt;/g, '<')
48
+ .replace(/&quot;/g, '"')
49
+ .replace(/&apos;/g, "'")
50
+ .replace(/&#39;/g, "'")
51
+ .replace(/&nbsp;/g, ' ')
52
+ .replace(/&mdash;/g, '—')
53
+ .replace(/&ndash;/g, '–')
54
+ .replace(/&hellip;/g, '…')
55
+ .replace(/&deg;/g, '°')
56
+ .replace(/&plusmn;/g, '±')
57
+ .trim());
58
+ }
59
+ /**
60
+ * Formats authors list from OpenAlex authorships data
61
+ * @param authorships - Array of authorship objects from OpenAlex
62
+ * @param maxAuthors - Maximum number of authors to show before truncating
63
+ * @returns Formatted author string
64
+ */
65
+ export function formatAuthors(authorships, maxAuthors = 3) {
66
+ if (!authorships || authorships.length === 0) {
67
+ return '';
68
+ }
69
+ const authors = authorships.map((authorship) => authorship.author.display_name);
70
+ if (authors.length <= maxAuthors) {
71
+ return authors.join(', ');
72
+ }
73
+ const firstAuthors = authors.slice(0, maxAuthors - 1);
74
+ const remainingCount = authors.length - maxAuthors + 1;
75
+ return `${firstAuthors.join(', ')}, et al. (${remainingCount} more)`;
76
+ }
package/package.json CHANGED
@@ -1,52 +1,59 @@
1
1
  {
2
2
  "name": "@curvenote/renderers",
3
- "version": "0.8.0",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "sideEffects": false,
4
6
  "type": "module",
5
- "exports": "./dist/index.js",
7
+ "module": "./dist/index.js",
6
8
  "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
7
15
  "files": [
8
16
  "dist"
9
17
  ],
10
- "engines": {
11
- "node": ">=16"
12
- },
13
- "license": "MIT",
14
- "repository": {
15
- "type": "git",
16
- "url": "https://github.com/curvenote/journal-theme.git",
17
- "directory": "packages/renderers"
18
- },
19
- "sideEffects": false,
20
18
  "scripts": {
21
- "clean": "rimraf dist",
22
- "lint": "eslint \"src/**/*.ts*\" \"src/**/*.tsx\" -c ./.eslintrc.cjs",
19
+ "build": "tsc && npm run copy-css",
20
+ "copy-css": "mkdir -p dist/components && cp src/components/*.css dist/components/ 2>/dev/null || true && cp src/*.css dist/ 2>/dev/null || true",
21
+ "dev": "tsc --watch",
22
+ "typecheck": "tsc --noEmit",
23
+ "compile": "npm run typecheck",
24
+ "lint": "eslint \"src/**/*.ts*\" -c ./.eslintrc.cjs",
23
25
  "lint:format": "prettier --check \"src/**/*.{ts,tsx,md}\"",
24
- "dev": "npm-run-all --parallel \"build:* -- --watch\"",
25
- "build:esm": "tsc",
26
- "build": "npm-run-all -l clean -p build:esm"
26
+ "test": "vitest run",
27
+ "clean": "rm -rf dist",
28
+ "prepublishOnly": "npm run build"
27
29
  },
28
30
  "dependencies": {
29
- "@curvenote/ext-blog": "^0.8.0",
30
- "@curvenote/ext-footer": "^0.8.0",
31
- "@curvenote/ext-landing": "^0.8.0",
32
- "@curvenote/ext-person": "^0.8.0",
33
- "@curvenote/theme": "^0.8.0",
34
- "@heroicons/react": "^2.1.5",
35
- "@myst-theme/providers": "^1.0.1",
36
- "@scienceicons/myst": "^1.0.4",
37
- "classnames": "^2.5.1",
38
- "lucide-react": "^0.456.0",
39
- "myst-to-react": "^1.0.1",
31
+ "@curvenote-theme/ui": "^1.0.0",
32
+ "@curvenote/any-widget": "^0.2.1",
33
+ "@curvenote/common": "^0.3.4",
34
+ "@curvenote/ext-blog": "^1.0.0",
35
+ "@curvenote/ext-person": "^1.0.0",
36
+ "@curvenote/react-utils": "^1.0.0",
37
+ "@scienceicons/react": "^0.0.13",
38
+ "class-variance-authority": "^0.7.1",
39
+ "hast-util-from-html": "^2.0.3",
40
+ "hast-util-to-mdast": "^10.1.2",
41
+ "lucide-react": "^0.525.0",
42
+ "mermaid": "^11.12.1",
43
+ "myst-common": "^1.9.3",
40
44
  "p-limit": "^3.1.0",
41
- "swr": "^2.1.5",
42
- "unist-util-select": "^4.0.3"
45
+ "react-router": "^7.1.1",
46
+ "sonner": "^2.0.6",
47
+ "swr": "^2.3.6",
48
+ "unist-util-select": "^5.1.0",
49
+ "unist-util-visit": "^5.0.0"
43
50
  },
44
51
  "peerDependencies": {
45
- "react": "^16.8 || ^17.0 || ^18.0",
46
- "react-dom": "^16.8 || ^17.0 || ^18.0"
52
+ "react": "^16.8 || ^17.0 || ^18.0 || ^19.0",
53
+ "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0"
47
54
  },
48
55
  "devDependencies": {
49
- "typescript": "latest"
56
+ "vitest": "^4.0.16"
50
57
  },
51
58
  "publishConfig": {
52
59
  "access": "public"
package/README.md DELETED
@@ -1,6 +0,0 @@
1
- # @curvenote/renderers
2
-
3
- [![@curvenote/renderers on npm](https://img.shields.io/npm/v/@curvenote/renderers.svg)](https://www.npmjs.com/package/@curvenote/renderers)
4
- [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/curvenote/curvenote/blob/main/LICENSE)
5
-
6
- Add Curvenote renderers to a site.
@@ -1,5 +0,0 @@
1
- import type { NodeRenderers } from '@myst-theme/providers';
2
- export * from './models.js';
3
- export * from './types.js';
4
- export declare const ANY_RENDERERS: NodeRenderers;
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/any/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAG3D,cAAc,aAAa,CAAC;AAC5B,cAAc,YAAY,CAAC;AAE3B,eAAO,MAAM,aAAa,EAAE,aAI3B,CAAC"}
package/dist/any/index.js DELETED
@@ -1,8 +0,0 @@
1
- import { AnyRenderer } from './renderers.js';
2
- export * from './models.js';
3
- export * from './types.js';
4
- export const ANY_RENDERERS = {
5
- block: {
6
- 'block[kind=any:bundle]': AnyRenderer,
7
- },
8
- };
@@ -1,18 +0,0 @@
1
- /**
2
- * Forked from https://github.com/manzt/anymyst/commit/d0b2c105397f5b1a0344b4b467c3790c498a84c6
3
- *
4
- * A shim for the anywidget model interface
5
- * @see {@link https://github.com/manzt/anywidget/tree/main/packages/types}
6
- */
7
- export declare class MystAnyModel {
8
- #private;
9
- constructor(state: Record<string, unknown>);
10
- get(name: string): unknown;
11
- set(key: string, value: unknown): void;
12
- on(name: string, cb: () => void | Promise<void>): void;
13
- off(_name: string, _cb: () => void | Promise<void>): void;
14
- save_changes(): void;
15
- send(_msg: unknown, _callbacks?: unknown, _buffers?: ArrayBuffer[]): void;
16
- get widget_manager(): void;
17
- }
18
- //# sourceMappingURL=models.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/any/models.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,YAAY;;gBAGX,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAG1C,GAAG,CAAC,IAAI,EAAE,MAAM;IAGhB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO;IAK/B,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAG/C,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAGlD,YAAY;IAGZ,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,WAAW,EAAE;IAGlE,IAAI,cAAc,SAEjB;CACF"}
@@ -1,49 +0,0 @@
1
- var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
2
- if (kind === "m") throw new TypeError("Private method is not writable");
3
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
4
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
5
- return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
6
- };
7
- var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
8
- if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
9
- if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
10
- return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
11
- };
12
- var _MystAnyModel_state, _MystAnyModel_target;
13
- /**
14
- * Forked from https://github.com/manzt/anymyst/commit/d0b2c105397f5b1a0344b4b467c3790c498a84c6
15
- *
16
- * A shim for the anywidget model interface
17
- * @see {@link https://github.com/manzt/anywidget/tree/main/packages/types}
18
- */
19
- export class MystAnyModel {
20
- constructor(state) {
21
- _MystAnyModel_state.set(this, void 0);
22
- _MystAnyModel_target.set(this, new EventTarget());
23
- __classPrivateFieldSet(this, _MystAnyModel_state, state, "f");
24
- }
25
- get(name) {
26
- return __classPrivateFieldGet(this, _MystAnyModel_state, "f")[name];
27
- }
28
- set(key, value) {
29
- __classPrivateFieldGet(this, _MystAnyModel_state, "f")[key] = value;
30
- __classPrivateFieldGet(this, _MystAnyModel_target, "f").dispatchEvent(new CustomEvent(`change:${key}`, { detail: value }));
31
- __classPrivateFieldGet(this, _MystAnyModel_target, "f").dispatchEvent(new CustomEvent('change', { detail: value }));
32
- }
33
- on(name, cb) {
34
- __classPrivateFieldGet(this, _MystAnyModel_target, "f").addEventListener(name, cb);
35
- }
36
- off(_name, _cb) {
37
- // TODO: should keep ref to listeners and then remove here
38
- }
39
- save_changes() {
40
- // nothing to sync but necessary
41
- }
42
- send(_msg, _callbacks, _buffers) {
43
- throw new Error('MystAnyModel.send not implemented yet.');
44
- }
45
- get widget_manager() {
46
- throw new Error('MystAnyModel.widget_manager does not exist.');
47
- }
48
- }
49
- _MystAnyModel_state = new WeakMap(), _MystAnyModel_target = new WeakMap();
@@ -1,5 +0,0 @@
1
- import type { AnyBundleDirective } from './types.js';
2
- export declare function AnyRenderer({ node }: {
3
- node: AnyBundleDirective;
4
- }): import("react/jsx-runtime").JSX.Element;
5
- //# sourceMappingURL=renderers.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"renderers.d.ts","sourceRoot":"","sources":["../../src/any/renderers.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAGrD,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,kBAAkB,CAAA;CAAE,2CAyIjE"}
@@ -1,113 +0,0 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
- /**
12
- * Forked from https://github.com/manzt/anymyst/commit/d0b2c105397f5b1a0344b4b467c3790c498a84c6
13
- *
14
- * A custom renderer for Myst to support anywidget front-end modules
15
- * @module
16
- *
17
- * @example
18
- * ```
19
- * <Document renderers={{ ...renderers, any: AnyMystRenderer }}></Document>
20
- * ```
21
- */
22
- import * as React from 'react';
23
- import { MystAnyModel } from './models.js';
24
- export function AnyRenderer({ node }) {
25
- var _a, _b;
26
- // basic validation
27
- const esmModuleUrl = (_a = node.data.esm) !== null && _a !== void 0 ? _a : node.data.import; // supports legacy import URL
28
- const isESMModuleUrlValid = esmModuleUrl &&
29
- typeof esmModuleUrl === 'string' &&
30
- (esmModuleUrl.startsWith('https://') || esmModuleUrl.startsWith('http://'));
31
- const validJson = node.data.json && typeof node.data.json === 'object';
32
- const ref = React.useRef(null);
33
- const [error, setError] = React.useState(null);
34
- React.useEffect(() => {
35
- // Reset error state on node change
36
- setError(null);
37
- // @see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal#implementing_an_abortable_api
38
- const controller = new AbortController();
39
- // if already aborted just ignore
40
- if (controller.signal.aborted) {
41
- return;
42
- }
43
- let maybeCleanupInitialize = undefined;
44
- let maybeCleanupRender = undefined;
45
- controller.signal.addEventListener('abort', () => __awaiter(this, void 0, void 0, function* () {
46
- yield (maybeCleanupRender === null || maybeCleanupRender === void 0 ? void 0 : maybeCleanupRender());
47
- yield (maybeCleanupInitialize === null || maybeCleanupInitialize === void 0 ? void 0 : maybeCleanupInitialize());
48
- }));
49
- // TODO: validation for import & styles URLs
50
- console.debug('AnyRenderer importing:', esmModuleUrl);
51
- import(esmModuleUrl)
52
- .then((mod) => __awaiter(this, void 0, void 0, function* () {
53
- var _a, _b, _c, _d, _e, _f, _g;
54
- if (!ref.current)
55
- return;
56
- console.debug('AnyRenderer imported', mod);
57
- const widget = mod.default;
58
- // TODO: validate the widget
59
- const model = new MystAnyModel(node.data.json);
60
- maybeCleanupInitialize = yield ((_a = widget.initialize) === null || _a === void 0 ? void 0 : _a.call(widget, { model }));
61
- // clear current contents
62
- (_b = ref.current) === null || _b === void 0 ? void 0 : _b.replaceChildren();
63
- // apply container classes
64
- if (node.data.class && ((_c = node.data.class) === null || _c === void 0 ? void 0 : _c.trim().length) > 0) {
65
- (_d = node.data.class) === null || _d === void 0 ? void 0 : _d.trim().split(' ').forEach((c) => {
66
- var _a;
67
- (_a = ref.current) === null || _a === void 0 ? void 0 : _a.classList.add(c);
68
- });
69
- }
70
- // apply styles
71
- let rootEl = ref.current;
72
- const shadow = true;
73
- const css = (_e = node.data.css) !== null && _e !== void 0 ? _e : node.data.styles; // supports legacy styles
74
- if (css) {
75
- if (shadow) {
76
- const shadowRoot = (_f = rootEl.shadowRoot) !== null && _f !== void 0 ? _f : rootEl.attachShadow({ mode: 'open' });
77
- shadowRoot.replaceChildren();
78
- const shadowEl = document.createElement('div');
79
- shadowRoot.appendChild(shadowEl);
80
- const link = document.createElement('link');
81
- link.rel = 'stylesheet';
82
- link.href = css;
83
- shadowRoot.appendChild(link);
84
- rootEl = shadowEl;
85
- }
86
- else {
87
- const link = document.createElement('link');
88
- link.rel = 'stylesheet';
89
- link.href = css;
90
- rootEl.appendChild(link);
91
- }
92
- }
93
- maybeCleanupRender = yield ((_g = widget.render) === null || _g === void 0 ? void 0 : _g.call(widget, {
94
- model,
95
- el: rootEl,
96
- }));
97
- }))
98
- .catch((err) => {
99
- console.error('AnyRenderer failed to import module:', err);
100
- setError(err instanceof Error ? err : new Error(String(err)));
101
- });
102
- return () => {
103
- controller === null || controller === void 0 ? void 0 : controller.abort();
104
- };
105
- }, [node]);
106
- if (error) {
107
- return (_jsxs("details", { className: "p-3 bg-gray-100 rounded border border-gray-300 cursor-pointer", children: [_jsxs("summary", { className: "text-sm text-gray-600 select-none", children: ["Failed to load ", _jsx("code", { className: "text-xs", children: "any:bundle" }), " module."] }), _jsxs("div", { className: "pt-2 mt-2 space-y-1 text-xs border-t border-gray-200", children: [_jsxs("div", { className: "text-gray-500", children: [_jsx("span", { className: "font-medium", children: "Bundle URL:" }), " ", esmModuleUrl] }), _jsxs("div", { className: "text-gray-700", children: [_jsx("span", { className: "font-medium", children: "Error:" }), " ", error.message] })] })] }));
108
- }
109
- if (!isESMModuleUrlValid || !validJson) {
110
- return (_jsxs("div", { className: "p-3 space-y-2 rounded-md border border-red-500", children: [_jsxs("div", { children: ["Invalid ", _jsx("code", { children: "any:bundle" }), " directive."] }), !isESMModuleUrlValid && (_jsxs("div", { className: "px-1", children: [_jsx("div", { children: "Invalid import URL" }), _jsx("div", { className: "text-sm text-gray-500", children: node.data.import })] })), !validJson && (_jsxs("div", { className: "px-1", children: [_jsx("div", { children: "Invalid JSON data" }), _jsx("div", { className: "text-sm text-gray-500", children: (_b = node.data.json) === null || _b === void 0 ? void 0 : _b.toString() })] }))] }));
111
- }
112
- return _jsx("div", { className: "relative w-full", ref: ref });
113
- }
@@ -1,22 +0,0 @@
1
- export type AnyBundleDirective = {
2
- /** The type of the directive */
3
- type: 'block';
4
- /** The kind of the directive */
5
- kind: 'any:bundle';
6
- /** The data to pass to the model */
7
- data: {
8
- /** The ES module to import */
9
- esm: string;
10
- import: string;
11
- /** The JSON data to initialize the widget */
12
- json: Record<string, unknown>;
13
- /** URL to a css stylesheet to load for the widget */
14
- css?: string;
15
- styles?: string;
16
- /** Tailwind classes to apply to the container element */
17
- class?: string;
18
- /** A static file path, folder path or glob pattern to static files to make available to the module */
19
- static?: string;
20
- };
21
- };
22
- //# sourceMappingURL=types.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/any/types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,gCAAgC;IAChC,IAAI,EAAE,YAAY,CAAC;IACnB,oCAAoC;IACpC,IAAI,EAAE;QACJ,8BAA8B;QAC9B,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,6CAA6C;QAC7C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,qDAAqD;QACrD,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,yDAAyD;QACzD,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,sGAAsG;QACtG,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH,CAAC"}
package/dist/any/types.js DELETED
@@ -1 +0,0 @@
1
- export {};
package/dist/cards.d.ts DELETED
@@ -1,8 +0,0 @@
1
- import type { NodeRenderer } from '@myst-theme/providers';
2
- export declare const CARD_RENDERERS: {
3
- card: {
4
- "card[kind=curvenoteArticleListItem]": NodeRenderer;
5
- "card[kind=curvenoteExternalListItem]": NodeRenderer;
6
- };
7
- };
8
- //# sourceMappingURL=cards.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cards.d.ts","sourceRoot":"","sources":["../src/cards.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAqD1D,eAAO,MAAM,cAAc;;;;;CAK1B,CAAC"}
package/dist/cards.js DELETED
@@ -1,15 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { ArticleListItemV2 } from '@curvenote/theme';
3
- import { MyST } from 'myst-to-react';
4
- import { CardKindArticleListItem, CardKindExternalListItem } from './transforms/index.js';
5
- const CustomCardsRenderer = ({ node }) => {
6
- const { title, url, thumbnail, authors, date, kind, collection, description, doi } = node.data.json;
7
- const { parsed } = node.data;
8
- return (_jsx("div", { className: "py-3", children: _jsx(ArticleListItemV2, { title: (parsed === null || parsed === void 0 ? void 0 : parsed.title) ? _jsx(MyST, { ast: parsed.title }) : (title !== null && title !== void 0 ? title : 'Untitled'), authors: authors !== null && authors !== void 0 ? authors : [], url: url, thumbnail: thumbnail, kind: kind, collection: collection, date: date, description: description, doi: doi, showThumbnail: node.data.showThumbnail }) }));
9
- };
10
- export const CARD_RENDERERS = {
11
- card: {
12
- [`card[kind=${CardKindArticleListItem}]`]: CustomCardsRenderer,
13
- [`card[kind=${CardKindExternalListItem}]`]: CustomCardsRenderer,
14
- },
15
- };
package/dist/cite.d.ts DELETED
@@ -1,17 +0,0 @@
1
- import type { NodeRenderer } from '@myst-theme/providers';
2
- import type { GenericParent } from 'myst-common';
3
- interface Props {
4
- value: string;
5
- message?: string;
6
- }
7
- export declare function InlineError({ value, message }: Props): import("react/jsx-runtime").JSX.Element;
8
- export declare const CiteGroup: NodeRenderer<GenericParent>;
9
- export declare const Cite: ({ label, error, children, }: {
10
- label?: string;
11
- error?: boolean;
12
- children: React.ReactNode;
13
- }) => import("react/jsx-runtime").JSX.Element;
14
- export declare const CiteRenderer: NodeRenderer;
15
- declare const CITE_RENDERERS: Record<string, NodeRenderer>;
16
- export default CITE_RENDERERS;
17
- //# sourceMappingURL=cite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cite.d.ts","sourceRoot":"","sources":["../src/cite.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAI1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGjD,UAAU,KAAK;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,KAAK,2CAOpD;AAgCD,eAAO,MAAM,SAAS,EAAE,YAAY,CAAC,aAAa,CAkDjD,CAAC;AAEF,eAAO,MAAM,IAAI,gCAId;IACD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,4CAsBA,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,YAO1B,CAAC;AAEF,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAGhD,CAAC;AAEF,eAAe,cAAc,CAAC"}
package/dist/cite.js DELETED
@@ -1,94 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- // This code was forked from `myst-to-react`.
3
- // https://github.com/jupyter-book/myst-theme/commit/61e24acebfb79dbe532088ce4f654ae8deb4de8b
4
- /**
5
- * @license
6
- * Copyright (c) 2024 Project Jupyter - Distributed under the terms of the MIT License
7
- */
8
- import classNames from 'classnames';
9
- import { useReferences, useSiteManifest } from '@myst-theme/providers';
10
- import { doi } from 'doi-utils';
11
- import { ExclamationCircleIcon } from '@heroicons/react/24/outline';
12
- import { HoverPopover, MyST } from 'myst-to-react';
13
- import { Fragment } from 'react/jsx-runtime';
14
- export function InlineError({ value, message }) {
15
- return (_jsxs("span", { className: "text-yellow-600", title: message || value, children: [_jsx(ExclamationCircleIcon, { width: "1rem", height: "1rem", className: "inline mr-1" }), value] }));
16
- }
17
- function useNumberedReferences() {
18
- var _a;
19
- const config = useSiteManifest();
20
- const numbered_references = !!((_a = config === null || config === void 0 ? void 0 : config.options) === null || _a === void 0 ? void 0 : _a.numbered_references);
21
- return numbered_references;
22
- }
23
- function CiteChild({ html }) {
24
- return (_jsx("div", { className: "hover-document article w-[500px] sm:max-w-[500px] p-3", dangerouslySetInnerHTML: { __html: html || '' } }));
25
- }
26
- // function CiteChildren({ citations }: { citations?: { enumerator: string; html: string }[] }) {
27
- // return (
28
- // <div className="hover-document article w-[500px] max-h-[500px] overflow-auto sm:max-w-[500px] p-3">
29
- // {citations?.map((c) => (
30
- // <div className="grid grid-cols-[35px_1fr] gap-2 my-1" key={c.enumerator}>
31
- // <div className="text-right select-none text-stone-500 dark:text-stone-300">
32
- // {c.enumerator}.
33
- // </div>
34
- // <div dangerouslySetInnerHTML={{ __html: c.html || '' }} />
35
- // </div>
36
- // ))}
37
- // </div>
38
- // );
39
- // }
40
- export const CiteGroup = ({ node }) => {
41
- var _a, _b;
42
- const numbered = useNumberedReferences();
43
- // const references = useReferences();
44
- const allCite = (_b = (_a = node.children) === null || _a === void 0 ? void 0 : _a.every((child) => child.type === 'cite')) !== null && _b !== void 0 ? _b : false;
45
- if (numbered && allCite && node.kind === 'parenthetical') {
46
- // const citations =
47
- // node.children?.map((child) => {
48
- // const label = child.label;
49
- // const {
50
- // html,
51
- // enumerator,
52
- // doi: doiString,
53
- // url: refUrl,
54
- // } = references?.cite?.data[label ?? ''] ?? {};
55
- // return { label, html, enumerator, doi: doiString, url: refUrl };
56
- // }) ?? [];
57
- // return (
58
- // <HoverPopover openDelay={300} card={<CiteChildren citations={citations as any} />}>
59
- // <sup className="cite-group hover-link">
60
- // <cite>{citations.map((c) => c.enumerator).join(', ')}</cite>
61
- // </sup>
62
- // </HoverPopover>
63
- // );
64
- return (_jsx("sup", { className: "cite-group", children: _jsx("cite", { children: node.children.map((c, i) => (_jsxs(Fragment, { children: [_jsx(MyST, { ast: c }), i < node.children.length - 1 ? ', ' : null] }, c.key + 'wrap'))) }) }));
65
- }
66
- return (_jsx("span", { className: classNames({
67
- 'cite-group': allCite,
68
- 'xref-group': !allCite,
69
- narrative: node.kind === 'narrative',
70
- parenthetical: node.kind === 'parenthetical',
71
- }), children: _jsx(MyST, { ast: node.children }) }));
72
- };
73
- export const Cite = ({ label, error, children, }) => {
74
- var _a, _b;
75
- const references = useReferences();
76
- if (!label) {
77
- return _jsx(InlineError, { value: "cite (no label)", message: 'Citation Has No Label' });
78
- }
79
- const { html, doi: doiString, url: refUrl } = (_b = (_a = references === null || references === void 0 ? void 0 : references.cite) === null || _a === void 0 ? void 0 : _a.data[label]) !== null && _b !== void 0 ? _b : {};
80
- if (error) {
81
- return _jsx(InlineError, { value: label, message: 'Citation Not Found' });
82
- }
83
- const url = doiString ? doi.buildUrl(doiString) : refUrl;
84
- return (_jsx(HoverPopover, { openDelay: 300, card: _jsx(CiteChild, { html: html }), children: _jsxs("cite", { children: [url && (_jsx("a", { href: url, target: "_blank", rel: "noreferrer", className: "hover-link", children: children })), !url && _jsx("span", { className: "hover-link", children: children })] }) }));
85
- };
86
- export const CiteRenderer = ({ node }) => {
87
- const numbered = useNumberedReferences();
88
- return (_jsx(Cite, { label: node.label, error: node.error, children: numbered && node.kind === 'parenthetical' ? node.enumerator : _jsx(MyST, { ast: node.children }) }));
89
- };
90
- const CITE_RENDERERS = {
91
- citeGroup: CiteGroup,
92
- cite: CiteRenderer,
93
- };
94
- export default CITE_RENDERERS;
@@ -1,6 +0,0 @@
1
- import { type NodeRenderer } from '@myst-theme/providers';
2
- export declare const CollectionsRenderer: NodeRenderer;
3
- export declare const COLLECTIONS_RENDERERS: {
4
- curvenoteCollections: NodeRenderer;
5
- };
6
- //# sourceMappingURL=collections.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"collections.d.ts","sourceRoot":"","sources":["../src/collections.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAgB3E,eAAO,MAAM,mBAAmB,EAAE,YA0CjC,CAAC;AAEF,eAAO,MAAM,qBAAqB;;CAAgD,CAAC"}