# HG changeset patch # User Goffi # Date 1588523111 -7200 # Node ID 1ec41ac1e7cffd9945b51c65f0d36407bd1fb9cc # Parent 08cd652dea14d2794d3fb27e0adee3998abc03ad server: seperation between production build dir and dev build dir: LiberviaRootResource instances's `build_path` is the path where generated files are put and served by the HTTP server, while `dev_buid_path` is used for temporary files/libraries needed for the generation/compilation of files. diff -r 08cd652dea14 -r 1ec41ac1e7cf libervia/pages/_browser/browser_meta.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libervia/pages/_browser/browser_meta.json Sun May 03 18:25:11 2020 +0200 @@ -0,0 +1,18 @@ +{ + "js": { + "package": { + "dependencies": { + "nunjucks": "latest", + "ogv": "latest" + } + }, + "brython_map": { + "nunjucks": "nunjucks/browser/nunjucks.min.js", + "ogv": { + "path": "ogv/dist/ogv.js", + "export": ["OGVCompat", "OGVLoader", "OGVMediaError", "OGVMediaType", "OGVTimeRanges", "OGVPlayer", "OGVVersion"], + "extra_init": "OGVLoader.base='/{build_dir}/node_modules/ogv/dist'" + } + } + } +} diff -r 08cd652dea14 -r 1ec41ac1e7cf libervia/server/constants.py --- a/libervia/server/constants.py Sun May 03 18:15:22 2020 +0200 +++ b/libervia/server/constants.py Sun May 03 18:25:11 2020 +0200 @@ -36,8 +36,13 @@ TASKS_DIR = "tasks" LIBERVIA_CACHE = "libervia" SITE_NAME_DEFAULT = "default" + # generated files will be accessible there BUILD_DIR = "__b" BUILD_DIR_DYN = "dyn" + # directory where build files are served to the client + PRODUCTION_BUILD_DIR = "sites" + # directory used for files needed temporarily (e.g. for compiling other files) + DEV_BUILD_DIR = "dev_build" TPL_RESOURCE = '_t' diff -r 08cd652dea14 -r 1ec41ac1e7cf libervia/server/server.py --- a/libervia/server/server.py Sun May 03 18:15:22 2020 +0200 +++ b/libervia/server/server.py Sun May 03 18:25:11 2020 +0200 @@ -192,12 +192,14 @@ self.pages_redirects = {} self.cached_urls = {} self.main_menu = None - build_path = host.getBuildPath(site_name) - build_path.mkdir(parents=True, exist_ok=True) + self.build_path = host.getBuildPath(site_name) + self.build_path.mkdir(parents=True, exist_ok=True) + self.dev_build_path = host.getBuildPath(site_name, dev=True) + self.dev_build_path.mkdir(parents=True, exist_ok=True) self.putChild( C.BUILD_DIR.encode(), ProtectedFile( - build_path, + self.build_path, defaultType="application/octet-stream"), ) @@ -825,7 +827,7 @@ res = existing_vhosts[encoded_site_name] else: # for root path we first check if there is a global static dir - # if not, we use default template's static dic + # if not, we use default template's static dir root_path = os.path.join(site_path, C.TEMPLATE_STATIC_DIR) if not os.path.isdir(root_path): root_path = os.path.join( @@ -1307,16 +1309,22 @@ for root in self.roots: root.putChild(path, wrapped_res) - def getBuildPath(self, site_name): + def getBuildPath(self, site_name: str, dev: bool=False) -> Path: """Generate build path for a given site name - @param site_name(unicode): name of the site - @return (Path): path to the build directory + @param site_name: name of the site + @param dev: return dev build dir if True, production one otherwise + dev build dir is used for installing dependencies needed temporarily (e.g. + to compile files), while production build path is the one served by the + HTTP server, where final files are downloaded. + @return: path to the build directory """ + sub_dir = C.DEV_BUILD_DIR if dev else C.PRODUCTION_BUILD_DIR build_path_elts = [ config.getConfig(self.main_conf, "", "local_dir"), C.CACHE_DIR, C.LIBERVIA_CACHE, + sub_dir, regex.pathEscape(site_name or C.SITE_NAME_DEFAULT)] build_path = Path("/".join(build_path_elts)) return build_path.expanduser().resolve() diff -r 08cd652dea14 -r 1ec41ac1e7cf libervia/server/tasks/implicit/task_sass.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libervia/server/tasks/implicit/task_sass.py Sun May 03 18:25:11 2020 +0200 @@ -0,0 +1,75 @@ +#!/ur/bin/env python3 + +import json +from pathlib import Path +from sat.core.i18n import _ +from sat.core.log import getLogger +from sat.core import exceptions +from libervia.server.constants import Const as C +from libervia.server.tasks import task + + +log = getLogger(__name__) + +SASS_SUFFIXES = ('.sass', '.scss') + + +class Task(task.Task): + """Compile .sass and .scss files found in themes browser paths""" + AFTER = ['js_modules'] + + async def prepare(self): + # we look for any Sass file, and cancel this task if none is found + sass_dirs = set() + for browser_path in self.resource.browser_modules.get('themes_browser_paths', []): + for p in browser_path.iterdir(): + if p.suffix in SASS_SUFFIXES: + sass_dirs.add(browser_path) + break + + if not sass_dirs: + raise exceptions.CancelError("No Sass file found") + + # we have some Sass files, we need to install the compiler + d_path = self.resource.dev_build_path + package_path = d_path / "package.json" + try: + with package_path.open() as f: + package = json.load(f) + except FileNotFoundError: + package = {} + except Exception as e: + log.error(f"Unexepected exception while parsing package.json: {e}") + + if 'node-sass' not in package.setdefault('dependencies', {}): + package['dependencies']['node-sass'] = 'latest' + with package_path.open('w') as f: + json.dump(package, f, indent=4) + + try: + cmd = self.findCommand('yarn') + except exceptions.NotFound: + cmd = self.findCommand('npm') + await self.runCommand(cmd, 'install', path=str(d_path)) + + self.WATCH_DIRS = list(sass_dirs) + + async def onDirEvent(self, host, filepath, flags): + if filepath.suffix in SASS_SUFFIXES: + await self.manager.runTaskInstance(self) + + async def start(self): + d_path = self.resource.dev_build_path + node_sass = d_path / 'node_modules' / 'node-sass' / 'bin' / 'node-sass' + for browser_path in self.resource.browser_modules['themes_browser_paths']: + for p in browser_path.iterdir(): + if p.suffix not in SASS_SUFFIXES: + continue + await self.runCommand( + str(node_sass), + "--omit-source-map-url", + "--output-style", "compressed", + "--output", str(self.build_path), + str(p), + path=str(self.build_path) + )