|
@@ -1,33 +1,29 @@
|
|
-from dataclasses import dataclass
|
|
|
|
from pathlib import Path
|
|
from pathlib import Path
|
|
from typing import Dict, List, Tuple
|
|
from typing import Dict, List, Tuple
|
|
|
|
|
|
import vbuild
|
|
import vbuild
|
|
-from starlette.responses import FileResponse
|
|
|
|
-from starlette.routing import Route
|
|
|
|
|
|
|
|
-
|
|
|
|
-@dataclass
|
|
|
|
-class Component:
|
|
|
|
- name: str
|
|
|
|
- path: Path
|
|
|
|
- dependencies: List[str]
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-components: Dict[str, Component] = {}
|
|
|
|
|
|
+vue_components: Dict[str, Path] = {}
|
|
|
|
+js_components: Dict[str, Path] = {}
|
|
|
|
+js_dependencies: List[Path] = []
|
|
|
|
|
|
|
|
|
|
def register_component(name: str, py_filepath: str, component_filepath: str, dependencies: List[str] = []) -> None:
|
|
def register_component(name: str, py_filepath: str, component_filepath: str, dependencies: List[str] = []) -> None:
|
|
- assert name not in components
|
|
|
|
- components[name] = Component(
|
|
|
|
- name=name,
|
|
|
|
- path=Path(py_filepath).parent / component_filepath,
|
|
|
|
- dependencies=[Path(py_filepath).parent / dependency for dependency in dependencies],
|
|
|
|
- )
|
|
|
|
|
|
+ suffix = Path(component_filepath).suffix.lower()
|
|
|
|
+ assert suffix in ['.vue', '.js'], 'Only VUE and JS components are supported.'
|
|
|
|
+ if suffix == '.vue':
|
|
|
|
+ assert name not in vue_components, f'Duplicate VUE component name {name}'
|
|
|
|
+ vue_components[name] = Path(py_filepath).parent / component_filepath
|
|
|
|
+ elif suffix == '.js':
|
|
|
|
+ assert name not in js_dependencies, f'Duplicate JS component name {name}'
|
|
|
|
+ js_components[name] = Path(py_filepath).parent / component_filepath
|
|
|
|
+ for dependency in dependencies:
|
|
|
|
+ assert Path(dependency).suffix == '.js', 'Only JS dependencies are supported.'
|
|
|
|
+ js_dependencies.append(Path(py_filepath).parent / dependency)
|
|
|
|
|
|
|
|
|
|
def generate_vue_content() -> Tuple[str]:
|
|
def generate_vue_content() -> Tuple[str]:
|
|
- builds = [vbuild.VBuild(c.name, c.path.read_text()) for c in components.values() if c.path.suffix == '.vue']
|
|
|
|
|
|
+ builds = [vbuild.VBuild(name, path.read_text()) for name, path in vue_components.items()]
|
|
return (
|
|
return (
|
|
'\n'.join(v.html for v in builds),
|
|
'\n'.join(v.html for v in builds),
|
|
'<style>' + '\n'.join(v.style for v in builds) + '</style>',
|
|
'<style>' + '\n'.join(v.style for v in builds) + '</style>',
|
|
@@ -35,32 +31,11 @@ def generate_vue_content() -> Tuple[str]:
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
-def get_js_components() -> List[Component]:
|
|
|
|
- return [c for c in components.values() if c.path.suffix == '.js']
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-def generate_js_routes() -> List[Route]:
|
|
|
|
- routes: List[Route] = []
|
|
|
|
- for component in components.values():
|
|
|
|
- for dependency in component.dependencies:
|
|
|
|
- routes.append(Route(f'/_vue/{component.name}/{dependency}',
|
|
|
|
- lambda _, path=dependency: FileResponse(path, media_type='text/javascript')))
|
|
|
|
- for component in get_js_components():
|
|
|
|
- routes.append(Route(f'/_vue/{component.name}',
|
|
|
|
- lambda _, path=component.path: FileResponse(path, media_type='text/javascript')))
|
|
|
|
- return routes
|
|
|
|
-
|
|
|
|
-
|
|
|
|
def generate_js_imports() -> str:
|
|
def generate_js_imports() -> str:
|
|
result = ''
|
|
result = ''
|
|
- for component in components.values():
|
|
|
|
- for dependency in component.dependencies:
|
|
|
|
- result += f'''
|
|
|
|
- import "/_vue/{component.name}/{dependency}";
|
|
|
|
- '''
|
|
|
|
- for component in get_js_components():
|
|
|
|
- result += f'''
|
|
|
|
- import {{ default as {component.name} }} from "/_vue/{component.name}";
|
|
|
|
- app.component("{component.name}", {component.name});
|
|
|
|
- '''
|
|
|
|
|
|
+ for path in js_dependencies:
|
|
|
|
+ result += f'import "/_vue/dependencies/{path}";\n'
|
|
|
|
+ for name, path in js_components.items():
|
|
|
|
+ result += f'import {{ default as {name} }} from "/_vue/components/{name}";\n'
|
|
|
|
+ result += f'app.component("{name}", {name});\n'
|
|
return result
|
|
return result
|