jac-client 0.2.0__py3-none-any.whl → 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- jac_client/docs/README.md +31 -1
- jac_client/docs/asset-serving/intro.md +209 -0
- jac_client/docs/assets/pipe_line-v2.svg +32 -0
- jac_client/docs/file-system/intro.md +90 -0
- jac_client/docs/styling/intro.md +250 -0
- jac_client/docs/styling/js-styling.md +373 -0
- jac_client/docs/styling/material-ui.md +346 -0
- jac_client/docs/styling/pure-css.md +305 -0
- jac_client/docs/styling/sass.md +409 -0
- jac_client/docs/styling/styled-components.md +401 -0
- jac_client/docs/styling/tailwind.md +303 -0
- jac_client/examples/asset-serving/css-with-image/.babelrc +9 -0
- jac_client/examples/asset-serving/css-with-image/README.md +91 -0
- jac_client/examples/asset-serving/css-with-image/app.jac +67 -0
- jac_client/examples/asset-serving/css-with-image/assets/burger.png +0 -0
- jac_client/examples/asset-serving/css-with-image/package.json +28 -0
- jac_client/examples/asset-serving/css-with-image/styles.css +27 -0
- jac_client/examples/asset-serving/css-with-image/vite.config.js +29 -0
- jac_client/examples/asset-serving/image-asset/.babelrc +9 -0
- jac_client/examples/asset-serving/image-asset/README.md +119 -0
- jac_client/examples/asset-serving/image-asset/app.jac +43 -0
- jac_client/examples/asset-serving/image-asset/assets/burger.png +0 -0
- jac_client/examples/asset-serving/image-asset/package.json +28 -0
- jac_client/examples/asset-serving/image-asset/styles.css +27 -0
- jac_client/examples/asset-serving/image-asset/vite.config.js +29 -0
- jac_client/examples/asset-serving/import-alias/.babelrc +9 -0
- jac_client/examples/asset-serving/import-alias/README.md +83 -0
- jac_client/examples/asset-serving/import-alias/app.jac +57 -0
- jac_client/examples/asset-serving/import-alias/assets/burger.png +0 -0
- jac_client/examples/asset-serving/import-alias/package.json +28 -0
- jac_client/examples/asset-serving/import-alias/vite.config.js +29 -0
- jac_client/examples/css-styling/js-styling/.babelrc +9 -0
- jac_client/examples/css-styling/js-styling/README.md +183 -0
- jac_client/examples/css-styling/js-styling/app.jac +63 -0
- jac_client/examples/css-styling/js-styling/package.json +28 -0
- jac_client/examples/css-styling/js-styling/styles.js +100 -0
- jac_client/examples/css-styling/js-styling/vite.config.js +28 -0
- jac_client/examples/css-styling/material-ui/.babelrc +9 -0
- jac_client/examples/css-styling/material-ui/README.md +16 -0
- jac_client/examples/css-styling/material-ui/app.jac +82 -0
- jac_client/examples/css-styling/material-ui/package.json +32 -0
- jac_client/examples/css-styling/material-ui/vite.config.js +28 -0
- jac_client/examples/css-styling/pure-css/.babelrc +9 -0
- jac_client/examples/css-styling/pure-css/README.md +16 -0
- jac_client/examples/css-styling/pure-css/app.jac +63 -0
- jac_client/examples/css-styling/pure-css/package.json +28 -0
- jac_client/examples/css-styling/pure-css/styles.css +112 -0
- jac_client/examples/css-styling/pure-css/vite.config.js +28 -0
- jac_client/examples/css-styling/sass-example/.babelrc +9 -0
- jac_client/examples/css-styling/sass-example/README.md +16 -0
- jac_client/examples/css-styling/sass-example/app.jac +63 -0
- jac_client/examples/css-styling/sass-example/package.json +29 -0
- jac_client/examples/css-styling/sass-example/styles.scss +158 -0
- jac_client/examples/css-styling/sass-example/vite.config.js +28 -0
- jac_client/examples/css-styling/styled-components/.babelrc +9 -0
- jac_client/examples/css-styling/styled-components/README.md +16 -0
- jac_client/examples/css-styling/styled-components/app.jac +66 -0
- jac_client/examples/css-styling/styled-components/package.json +29 -0
- jac_client/examples/css-styling/styled-components/styled.js +91 -0
- jac_client/examples/css-styling/styled-components/vite.config.js +28 -0
- jac_client/examples/css-styling/tailwind-example/.babelrc +9 -0
- jac_client/examples/css-styling/tailwind-example/README.md +16 -0
- jac_client/examples/css-styling/tailwind-example/app.jac +64 -0
- jac_client/examples/css-styling/tailwind-example/global.css +1 -0
- jac_client/examples/css-styling/tailwind-example/package.json +30 -0
- jac_client/examples/css-styling/tailwind-example/vite.config.js +30 -0
- jac_client/examples/with-router/app.jac +1 -1
- jac_client/plugin/cli.py +5 -0
- jac_client/plugin/client.py +64 -3
- jac_client/plugin/vite_client_bundle.py +96 -1
- jac_client/tests/__init__.py +0 -1
- jac_client/tests/fixtures/cl_file/app.cl.jac +38 -0
- jac_client/tests/fixtures/cl_file/app.jac +15 -0
- jac_client/tests/fixtures/js_import/app.jac +1 -1
- jac_client/tests/fixtures/relative_import/button.jac +2 -2
- jac_client/tests/fixtures/test_fragments_spread/app.jac +2 -2
- jac_client/tests/test_asset_examples.py +339 -0
- jac_client/tests/test_cl.py +165 -87
- jac_client/tests/test_create_jac_app.py +40 -44
- {jac_client-0.2.0.dist-info → jac_client-0.2.1.dist-info}/METADATA +2 -2
- jac_client-0.2.1.dist-info/RECORD +140 -0
- jac_client-0.2.0.dist-info/RECORD +0 -72
- {jac_client-0.2.0.dist-info → jac_client-0.2.1.dist-info}/WHEEL +0 -0
- {jac_client-0.2.0.dist-info → jac_client-0.2.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"""Tests for asset-serving and css-styling examples."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
import json
|
|
7
|
+
import shutil
|
|
8
|
+
import tempfile
|
|
9
|
+
import subprocess
|
|
10
|
+
|
|
11
|
+
from jaclang.runtimelib.machine import JacMachine as Jac
|
|
12
|
+
from jaclang.utils.test import TestCase
|
|
13
|
+
from jac_client.plugin.vite_client_bundle import ViteClientBundleBuilder
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AssetServingExampleTests(TestCase):
|
|
17
|
+
"""Test asset-serving examples."""
|
|
18
|
+
|
|
19
|
+
def setUp(self) -> None:
|
|
20
|
+
Jac.reset_machine()
|
|
21
|
+
return super().setUp()
|
|
22
|
+
|
|
23
|
+
def tearDown(self) -> None:
|
|
24
|
+
Jac.reset_machine()
|
|
25
|
+
return super().tearDown()
|
|
26
|
+
|
|
27
|
+
def _create_test_project_with_vite(
|
|
28
|
+
self, temp_path: Path, include_assets: bool = False
|
|
29
|
+
) -> tuple[Path, Path]:
|
|
30
|
+
"""Create a minimal test project with Vite installed.
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
temp_path: Path to the temporary directory
|
|
34
|
+
include_assets: If True, includes asset handling setup
|
|
35
|
+
"""
|
|
36
|
+
# Create package.json with base dependencies
|
|
37
|
+
package_data = {
|
|
38
|
+
"name": "test-client",
|
|
39
|
+
"version": "0.0.1",
|
|
40
|
+
"type": "module",
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "npm run compile && vite build",
|
|
43
|
+
"dev": "vite dev",
|
|
44
|
+
"preview": "vite preview",
|
|
45
|
+
"compile": 'babel src --out-dir build --extensions ".jsx,.js" --out-file-extension .js',
|
|
46
|
+
},
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"react": "^19.2.0",
|
|
49
|
+
"react-dom": "^19.2.0",
|
|
50
|
+
"react-router-dom": "^7.3.0",
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"vite": "^6.4.1",
|
|
54
|
+
"@babel/cli": "^7.28.3",
|
|
55
|
+
"@babel/core": "^7.28.5",
|
|
56
|
+
"@babel/preset-env": "^7.28.5",
|
|
57
|
+
"@babel/preset-react": "^7.28.5",
|
|
58
|
+
},
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
package_json = temp_path / "package.json"
|
|
62
|
+
with package_json.open("w", encoding="utf-8") as f:
|
|
63
|
+
json.dump(package_data, f, indent=2)
|
|
64
|
+
|
|
65
|
+
# Create .babelrc file
|
|
66
|
+
babelrc = temp_path / ".babelrc"
|
|
67
|
+
babelrc.write_text(
|
|
68
|
+
"""{
|
|
69
|
+
"presets": [[
|
|
70
|
+
"@babel/preset-env",
|
|
71
|
+
{
|
|
72
|
+
"modules": false
|
|
73
|
+
}
|
|
74
|
+
], "@babel/preset-react"]
|
|
75
|
+
}
|
|
76
|
+
""",
|
|
77
|
+
encoding="utf-8",
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Create vite.config.js file
|
|
81
|
+
vite_config = temp_path / "vite.config.js"
|
|
82
|
+
if include_assets:
|
|
83
|
+
vite_config.write_text(
|
|
84
|
+
"""import { defineConfig } from "vite";
|
|
85
|
+
import path from "path";
|
|
86
|
+
import { fileURLToPath } from "url";
|
|
87
|
+
|
|
88
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
89
|
+
|
|
90
|
+
export default defineConfig({
|
|
91
|
+
root: ".",
|
|
92
|
+
build: {
|
|
93
|
+
rollupOptions: {
|
|
94
|
+
input: "build/main.js",
|
|
95
|
+
output: {
|
|
96
|
+
entryFileNames: "client.[hash].js",
|
|
97
|
+
assetFileNames: "[name].[ext]",
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
outDir: "dist",
|
|
101
|
+
emptyOutDir: true,
|
|
102
|
+
minify: false,
|
|
103
|
+
},
|
|
104
|
+
publicDir: false,
|
|
105
|
+
resolve: {
|
|
106
|
+
alias: {
|
|
107
|
+
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
108
|
+
"@jac-client/assets": path.resolve(__dirname, "src/assets"),
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
""",
|
|
113
|
+
encoding="utf-8",
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
vite_config.write_text(
|
|
117
|
+
"""import { defineConfig } from "vite";
|
|
118
|
+
import path from "path";
|
|
119
|
+
import { fileURLToPath } from "url";
|
|
120
|
+
|
|
121
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
122
|
+
|
|
123
|
+
export default defineConfig({
|
|
124
|
+
root: ".",
|
|
125
|
+
build: {
|
|
126
|
+
rollupOptions: {
|
|
127
|
+
input: "build/main.js",
|
|
128
|
+
output: {
|
|
129
|
+
entryFileNames: "client.[hash].js",
|
|
130
|
+
assetFileNames: "[name].[ext]",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
outDir: "dist",
|
|
134
|
+
emptyOutDir: true,
|
|
135
|
+
minify: false,
|
|
136
|
+
},
|
|
137
|
+
publicDir: false,
|
|
138
|
+
resolve: {
|
|
139
|
+
alias: {
|
|
140
|
+
"@jac-client/utils": path.resolve(__dirname, "src/client_runtime.js"),
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
""",
|
|
145
|
+
encoding="utf-8",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Install dependencies
|
|
149
|
+
result = subprocess.run(
|
|
150
|
+
["npm", "install"],
|
|
151
|
+
cwd=temp_path,
|
|
152
|
+
check=False,
|
|
153
|
+
capture_output=True,
|
|
154
|
+
text=True,
|
|
155
|
+
)
|
|
156
|
+
if result.returncode != 0:
|
|
157
|
+
error_msg = f"npm install failed with exit code {result.returncode}\n"
|
|
158
|
+
error_msg += f"stdout: {result.stdout}\n"
|
|
159
|
+
error_msg += f"stderr: {result.stderr}\n"
|
|
160
|
+
raise RuntimeError(error_msg)
|
|
161
|
+
|
|
162
|
+
# Create output directory
|
|
163
|
+
output_dir = temp_path / "dist"
|
|
164
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
165
|
+
|
|
166
|
+
src_dir = temp_path / "src"
|
|
167
|
+
src_dir.mkdir(parents=True, exist_ok=True)
|
|
168
|
+
|
|
169
|
+
build_dir = temp_path / "build"
|
|
170
|
+
build_dir.mkdir(parents=True, exist_ok=True)
|
|
171
|
+
|
|
172
|
+
return package_json, output_dir
|
|
173
|
+
|
|
174
|
+
def test_image_asset_example(self) -> None:
|
|
175
|
+
"""Test image-asset example with static asset paths."""
|
|
176
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
177
|
+
temp_path = Path(temp_dir)
|
|
178
|
+
|
|
179
|
+
package_json, output_dir = self._create_test_project_with_vite(
|
|
180
|
+
temp_path, include_assets=True
|
|
181
|
+
)
|
|
182
|
+
runtime_path = (
|
|
183
|
+
Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
# Initialize the Vite builder
|
|
187
|
+
builder = ViteClientBundleBuilder(
|
|
188
|
+
runtime_path=runtime_path,
|
|
189
|
+
vite_package_json=package_json,
|
|
190
|
+
vite_output_dir=output_dir,
|
|
191
|
+
vite_minify=False,
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Import the image-asset example
|
|
195
|
+
examples_dir = (
|
|
196
|
+
Path(__file__).parent.parent
|
|
197
|
+
/ "examples"
|
|
198
|
+
/ "asset-serving"
|
|
199
|
+
/ "image-asset"
|
|
200
|
+
)
|
|
201
|
+
(module,) = Jac.jac_import("app", str(examples_dir))
|
|
202
|
+
|
|
203
|
+
# Build the bundle
|
|
204
|
+
bundle = builder.build(module, force=True)
|
|
205
|
+
|
|
206
|
+
# Verify bundle structure
|
|
207
|
+
self.assertIsNotNone(bundle)
|
|
208
|
+
self.assertEqual(bundle.module_name, "app")
|
|
209
|
+
self.assertIn("app", bundle.client_functions)
|
|
210
|
+
|
|
211
|
+
# Verify image path is in the bundle
|
|
212
|
+
self.assertIn("/static/assets/burger.png", bundle.code)
|
|
213
|
+
|
|
214
|
+
# Verify bundle was written to output directory
|
|
215
|
+
bundle_files = list(output_dir.glob("client.*.js"))
|
|
216
|
+
self.assertGreater(
|
|
217
|
+
len(bundle_files), 0, "Expected at least one bundle file"
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
# Cleanup
|
|
221
|
+
builder.cleanup_temp_dir()
|
|
222
|
+
|
|
223
|
+
def test_css_with_image_example(self) -> None:
|
|
224
|
+
"""Test css-with-image example with CSS and image assets."""
|
|
225
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
226
|
+
temp_path = Path(temp_dir)
|
|
227
|
+
|
|
228
|
+
package_json, output_dir = self._create_test_project_with_vite(
|
|
229
|
+
temp_path, include_assets=True
|
|
230
|
+
)
|
|
231
|
+
runtime_path = (
|
|
232
|
+
Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# Initialize the Vite builder
|
|
236
|
+
builder = ViteClientBundleBuilder(
|
|
237
|
+
runtime_path=runtime_path,
|
|
238
|
+
vite_package_json=package_json,
|
|
239
|
+
vite_output_dir=output_dir,
|
|
240
|
+
vite_minify=False,
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Import the css-with-image example
|
|
244
|
+
examples_dir = (
|
|
245
|
+
Path(__file__).parent.parent
|
|
246
|
+
/ "examples"
|
|
247
|
+
/ "asset-serving"
|
|
248
|
+
/ "css-with-image"
|
|
249
|
+
)
|
|
250
|
+
(module,) = Jac.jac_import("app", str(examples_dir))
|
|
251
|
+
|
|
252
|
+
# Build the bundle
|
|
253
|
+
bundle = builder.build(module, force=True)
|
|
254
|
+
|
|
255
|
+
# Verify bundle structure
|
|
256
|
+
self.assertIsNotNone(bundle)
|
|
257
|
+
self.assertEqual(bundle.module_name, "app")
|
|
258
|
+
self.assertIn("app", bundle.client_functions)
|
|
259
|
+
|
|
260
|
+
# Verify CSS import is present (CSS should be extracted to separate file)
|
|
261
|
+
# The bundle should reference the CSS file
|
|
262
|
+
self.assertIn("import", bundle.code.lower())
|
|
263
|
+
|
|
264
|
+
# Verify image paths are in the bundle
|
|
265
|
+
self.assertIn("/static/assets/burger.png", bundle.code)
|
|
266
|
+
|
|
267
|
+
# Verify CSS file was extracted
|
|
268
|
+
css_files = list(output_dir.glob("*.css"))
|
|
269
|
+
self.assertGreater(len(css_files), 0, "Expected at least one CSS file")
|
|
270
|
+
|
|
271
|
+
# Verify bundle was written to output directory
|
|
272
|
+
bundle_files = list(output_dir.glob("client.*.js"))
|
|
273
|
+
self.assertGreater(
|
|
274
|
+
len(bundle_files), 0, "Expected at least one bundle file"
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# Cleanup
|
|
278
|
+
builder.cleanup_temp_dir()
|
|
279
|
+
|
|
280
|
+
def test_import_alias_example(self) -> None:
|
|
281
|
+
"""Test import-alias example with @jac-client/assets alias."""
|
|
282
|
+
with tempfile.TemporaryDirectory() as temp_dir:
|
|
283
|
+
temp_path = Path(temp_dir)
|
|
284
|
+
package_json, output_dir = self._create_test_project_with_vite(
|
|
285
|
+
temp_path, include_assets=True
|
|
286
|
+
)
|
|
287
|
+
runtime_path = (
|
|
288
|
+
Path(__file__).parent.parent / "plugin" / "client_runtime.jac"
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
# Initialize the Vite builder
|
|
292
|
+
builder = ViteClientBundleBuilder(
|
|
293
|
+
runtime_path=runtime_path,
|
|
294
|
+
vite_package_json=package_json,
|
|
295
|
+
vite_output_dir=output_dir,
|
|
296
|
+
vite_minify=False,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# Import the import-alias example
|
|
300
|
+
examples_dir = (
|
|
301
|
+
Path(__file__).parent.parent
|
|
302
|
+
/ "examples"
|
|
303
|
+
/ "asset-serving"
|
|
304
|
+
/ "import-alias"
|
|
305
|
+
)
|
|
306
|
+
(module,) = Jac.jac_import("app", str(examples_dir))
|
|
307
|
+
|
|
308
|
+
# Copy assets from example directory to temp project's src/assets/
|
|
309
|
+
# This is needed because @jac-client/assets alias points to src/assets
|
|
310
|
+
example_assets_dir = examples_dir / "assets"
|
|
311
|
+
temp_assets_dir = temp_path / "src" / "assets"
|
|
312
|
+
if example_assets_dir.exists():
|
|
313
|
+
temp_assets_dir.mkdir(parents=True, exist_ok=True)
|
|
314
|
+
# Copy all files from example assets to temp assets
|
|
315
|
+
for asset_file in example_assets_dir.iterdir():
|
|
316
|
+
if asset_file.is_file():
|
|
317
|
+
shutil.copy2(asset_file, temp_assets_dir / asset_file.name)
|
|
318
|
+
|
|
319
|
+
# Build the bundle
|
|
320
|
+
bundle = builder.build(module, force=True)
|
|
321
|
+
|
|
322
|
+
# Verify bundle structure
|
|
323
|
+
self.assertIsNotNone(bundle)
|
|
324
|
+
self.assertEqual(bundle.module_name, "app")
|
|
325
|
+
self.assertIn("app", bundle.client_functions)
|
|
326
|
+
|
|
327
|
+
# Verify the import alias was processed by Vite
|
|
328
|
+
# Vite should have resolved the asset import
|
|
329
|
+
# The bundle should contain the processed asset URL
|
|
330
|
+
self.assertIn("burgerImage", bundle.code)
|
|
331
|
+
|
|
332
|
+
# Verify bundle was written to output directory
|
|
333
|
+
bundle_files = list(output_dir.glob("client.*.js"))
|
|
334
|
+
self.assertGreater(
|
|
335
|
+
len(bundle_files), 0, "Expected at least one bundle file"
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
# Cleanup
|
|
339
|
+
builder.cleanup_temp_dir()
|