From 5f4f74cc38ed9c7e71e2aaf8826546f3d260e309 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 18:34:13 +0000 Subject: [PATCH 1/3] Initial plan From d86ce4d51e5e2f23f963d315a502909042a2a330 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 16 Mar 2026 18:37:38 +0000 Subject: [PATCH 2/3] Remove API.md and jsdom/dompurify/marked packages Co-authored-by: thehabes <3287006+thehabes@users.noreply.github.com> --- API.md | 485 ------------------------------- __tests__/mount.test.js | 7 +- index.js | 50 ---- package-lock.json | 612 ---------------------------------------- package.json | 3 - 5 files changed, 1 insertion(+), 1156 deletions(-) delete mode 100644 API.md diff --git a/API.md b/API.md deleted file mode 100644 index 50de059f..00000000 --- a/API.md +++ /dev/null @@ -1,485 +0,0 @@ -# TPEN Services API Documentation - -This document provides an overview of the available routes in the TPEN Services API. These routes allow interaction with the application for various functionalities. - -## Base URL - -- **Production**: [https://api.t-pen.org](https://api.t-pen.org) -- **Development**: [https://dev.api.t-pen.org](https://dev.api.t-pen.org) - -## Endpoints - -### 1. **Authentication** - -Endpoints marked with a 🔐 requiring authentication expect a valid JWT token in the `Authorization` header. Use the [public TPEN3 login](https://three.t-pen.org/login/) to get one of these JWT tokens. - ---- - -### 2. **Project** - -#### `POST /project/create` 🔐 - -- **Description**: Create a new project. This is a high-skill maneuver requiring a complete project object. -- **Request Body**: - - ```json - { - "label": "string", - "metadata": [ { Metadata } ], - "layers": [ { Layer } ], - "manifests": [ "URIs" ], - "creator": "URI", - "group": "hexstring" - } - ``` - -- **Responses**: - - - **201**: Project created successfully - - **400**: Project creation failed, validation errors - - **401**: Unauthorized - - **500**: Server error - - The Location header of a successful response is the Project id. - -#### `POST /import?createFrom="URL"` 🔐 - -- **Description**: Create a new project by importing a web resource. -- **Request Body**: - - ```json - { - "url": "URL" - } - ``` - -- **Responses**: - - - **201**: Project created successfully - - **400**: Project creation failed, validation errors - - **401**: Unauthorized - - **500**: Server error - - The Location header of a successful response is the Project id. The project will be created with the label and metadata of the imported resource. A complete project object will be created with the imported resource as the first manifest and returned. - -#### `GET /project/:id` 🔐 - -- **Description**: Retrieve a project by ID. -- **Parameters**: - - `id`: ID of the project. -- **Responses**: - - - **200**: Project found - ```json - { - "id": "string", - "label": "string", - "metadata": [ { Metadata } ], - "creator": "URI", - "layers": [ { Layer } ], - "manifests": [ "URIs" ], - "group": "hexstring", - "tools": [ "string" ], - "options": { OptionsMap } - } - ``` - - **404**: Project not found - - **401**: Unauthorized - - **403**: Forbidden - - **500**: Server error - -The response is not a complete Project data object, but a projection designed for use in the client interface. - ---- - -### 3. **Collaborators** - -Manage the users and roles in a Project. - -#### `POST /project/:projectId/invite-member` 🔐 - -- **Description**: Invite a user to a project. If the user does not have a TPEN account, they will be sent an email invitation. -- **Parameters**: - - `projectId`: ID of the project as a hexstring or the Project slug. -- **Request Body**: - - ```json - { - "email": "string", - "roles": ["string"] | "string" - } - ``` - - - `email`: The email address of the user to invite. - - `roles`: The roles of the user in the project as an array or space-delimited string. -- **Responses**: - - - **200**: User invited successfully - - **400**: User invitation failed, validation errors - - **401**: Unauthorized - - **403**: Forbidden - - **500**: Server error - -This API is not able to track the status of the invitation. Email addresses that fail to be delivered or are rejected by the recipient will not be reported. - -#### `POST /project/:projectId/remove-member` 🔐 - -- **Description**: Remove a user from a project group. -- **Parameters**: - - `projectId`: ID of the project. -- **Request Body**: - - ```json - { - "userID": "string" - } - ``` -- **Responses**: - - - **204**: User removed successfully - - **401**: Unauthorized - - **403**: Forbidden - - **500**: Server error - -This removes a user and their roles from the project. The user will no longer have access to the project, but their annotations will remain with full attribution. - -#### `PUT /project/:projectId/collaborator/:collaboratorId/setRoles` 🔐 - -- **Description**: Set the roles of a User in a project, replacing all currently defined roles. -- **Parameters**: - - `projectId`: ID of the project. - - `collaboratorId`: ID of the collaborator. -- **Request Body**: - - ```json - { - "roles": ["string"] | "string" - } - ``` -- **Responses**: - - - **200**: Roles set successfully - - **400**: Roles setting failed, validation errors - - **401**: Unauthorized - - **403**: Forbidden - - **500**: Server error - -The User requesting this action must have permissions to set roles for the collaborator. The OWNER role cannot be set using this endpoint. - -#### `POST /project/:projectId/switch/owner` 🔐 - -- **Description**: Transfer ownership of a project to another user. -- **Parameters**: - - `projectId`: ID of the project. -- **Request Body**: - - ```json - { - "newOwnerId": "hexstring" - } - ``` -- **Responses**: - - - **200**: Ownership transferred successfully - - **400**: Ownership transfer failed, validation errors - - **401**: Unauthorized - - **403**: Forbidden - - **500**: Server error - -The User requesting this action must be the current owner of the project. The OWNER role will be removed from the current owner and assigned to the new owner. The new owner must be a member of the project. If the current owner has no other roles, the CONTRIBUTOR role will be assigned to them. - -#### `POST /project/:projectId/setCustomRoles` 🔐 - -- **Description**: Set custom roles for a Project group. Custom roles must be provided as a JSON object with keys as roles and values as arrays of permissions or space-delimited strings. -- **Parameters**: - - `projectId`: ID of the project. -- **Request Body**: - - ```json - { - "roles": { - "roleName": ["permission1", "permission2"] | "space-delimited permissions" - } - } - ``` - -- **Responses**: - - - **200**: Custom roles set successfully - - **400**: Invalid request, validation errors - - **401**: Unauthenticated request - - **403**: Permission denied - - **500**: Server error - -The User requesting this action must have permissions to update roles. Default roles cannot be modified using this endpoint. Custom roles can be complicated and there is more detailed description of their use in the [Cookbook](#). - ---- - -### 4. **Users** - -Private account modification, personal details, and public profile retrieval. - -#### `GET /my/profile` 🔐 - -- **Description**: Retrieve the profile of the authenticated user. -- **Responses**: - - - **200**: Profile found - ```json - { - "_id": "hexstring", - "_sub": "string", - "agent": "URI", - "email": "string", - "profile": { - "displayName": "string", - "custom": Any - } - "name": "string" - } - ``` - - **401**: Unauthorized - - **500**: Server error - -Users can always see and manipulate their own profile. The profile object is a projection of the full user object. - -#### `GET /my/projects` 🔐 - -- **Description**: Retrieve a list of projects the authenticated user is a member of. -- **Responses**: - - - **200**: Projects found (or empty list if user has no projects) - ```json - { - "metrics": { - "newest": "project:hexstring/page:hexstring", - "lastModified": "project:hexstring/page:hexstring", - "myRecent": "hexstring" - }, - "projects": [ - { - "_id": "hexstring", - "label": "string", - "roles": ["string"] - }, ... - ] - } - ``` - - When the user has no projects, returns: - ```json - { - "metrics": null, - "projects": [] - } - ``` - - **401**: Unauthorized - - **500**: Server error - -The response includes a list of projects the user is a member of regardless of the permissions afforded to them in each project, along with metrics about the newest and most recently modified projects. - -#### `GET /user/:id` - -- **Description**: Retrieve the public profile of a user. -- **Parameters**: - - `id`: ID of the user. -- **Responses**: - - - **200**: Profile found - ```json - { - "_id": "hexstring", - "displayName": "string", - "custom": Any - } - ``` - - **404**: Profile not found - - **500**: Server error - -The response is a projection of the full user object. The public profile is available to all users and serialized into this response with whatever the user has chosen to share. The `custom` field is not an actual property - it is a placeholder for any additional fields the user has added to their profile. The `displayName` and `_id` fields are always present. - ---- - -### 5. **Layers** - -#### `POST /project/:projectId/layer` 🔐 - -- **Description**: Create a new layer within a project. -- **Parameters**: - - `projectId`: ID of the project. -- **Request Body**: - - ```json - { - "label": "string", - "canvases": ["string"] - } - ``` - -- **Responses**: - - - **201**: Layer created successfully - ```json - { - "id": "string", - "label": "string", - "pages": ["string"] - } - ``` - - **400**: Invalid input - - **404**: Project not found - - **401**: Unauthorized - - **500**: Server error - -Note that requests without at least one canvas are considered invalid. - -#### `PUT /project/:projectId/layer/:layerId` 🔐 - -- **Description**: Update an existing layer within a project. -- **Parameters**: - - `projectId`: ID of the project. - - `layerId`: ID of the layer. -- **Request Body**: - - ```json - { - "label": "string", - "canvases": ["string"] - } - ``` - -- **Responses**: - - - **200**: Layer updated successfully - ```json - { - "id": "string", - "label": "string", - "pages": ["string"] - } - ``` - - **400**: Invalid input - - **404**: Layer or project not found - - **401**: Unauthorized - - **500**: Server error - -Note that you may not empty the canvases of an existing layer. If the `canvases` property is an empty array the request will be treated as if it did not contain the `canvases` property at all. - -#### `GET /project/:projectId/layer/:layerId` - -- **Description**: Get an existing layer within a project. -- **Parameters**: - - `projectId`: ID of the project. - - `layerId`: ID of the layer. - -- **Responses**: - - - **200**: Layer found - ```json - { - "@context": "string", - "id": "string", - "type": "AnnotationCollection", - "label": { - "none":[ - "TPEN3 Layer" - ] - }, - "total": "integer", - "first": "string", - "last": "string" - } - ``` - - **500**: Server error - -#### `GET /project/:projectId/layer/:layerId/page/:pageid` -#### `GET /project/:projectId/page/:pageid` - -- **Description**: Get an existing page within a project. -- **Parameters**: - - `projectId`: ID of the project. - - `layerId`: Optional. ID of the layer. - - `pageId`: The ID of the page. - -- **Responses**: - - - **200**: Page found - ```json - { - "@context": "string", - "id": "string", - "type": "AnnotationPage", - "label": { - "none":[ - "TPEN3 Page" - ] - }, - "target": "string", - "items":[ {"type": "Canvas"} ], - "prev": "string", - "next": "string" - } - ``` - - **500**: Server error - -#### `GET /project/:projectId/page/:pageid/resolved` - -- **Description**: Get a fully resolved page with complete annotation data from RERUM. This endpoint resolves all annotation references in the page's items array by fetching the full annotation objects from RERUM which will include the Annotation body. -- **Parameters**: - - `projectId`: ID of the project. - - `pageId`: The ID of the page. - -- **Responses**: - - - **200**: Page found with fully resolved annotations - ```json - { - "@context": "http://www.w3.org/ns/anno.jsonld", - "id": "string", - "type": "AnnotationPage", - "label": { - "none":[ - "TPEN3 Page" - ] - }, - "target": "string", - "items": [ - { - "@context": "http://iiif.io/api/presentation/3/context.json", - "id": "string", - "type": "Annotation", - "motivation": "transcribing", - "target": { - "source": "string", - "type": "SpecificResource", - "selector": { - "type": "FragmentSelector", - "value": "string" - } - }, - "creator": "string", - "body": { - "type": "TextualBody", - "value": "string", - "format": "text/plain" - }, - "_createdAt": "timestamp", - "_modifiedAt": "timestamp", - "__rerum": { - "@context": "http://store.rerum.io/v1/context.json", - "createdAt": "timestamp", - "isOverwritten": "string" - } - } - ], - "partOf": [{"type":"Collection"}], - "prev": "string", - "next": "string", - "_createdAt": "timestamp", - "_modifiedAt": "timestamp" - } - ``` - - **404**: Page not found - - **500**: Server error - -**Note**: This endpoint is useful when you need complete annotation data in a single request instead of making multiple API calls to fetch individual annotations from RERUM. The annotations are resolved in parallel for better performance. diff --git a/__tests__/mount.test.js b/__tests__/mount.test.js index f21686a1..38dde54d 100644 --- a/__tests__/mount.test.js +++ b/__tests__/mount.test.js @@ -87,14 +87,10 @@ function routeExists(path, method = null) { describe('Check to see that all expected route patterns exist. #exists_unit', () => { - describe('Root and API routes', () => { + describe('Root routes', () => { it('GET / -- root index route', () => { expect(routeExists('/', 'get')).toBe(true) }) - - it('GET /api -- API documentation route', () => { - expect(routeExists('/api', 'get')).toBe(true) - }) }) describe('Private user routes (/my)', () => { @@ -343,7 +339,6 @@ describe('Check to see that critical repo files are present #exists_unit', () => expect(fs.existsSync(filePath+"CODEOWNERS")).toBeTruthy() expect(fs.existsSync(filePath+"CONTRIBUTING.md")).toBeTruthy() expect(fs.existsSync(filePath+"README.md")).toBeTruthy() - expect(fs.existsSync(filePath+"API.md")).toBeTruthy() expect(fs.existsSync(filePath+"LICENSE.md")).toBeTruthy() expect(fs.existsSync(filePath+".gitignore")).toBeTruthy() expect(fs.existsSync(filePath+"package.json")).toBeTruthy() diff --git a/index.js b/index.js index 40eefb70..a7246d34 100644 --- a/index.js +++ b/index.js @@ -16,32 +16,6 @@ export function respondWithHTML(res) { res.status(200).sendFile('index.html').end() } -import { JSDOM } from 'jsdom' -import DOMPurify from 'dompurify' - -const window = new JSDOM('').window -const purify = DOMPurify(window) - -import fs from 'fs' -import { marked } from 'marked' - -marked.use({ - gfm: true, -}) - -router - .route("/api") - .get(function (_req,res) { - fs.readFile('API.md', 'utf8', (err, data) => { - if (err) { - return respondWithError(res, 500, 'Failed to read API.md') - } - res.format({ - html: () => res.send(makeCleanFileFromMarkdown(data)) - }) - }) - }) - router .route("/") .get(function (_req, res, next) { @@ -52,27 +26,3 @@ router }) export { router as default } - -function makeCleanFileFromMarkdown(file) { - const sanitizedContent = purify.sanitize(marked.parse(file)) - return ` - - - - - - - API Documentation - - - - - - -
- ${sanitizedContent} -
- - - ` -} diff --git a/package-lock.json b/package-lock.json index f369b697..11c13d2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,15 +13,12 @@ "cookie-parser": "^1.4.7", "cors": "^2.8.6", "debug": "^4.4.3", - "dompurify": "^3.3.3", "dotenv": "^17.3.1", "express": "^5.2.1", "express-list-endpoints": "^7.1.1", "express-oauth2-jwt-bearer": "^1.7.4", "image-size": "^2.0.2", - "jsdom": "27.0.0", "mariadb": "^3.5.2", - "marked": "^17.0.4", "mime-types": "^3.0.2", "mongodb": "^7.1.0", "morgan": "^1.10.1", @@ -40,34 +37,6 @@ "npm": ">=11.0.0" } }, - "node_modules/@asamuzakjp/dom-selector": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.8.1.tgz", - "integrity": "sha512-MvRz1nCqW0fsy8Qz4dnLIvhOlMzqDVBabZx6lH+YywFDdjXhMY37SmpV1XFX3JzG5GWHn63j6HX6QPr3lZXHvQ==", - "license": "MIT", - "dependencies": { - "@asamuzakjp/nwsapi": "^2.3.9", - "bidi-js": "^1.0.3", - "css-tree": "^3.1.0", - "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.2.6" - } - }, - "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/@asamuzakjp/nwsapi": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", - "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", - "license": "MIT" - }, "node_modules/@babel/code-frame": { "version": "7.29.0", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", @@ -564,22 +533,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@csstools/css-syntax-patches-for-csstree": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.0.tgz", - "integrity": "sha512-H4tuz2nhWgNKLt1inYpoVCfbJbMwX/lQKp3g69rrrIMIYlFD9+zTykOKhNR8uGrAmbS/kT9n6hTFkmDkxLgeTA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0" - }, "node_modules/@emnapi/core": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.8.1.tgz", @@ -1331,13 +1284,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/trusted-types": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", - "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", - "license": "MIT", - "optional": true - }, "node_modules/@types/webidl-conversions": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", @@ -1483,9 +1429,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1500,9 +1443,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1517,9 +1457,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1534,9 +1471,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1551,9 +1485,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1568,9 +1499,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1585,9 +1513,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -1602,9 +1527,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -1690,15 +1612,6 @@ "node": ">= 0.6" } }, - "node_modules/agent-base": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", - "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -1926,15 +1839,6 @@ "node": ">= 0.8" } }, - "node_modules/bidi-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz", - "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==", - "license": "MIT", - "dependencies": { - "require-from-string": "^2.0.2" - } - }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2451,194 +2355,6 @@ "node": ">= 8" } }, - "node_modules/css-tree": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", - "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", - "license": "MIT", - "dependencies": { - "mdn-data": "2.27.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/cssstyle": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz", - "integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==", - "license": "MIT", - "dependencies": { - "@asamuzakjp/css-color": "^4.1.1", - "@csstools/css-syntax-patches-for-csstree": "^1.0.21", - "css-tree": "^3.1.0", - "lru-cache": "^11.2.4" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/cssstyle/node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", - "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", - "license": "MIT", - "dependencies": { - "@csstools/css-calc": "^2.1.3", - "@csstools/css-color-parser": "^3.0.9", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" - } - }, - "node_modules/cssstyle/node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/cssstyle/node_modules/@csstools/color-helpers": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", - "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=18" - } - }, - "node_modules/cssstyle/node_modules/@csstools/css-calc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", - "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/cssstyle/node_modules/@csstools/css-color-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", - "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "dependencies": { - "@csstools/color-helpers": "^5.1.0", - "@csstools/css-calc": "^2.1.4" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/cssstyle/node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" - } - }, - "node_modules/cssstyle/node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cssstyle/node_modules/lru-cache": { - "version": "11.2.6", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz", - "integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==", - "license": "BlueOak-1.0.0", - "engines": { - "node": "20 || >=22" - } - }, - "node_modules/data-urls": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-6.0.1.tgz", - "integrity": "sha512-euIQENZg6x8mj3fO6o9+fOW8MimUI4PpD/fZBhJfeioZVy9TUpM4UY7KjQNVZFlqwJ0UdzRDzkycB997HEq1BQ==", - "license": "MIT", - "dependencies": { - "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^15.1.0" - }, - "engines": { - "node": ">=20" - } - }, - "node_modules/data-urls/node_modules/whatwg-mimetype": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", - "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", - "license": "MIT", - "engines": { - "node": ">=20" - } - }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -2656,12 +2372,6 @@ } } }, - "node_modules/decimal.js": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", - "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "license": "MIT" - }, "node_modules/dedent": { "version": "1.7.2", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", @@ -2746,15 +2456,6 @@ "node": ">=0.3.1" } }, - "node_modules/dompurify": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.3.tgz", - "integrity": "sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==", - "license": "(MPL-2.0 OR Apache-2.0)", - "optionalDependencies": { - "@types/trusted-types": "^2.0.7" - } - }, "node_modules/dotenv": { "version": "17.3.1", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.3.1.tgz", @@ -2830,18 +2531,6 @@ "node": ">= 0.8" } }, - "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -3459,18 +3148,6 @@ "node": ">= 0.4" } }, - "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "license": "MIT", - "dependencies": { - "whatwg-encoding": "^3.1.1" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/html-escaper": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", @@ -3498,32 +3175,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "license": "MIT", - "dependencies": { - "agent-base": "^7.1.2", - "debug": "4" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -3699,12 +3350,6 @@ "node": ">=0.12.0" } }, - "node_modules/is-potential-custom-element-name": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", - "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "license": "MIT" - }, "node_modules/is-promise": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", @@ -4453,45 +4098,6 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsdom": { - "version": "27.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-27.0.0.tgz", - "integrity": "sha512-lIHeR1qlIRrIN5VMccd8tI2Sgw6ieYXSVktcSHaNe3Z5nE/tcPQYQWOq00wxMvYOsz+73eAkNenVvmPC6bba9A==", - "license": "MIT", - "dependencies": { - "@asamuzakjp/dom-selector": "^6.5.4", - "cssstyle": "^5.3.0", - "data-urls": "^6.0.0", - "decimal.js": "^10.5.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.6", - "is-potential-custom-element-name": "^1.0.1", - "parse5": "^7.3.0", - "rrweb-cssom": "^0.8.0", - "saxes": "^6.0.0", - "symbol-tree": "^3.2.4", - "tough-cookie": "^6.0.0", - "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^8.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^15.0.0", - "ws": "^8.18.2", - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=20" - }, - "peerDependencies": { - "canvas": "^3.0.0" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -4632,18 +4238,6 @@ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "license": "ISC" }, - "node_modules/marked": { - "version": "17.0.4", - "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.4.tgz", - "integrity": "sha512-NOmVMM+KAokHMvjWmC5N/ZOvgmSWuqJB8FoYI019j4ogb/PeRMKoKIjReZ2w3376kkA8dSJIP8uD993Kxc0iRQ==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 20" - } - }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -4653,12 +4247,6 @@ "node": ">= 0.4" } }, - "node_modules/mdn-data": { - "version": "2.27.1", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", - "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", - "license": "CC0-1.0" - }, "node_modules/media-typer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", @@ -5256,18 +4844,6 @@ "license": "MIT", "optional": true }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -5540,15 +5116,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", @@ -5588,12 +5155,6 @@ "node": ">= 18" } }, - "node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "license": "MIT" - }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -5606,18 +5167,6 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, - "node_modules/saxes": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", - "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "license": "ISC", - "dependencies": { - "xmlchars": "^2.2.0" - }, - "engines": { - "node": ">=v12.22.7" - } - }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -5851,15 +5400,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-support": { "version": "0.5.13", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", @@ -6149,12 +5689,6 @@ "license": "ISC", "optional": true }, - "node_modules/symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "license": "MIT" - }, "node_modules/synckit": { "version": "0.11.12", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz", @@ -6232,24 +5766,6 @@ "node": "*" } }, - "node_modules/tldts": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.25.tgz", - "integrity": "sha512-keinCnPbwXEUG3ilrWQZU+CqcTTzHq9m2HhoUP2l7Xmi8l1LuijAXLpAJ5zRW+ifKTNscs4NdCkfkDCBYm352w==", - "license": "MIT", - "dependencies": { - "tldts-core": "^7.0.25" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "7.0.25", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.25.tgz", - "integrity": "sha512-ZjCZK0rppSBu7rjHYDYsEaMOIbbT+nWF57hKkv4IUmZWBNrBWBOjIElc0mKRgLM8bm7x/BBlof6t2gi/Oq/Asw==", - "license": "MIT" - }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -6289,34 +5805,10 @@ "nodetouch": "bin/nodetouch.js" } }, - "node_modules/tough-cookie": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz", - "integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==", - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^7.0.5" - }, - "engines": { - "node": ">=16" - } - }, "node_modules/tpen3-services": { "resolved": "", "link": true }, - "node_modules/tr46": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", - "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", - "license": "MIT", - "dependencies": { - "punycode": "^2.3.1" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -6474,18 +5966,6 @@ "node": ">= 0.8" } }, - "node_modules/w3c-xmlserializer": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", - "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "license": "MIT", - "dependencies": { - "xml-name-validator": "^5.0.0" - }, - "engines": { - "node": ">=18" - } - }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -6496,62 +5976,6 @@ "makeerror": "1.0.12" } }, - "node_modules/webidl-conversions": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", - "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=20" - } - }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", - "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/whatwg-url": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-15.1.0.tgz", - "integrity": "sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==", - "license": "MIT", - "dependencies": { - "tr46": "^6.0.0", - "webidl-conversions": "^8.0.0" - }, - "engines": { - "node": ">=20" - } - }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6683,42 +6107,6 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, - "node_modules/ws": { - "version": "8.19.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz", - "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xml-name-validator": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", - "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "license": "Apache-2.0", - "engines": { - "node": ">=18" - } - }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "license": "MIT" - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/package.json b/package.json index cdc26259..4e9c8b3b 100644 --- a/package.json +++ b/package.json @@ -37,15 +37,12 @@ "cookie-parser": "^1.4.7", "cors": "^2.8.6", "debug": "^4.4.3", - "dompurify": "^3.3.3", "dotenv": "^17.3.1", "express": "^5.2.1", "express-list-endpoints": "^7.1.1", "express-oauth2-jwt-bearer": "^1.7.4", "image-size": "^2.0.2", - "jsdom": "27.0.0", "mariadb": "^3.5.2", - "marked": "^17.0.4", "mime-types": "^3.0.2", "mongodb": "^7.1.0", "morgan": "^1.10.1", From 54b370f4c17e0f10be5093e8960466af10804f06 Mon Sep 17 00:00:00 2001 From: Bryan Haberberger Date: Mon, 16 Mar 2026 13:43:53 -0500 Subject: [PATCH 3/3] changes during review --- public/API.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/API.html b/public/API.html index 3b2b4d40..1c0ea621 100644 --- a/public/API.html +++ b/public/API.html @@ -686,7 +686,7 @@

GET/project/:projectId/page/:pageid