Skip to content

Commit

Permalink
Add cell-extension package
Browse files Browse the repository at this point in the history
  • Loading branch information
tmetzl committed Oct 24, 2024
1 parent e48e29c commit eeed150
Show file tree
Hide file tree
Showing 8 changed files with 424 additions and 0 deletions.
201 changes: 201 additions & 0 deletions packages/cell-extension/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
{
"name": "@e2xgrader/cell-extension",
"version": "0.1.0",
"description": "A JupyterLab extension which bundles e2xgrader extensions",
"keywords": [
"jupyter",
"jupyterlab",
"jupyterlab-extension"
],
"homepage": "https://github.com/DigiKlausur/e2xgrader",
"bugs": {
"url": "https://github.com/DigiKlausur/e2xgrader/issues"
},
"license": "MIT",
"author": {
"name": "Tim Metzler",
"email": "[email protected]"
},
"files": [
"lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}",
"style/**/*.{css,js,eot,gif,html,jpg,json,png,svg,woff2,ttf}",
"src/**/*.{ts,tsx}",
"schema/*.json"
],
"main": "lib/index.js",
"types": "lib/index.d.ts",
"style": "style/index.css",
"repository": {
"type": "git",
"url": "https://github.com/DigiKlausur/e2xgrader.git"
},
"scripts": {
"build": "jlpm build:lib && jlpm build:labextension:dev",
"build:prod": "jlpm clean && jlpm build:lib:prod && jlpm build:labextension",
"build:labextension": "jupyter labextension build .",
"build:labextension:dev": "jupyter labextension build --development True .",
"build:lib": "tsc --sourceMap",
"build:lib:prod": "tsc",
"clean": "jlpm clean:lib",
"clean:lib": "rimraf lib tsconfig.tsbuildinfo",
"clean:lintcache": "rimraf .eslintcache .stylelintcache",
"clean:labextension": "rimraf e2xgrader_extensions/labextension e2xgrader_extensions/_version.py",
"clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache",
"eslint": "jlpm eslint:check --fix",
"eslint:check": "eslint . --cache --ext .ts,.tsx",
"install:extension": "jlpm build",
"lint": "jlpm stylelint && jlpm prettier && jlpm eslint",
"lint:check": "jlpm stylelint:check && jlpm prettier:check && jlpm eslint:check",
"prettier": "jlpm prettier:base --write --list-different",
"prettier:base": "prettier \"**/*{.ts,.tsx,.js,.jsx,.css,.json,.md}\"",
"prettier:check": "jlpm prettier:base --check",
"stylelint": "jlpm stylelint:check --fix",
"stylelint:check": "stylelint --cache \"style/**/*.css\"",
"test": "jest --coverage",
"watch": "run-p watch:src watch:labextension",
"watch:src": "tsc -w --sourceMap",
"watch:labextension": "jupyter labextension watch ."
},
"dependencies": {
"@e2xgrader/cells": "^0.1.0",
"@e2xgrader/settings": "^0.1.0",
"@jupyterlab/application": "^4.0.0",
"@jupyterlab/cells": "^4.2.5",
"@jupyterlab/notebook": "^4.2.5",
"@jupyterlab/settingregistry": "^4.0.0"
},
"devDependencies": {
"@jupyterlab/builder": "^4.0.0",
"@jupyterlab/testutils": "^4.0.0",
"@types/jest": "^29.2.0",
"@types/json-schema": "^7.0.11",
"@types/react": "^18.0.26",
"@types/react-addons-linked-state-mixin": "^0.14.22",
"@typescript-eslint/eslint-plugin": "^6.1.0",
"@typescript-eslint/parser": "^6.1.0",
"css-loader": "^6.7.1",
"eslint": "^8.36.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.2.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.0",
"rimraf": "^5.0.1",
"source-map-loader": "^1.0.2",
"style-loader": "^3.3.1",
"stylelint": "^15.10.1",
"stylelint-config-recommended": "^13.0.0",
"stylelint-config-standard": "^34.0.0",
"stylelint-csstree-validator": "^3.0.0",
"stylelint-prettier": "^4.0.0",
"typescript": "~5.0.2",
"yjs": "^13.5.0"
},
"sideEffects": [
"style/*.css",
"style/index.js"
],
"styleModule": "style/index.js",
"publishConfig": {
"access": "public"
},
"jupyterlab": {
"extension": true,
"outputDir": "../../e2xgrader/static/labextensions/@e2xgrader/cell-extension",
"schemaDir": "schema"
},
"eslintIgnore": [
"node_modules",
"dist",
"coverage",
"**/*.d.ts",
"tests",
"**/__tests__",
"ui-tests"
],
"eslintConfig": {
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:prettier/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "tsconfig.json",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
"@typescript-eslint/naming-convention": [
"error",
{
"selector": "interface",
"format": [
"PascalCase"
],
"custom": {
"regex": "^I[A-Z]",
"match": true
}
}
],
"@typescript-eslint/no-unused-vars": [
"warn",
{
"args": "none"
}
],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-namespace": "off",
"@typescript-eslint/no-use-before-define": "off",
"@typescript-eslint/quotes": [
"error",
"single",
{
"avoidEscape": true,
"allowTemplateLiterals": false
}
],
"curly": [
"error",
"all"
],
"eqeqeq": "error",
"prefer-arrow-callback": "error"
}
},
"prettier": {
"singleQuote": true,
"trailingComma": "none",
"arrowParens": "avoid",
"endOfLine": "auto",
"overrides": [
{
"files": "package.json",
"options": {
"tabWidth": 4
}
}
]
},
"stylelint": {
"extends": [
"stylelint-config-recommended",
"stylelint-config-standard",
"stylelint-prettier/recommended"
],
"plugins": [
"stylelint-csstree-validator"
],
"rules": {
"csstree/validator": true,
"property-no-vendor-prefix": null,
"selector-class-pattern": "^([a-z][A-z\\d]*)(-[A-z\\d]+)*$",
"selector-no-vendor-prefix": null,
"value-no-vendor-prefix": null
}
}
}
69 changes: 69 additions & 0 deletions packages/cell-extension/schema/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"jupyter.lab.shortcuts": [],
"title": "@e2xgrader/cell-extension",
"description": "@e2xgrader/cell-extension settings.",
"properties": {
"edit_mode": {
"title": "Edit Mode",
"description": "If the edit cell button is displayed",
"type": "boolean",
"default": true
},
"dummy": {
"title": "Dummy",
"description": "A dummy setting",
"type": "string",
"default": "dummy"
},
"drawDomain": {
"title": "drawDomain",
"description": "The URL of the diagram editor",
"type": "string",
"default": "https://embed.diagrams.net/"
},
"drawOrigin": {
"title": "drawOrigin URL",
"description": "The URL of the origin of the diagram editor",
"type": "string",
"default": "https://embed.diagrams.net/"
},
"drawLibs": {
"title": "Diagram Libraries",
"description": "Libraries that are active by default. If empty standard libraries are active.",
"type": "array",
"items": {
"type": "string"
},
"default": []
},
"diagram_options": {
"title": "Diagram Editor Options",
"description": "The options for the diagram editor",
"type": "object",
"properties": {
"drawDomain": {
"title": "drawDomain",
"description": "The URL of the diagram editor",
"type": "string",
"default": "https://embed.diagrams.net/"
},
"drawOrigin": {
"title": "drawOrigin URL",
"description": "The URL of the origin of the diagram editor",
"type": "string",
"default": "https://embed.diagrams.net/"
},
"libs": {
"title": "Diagram Libraries",
"description": "Libraries that are active by default. If empty standard libraries are active.",
"type": "array",
"items": {
"type": "string"
},
"default": []
}
}
}
},
"type": "object"
}
105 changes: 105 additions & 0 deletions packages/cell-extension/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import {
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';

import { ISettingRegistry } from '@jupyterlab/settingregistry';
import { INotebookTracker } from '@jupyterlab/notebook';

import { MarkdownCell } from '@jupyterlab/cells';
import { e2xCellFactory, e2xCellUtils } from '@e2xgrader/cells';
import Settings from '@e2xgrader/settings';

const PLUGIN_ID = '@e2xgrader/cell-extension:plugin';

function listenToMetadataChanges(cell: MarkdownCell) {
const model = cell.model;
// Problem: This does not seem to be triggered when a metadata key is removed via the metadata editor
// However, it is triggered when the metadata is changed via deleteMetadata
model.metadataChanged.connect((_: any, args: any) => {
console.log(
'Did the e2xgrader cell type change?',
e2xCellUtils.hasE2xGraderCellTypeChanged(args)
);
if (e2xCellUtils.hasE2xGraderCellTypeChanged(args)) {
e2xCellUtils.forceRender(cell);
}
});
}

function listenToRenderChanges(cell: MarkdownCell) {
cell.renderedChanged.connect((_: any, isRendered: boolean) => {
// Skip if the cell is not rendered
if (!isRendered) {
return;
}
Settings.getInstance(PLUGIN_ID).then(
(settings: ISettingRegistry.ISettings) => {
console.log('Settings loaded:', settings);
const e2xCell = e2xCellFactory(cell, settings);
if (e2xCell) {
e2xCell.onCellRendered();
}
}
);
});
e2xCellUtils.forceRender(cell);
}

/**
* Initialization data for the e2xgrader_cells extension.
*/
const plugin: JupyterFrontEndPlugin<void> = {
id: PLUGIN_ID,
description: 'A JupyterLab for displaying custom e2xgrader cells',
autoStart: true,
requires: [INotebookTracker, ISettingRegistry],
activate: (
app: JupyterFrontEnd,
notebooks: INotebookTracker,
settings: ISettingRegistry
) => {
Settings.initialize(PLUGIN_ID, settings);
console.log('JupyterLab extension e2xgrader_cells is activated!');

notebooks.widgetAdded.connect((_, notebookPanel) => {
const notebook = notebookPanel.content;

if (!notebook?.model) {
return;
}

notebook.model.cells.changed.connect((_, args) => {
// Skip if the cell is not being added
if (args.type !== 'add') {
return;
}

for (const cell of args.newValues) {
// Skip non markdown cells
if (!cell.type || cell.type !== 'markdown') {
continue;
}
// Find the widget by matching ids
const cellWidget = notebook.widgets.find(
widget => widget.model.id === cell.id
);
if (!cellWidget) {
console.error('Cell widget not found');
continue;
}

const markdownCellWidget = cellWidget as MarkdownCell;

listenToMetadataChanges(markdownCellWidget);
listenToRenderChanges(markdownCellWidget);

// Rerender e2xgrader cells
e2xCellUtils.forceRender(markdownCellWidget);
}
});
});
}
};

export default plugin;
5 changes: 5 additions & 0 deletions packages/cell-extension/style/base.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/*
See the JupyterLab Developer Guide for useful CSS Patterns:
https://jupyterlab.readthedocs.io/en/stable/developer/css.html
*/
Loading

0 comments on commit eeed150

Please sign in to comment.