Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Integrate theme cookiecutter #196

Merged
merged 2 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 68 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ jobs:
- name: Create server extension pip install
run: |
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['has_server_extension']='y'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; cookiecutter('.', extra_context=d, no_input=True)"
cd myextension
pip install .
pip install jupyterlab
Expand All @@ -223,7 +223,7 @@ jobs:
- name: Create server extension pip develop
run: |
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['has_server_extension']='y'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; cookiecutter('.', extra_context=d, no_input=True)"
cd myextension
pip install -e .
pip install jupyterlab
Expand Down Expand Up @@ -255,7 +255,7 @@ jobs:
- name: Install server extension from a tarball
run: |
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['has_server_extension']='y'; cookiecutter('.', extra_context=d, no_input=True)"
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='server'; cookiecutter('.', extra_context=d, no_input=True)"
cd myextension
pip install --pre jupyterlab
jupyter lab clean --all
Expand Down Expand Up @@ -322,3 +322,68 @@ jobs:
jupyter server extension list
jupyter server extension list 2>&1 | grep -ie "myextension.*OK"
python -m jupyterlab.browser_check --no-chrome-test

theme:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install node
uses: actions/setup-node@v1
with:
node-version: "12.x"
- name: Install Python
uses: actions/setup-python@v2
with:
python-version: "3.7"
architecture: "x64"

- name: Setup pip cache
uses: actions/cache@v2
with:
path: ~/.cache/pip
key: pip-3.7-${{ hashFiles('package.json') }}
restore-keys: |
pip-3.7-
pip-

- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"

- name: Setup yarn cache
uses: actions/cache@v2
id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
yarn-

- name: Install dependencies
run: |
python -m pip install cookiecutter check-manifest build

- name: Create pure frontend extension
run: |
set -eux
# Trick to use custom parameters
python -c "from cookiecutter.main import cookiecutter; import json; f=open('cookiecutter.json'); d=json.load(f); f.close(); d['kind']='theme'; cookiecutter('.', extra_context=d, no_input=True)"
pushd mytheme
pip install jupyterlab
jlpm install
pip install -e .
jupyter labextension develop . --overwrite
jupyter labextension list
jupyter labextension list 2>&1 | grep -ie "mytheme.*OK"
python -m jupyterlab.browser_check

jupyter labextension uninstall mytheme
pip uninstall -y mytheme jupyterlab

git init && git add .
check-manifest -v

popd
rm -rf mytheme
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
![Github Actions Status](https://github.com/jupyterlab/extension-cookiecutter-ts/workflows/CI/badge.svg)

A [cookiecutter](https://github.com/audreyr/cookiecutter) template for creating
a JupyterLab extension using TypeScript with optionally a server extension.
a JupyterLab extension. Three kinds of extension are supported:
- _frontend_: Pure frontend extension written in TypeScript.
- _server_: Extension with frontend (in TypeScript) and backend (in Python) parts.
- _theme_: Theme for JupyterLab (using CSS variables).

> See also [extension-cookiecutter-js](https://github.com/jupyterlab/extension-cookiecutter-js)
for an extension in CommonJS.
Expand Down
4 changes: 2 additions & 2 deletions cookiecutter.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"kind": ["frontend", "server", "theme"],
"author_name": "",
"author_email": "",
"labextension_name": "myextension",
"labextension_name": "{% if cookiecutter.kind == 'theme' %}mytheme{% else %}myextension{% endif %}",
"python_name": "{{ cookiecutter.labextension_name | replace('-', '_') }}",
"project_short_description": "A JupyterLab extension.",
"has_settings": "n",
"has_server_extension": "n",
"has_binder": "n",
"repository": "https://github.com/github_username/{{ cookiecutter.labextension_name }}",
"_copy_without_render": [
Expand Down
11 changes: 10 additions & 1 deletion hooks/post_gen_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ def remove_path(path: str) -> None:
if not "{{ cookiecutter.has_settings }}".lower().startswith("y"):
remove_path(PROJECT_DIRECTORY / "schema")

if not "{{ cookiecutter.has_server_extension }}".lower().startswith("y"):
if "{{ cookiecutter.kind }}".lower() == "theme":
for f in (
"style/index.js",
"style/base.css"
):
remove_path(PROJECT_DIRECTORY / f)
else:
remove_path(PROJECT_DIRECTORY / "style/variable.css")

if not "{{ cookiecutter.kind }}".lower() == "server":
for f in (
"{{ cookiecutter.python_name }}/handlers.py",
"src/handler.ts",
Expand Down
2 changes: 1 addition & 1 deletion {{cookiecutter.python_name}}/.github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
jlpm
jlpm run eslint:check
python -m pip install .
{% if cookiecutter.has_server_extension.lower().startswith('y') %}
{% if cookiecutter.kind.lower() == 'server' %}
jupyter server extension list 2>&1 | grep -ie "{{ cookiecutter.python_name }}.*OK"
{% endif %}
jupyter labextension list 2>&1 | grep -ie "{{ cookiecutter.labextension_name }}.*OK"
Expand Down
2 changes: 1 addition & 1 deletion {{cookiecutter.python_name}}/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
include LICENSE
include *.md
include pyproject.toml{% if cookiecutter.has_server_extension == "y" %}
include pyproject.toml{% if cookiecutter.kind == "server" %}
recursive-include jupyter-config *.json{% endif %}

include package.json
Expand Down
8 changes: 4 additions & 4 deletions {{cookiecutter.python_name}}/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

{{ cookiecutter.project_short_description }}

{% if cookiecutter.has_server_extension.lower().startswith('y') %}
{% if cookiecutter.kind.lower() == 'server' %}
This extension is composed of a Python package named `{{ cookiecutter.python_name }}`
for the server extension and a NPM package named `{{ cookiecutter.labextension_name }}`
for the frontend extension.
Expand All @@ -33,7 +33,7 @@ To remove the extension, execute:
pip uninstall {{ cookiecutter.python_name }}
```

{% if cookiecutter.has_server_extension.lower().startswith('y') %}
{% if cookiecutter.kind.lower() == 'server' %}
## Troubleshoot

If you are seeing the frontend extension, but it is not working, check
Expand Down Expand Up @@ -67,7 +67,7 @@ The `jlpm` command is JupyterLab's pinned version of
# Install package in development mode
pip install -e .
# Link your development version of the extension with JupyterLab
jupyter labextension develop . --overwrite{% if cookiecutter.has_server_extension.lower().startswith('y') %}
jupyter labextension develop . --overwrite{% if cookiecutter.kind.lower() == 'server' %}
# Server extension must be manually installed in develop mode
jupyter server extension enable {{ cookiecutter.python_name }}{% endif %}
# Rebuild extension Typescript source after making changes
Expand All @@ -93,7 +93,7 @@ jupyter lab build --minimize=False

### Development uninstall

```bash{% if cookiecutter.has_server_extension.lower().startswith('y') %}
```bash{% if cookiecutter.kind.lower() == 'server' %}
# Server extension must be manually disabled in develop mode
jupyter server extension disable {{ cookiecutter.python_name }}{% endif %}
pip uninstall {{ cookiecutter.python_name }}
Expand Down
20 changes: 11 additions & 9 deletions {{cookiecutter.python_name}}/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,9 @@
"watch:labextension": "jupyter labextension watch ."
},
"dependencies": {
"@jupyterlab/application": "^3.1.0"{% if cookiecutter.has_settings.lower().startswith('y') %},
"@jupyterlab/settingregistry": "^3.1.0"{% endif %}{% if cookiecutter.has_server_extension.lower().startswith('y') %},
"@jupyterlab/application": "^3.1.0"{% if cookiecutter.kind.lower() == 'theme' %},
"@jupyterlab/apputils": "^3.1.0"{% endif %}{% if cookiecutter.has_settings.lower().startswith('y') %},
"@jupyterlab/settingregistry": "^3.1.0"{% endif %}{% if cookiecutter.kind.lower() == 'server' %},
"@jupyterlab/coreutils": "^5.1.0",
"@jupyterlab/services": "^6.1.0"
{% endif %}
Expand All @@ -58,22 +59,22 @@
"@typescript-eslint/parser": "^4.8.1",
"eslint": "^7.14.0",
"eslint-config-prettier": "^6.15.0",
"eslint-plugin-prettier": "^3.1.4", {% if cookiecutter.has_server_extension.lower().startswith('y') %}
"mkdirp": "^1.0.3", {% endif %}
"eslint-plugin-prettier": "^3.1.4",{% if cookiecutter.kind.lower() == 'server' %}
"mkdirp": "^1.0.3",{% endif %}
"npm-run-all": "^4.1.5",
"prettier": "^2.1.1",
"rimraf": "^3.0.2",
"typescript": "~4.1.3"
},
"sideEffects": [
"style/*.css",
"style/*.css"{% if cookiecutter.kind.lower() != 'theme' %},
"style/index.js"
],
"styleModule": "style/index.js",
"styleModule": "style/index.js",{% else %}],{% endif %}
"publishConfig": {
"access": "public"
},
"jupyterlab": { {% if cookiecutter.has_server_extension.lower().startswith('y') %}
"jupyterlab": { {% if cookiecutter.kind.lower() == 'server' %}
"discovery": {
"server": {
"managers": [
Expand All @@ -83,10 +84,11 @@
"name": "{{ cookiecutter.python_name }}"
}
}
}, {% endif %}
},{% endif %}
"extension": true,
"outputDir": "{{cookiecutter.python_name}}/labextension"{% if cookiecutter.has_settings.lower().startswith('y') %},
"schemaDir": "schema"{% endif %}
"schemaDir": "schema"{% endif %}{% if cookiecutter.kind.lower() == 'theme' %},
"themePath": "style/index.css"{% endif %}
},
"jupyter-releaser": {
"hooks": {
Expand Down
8 changes: 4 additions & 4 deletions {{cookiecutter.python_name}}/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@

# Representative files that should exist after a successful build
ensured_targets = [
str(lab_path / "package.json"),
str(lab_path / "static/style.js")
str(lab_path / "package.json"){% if cookiecutter.kind.lower() != "theme" %},
str(lab_path / "static/style.js"){% endif %}
]

labext_name = "{{ cookiecutter.labextension_name }}"

data_files_spec = [
("share/jupyter/labextensions/%s" % labext_name, str(lab_path.relative_to(HERE)), "**"),
("share/jupyter/labextensions/%s" % labext_name, str("."), "install.json"),{% if cookiecutter.has_server_extension == "y" %}
("share/jupyter/labextensions/%s" % labext_name, str("."), "install.json"),{% if cookiecutter.kind.lower() == "server" %}
("etc/jupyter/jupyter_server_config.d",
"jupyter-config/server-config", "{{ cookiecutter.python_name }}.json"),
# For backward compatibility with notebook server
Expand Down Expand Up @@ -55,7 +55,7 @@
long_description=long_description,
long_description_content_type="text/markdown",
packages=setuptools.find_packages(),
install_requires=[{% if cookiecutter.has_server_extension == "y" %}
install_requires=[{% if cookiecutter.kind.lower() == "server" %}
"jupyter_server>=1.6,<2"
{% endif %}],
zip_safe=False,
Expand Down
23 changes: 17 additions & 6 deletions {{cookiecutter.python_name}}/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
JupyterFrontEnd,
JupyterFrontEndPlugin
} from '@jupyterlab/application';{% if cookiecutter.has_settings.lower().startswith('y') %}
} from '@jupyterlab/application';{% if cookiecutter.kind.lower() == 'theme' %}

import { ISettingRegistry } from '@jupyterlab/settingregistry';{% endif %}{% if cookiecutter.has_server_extension.lower().startswith('y') %}
import { IThemeManager } from '@jupyterlab/apputils';{% endif %}{% if cookiecutter.has_settings.lower().startswith('y') %}

import { ISettingRegistry } from '@jupyterlab/settingregistry';{% endif %}{% if cookiecutter.kind.lower() == 'server' %}

import { requestAPI } from './handler';{% endif %}

Expand All @@ -12,10 +14,19 @@ import { requestAPI } from './handler';{% endif %}
*/
const plugin: JupyterFrontEndPlugin<void> = {
id: '{{ cookiecutter.labextension_name }}:plugin',
autoStart: true,{% if cookiecutter.has_settings.lower().startswith('y') %}
autoStart: true,{% if cookiecutter.kind.lower() == 'theme' %}
requires: [IThemeManager],{% endif %}{% if cookiecutter.has_settings.lower().startswith('y') %}
optional: [ISettingRegistry],{% endif %}
activate: (app: JupyterFrontEnd{% if cookiecutter.has_settings.lower().startswith('y') %}, settingRegistry: ISettingRegistry | null{% endif %}) => {
console.log('JupyterLab extension {{ cookiecutter.labextension_name }} is activated!');{% if cookiecutter.has_settings.lower().startswith('y') %}
activate: (app: JupyterFrontEnd{% if cookiecutter.kind.lower() == 'theme' %}, manager: IThemeManager{% endif %}{% if cookiecutter.has_settings.lower().startswith('y') %}, settingRegistry: ISettingRegistry | null{% endif %}) => {
console.log('JupyterLab extension {{ cookiecutter.labextension_name }} is activated!');{% if cookiecutter.kind.lower() == 'theme' %}
const style = '{{ cookiecutter.labextension_name }}/index.css';

manager.register({
name: '{{ cookiecutter.labextension_name }}',
isLight: true,
load: () => manager.loadCSS(style),
unload: () => Promise.resolve(undefined)
});{% endif %}{% if cookiecutter.has_settings.lower().startswith('y') %}

if (settingRegistry) {
settingRegistry
Expand All @@ -26,7 +37,7 @@ const plugin: JupyterFrontEndPlugin<void> = {
.catch(reason => {
console.error('Failed to load settings for {{ cookiecutter.labextension_name }}.', reason);
});
}{% endif %}{% if cookiecutter.has_server_extension.lower().startswith('y') %}
}{% endif %}{% if cookiecutter.kind.lower() == 'server' %}

requestAPI<any>('get_example')
.then(data => {
Expand Down
13 changes: 13 additions & 0 deletions {{cookiecutter.python_name}}/style/index.css
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
{% if cookiecutter.kind.lower() == 'theme' %}@import './variables.css';

/* Set the default typography for monospace elements */
tt,
code,
kbd,
samp,
pre {
font-family: var(--jp-code-font-family);
font-size: var(--jp-code-font-size);
line-height: var(--jp-code-line-height);
}{% else %}
@import url('base.css');
{% endif %}
Loading