From 7c34e636c90aec48a33447e178c741affb7de41c Mon Sep 17 00:00:00 2001 From: Guilherme Caponetto <638737+caponetto@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:32:17 -0300 Subject: [PATCH] Readd deleted extension (Code Viewer, Scala and R editors) (#100) --- .eslintrc.json | 14 +- cypress/tests/reditor.cy.ts | 86 ++++++ .../elyra_code_viewer_extension/__init__.py | 14 + .../elyra_r_editor_extension/__init__.py | 14 + .../elyra_scala_editor_extension/__init__.py | 14 + packages/code-viewer/install.json | 5 + packages/code-viewer/package.json | 75 +++++ packages/code-viewer/setup.py | 1 + packages/code-viewer/src/CodeViewerWidget.ts | 92 ++++++ packages/code-viewer/src/index.ts | 126 +++++++++ packages/code-viewer/style/index.css | 15 + packages/code-viewer/tsconfig.json | 7 + packages/r-editor/install.json | 5 + packages/r-editor/package.json | 82 ++++++ packages/r-editor/setup.py | 1 + packages/r-editor/src/REditor.tsx | 39 +++ packages/r-editor/src/index.ts | 260 +++++++++++++++++ packages/r-editor/style/index.css | 15 + packages/r-editor/tsconfig.json | 7 + packages/scala-editor/install.json | 5 + packages/scala-editor/package.json | 82 ++++++ packages/scala-editor/setup.py | 1 + packages/scala-editor/src/ScalaEditor.tsx | 39 +++ packages/scala-editor/src/index.ts | 264 ++++++++++++++++++ packages/scala-editor/style/index.css | 15 + packages/scala-editor/tsconfig.json | 7 + pyproject.toml | 16 ++ yarn.lock | 62 ++++ 28 files changed, 1350 insertions(+), 13 deletions(-) create mode 100644 cypress/tests/reditor.cy.ts create mode 100644 labextensions/elyra_code_viewer_extension/__init__.py create mode 100644 labextensions/elyra_r_editor_extension/__init__.py create mode 100644 labextensions/elyra_scala_editor_extension/__init__.py create mode 100644 packages/code-viewer/install.json create mode 100644 packages/code-viewer/package.json create mode 100644 packages/code-viewer/setup.py create mode 100644 packages/code-viewer/src/CodeViewerWidget.ts create mode 100644 packages/code-viewer/src/index.ts create mode 100644 packages/code-viewer/style/index.css create mode 100644 packages/code-viewer/tsconfig.json create mode 100644 packages/r-editor/install.json create mode 100644 packages/r-editor/package.json create mode 100644 packages/r-editor/setup.py create mode 100644 packages/r-editor/src/REditor.tsx create mode 100644 packages/r-editor/src/index.ts create mode 100644 packages/r-editor/style/index.css create mode 100644 packages/r-editor/tsconfig.json create mode 100644 packages/scala-editor/install.json create mode 100644 packages/scala-editor/package.json create mode 100644 packages/scala-editor/setup.py create mode 100644 packages/scala-editor/src/ScalaEditor.tsx create mode 100644 packages/scala-editor/src/index.ts create mode 100644 packages/scala-editor/style/index.css create mode 100644 packages/scala-editor/tsconfig.json diff --git a/.eslintrc.json b/.eslintrc.json index 595327498..1737e33c3 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -73,17 +73,5 @@ "react": { "version": "detect" } - }, - "ignorePatterns": [ - "packages/pipeline-editor/elyra_pipeline_editor_extension/*", - "packages/theme/elyra_theme_extension/*", - "packages/script-debugger/elyra_script_debugger_extension/*", - "packages/script-editor/elyra_script_editor/*", - "packages/code-snippet/elyra_code_snippet_extension/*", - "packages/metadata/elyra_metadata_extension/*", - "packages/metadata-common/elyra_metadata_common/*", - "packages/python-editor/elyra_python_editor_extension/*", - "packages/services/elyra_services/*", - "packages/ui-components/elyra_ui_components/*" - ] + } } diff --git a/cypress/tests/reditor.cy.ts b/cypress/tests/reditor.cy.ts new file mode 100644 index 000000000..0a456461c --- /dev/null +++ b/cypress/tests/reditor.cy.ts @@ -0,0 +1,86 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +describe.skip('R Editor tests (skipped as this extension is not part of ODH distribution)', () => { + before(() => { + cy.resetJupyterLab(); + cy.bootstrapFile('helloworld.r'); // load R file used to check existing contents + }); + + after(() => { + // delete files created for testing + cy.deleteFile('untitled*.r'); + cy.deleteFile('helloworld.r'); // delete R file used for testing + }); + + // R Editor Tests + it('opens blank R file from launcher', () => { + cy.createNewScriptEditor('R'); + cy.get('.lm-TabBar-tab[data-type="document-title"]'); + cy.closeTab(-1); + }); + + // Flaky test: Missing expected items in the context menu; it works manually though. + it.skip('check R editor tab right click content', () => { + cy.createNewScriptEditor('R'); + cy.checkRightClickTabContent('R'); + cy.closeTab(-1); + }); + + it('close R editor', () => { + cy.createNewScriptEditor('R'); + cy.closeTab(-1); + }); + + it('open R file with expected content', () => { + cy.openFileAndCheckContent('r'); + cy.closeTab(-1); + }); + + it('check icons', () => { + // Check file menu editor contents + cy.findByRole('menuitem', { name: /file/i }).click(); + cy.findByText(/^new$/i).click(); + cy.get( + '[data-command="script-editor:create-new-r-editor"] svg[data-icon="elyra:rIcon"]' + ); + + // Check r icons from launcher & file explorer + cy.get( + '.jp-LauncherCard[data-category="Elyra"][title="Create a new R Editor"] svg[data-icon="elyra:rIcon"]' + ).click(); + cy.get( + '#filebrowser [title*="Name: untitled.r"] svg[data-icon="elyra:rIcon"]' + ); + cy.closeTab(-1); + }); + + it('opens blank R file from menu', () => { + cy.findByRole('menuitem', { name: /file/i }).click(); + cy.findByText(/^new$/i).click(); + + cy.get( + '[data-command="script-editor:create-new-r-editor"] > .lm-Menu-itemLabel' + ).click(); + cy.closeTab(-1); + }); + + it('check toolbar and its content for R file', () => { + cy.createNewScriptEditor('R'); + cy.checkScriptEditorToolbarContent(); + cy.closeTab(-1); + }); +}); diff --git a/labextensions/elyra_code_viewer_extension/__init__.py b/labextensions/elyra_code_viewer_extension/__init__.py new file mode 100644 index 000000000..7b6a8f18d --- /dev/null +++ b/labextensions/elyra_code_viewer_extension/__init__.py @@ -0,0 +1,14 @@ +try: + from ._version import __version__ +except ImportError: + # Fallback when using the package in dev mode without installing + # in editable mode with pip. It is highly recommended to install + # the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs + import warnings + + warnings.warn("Importing 'elyra_code_viewer_extension' outside a proper installation.") + __version__ = "dev" + + +def _jupyter_labextension_paths(): + return [{"src": "labextension", "dest": "@elyra/code-viewer-extension"}] diff --git a/labextensions/elyra_r_editor_extension/__init__.py b/labextensions/elyra_r_editor_extension/__init__.py new file mode 100644 index 000000000..605e17574 --- /dev/null +++ b/labextensions/elyra_r_editor_extension/__init__.py @@ -0,0 +1,14 @@ +try: + from ._version import __version__ +except ImportError: + # Fallback when using the package in dev mode without installing + # in editable mode with pip. It is highly recommended to install + # the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs + import warnings + + warnings.warn("Importing 'elyra_r_editor_extension' outside a proper installation.") + __version__ = "dev" + + +def _jupyter_labextension_paths(): + return [{"src": "labextension", "dest": "@elyra/r-editor-extension"}] diff --git a/labextensions/elyra_scala_editor_extension/__init__.py b/labextensions/elyra_scala_editor_extension/__init__.py new file mode 100644 index 000000000..536f9201b --- /dev/null +++ b/labextensions/elyra_scala_editor_extension/__init__.py @@ -0,0 +1,14 @@ +try: + from ._version import __version__ +except ImportError: + # Fallback when using the package in dev mode without installing + # in editable mode with pip. It is highly recommended to install + # the package from a stable release or in editable mode: https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs + import warnings + + warnings.warn("Importing 'elyra_scala_editor_extension' outside a proper installation.") + __version__ = "dev" + + +def _jupyter_labextension_paths(): + return [{"src": "labextension", "dest": "@elyra/scala-editor-extension"}] diff --git a/packages/code-viewer/install.json b/packages/code-viewer/install.json new file mode 100644 index 000000000..a957fc7d6 --- /dev/null +++ b/packages/code-viewer/install.json @@ -0,0 +1,5 @@ +{ + "packageManager": "python", + "packageName": "elyra_code_viewer_extension", + "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package elyra_code_viewer_extension" +} diff --git a/packages/code-viewer/package.json b/packages/code-viewer/package.json new file mode 100644 index 000000000..3136df2d1 --- /dev/null +++ b/packages/code-viewer/package.json @@ -0,0 +1,75 @@ +{ + "name": "@elyra/code-viewer-extension", + "version": "0.0.0-dev", + "description": "JupyterLab extension - Display code without a file", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/elyra-ai/elyra", + "bugs": { + "url": "https://github.com/elyra-ai/elyra/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/elyra-ai/elyra/" + }, + "license": "Apache-2.0", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "files": [ + "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", + "src/**/*.{ts,tsx}", + "style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}" + ], + "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 ../../../../labextensions/elyra_code_viewer_extension/labextension ../../../../labextensions/elyra_code_viewer_extension/_version.py", + "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", + "cy:instrument": "npx nyc instrument --compact=false --in-place src/ src/", + "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 --passWithNoTests", + "watch": "run-p watch:src watch:labextension", + "watch:src": "tsc -w --sourceMap", + "watch:labextension": "jupyter labextension watch ." + }, + "dependencies": { + "@jupyterlab/application": "^4.2.5", + "@jupyterlab/apputils": "^4.2.5", + "@jupyterlab/codeeditor": "^4.2.5", + "@jupyterlab/ui-components": "^4.2.5", + "@lumino/algorithm": "*", + "@lumino/widgets": "^2.3.1" + }, + "devDependencies": { + "@jupyterlab/builder": "^4.2.5", + "rimraf": "~5.0.5", + "typescript": "~5.1.6" + }, + "publishConfig": { + "access": "public" + }, + "jupyterlab": { + "extension": true, + "outputDir": "../../labextensions/elyra_code_viewer_extension/labextension" + } +} diff --git a/packages/code-viewer/setup.py b/packages/code-viewer/setup.py new file mode 100644 index 000000000..aefdf20db --- /dev/null +++ b/packages/code-viewer/setup.py @@ -0,0 +1 @@ +__import__("setuptools").setup() diff --git a/packages/code-viewer/src/CodeViewerWidget.ts b/packages/code-viewer/src/CodeViewerWidget.ts new file mode 100644 index 000000000..42d690ac2 --- /dev/null +++ b/packages/code-viewer/src/CodeViewerWidget.ts @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { CodeEditor, CodeEditorWrapper } from '@jupyterlab/codeeditor'; +import { StackedLayout, Widget } from '@lumino/widgets'; + +export class CodeViewerWidget extends Widget { + /** + * Construct a new code viewer widget. + */ + constructor(options: CodeViewerWidget.IOptions) { + super(); + this.model = options.model; + + const editorWidget = new CodeEditorWrapper({ + factory: options.factory, + model: options.model + }); + this.editor = editorWidget.editor; + this.editor.setOption('readOnly', true); + + const layout = (this.layout = new StackedLayout()); + layout.addWidget(editorWidget); + } + + static getCodeViewer( + options: CodeViewerWidget.INoModelOptions + ): CodeViewerWidget { + const model = new CodeEditor.Model({ mimeType: options.mimeType }); + model.sharedModel.source = options.content; + return new CodeViewerWidget({ factory: options.factory, model }); + } + + getContent = (): string => this.model.sharedModel.getSource(); + getMimeType = (): string => this.model.mimeType; + + model: CodeEditor.IModel; + editor: CodeEditor.IEditor; +} + +/** + * The namespace for code viewer widget. + */ +export namespace CodeViewerWidget { + /** + * The options used to create an code viewer widget. + */ + export interface IOptions { + /** + * A code editor factory. + */ + factory: CodeEditor.Factory; + + /** + * The content model for the viewer. + */ + model: CodeEditor.IModel; + } + + /** + * The options used to create an code viewer widget without a model. + */ + export interface INoModelOptions { + /** + * A code editor factory. + */ + factory: CodeEditor.Factory; + + /** + * The content to display in the viewer. + */ + content: string; + + /** + * The mime type for the content. + */ + mimeType?: string; + } +} diff --git a/packages/code-viewer/src/index.ts b/packages/code-viewer/src/index.ts new file mode 100644 index 000000000..ca9a46416 --- /dev/null +++ b/packages/code-viewer/src/index.ts @@ -0,0 +1,126 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + ILayoutRestorer, + JupyterFrontEnd, + JupyterFrontEndPlugin +} from '@jupyterlab/application'; +import { MainAreaWidget, WidgetTracker } from '@jupyterlab/apputils'; +import { CodeEditor, IEditorServices } from '@jupyterlab/codeeditor'; +import { textEditorIcon } from '@jupyterlab/ui-components'; +import { toArray } from '@lumino/algorithm'; + +import { CodeViewerWidget } from './CodeViewerWidget'; + +const ELYRA_CODE_VIEWER_NAMESPACE = 'elyra-code-viewer-extension'; + +interface IOpenCodeViewerArgs { + content: string; + label?: string; + mimeType?: string; + extension?: string; + widgetId?: string; +} + +/** + * The command IDs used by the code-viewer plugin. + */ +const CommandIDs = { + openViewer: 'elyra-code-viewer:open' +}; + +/** + * Initialization data for the code-viewer extension. + */ +const extension: JupyterFrontEndPlugin = { + id: ELYRA_CODE_VIEWER_NAMESPACE, + autoStart: true, + requires: [IEditorServices], + optional: [ILayoutRestorer], + activate: ( + app: JupyterFrontEnd, + editorServices: IEditorServices, + restorer: ILayoutRestorer + ) => { + console.log('Elyra - code-viewer extension is activated!'); + + const tracker = new WidgetTracker>({ + namespace: ELYRA_CODE_VIEWER_NAMESPACE + }); + + // Handle state restoration + if (restorer) { + void restorer.restore(tracker, { + command: CommandIDs.openViewer, + args: (widget) => ({ + content: widget.content.getContent(), + label: widget.content.title.label, + mimeType: widget.content.getMimeType(), + widgetId: widget.content.id + }), + name: (widget) => widget.content.id + }); + } + + const openCodeViewer = async ( + args: IOpenCodeViewerArgs + ): Promise => { + const func = editorServices.factoryService.newDocumentEditor; + const factory: CodeEditor.Factory = (options) => { + return func(options); + }; + + // Derive mimetype from extension + let mimetype = args.mimeType; + if (!mimetype && args.extension) { + mimetype = editorServices.mimeTypeService.getMimeTypeByFilePath( + `temp.${args.extension.replace(/\\.$/, '')}` + ); + } + + const widget = CodeViewerWidget.getCodeViewer({ + factory, + content: args.content, + mimeType: mimetype + }); + widget.title.label = args.label || 'Code Viewer'; + widget.title.caption = widget.title.label; + + // Get the fileType based on the mimetype to determine the icon + const fileType = toArray(app.docRegistry.fileTypes()).find((fileType) => { + return mimetype ? fileType.mimeTypes.includes(mimetype) : undefined; + }); + widget.title.icon = fileType?.icon ?? textEditorIcon; + + if (args.widgetId) { + widget.id = args.widgetId; + } + const main = new MainAreaWidget({ content: widget }); + await tracker.add(main); + app.shell.add(main, 'main'); + return widget; + }; + + app.commands.addCommand(CommandIDs.openViewer, { + execute: (args) => { + return openCodeViewer(args as unknown as IOpenCodeViewerArgs); + } + }); + } +}; + +export default extension; diff --git a/packages/code-viewer/style/index.css b/packages/code-viewer/style/index.css new file mode 100644 index 000000000..c89f75005 --- /dev/null +++ b/packages/code-viewer/style/index.css @@ -0,0 +1,15 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/packages/code-viewer/tsconfig.json b/packages/code-viewer/tsconfig.json new file mode 100644 index 000000000..84575cb5f --- /dev/null +++ b/packages/code-viewer/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src"] +} diff --git a/packages/r-editor/install.json b/packages/r-editor/install.json new file mode 100644 index 000000000..979cbb858 --- /dev/null +++ b/packages/r-editor/install.json @@ -0,0 +1,5 @@ +{ + "packageManager": "python", + "packageName": "elyra_r_editor_extension", + "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package elyra_r_editor_extension" +} diff --git a/packages/r-editor/package.json b/packages/r-editor/package.json new file mode 100644 index 000000000..6b2086a6a --- /dev/null +++ b/packages/r-editor/package.json @@ -0,0 +1,82 @@ +{ + "name": "@elyra/r-editor-extension", + "version": "0.0.0-dev", + "description": "JupyterLab extension - Run R scripts using a kernel runtime", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/elyra-ai/elyra", + "bugs": { + "url": "https://github.com/elyra-ai/elyra/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/elyra-ai/elyra/" + }, + "license": "Apache-2.0", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "files": [ + "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", + "src/**/*.{ts,tsx}", + "style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}" + ], + "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 ../../../../labextensions/elyra_r_editor_extension/labextension ../../../../labextensions/elyra_r_editor_extension/_version.py", + "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", + "cy:instrument": "npx nyc instrument --compact=false --in-place src/ src/", + "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 --passWithNoTests", + "watch": "run-p watch:src watch:labextension", + "watch:src": "tsc -w --sourceMap", + "watch:labextension": "jupyter labextension watch ." + }, + "dependencies": { + "@elyra/script-editor": "0.0.0-dev", + "@elyra/ui-components": "0.0.0-dev", + "@jupyterlab/application": "^4.2.5", + "@jupyterlab/apputils": "^4.2.5", + "@jupyterlab/codeeditor": "^4.2.5", + "@jupyterlab/docregistry": "^4.2.5", + "@jupyterlab/filebrowser": "^4.2.5", + "@jupyterlab/fileeditor": "^4.2.5", + "@jupyterlab/launcher": "^4.2.5", + "@jupyterlab/mainmenu": "^4.2.5", + "@jupyterlab/settingregistry": "^4.2.5", + "@jupyterlab/ui-components": "^4.2.5", + "@lumino/coreutils": "^2.1.2" + }, + "devDependencies": { + "@jupyterlab/builder": "^4.2.5", + "rimraf": "~5.0.5", + "typescript": "~5.1.6" + }, + "publishConfig": { + "access": "public" + }, + "jupyterlab": { + "extension": true, + "outputDir": "../../labextensions/elyra_r_editor_extension/labextension" + } +} diff --git a/packages/r-editor/setup.py b/packages/r-editor/setup.py new file mode 100644 index 000000000..aefdf20db --- /dev/null +++ b/packages/r-editor/setup.py @@ -0,0 +1 @@ +__import__("setuptools").setup() diff --git a/packages/r-editor/src/REditor.tsx b/packages/r-editor/src/REditor.tsx new file mode 100644 index 000000000..e5191b9a6 --- /dev/null +++ b/packages/r-editor/src/REditor.tsx @@ -0,0 +1,39 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ScriptEditor } from '@elyra/script-editor'; +import { rIcon } from '@elyra/ui-components'; + +import { DocumentRegistry, DocumentWidget } from '@jupyterlab/docregistry'; +import { FileEditor } from '@jupyterlab/fileeditor'; +import { LabIcon } from '@jupyterlab/ui-components'; + +export class REditor extends ScriptEditor { + /** + * Construct a new R Editor widget. + */ + constructor( + options: DocumentWidget.IOptions + ) { + super(options); + } + getLanguage(): string { + return 'R'; + } + + getIcon(): LabIcon { + return rIcon; + } +} diff --git a/packages/r-editor/src/index.ts b/packages/r-editor/src/index.ts new file mode 100644 index 000000000..0dcdc37fe --- /dev/null +++ b/packages/r-editor/src/index.ts @@ -0,0 +1,260 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ScriptEditorWidgetFactory, ScriptEditor } from '@elyra/script-editor'; +import { rIcon } from '@elyra/ui-components'; + +import { + JupyterFrontEnd, + JupyterFrontEndPlugin, + ILayoutRestorer +} from '@jupyterlab/application'; +import { WidgetTracker, ICommandPalette } from '@jupyterlab/apputils'; +import { CodeEditor, IEditorServices } from '@jupyterlab/codeeditor'; +import { + IDocumentWidget, + DocumentRegistry, + DocumentWidget +} from '@jupyterlab/docregistry'; +import { IFileBrowserFactory } from '@jupyterlab/filebrowser'; +import { FileEditor, IEditorTracker } from '@jupyterlab/fileeditor'; +import { ILauncher } from '@jupyterlab/launcher'; +import { IMainMenu } from '@jupyterlab/mainmenu'; +import { ISettingRegistry } from '@jupyterlab/settingregistry'; + +import { JSONObject } from '@lumino/coreutils'; + +import { REditor } from './REditor'; + +const R_FACTORY = 'R Editor'; +const R = 'r'; +const R_EDITOR_NAMESPACE = 'elyra-r-script-editor-extension'; + +const commandIDs = { + createNewREditor: 'script-editor:create-new-r-editor', + openDocManager: 'docmanager:open', + newDocManager: 'docmanager:new-untitled' +}; + +/** + * Initialization data for the r-editor-extension extension. + */ +const extension: JupyterFrontEndPlugin = { + id: R_EDITOR_NAMESPACE, + autoStart: true, + requires: [ + IEditorServices, + IEditorTracker, + ICommandPalette, + ISettingRegistry, + IFileBrowserFactory + ], + optional: [ILayoutRestorer, IMainMenu, ILauncher], + activate: ( + app: JupyterFrontEnd, + editorServices: IEditorServices, + editorTracker: IEditorTracker, + palette: ICommandPalette, + settingRegistry: ISettingRegistry, + browserFactory: IFileBrowserFactory, + restorer: ILayoutRestorer | null, + menu: IMainMenu | null, + launcher: ILauncher | null + ) => { + console.log('Elyra - r-editor extension is activated!'); + + const factory = new ScriptEditorWidgetFactory({ + editorServices, + factoryOptions: { + name: R_FACTORY, + fileTypes: [R], + defaultFor: [R] + }, + instanceCreator: ( + options: DocumentWidget.IOptions< + FileEditor, + DocumentRegistry.ICodeModel + > + ): ScriptEditor => new REditor(options) + }); + + app.docRegistry.addFileType({ + name: R, + displayName: 'R File', + extensions: ['.r'], + pattern: '.*\\.r$', + mimeTypes: ['text/x-rsrc'], + icon: rIcon + }); + + const { restored } = app; + + /** + * Track REditor widget on page refresh + */ + const tracker = new WidgetTracker({ + namespace: R_EDITOR_NAMESPACE + }); + + let config: CodeEditor.IOptions['config'] = {}; + + if (restorer) { + // Handle state restoration + void restorer.restore(tracker, { + command: commandIDs.openDocManager, + args: (widget) => ({ + path: widget.context.path, + factory: R_FACTORY + }), + name: (widget) => widget.context.path + }); + } + + /** + * Update the setting values. Adapted from fileeditor-extension. + */ + const updateSettings = (settings: ISettingRegistry.ISettings): void => { + config = { + ...(settings.get('editorConfig').composite as JSONObject) + }; + app.commands.notifyCommandChanged(); + }; + + /** + * Update the settings of the current tracker instances. Adapted from fileeditor-extension. + */ + const updateTracker = (): void => { + tracker.forEach((widget) => { + updateWidget(widget); + }); + }; + + /** + * Update the settings of a widget. Adapted from fileeditor-extension. + */ + const updateWidget = (widget: ScriptEditor): void => { + if (!editorTracker.has(widget)) { + (editorTracker as WidgetTracker>).add( + widget + ); + } + + const editor = widget.content.editor; + const editorConfigOptions = config || {}; + + Object.keys(editorConfigOptions).forEach((key) => { + const optionValue = editorConfigOptions[key]; + if (optionValue !== undefined) { + editor.setOption(key, optionValue); + } + }); + }; + + // Fetch the initial state of the settings. Adapted from fileeditor-extension. + Promise.all([ + settingRegistry.load('@jupyterlab/fileeditor-extension:plugin'), + restored + ]) + .then(([settings]) => { + updateSettings(settings); + updateTracker(); + settings.changed.connect(() => { + updateSettings(settings); + updateTracker(); + }); + }) + .catch((reason: Error) => { + console.error(reason.message); + updateTracker(); + }); + + app.docRegistry.addWidgetFactory(factory); + + factory.widgetCreated.connect((sender, widget) => { + void tracker.add(widget); + + // Notify the widget tracker if restore data needs to update + widget.context.pathChanged.connect(() => { + void tracker.save(widget); + }); + updateWidget(widget); + }); + + // Handle the settings of new widgets. Adapted from fileeditor-extension. + tracker.widgetAdded.connect((sender, widget) => { + updateWidget(widget); + }); + + /** + * Create new r editor from launcher and file menu + */ + + // Add a r launcher + if (launcher) { + launcher.add({ + command: commandIDs.createNewREditor, + category: 'Elyra', + rank: 5 + }); + } + + if (menu) { + // Add new r file creation to the file menu + menu.fileMenu.newMenu.addGroup( + [{ command: commandIDs.createNewREditor, args: { isMenu: true } }], + 93 + ); + } + + // Function to create a new untitled r file, given the current working directory + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- `app.commands.execute` returns a Promise + const createNew = (cwd: string): Promise => { + return app.commands + .execute(commandIDs.newDocManager, { + path: cwd, + type: 'file', + ext: '.r' + }) + .then((model) => { + return app.commands.execute(commandIDs.openDocManager, { + path: model.path, + factory: R_FACTORY + }); + }); + }; + + // Add a command to create new R editor + app.commands.addCommand(commandIDs.createNewREditor, { + label: (args) => (args['isPalette'] ? 'New R Editor' : 'R Editor'), + caption: 'Create a new R Editor', + icon: (args) => (args['isPalette'] ? undefined : rIcon), + execute: (args) => { + //Use file browser's current path instead of defaultBrowser.model.path + const fileBrowser = browserFactory.createFileBrowser('myFileBrowser'); + const cwd = args['cwd'] ? String(args['cwd']) : fileBrowser.model.path; + return createNew(cwd); + } + }); + + palette.addItem({ + command: commandIDs.createNewREditor, + args: { isPalette: true }, + category: 'Elyra' + }); + } +}; + +export default extension; diff --git a/packages/r-editor/style/index.css b/packages/r-editor/style/index.css new file mode 100644 index 000000000..c89f75005 --- /dev/null +++ b/packages/r-editor/style/index.css @@ -0,0 +1,15 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/packages/r-editor/tsconfig.json b/packages/r-editor/tsconfig.json new file mode 100644 index 000000000..84575cb5f --- /dev/null +++ b/packages/r-editor/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src"] +} diff --git a/packages/scala-editor/install.json b/packages/scala-editor/install.json new file mode 100644 index 000000000..c4d2b6a80 --- /dev/null +++ b/packages/scala-editor/install.json @@ -0,0 +1,5 @@ +{ + "packageManager": "python", + "packageName": "elyra_scala_editor_extension", + "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package elyra_scala_editor_extension" +} diff --git a/packages/scala-editor/package.json b/packages/scala-editor/package.json new file mode 100644 index 000000000..a4cbd53c5 --- /dev/null +++ b/packages/scala-editor/package.json @@ -0,0 +1,82 @@ +{ + "name": "@elyra/scala-editor-extension", + "version": "0.0.0-dev", + "description": "JupyterLab extension - Run scala code using a kernel runtime", + "keywords": [ + "jupyter", + "jupyterlab", + "jupyterlab-extension" + ], + "homepage": "https://github.com/elyra-ai/elyra", + "bugs": { + "url": "https://github.com/elyra-ai/elyra/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/elyra-ai/elyra/" + }, + "license": "Apache-2.0", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "style": "style/index.css", + "files": [ + "lib/**/*.{d.ts,eot,gif,html,jpg,js,js.map,json,png,svg,woff2,ttf}", + "src/**/*.{ts,tsx}", + "style/**/*.{css,eot,gif,html,jpg,json,png,svg,woff2,ttf}" + ], + "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 ../../../../labextensions/elyra_scala_editor_extension/labextension ../../../../labextensions/elyra_scala_editor_extension/_version.py", + "clean:all": "jlpm clean:lib && jlpm clean:labextension && jlpm clean:lintcache", + "cy:instrument": "npx nyc instrument --compact=false --in-place src/ src/", + "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 --passWithNoTests", + "watch": "run-p watch:src watch:labextension", + "watch:src": "tsc -w --sourceMap", + "watch:labextension": "jupyter labextension watch ." + }, + "dependencies": { + "@elyra/script-editor": "0.0.0-dev", + "@elyra/ui-components": "0.0.0-dev", + "@jupyterlab/application": "^4.2.5", + "@jupyterlab/apputils": "^4.2.5", + "@jupyterlab/codeeditor": "^4.2.5", + "@jupyterlab/docregistry": "^4.2.5", + "@jupyterlab/filebrowser": "^4.2.5", + "@jupyterlab/fileeditor": "^4.2.5", + "@jupyterlab/launcher": "^4.2.5", + "@jupyterlab/mainmenu": "^4.2.5", + "@jupyterlab/settingregistry": "^4.2.5", + "@jupyterlab/ui-components": "^4.2.5", + "@lumino/coreutils": "^2.1.2" + }, + "devDependencies": { + "@jupyterlab/builder": "^4.2.5", + "rimraf": "~5.0.5", + "typescript": "~5.1.6" + }, + "publishConfig": { + "access": "public" + }, + "jupyterlab": { + "extension": true, + "outputDir": "../../labextensions/elyra_scala_editor_extension/labextension" + } +} diff --git a/packages/scala-editor/setup.py b/packages/scala-editor/setup.py new file mode 100644 index 000000000..aefdf20db --- /dev/null +++ b/packages/scala-editor/setup.py @@ -0,0 +1 @@ +__import__("setuptools").setup() diff --git a/packages/scala-editor/src/ScalaEditor.tsx b/packages/scala-editor/src/ScalaEditor.tsx new file mode 100644 index 000000000..77d208d93 --- /dev/null +++ b/packages/scala-editor/src/ScalaEditor.tsx @@ -0,0 +1,39 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { ScriptEditor } from '@elyra/script-editor'; +import { scalaIcon } from '@elyra/ui-components'; + +import { DocumentRegistry, DocumentWidget } from '@jupyterlab/docregistry'; +import { FileEditor } from '@jupyterlab/fileeditor'; +import { LabIcon } from '@jupyterlab/ui-components'; + +export class ScalaEditor extends ScriptEditor { + /** + * Construct a new Scala Editor widget. + */ + constructor( + options: DocumentWidget.IOptions + ) { + super(options); + } + getLanguage(): string { + return 'scala'; + } + + getIcon(): LabIcon { + return scalaIcon; + } +} diff --git a/packages/scala-editor/src/index.ts b/packages/scala-editor/src/index.ts new file mode 100644 index 000000000..4b4197a6b --- /dev/null +++ b/packages/scala-editor/src/index.ts @@ -0,0 +1,264 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ScriptEditorWidgetFactory, ScriptEditor } from '@elyra/script-editor'; +import { scalaIcon } from '@elyra/ui-components'; + +import { + JupyterFrontEnd, + JupyterFrontEndPlugin, + ILayoutRestorer +} from '@jupyterlab/application'; +import { WidgetTracker, ICommandPalette } from '@jupyterlab/apputils'; +import { CodeEditor, IEditorServices } from '@jupyterlab/codeeditor'; +import { + IDocumentWidget, + DocumentRegistry, + DocumentWidget +} from '@jupyterlab/docregistry'; +import { IFileBrowserFactory } from '@jupyterlab/filebrowser'; +import { FileEditor, IEditorTracker } from '@jupyterlab/fileeditor'; +import { ILauncher } from '@jupyterlab/launcher'; +import { IMainMenu } from '@jupyterlab/mainmenu'; +import { ISettingRegistry } from '@jupyterlab/settingregistry'; + +import { JSONObject } from '@lumino/coreutils'; + +import { ScalaEditor } from './ScalaEditor'; + +const SCALA_FACTORY = 'Scala Editor'; +const SCALA = 'scala'; +const SCALA_EDITOR_NAMESPACE = 'elyra-scala-editor-extension'; + +const commandIDs = { + createNewScalaEditor: 'script-editor:create-new-scala-editor', + openDocManager: 'docmanager:open', + newDocManager: 'docmanager:new-untitled' +}; + +/** + * Initialization data for the scala-editor-extension extension. + */ +const extension: JupyterFrontEndPlugin = { + id: SCALA_EDITOR_NAMESPACE, + autoStart: true, + requires: [ + IEditorServices, + IEditorTracker, + ICommandPalette, + ISettingRegistry, + IFileBrowserFactory + ], + optional: [ILayoutRestorer, IMainMenu, ILauncher], + activate: ( + app: JupyterFrontEnd, + editorServices: IEditorServices, + editorTracker: IEditorTracker, + palette: ICommandPalette, + settingRegistry: ISettingRegistry, + browserFactory: IFileBrowserFactory, + restorer: ILayoutRestorer | null, + menu: IMainMenu | null, + launcher: ILauncher | null + ) => { + console.log('Elyra - scala-editor extension is activated!'); + + const factory = new ScriptEditorWidgetFactory({ + editorServices, + factoryOptions: { + name: SCALA_FACTORY, + fileTypes: [SCALA], + defaultFor: [SCALA] + }, + instanceCreator: ( + options: DocumentWidget.IOptions< + FileEditor, + DocumentRegistry.ICodeModel + > + ): ScriptEditor => new ScalaEditor(options) + }); + + app.docRegistry.addFileType({ + name: SCALA, + displayName: 'Scala File', + extensions: ['.scala'], + pattern: '.*\\.scala$', + mimeTypes: ['text/x-scala'], + icon: scalaIcon + }); + + const { restored } = app; + + /** + * Track ScalaEditor widget on page refresh + */ + const tracker = new WidgetTracker({ + namespace: SCALA_EDITOR_NAMESPACE + }); + + //no default config so we set it to an empty object + let config: CodeEditor.IOptions['config'] = {}; + + if (restorer) { + // Handle state restoration + void restorer.restore(tracker, { + command: commandIDs.openDocManager, + args: (widget) => ({ + path: widget.context.path, + factory: SCALA_FACTORY + }), + name: (widget) => widget.context.path + }); + } + + /** + * Update the setting values. Adapted from fileeditor-extension. + */ + + //replaced default Config + const updateSettings = (settings: ISettingRegistry.ISettings): void => { + config = { + ...(settings.get('editorConfig').composite as JSONObject) + }; + app.commands.notifyCommandChanged(); + }; + + /** + * Update the settings of the current tracker instances. Adapted from fileeditor-extension. + */ + const updateTracker = (): void => { + tracker.forEach((widget) => { + updateWidget(widget); + }); + }; + + /** + * Update the settings of a widget. Adapted from fileeditor-extension. + */ + const updateWidget = (widget: ScriptEditor): void => { + if (!editorTracker.has(widget)) { + (editorTracker as WidgetTracker>).add( + widget + ); + } + + const editor = widget.content.editor; + const editorConfigOptions = config || {}; + + Object.keys(editorConfigOptions).forEach((key) => { + const optionValue = editorConfigOptions[key]; + if (optionValue !== undefined) { + editor.setOption(key, optionValue); + } + }); + }; + + // Fetch the initial state of the settings. Adapted from fileeditor-extension. + Promise.all([ + settingRegistry.load('@jupyterlab/fileeditor-extension:plugin'), + restored + ]) + .then(([settings]) => { + updateSettings(settings); + updateTracker(); + settings.changed.connect(() => { + updateSettings(settings); + updateTracker(); + }); + }) + .catch((reason: Error) => { + console.error(reason.message); + updateTracker(); + }); + + app.docRegistry.addWidgetFactory(factory); + + factory.widgetCreated.connect((sender, widget) => { + void tracker.add(widget); + + // Notify the widget tracker if restore data needs to update + widget.context.pathChanged.connect(() => { + void tracker.save(widget); + }); + updateWidget(widget); + }); + + // Handle the settings of new widgets. Adapted from fileeditor-extension. + tracker.widgetAdded.connect((sender, widget) => { + updateWidget(widget); + }); + + /** + * Create new scala editor from launcher and file menu + */ + + // Add an scala launcher + if (launcher) { + launcher.add({ + command: commandIDs.createNewScalaEditor, + category: 'Elyra', + rank: 4 + }); + } + + if (menu) { + // Add new scala editor creation to the file menu + menu.fileMenu.newMenu.addGroup( + [{ command: commandIDs.createNewScalaEditor, args: { isMenu: true } }], + 92 + ); + } + + // Function to create a new untitled scala file, given the current working directory + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- `app.commands.execute` returns a Promise + const createNew = (cwd: string): Promise => { + return app.commands + .execute(commandIDs.newDocManager, { + path: cwd, + type: 'file', + ext: '.scala' + }) + .then((model) => { + return app.commands.execute(commandIDs.openDocManager, { + path: model.path, + factory: SCALA_FACTORY + }); + }); + }; + + // Add a command to create new scala editor + app.commands.addCommand(commandIDs.createNewScalaEditor, { + label: (args) => + args['isPalette'] ? 'New Scala Editor' : 'Scala Editor', + caption: 'Create a new Scala Editor', + icon: (args) => (args['isPalette'] ? undefined : scalaIcon), + execute: (args) => { + //Use file browser's current path instead of defaultBrowser.model.path + const fileBrowser = browserFactory.createFileBrowser('myFileBrowser'); + const cwd = args['cwd'] ? String(args['cwd']) : fileBrowser.model.path; + return createNew(cwd); + } + }); + + palette.addItem({ + command: commandIDs.createNewScalaEditor, + args: { isPalette: true }, + category: 'Elyra' + }); + } +}; + +export default extension; diff --git a/packages/scala-editor/style/index.css b/packages/scala-editor/style/index.css new file mode 100644 index 000000000..c89f75005 --- /dev/null +++ b/packages/scala-editor/style/index.css @@ -0,0 +1,15 @@ +/* + * Copyright 2018-2025 Elyra Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ diff --git a/packages/scala-editor/tsconfig.json b/packages/scala-editor/tsconfig.json new file mode 100644 index 000000000..84575cb5f --- /dev/null +++ b/packages/scala-editor/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib" + }, + "include": ["src"] +} diff --git a/pyproject.toml b/pyproject.toml index 484e8f444..0dce43b96 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -154,10 +154,16 @@ ignore-vcs = true # Include data files with dist [tool.hatch.build.targets.wheel.shared-data] "labextensions/elyra_code_snippet_extension/labextension" = "share/jupyter/labextensions/@elyra/code-snippet-extension" +# This extension is not part of ODH distribution +# "labextensions/elyra_code_viewer_extension/labextension" = "share/jupyter/labextensions/@elyra/code-viewer-extension" "labextensions/elyra_metadata_common/labextension" = "share/jupyter/labextensions/@elyra/metadata-common" "labextensions/elyra_metadata_extension/labextension" = "share/jupyter/labextensions/@elyra/metadata-extension" "labextensions/elyra_pipeline_editor_extension/labextension" = "share/jupyter/labextensions/@elyra/pipeline-editor-extension" "labextensions/elyra_python_editor_extension/labextension" = "share/jupyter/labextensions/@elyra/python-editor-extension" +# This extension is not part of ODH distribution +# "labextensions/elyra_r_editor_extension/labextension" = "share/jupyter/labextensions/@elyra/r-editor-extension" +# This extension is not part of ODH distribution +# "labextensions/elyra_scala_editor_extension/labextension" = "share/jupyter/labextensions/@elyra/scala-editor-extension" "labextensions/elyra_script_debugger_extension/labextension" = "share/jupyter/labextensions/@elyra/script-debugger-extension" "labextensions/elyra_script_editor/labextension" = "share/jupyter/labextensions/@elyra/script-editor" "labextensions/elyra_services/labextension" = "share/jupyter/labextensions/@elyra/services" @@ -175,10 +181,16 @@ ignore-vcs = true [tool.hatch.build.targets.sdist] artifacts = [ "labextensions/elyra_code_snippet_extension/labextension", + # This extension is not part of ODH distribution + # "labextensions/elyra_code_viewer_extension/labextension", "labextensions/elyra_metadata_common/labextension", "labextensions/elyra_metadata_extension/labextension", "labextensions/elyra_pipeline_editor_extension/labextension", "labextensions/elyra_python_editor_extension/labextension", + # This extension is not part of ODH distribution + # "labextensions/elyra_r_editor_extension/labextension", + # This extension is not part of ODH distribution + # "labextensions/elyra_scala_editor_extension/labextension", "labextensions/elyra_script_debugger_extension/labextension", "labextensions/elyra_script_editor/labextension", "labextensions/elyra_services/labextension", @@ -207,6 +219,10 @@ exclude = [ "*.sh", "docs", "build/release", + # Code Viewer, R editor and Scala editor extensions are not part of ODH distribution + "labextensions/elyra_code_viewer_extension", + "labextensions/elyra_r_editor_extension", + "labextensions/elyra_scala_editor_extension", ] # Move flake8 configuration from setup.cfg. Use pflake8 instead of flake8. diff --git a/yarn.lock b/yarn.lock index 001dbbcb9..52089d0e2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3199,6 +3199,22 @@ __metadata: languageName: unknown linkType: soft +"@elyra/code-viewer-extension@workspace:packages/code-viewer": + version: 0.0.0-use.local + resolution: "@elyra/code-viewer-extension@workspace:packages/code-viewer" + dependencies: + "@jupyterlab/application": ^4.2.5 + "@jupyterlab/apputils": ^4.2.5 + "@jupyterlab/builder": ^4.2.5 + "@jupyterlab/codeeditor": ^4.2.5 + "@jupyterlab/ui-components": ^4.2.5 + "@lumino/algorithm": "*" + "@lumino/widgets": ^2.3.1 + rimraf: ~5.0.5 + typescript: ~5.1.6 + languageName: unknown + linkType: soft + "@elyra/metadata-common@0.0.0-dev, @elyra/metadata-common@workspace:packages/metadata-common": version: 0.0.0-use.local resolution: "@elyra/metadata-common@workspace:packages/metadata-common" @@ -3364,6 +3380,52 @@ __metadata: languageName: unknown linkType: soft +"@elyra/r-editor-extension@workspace:packages/r-editor": + version: 0.0.0-use.local + resolution: "@elyra/r-editor-extension@workspace:packages/r-editor" + dependencies: + "@elyra/script-editor": 0.0.0-dev + "@elyra/ui-components": 0.0.0-dev + "@jupyterlab/application": ^4.2.5 + "@jupyterlab/apputils": ^4.2.5 + "@jupyterlab/builder": ^4.2.5 + "@jupyterlab/codeeditor": ^4.2.5 + "@jupyterlab/docregistry": ^4.2.5 + "@jupyterlab/filebrowser": ^4.2.5 + "@jupyterlab/fileeditor": ^4.2.5 + "@jupyterlab/launcher": ^4.2.5 + "@jupyterlab/mainmenu": ^4.2.5 + "@jupyterlab/settingregistry": ^4.2.5 + "@jupyterlab/ui-components": ^4.2.5 + "@lumino/coreutils": ^2.1.2 + rimraf: ~5.0.5 + typescript: ~5.1.6 + languageName: unknown + linkType: soft + +"@elyra/scala-editor-extension@workspace:packages/scala-editor": + version: 0.0.0-use.local + resolution: "@elyra/scala-editor-extension@workspace:packages/scala-editor" + dependencies: + "@elyra/script-editor": 0.0.0-dev + "@elyra/ui-components": 0.0.0-dev + "@jupyterlab/application": ^4.2.5 + "@jupyterlab/apputils": ^4.2.5 + "@jupyterlab/builder": ^4.2.5 + "@jupyterlab/codeeditor": ^4.2.5 + "@jupyterlab/docregistry": ^4.2.5 + "@jupyterlab/filebrowser": ^4.2.5 + "@jupyterlab/fileeditor": ^4.2.5 + "@jupyterlab/launcher": ^4.2.5 + "@jupyterlab/mainmenu": ^4.2.5 + "@jupyterlab/settingregistry": ^4.2.5 + "@jupyterlab/ui-components": ^4.2.5 + "@lumino/coreutils": ^2.1.2 + rimraf: ~5.0.5 + typescript: ~5.1.6 + languageName: unknown + linkType: soft + "@elyra/script-debugger-extension@workspace:packages/script-debugger": version: 0.0.0-use.local resolution: "@elyra/script-debugger-extension@workspace:packages/script-debugger"