Skip to content

Commit 3cf8cf6

Browse files
committed
prepare template
1 parent f24ea7b commit 3cf8cf6

File tree

8 files changed

+247
-36
lines changed

8 files changed

+247
-36
lines changed

.github/workflows/ci.yml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
tags:
7+
- 'v*.*.*'
8+
pull_request:
9+
branches: [ master ]
10+
11+
jobs:
12+
build:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- uses: actions/checkout@v2
16+
- name: Set up Python
17+
uses: actions/setup-python@v2
18+
with:
19+
python-version: 3.9
20+
- name: Install dependencies
21+
run: |
22+
python -m pip install --upgrade pip
23+
python -m pip install -r ./requirements.txt
24+
- name: Build
25+
run: |
26+
python ./build.py
27+
- id: check-tag
28+
run: |
29+
if [[ "${{ github.event.ref }}" =~ ^refs/tags/v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
30+
echo ::set-output name=match::true
31+
fi
32+
33+
- name: Release
34+
if: ${{ github.event_name == 'push' && steps.check-tag.outputs.match == 'true' }}
35+
uses: softprops/action-gh-release@v1
36+
with:
37+
token: ${{ secrets.GITHUB_TOKEN }}
38+
body: |
39+
Auto-generated release
40+
prerelease: ${{ contains(github.event.ref, '-beta') }}
41+
fail_on_unmatched_files: true
42+
files: *.xdc

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
__target__
22
*.xdc
3-
*~
3+
*~
4+
build/

README.md

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,49 @@
11
# Webxdc development with Python
22

3-
This is an example project to show how to develop webxdc apps with Python.
3+
This is a project template to develop Webxdc apps with the Python programming language!
44

55
## Requirements
66

7-
This project depends on:
8-
- [Python](https://python.org/)
9-
- [Transcrypt](https://www.transcrypt.org/)
7+
To transpile Python code into JavaScript, [Transcrypt](https://www.transcrypt.org/) is
8+
used, to install it and also other tools to minify/optimize the final webxdc, run:
109

11-
Check their documentation to know how to install them.
10+
```sh
11+
python -m pip install -r ./requirements.txt
12+
```
1213

1314
## Building
1415

15-
To convert your Python code to JavaScript, execute:
16+
To package your Webxdc:
1617

1718
```sh
18-
python -m transcrypt app.py
19+
python ./build.py
1920
```
2021

22+
The output is a file with `.xdc` extension.
23+
2124
## Testing
2225

23-
After building, you are ready to test the app. The project comes with an
26+
After building, you can test the app. The project comes with an
2427
small simulator that allows to test your app in your browser, to do it
25-
just go to the root of the project and run this command:
28+
just go to the root of the project and run:
2629

2730
```sh
2831
python -m http.server
2932
```
3033

3134
then open in your browser the URL that is displayed in the shell.
3235

33-
## Packaging
36+
## Releasing
3437

35-
To use the app in Delta Chat, you need to package it in a `.xdc` archive,
36-
the `create-xdc.sh` script helps you to do that:
38+
To automatically build and create a new GitHub release with your `.xdc` file:
3739

38-
```sh
39-
./create-xdc.sh
4040
```
41+
git tag v1.0.1
42+
git push origin v1.0.1
43+
```
44+
45+
## Try it now!
46+
47+
### GitHub Template
48+
49+
[Create a repo from this template on GitHub](https://github.com/webxdc/webxdc-python/generate).

build.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
#!/usr/bin/env python3
2+
import argparse
3+
import os
4+
import shutil
5+
import sys
6+
7+
import htmlmin
8+
import lesscpy
9+
from jsmin import jsmin
10+
11+
12+
def get_parser() -> argparse.ArgumentParser:
13+
parser = argparse.ArgumentParser(
14+
description="App Builder",
15+
)
16+
parser.add_argument(
17+
"-n",
18+
"--name",
19+
default=os.path.basename(os.path.dirname(os.path.abspath(__file__))),
20+
help="App package's base name",
21+
)
22+
parser.add_argument(
23+
"-d",
24+
"--debug",
25+
action="store_true",
26+
help="Bundle webxdc package with debugging tools included",
27+
)
28+
29+
return parser
30+
31+
32+
def size_fmt(num: float) -> str:
33+
suffix = "B"
34+
for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]:
35+
if abs(num) < 1024.0:
36+
return "%3.1f%s%s" % (num, unit, suffix) # noqa
37+
num /= 1024.0
38+
return "%.1f%s%s" % (num, "Yi", suffix) # noqa
39+
40+
41+
def minify_js() -> None:
42+
if os.path.exists("js"):
43+
os.makedirs("build/js")
44+
45+
bundle = False
46+
with open("index.html", encoding="utf-8") as src:
47+
if "js/bundle.js" in src.read():
48+
bundle = True
49+
50+
if bundle:
51+
with open(f"build/js/bundle.js", "w", encoding="utf-8") as dest:
52+
for filename in sorted(os.listdir("js")):
53+
if not filename.endswith(".js"):
54+
continue
55+
with open(f"js/{filename}", encoding="utf-8") as src:
56+
if filename.endswith(".min.js"):
57+
text = src.read()
58+
else:
59+
text = jsmin(src.read())
60+
dest.write(text)
61+
if not text.endswith(";"):
62+
dest.write(";")
63+
else:
64+
files.extend(
65+
[f"js/{name}" for name in os.listdir("js") if name.endswith(".min.js")]
66+
)
67+
for filename in os.listdir("js"):
68+
if not filename.endswith(".min.js"):
69+
with open(f"js/{filename}", encoding="utf-8") as src:
70+
with open(
71+
f"build/js/{filename}", "w", encoding="utf-8"
72+
) as dest:
73+
dest.write(jsmin(src.read()))
74+
75+
76+
def minify_css() -> None:
77+
if os.path.exists("css"):
78+
os.makedirs("build/css")
79+
80+
bundle = False
81+
with open("index.html", encoding="utf-8") as src:
82+
if "css/bundle.css" in src.read():
83+
bundle = True
84+
85+
if bundle:
86+
with open(f"build/css/bundle.css", "w", encoding="utf-8") as dest:
87+
for filename in sorted(os.listdir("css")):
88+
if not filename.endswith(".css"):
89+
continue
90+
with open(f"css/{filename}", encoding="utf-8") as src:
91+
if filename.endswith(".min.css"):
92+
dest.write(src.read())
93+
else:
94+
dest.write(lesscpy.compile(src, minify=True, xminify=True))
95+
else:
96+
files.extend(
97+
[
98+
f"css/{name}"
99+
for name in os.listdir("css")
100+
if name.endswith(".min.css")
101+
]
102+
)
103+
for filename in os.listdir("css"):
104+
if not filename.endswith(".min.css"):
105+
with open(f"css/{filename}", encoding="utf-8") as src:
106+
with open(
107+
f"build/css/{filename}", "w", encoding="utf-8"
108+
) as dest:
109+
dest.write(lesscpy.compile(src, minify=True, xminify=True))
110+
111+
112+
def minify_html() -> None:
113+
for filename in os.listdir():
114+
if filename.endswith(".html"):
115+
with open(filename, encoding="utf-8") as src:
116+
with open(f"build/{filename}", "w", encoding="utf-8") as dest:
117+
dest.write(htmlmin.minify(src.read()))
118+
119+
120+
if __name__ == "__main__":
121+
args = get_parser().parse_args()
122+
app_archive = args.name if args.name.endswith(".xdc") else f"{args.name}.xdc"
123+
files = []
124+
125+
# CLEAN
126+
shutil.rmtree("build", ignore_errors=True)
127+
for name in os.listdir():
128+
if os.path.isfile(name) and name.endswith(".xdc"):
129+
os.remove(name)
130+
131+
if args.debug:
132+
files.append("eruda.min.js")
133+
134+
if os.path.exists("assets"):
135+
shutil.copytree("assets", "build/assets")
136+
137+
# TRANSCRYPT
138+
if os.path.exists("app.py"):
139+
from transcrypt.__main__ import main as transcrypt
140+
141+
sys.argv = ["transcrypt"]
142+
if args.debug:
143+
sys.argv.append("-n")
144+
sys.argv.append("app.py")
145+
transcrypt()
146+
shutil.copytree("__target__", "build/__target__")
147+
os.remove(f"build/__target__/app.project")
148+
149+
minify_js()
150+
minify_css()
151+
minify_html()
152+
153+
# ADD METADATA
154+
for name in ("manifest.toml", "icon.png", "icon.jpg"):
155+
if os.path.exists(name):
156+
files.append(name)
157+
158+
for path in files:
159+
shutil.copyfile(f"{path}", f"build/{path}")
160+
project_root = os.path.abspath(".")
161+
os.chdir("build")
162+
shutil.make_archive(f"{project_root}/{app_archive}", "zip")
163+
os.chdir(project_root)
164+
os.rename(f"{app_archive}.zip", app_archive)
165+
166+
# for testing:
167+
if os.path.exists("webxdc.js"):
168+
shutil.copyfile("webxdc.js", "build/webxdc.js")
169+
170+
with open(app_archive, "rb") as file:
171+
size = len(file.read())
172+
print(f"App saved as: {app_archive} ({size_fmt(size)})")

create-xdc.sh

Lines changed: 0 additions & 20 deletions
This file was deleted.

icon.png

1.93 KB
Loading

manifest.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
name = "Python app"
1+
name = "Python App"
2+
3+
# uncomment the following line and set it your source repo; it is shown in the Webxdc's menu then
4+
#source_code_url = "https://gitsth.org/your/repo"

requirements.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
htmlmin>=0.1.12
2+
jsmin>=3.0.0
3+
lesscpy>=0.15.0
4+
Transcrypt>=3.9.0

0 commit comments

Comments
 (0)