make.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. #!/usr/bin/python
  2. ###
  3. ### Build script for the la-warch app. This script is responsible
  4. ### for building app from source, and config. Config file is
  5. ###
  6. ### ./config.json
  7. ###
  8. ### This file has documentation, with options that could be change to
  9. ### make this app more flexible for the end users.
  10. if not __name__ == "__main__":
  11. print("This is build system. Can be only executed as app.")
  12. exit(-2)
  13. import json
  14. import pathlib
  15. import shutil
  16. import subprocess
  17. import datetime
  18. # Current release
  19. release = datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")
  20. # Root project directory
  21. root = pathlib.Path("./")
  22. # This is root source dir
  23. source = root / pathlib.Path("./source/")
  24. # Sources with types of content
  25. script_source = source / pathlib.Path("./scripts/")
  26. sass_source = source / pathlib.Path("./theme/")
  27. static_files = source / pathlib.Path("./static/")
  28. templates = source / pathlib.Path("./templates/")
  29. # Specific files, like loaders, main view, etc.
  30. app_view_file = templates / pathlib.Path("view.html")
  31. script_loader_file = script_source / pathlib.Path("loader.js")
  32. sass_loader_file = sass_source / pathlib.Path("loader.sass")
  33. config = root / pathlib.Path("config.json")
  34. # Build dir
  35. build = root / pathlib.Path("./build/")
  36. # Result specific files
  37. app_view_result_file = build / pathlib.Path("index.html")
  38. script_loader_result_file = build / pathlib.Path("bundle.js")
  39. sass_loader_result_file = build / pathlib.Path("bundle.css")
  40. # Checking that directories exists
  41. if not source.is_dir():
  42. print("Source directory not exists.")
  43. exit(-1)
  44. if not script_source.is_dir():
  45. print("Script source directory not exists.")
  46. exit(-1)
  47. if not sass_source.is_dir():
  48. print("Sass source director not exists.")
  49. exit(-1)
  50. if not static_files.is_dir():
  51. print("Static files directory not exists.")
  52. exit(-1)
  53. if not templates.is_dir():
  54. print("Templates directory not exists.")
  55. exit(-1)
  56. # Checking files
  57. if not app_view_file.is_file():
  58. print("App view file not exists.")
  59. exit(-1)
  60. # Check config file
  61. if not config.is_file():
  62. print("App config file not exists.")
  63. exit(-1)
  64. # Check script loader file
  65. if not script_loader_file.is_file():
  66. print("Script loader file not exists.")
  67. exit(-1)
  68. # Check SASS loader file
  69. if not sass_loader_file.is_file():
  70. print("SASS loader file not exists.")
  71. exit(-1)
  72. # Prepare result directory
  73. if build.is_dir():
  74. shutil.rmtree(build)
  75. build.mkdir()
  76. # Parse config json
  77. try:
  78. with config.open() as handle:
  79. config = json.loads(handle.read())
  80. except event:
  81. print(str(event))
  82. print("Can not parse config file.")
  83. exit(-1)
  84. def get_config_section(
  85. name: str,
  86. alt: str | int | float | list | None = None
  87. ) -> str | int | float | list:
  88. '''
  89. This get section from root config file, or raise exception when section
  90. not exists, and alt is set to None. When alt is provided, and section
  91. not exists then return alt. If section exists, then return section.
  92. Parameters:
  93. name (str): Name of the section
  94. alt (str | int | float | list | None) = None: Alternative value
  95. Returns:
  96. (str | int | flaot | list): Value of the section
  97. '''
  98. global config
  99. if name in config:
  100. return config[name]
  101. if alt is not None:
  102. return alt
  103. print("Not found section \"" + name + "\" in config.")
  104. exit(-2)
  105. def compile(*command: list) -> None:
  106. '''
  107. This function execute command, and when command not exit without
  108. error code, that mean not return 0, then it print STDOUT and STDERR
  109. from the command.
  110. Parameters:
  111. command (list): Command as list of str
  112. '''
  113. result = subprocess.run(command, capture_output = True)
  114. if result.returncode == 0:
  115. return
  116. print(result.stdout.decode("UTF-8"))
  117. print(result.stderr.decode("UTF-8"))
  118. print("Compilation end with error.")
  119. exit(-5)
  120. # Rendering app view
  121. from source.make.render import render
  122. from source.make.dom import link, script
  123. app_view_render = render(app_view_file)
  124. # App view use HTML description as replace tags
  125. app_view_render.start_tag = "<!--"
  126. app_view_render.stop_tag = "-->"
  127. view_params = get_config_section("view-params")
  128. # Replace all elements from view-params config section
  129. for param in view_params.keys():
  130. if param == "bundle_items":
  131. print("Can not use param \"bundle_items\", it is reserved.")
  132. exit(-3)
  133. content = view_params[param]
  134. if type(content) is str:
  135. app_view_render.add(param, content)
  136. continue
  137. if type(content) is float or type(content) is int:
  138. app_view_render.add(param, str(content))
  139. continue
  140. print("Param " + param + " not contain string or number.")
  141. exit(-3)
  142. # Generating tags
  143. sass_link = link()
  144. sass_link.rel = "stylesheet"
  145. sass_link.type = "text/css"
  146. sass_link.href = "./" + sass_loader_result_file.name + "?version=" + release
  147. js_script = script()
  148. js_script.src = "./" + script_loader_result_file.name + "?version=" + release
  149. bundle_items = sass_link.render() + js_script.render()
  150. # Add bundle items tags
  151. app_view_render.add("bundle_items", bundle_items)
  152. # Render and save app view
  153. app_view = app_view_render.finalize()
  154. try:
  155. with app_view_result_file.open("w") as handle:
  156. handle.write(app_view)
  157. except event:
  158. print("Can not save app view.")
  159. print(str(event))
  160. exit(-4)
  161. # Bundle JS script source
  162. compile(
  163. "esbuild",
  164. str(script_loader_file),
  165. "--bundle",
  166. "--minify",
  167. "--outfile=" + str(script_loader_result_file)
  168. )
  169. # Bundle SASS themes source
  170. compile(
  171. "sass",
  172. "--sourcemap=none",
  173. "-t compressed",
  174. str(sass_loader_file),
  175. str(sass_loader_result_file)
  176. )
  177. print("Build success!")