vue.py 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. from dataclasses import dataclass
  2. from pathlib import Path
  3. from typing import Dict, List, Set, Tuple
  4. import vbuild
  5. from . import globals
  6. from .ids import IncrementingStringIds
  7. @dataclass
  8. class Component:
  9. name: str
  10. path: Path
  11. @dataclass
  12. class Dependency:
  13. id: int
  14. path: Path
  15. dependents: Set[str]
  16. dependency_ids = IncrementingStringIds()
  17. vue_components: Dict[str, Component] = {}
  18. js_components: Dict[str, Component] = {}
  19. js_dependencies: Dict[int, Dependency] = {}
  20. def register_component(name: str, py_filepath: str, component_filepath: str, dependencies: List[str] = []) -> None:
  21. suffix = Path(component_filepath).suffix.lower()
  22. assert suffix in ['.vue', '.js'], 'Only VUE and JS components are supported.'
  23. if suffix == '.vue':
  24. assert name not in vue_components, f'Duplicate VUE component name {name}'
  25. vue_components[name] = Component(name=name, path=Path(py_filepath).parent / component_filepath)
  26. elif suffix == '.js':
  27. assert name not in js_components, f'Duplicate JS component name {name}'
  28. js_components[name] = Component(name=name, path=Path(py_filepath).parent / component_filepath)
  29. for dependency in dependencies:
  30. path = Path(py_filepath).parent / dependency
  31. assert path.suffix == '.js', 'Only JS dependencies are supported.'
  32. id = dependency_ids.get(str(path.resolve()))
  33. if id not in js_dependencies:
  34. js_dependencies[id] = Dependency(id=id, path=path, dependents=set())
  35. js_dependencies[id].dependents.add(name)
  36. def generate_vue_content() -> Tuple[str, str, str]:
  37. builds = [
  38. vbuild.VBuild(name, component.path.read_text())
  39. for name, component in vue_components.items()
  40. if name not in globals.excludes
  41. ]
  42. return (
  43. '\n'.join(v.html for v in builds),
  44. '<style>' + '\n'.join(v.style for v in builds) + '</style>',
  45. '\n'.join(v.script.replace('Vue.component', 'app.component', 1) for v in builds),
  46. )
  47. def generate_js_imports(prefix: str) -> str:
  48. result = ''
  49. for id, dependency in js_dependencies.items():
  50. if not dependency.dependents.difference(globals.excludes):
  51. continue
  52. result += f'import "{prefix}/_nicegui/dependencies/{id}/{dependency.path.name}";\n'
  53. for name in js_components:
  54. if name in globals.excludes:
  55. continue
  56. result += f'import {{ default as {name} }} from "{prefix}/_nicegui/components/{name}";\n'
  57. result += f'app.component("{name}", {name});\n'
  58. return result