Skip to content

Commit

Permalink
Merge pull request #196 from fcollonval/ft/merge-theme-tpl
Browse files Browse the repository at this point in the history
Integrate theme cookiecutter
  • Loading branch information
jtpio committed Jan 21, 2022
2 parents 5a8b64f + 219475b commit be2dd2e
Show file tree
Hide file tree
Showing 13 changed files with 514 additions and 36 deletions.
71 changes: 68 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,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 @@ -145,7 +145,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 @@ -177,7 +177,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 jupyterlab
jupyter lab clean --all
Expand Down Expand Up @@ -247,3 +247,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 }}"
}
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 @@ -25,7 +25,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

0 comments on commit be2dd2e

Please sign in to comment.