def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" name = options['name'] swatch = options['swatch'] if not swatch: LOGGER.error('The -s option is mandatory') sys.exit(1) parent = options['parent'] version = '' # See if we need bootswatch for bootstrap v2 or v3 themes = utils.get_theme_chain(parent) if 'bootstrap3' not in themes and 'bootstrap3-jinja' not in themes: version = '2' elif 'bootstrap' not in themes and 'bootstrap-jinja' not in themes: LOGGER.warn('"bootswatch_theme" only makes sense for themes that use bootstrap') elif 'bootstrap3-gradients' in themes or 'bootstrap3-gradients-jinja' in themes: LOGGER.warn('"bootswatch_theme" doesn\'t work well with the bootstrap3-gradients family') LOGGER.info("Creating '{0}' theme from '{1}' and '{2}'".format(name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): url = 'http://bootswatch.com' if version: url += '/' + version url = '/'.join((url, swatch, fname)) LOGGER.info("Downloading: " + url) data = requests.get(url).text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data.encode('utf-8')) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent.encode('utf-8')) LOGGER.notice('Theme created. Change the THEME setting to "{0}" to use it.'.format(name))
def new_theme(self, name, engine, parent): """Create a new theme.""" base = 'themes' themedir = os.path.join(base, name) LOGGER.info("Creating theme {0} with parent {1} and engine {2} in {3}".format(name, parent, engine, themedir)) if not os.path.exists(base): os.mkdir(base) LOGGER.info("Created directory {0}".format(base)) # Check if engine and parent match engine_file = utils.get_asset_path('engine', utils.get_theme_chain(parent, self.site.themes_dirs)) with io.open(engine_file, 'r', encoding='utf-8') as fh: parent_engine = fh.read().strip() if parent_engine != engine: LOGGER.error("Cannot use engine {0} because parent theme '{1}' uses {2}".format(engine, parent, parent_engine)) return 2 # Create theme if not os.path.exists(themedir): os.mkdir(themedir) LOGGER.info("Created directory {0}".format(themedir)) else: LOGGER.error("Theme already exists") return 2 with io.open(os.path.join(themedir, 'parent'), 'w', encoding='utf-8') as fh: fh.write(parent + '\n') LOGGER.info("Created file {0}".format(os.path.join(themedir, 'parent'))) with io.open(os.path.join(themedir, 'engine'), 'w', encoding='utf-8') as fh: fh.write(engine + '\n') LOGGER.info("Created file {0}".format(os.path.join(themedir, 'engine'))) LOGGER.info("Theme {0} created successfully.".format(themedir)) LOGGER.notice('Remember to set THEME="{0}" in conf.py to use this theme.'.format(name))
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" name = options['name'] swatch = options['swatch'] if not swatch: LOGGER.error('The -s option is mandatory') return 1 parent = options['parent'] version = '' # See if we need bootswatch for bootstrap v2 or v3 themes = utils.get_theme_chain(parent) if 'bootstrap3' not in themes and 'bootstrap3-jinja' not in themes: version = '2' elif 'bootstrap' not in themes and 'bootstrap-jinja' not in themes: LOGGER.warn('"bootswatch_theme" only makes sense for themes that use bootstrap') elif 'bootstrap3-gradients' in themes or 'bootstrap3-gradients-jinja' in themes: LOGGER.warn('"bootswatch_theme" doesn\'t work well with the bootstrap3-gradients family') LOGGER.info("Creating '{0}' theme from '{1}' and '{2}'".format(name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): url = 'https://bootswatch.com' if version: url += '/' + version url = '/'.join((url, swatch, fname)) LOGGER.info("Downloading: " + url) data = requests.get(url).text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data.encode('utf-8')) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent.encode('utf-8')) LOGGER.notice('Theme created. Change the THEME setting to "{0}" to use it.'.format(name))
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" if requests is None: utils.req_missing(['requests'], 'install Bootswatch themes') name = options['name'] swatch = options['swatch'] parent = options['parent'] version = '' # See if we need bootswatch for bootstrap v2 or v3 themes = utils.get_theme_chain(parent) if 'bootstrap3' not in themes: version = '2' elif 'bootstrap' not in themes: LOGGER.warn( '"bootswatch_theme" only makes sense for themes that use bootstrap' ) LOGGER.notice("Creating '{0}' theme from '{1}' and '{2}'".format( name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): url = '/'.join(('http://bootswatch.com', version, swatch, fname)) LOGGER.notice("Downloading: " + url) data = requests.get(url).text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data.encode('utf-8')) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent.encode('utf-8')) LOGGER.notice( 'Theme created. Change the THEME setting to "{0}" to use ' 'it.'.format(name))
def build_demo(theme, themes_dir, demo_source, demo_destination): demo_destination = os.path.abspath(demo_destination) if os.path.isdir(demo_source): shutil.rmtree(demo_source) if os.path.isdir(demo_destination): shutil.rmtree(demo_destination) sys.stderr.write('=> Building {}...\n'.format(theme)) subprocess.check_call(["nikola", "init", "-qd", demo_source], stdout=subprocess.PIPE) os.symlink(os.path.abspath(themes_dir), os.path.abspath("/".join([demo_source, "themes"]))) conf_path = "/".join([demo_source, "conf.py"]) book_path = "/".join([demo_source, "templates", "book.tmpl"]) lorem_path = "/".join([demo_source, "posts", "lorem-ipsum.rst"]) # Get custom required settings from the theme themes = utils.get_theme_chain(theme, themes_dirs=[themes_dir, 'themes']) engine_path = utils.get_asset_path('engine', themes) extra_conf_path = utils.get_asset_path('conf.py.sample', themes) extra_conf = '' if extra_conf_path: extra_conf = io.open(extra_conf_path, 'r', encoding="utf-8").read() if engine_path: engine = io.open(engine_path, 'r', encoding="utf-8").read().strip() if engine == 'jinja': shutil.copy('book-jinja.tmpl', book_path) with io.open(conf_path, "a", encoding="utf-8") as conf: conf.write(u"\n\nTHEME = '{0}'\nUSE_BUNDLES = False\nOUTPUT_FOLDER = '{1}'\nSOCIAL_BUTTONS_CODE = ''\nUSE_BASE_TAG = False\n\n{2}\n".format(theme, demo_destination, extra_conf)) shutil.copy(LOREM_BASE, lorem_path) with cd(demo_source): subprocess.check_call(["nikola", "build"], stdout=subprocess.PIPE) sys.stderr.write('=> Done building {}\n'.format(theme))
def init_theme(theme): t_path = "/".join(["sites", theme]) o_path = os.path.abspath("/".join(["output", "v7", theme])) if os.path.isdir(t_path): shutil.rmtree(t_path) if os.path.isdir(o_path): shutil.rmtree(o_path) subprocess.check_call(["nikola", "init", "-qd", t_path], stdout=subprocess.PIPE) os.symlink(os.path.abspath("v7"), os.path.abspath("/".join([t_path, "themes"]))) conf_path = "/".join([t_path, "conf.py"]) # Get custom required settings from the theme themes = utils.get_theme_chain(theme, _themes_dir='v7') extra_conf_path = utils.get_asset_path('conf.py.sample', themes, _themes_dir='v7') extra_conf = '' if extra_conf_path: extra_conf = io.open(extra_conf_path, 'r', encoding="utf-8").read() with io.open(conf_path, "a", encoding="utf-8") as conf: conf.write( u"\n\n{2}\n\nTHEME = '{0}'\n\nUSE_BUNDLES = False\n\nOUTPUT_FOLDER = '{1}'\n\nSOCIAL_BUTTONS_CODE = ''\nUSE_BASE_TAG = False\n" .format(theme, o_path, extra_conf))
def get_data(theme): data = {} data['chain'] = utils.get_theme_chain(theme, DIR) data['name'] = theme readme = utils.get_asset_path('README.md', data['chain'], _themes_dir=DIR) conf_sample = utils.get_asset_path('conf.py.sample', data['chain'], _themes_dir=DIR) if readme: data['readme'] = io.open(readme, 'r', encoding='utf-8').read() else: data['readme'] = 'No README.md file available.' if conf_sample: data['confpy'] = pygments.highlight( io.open(conf_sample, 'r', encoding='utf-8').read(), PythonLexer(), HtmlFormatter(cssclass='code')) else: data['confpy'] = None data['bootswatch'] = ('bootstrap' in data['chain'] or 'bootstrap-jinja' in data['chain'] or 'bootstrap3-jinja' in data['chain'] or 'bootstrap3' in data['chain']) and \ 'bootstrap3-gradients' not in data['chain'] data['engine'] = utils.get_template_engine(data['chain'], DIR) data['chain'] = data['chain'][::-1] data['allver'] = [] for v in ALL_VERSIONS_SUPPORTED: if glob.glob('v{0}/*'.format(v)): data['allver'].append(v) return data
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" if requests is None: utils.req_missing(["requests"], "install Bootswatch themes") name = options["name"] swatch = options["swatch"] parent = options["parent"] version = "" # See if we need bootswatch for bootstrap v2 or v3 themes = utils.get_theme_chain(parent) if "bootstrap3" not in themes: version = "2" elif "bootstrap" not in themes: LOGGER.warn('"bootswatch_theme" only makes sense for themes that use bootstrap') elif "bootstrap3-gradients" in themes or "bootstrap3-gradients-jinja" in themes: LOGGER.warn('"bootswatch_theme" doesn\'t work well with the bootstrap3-gradients family') LOGGER.info("Creating '{0}' theme from '{1}' and '{2}'".format(name, swatch, parent)) utils.makedirs(os.path.join("themes", name, "assets", "css")) for fname in ("bootstrap.min.css", "bootstrap.css"): url = "/".join(("http://bootswatch.com", version, swatch, fname)) LOGGER.info("Downloading: " + url) data = requests.get(url).text with open(os.path.join("themes", name, "assets", "css", fname), "wb+") as output: output.write(data.encode("utf-8")) with open(os.path.join("themes", name, "parent"), "wb+") as output: output.write(parent.encode("utf-8")) LOGGER.notice('Theme created. Change the THEME setting to "{0}" to use it.'.format(name))
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" if requests is None: utils.req_missing(['requests'], 'install Bootswatch themes') name = options['name'] swatch = options['swatch'] parent = options['parent'] version = '' # See if we need bootswatch for bootstrap v2 or v3 themes = utils.get_theme_chain(parent) if 'bootstrap3' not in themes: version = '2' elif 'bootstrap' not in themes: LOGGER.warn('"bootswatch_theme" only makes sense for themes that use bootstrap') LOGGER.notice("Creating '{0}' theme from '{1}' and '{2}'".format(name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): url = '/'.join(('http://bootswatch.com', version, swatch, fname)) LOGGER.notice("Downloading: " + url) data = requests.get(url).text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data.encode('utf-8')) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent.encode('utf-8')) LOGGER.notice('Theme created. Change the THEME setting to "{0}" to use ' 'it.'.format(name))
def get_data(theme): data = {} data['chain'] = utils.get_theme_chain(theme) data['name'] = theme readme = utils.get_asset_path('README.md', data['chain']) conf_sample = utils.get_asset_path('conf.py.sample', data['chain']) if readme: data['readme'] = codecs.open(readme, 'r', 'utf8').read() else: data['readme'] = 'No README.md file available.' if conf_sample: data['confpy'] = pygments.highlight( codecs.open(conf_sample, 'r', 'utf8').read(), PythonLexer(), HtmlFormatter(cssclass='code')) else: data['confpy'] = None data['bootswatch'] = ('bootstrap' in data['chain'] or 'bootstrap-jinja' in data['chain'] or 'bootstrap3-jinja' in data['chain'] or 'bootstrap3' in data['chain']) and \ 'bootstrap3-gradients' not in data['chain'] data['engine'] = utils.get_template_engine(data['chain']) data['chain'] = data['chain'][::-1] return data
def test_get_asset_path(): assert get_asset_path('assets/css/nikola_rst.css', get_theme_chain('bootstrap4', ['themes'])).replace( '\\', '/').endswith('nikola/data/themes/base/assets/css/nikola_rst.css') assert get_asset_path('assets/css/theme.css', get_theme_chain('bootstrap4', ['themes'])).replace( '\\', '/').endswith( 'nikola/data/themes/bootstrap4/assets/css/theme.css') assert get_asset_path( 'nikola.py', get_theme_chain('bootstrap4', ['themes']), {'nikola': ''}).replace( '\\', '/').endswith('nikola/nikola.py') assert get_asset_path('nikola.py', get_theme_chain( 'bootstrap4', ['themes']), {'nikola': 'nikola'}) is None assert get_asset_path( 'nikola/nikola.py', get_theme_chain('bootstrap4', ['themes']), {'nikola': 'nikola'}).replace( '\\', '/').endswith('nikola/nikola.py')
def test_get_asset_path(path, files_folders, expected_path_end): theme_chain = get_theme_chain("bootstrap4", ["themes"]) asset_path = get_asset_path(path, theme_chain, files_folders) if expected_path_end: asset_path = asset_path.replace("\\", "/") assert asset_path.endswith(expected_path_end) else: assert asset_path is None
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" name = options['name'] swatch = options['swatch'] if not swatch: LOGGER.error('The -s option is mandatory') return 1 parent = options['parent'] version = '4' # Check which Bootstrap version to use themes = utils.get_theme_chain(parent, self.site.themes_dirs) if _check_for_theme('bootstrap', themes) or _check_for_theme( 'bootstrap-jinja', themes): version = '2' elif _check_for_theme('bootstrap3', themes) or _check_for_theme( 'bootstrap3-jinja', themes): version = '3' elif _check_for_theme('bootstrap4', themes) or _check_for_theme( 'bootstrap4-jinja', themes): version = '4' elif not _check_for_theme('bootstrap4', themes) and not _check_for_theme( 'bootstrap4-jinja', themes): LOGGER.warn( '"bootswatch_theme" only makes sense for themes that use bootstrap' ) elif _check_for_theme('bootstrap3-gradients', themes) or _check_for_theme( 'bootstrap3-gradients-jinja', themes): LOGGER.warn( '"bootswatch_theme" doesn\'t work well with the bootstrap3-gradients family' ) LOGGER.info("Creating '{0}' theme from '{1}' and '{2}'".format( name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): url = 'https://bootswatch.com' if version: url += '/' + version url = '/'.join((url, swatch, fname)) LOGGER.info("Downloading: " + url) r = requests.get(url) if r.status_code > 299: LOGGER.error('Error {} getting {}', r.status_code, url) exit(1) data = r.text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data.encode('utf-8')) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent.encode('utf-8')) LOGGER.notice( 'Theme created. Change the THEME setting to "{0}" to use it.'. format(name))
def new_theme(self, name, engine, parent, create_legacy_meta=False): """Create a new theme.""" base = 'themes' themedir = os.path.join(base, name) LOGGER.info( "Creating theme {0} with parent {1} and engine {2} in {3}".format( name, parent, engine, themedir)) if not os.path.exists(base): os.mkdir(base) LOGGER.info("Created directory {0}".format(base)) # Check if engine and parent match parent_engine = utils.get_template_engine( utils.get_theme_chain(parent, self.site.themes_dirs)) if parent_engine != engine: LOGGER.error( "Cannot use engine {0} because parent theme '{1}' uses {2}". format(engine, parent, parent_engine)) return 2 # Create theme if not os.path.exists(themedir): os.mkdir(themedir) LOGGER.info("Created directory {0}".format(themedir)) else: LOGGER.error("Theme already exists") return 2 cp = configparser.ConfigParser() cp['Theme'] = {'engine': engine, 'parent': parent} theme_meta_path = os.path.join(themedir, name + '.theme') with io.open(theme_meta_path, 'w', encoding='utf-8') as fh: cp.write(fh) LOGGER.info("Created file {0}".format(theme_meta_path)) if create_legacy_meta: with io.open(os.path.join(themedir, 'parent'), 'w', encoding='utf-8') as fh: fh.write(parent + '\n') LOGGER.info("Created file {0}".format( os.path.join(themedir, 'parent'))) with io.open(os.path.join(themedir, 'engine'), 'w', encoding='utf-8') as fh: fh.write(engine + '\n') LOGGER.info("Created file {0}".format( os.path.join(themedir, 'engine'))) LOGGER.info("Theme {0} created successfully.".format(themedir)) LOGGER.info( 'Remember to set THEME="{0}" in conf.py to use this theme.'.format( name))
def test_get_asset_path(): assert get_asset_path( 'assets/css/rst.css', get_theme_chain('bootstrap3', ['themes'])).replace( '\\', '/').endswith('nikola/data/themes/base/assets/css/rst.css') assert get_asset_path( 'assets/css/theme.css', get_theme_chain('bootstrap3', ['themes'])).replace( '\\', '/').endswith('nikola/data/themes/bootstrap3/assets/css/theme.css') assert get_asset_path('nikola.py', get_theme_chain('bootstrap3', ['themes']), { 'nikola': '' }).replace('\\', '/').endswith('nikola/nikola.py') assert get_asset_path('nikola.py', get_theme_chain( 'bootstrap3', ['themes']), {'nikola': 'nikola'}) is None assert get_asset_path('nikola/nikola.py', get_theme_chain('bootstrap3', ['themes']), { 'nikola': 'nikola' }).replace('\\', '/').endswith('nikola/nikola.py')
def parse_theme_info(post, pkg_dir, config): theme = os.path.basename(pkg_dir) data = {} data['name'] = theme out_path = post.folder_relative + '/' + theme demo_dir = config['demo_screenshots_map'].get(out_path, out_path) data['previewimage'] = '/' + demo_dir + '.png' data['previewimage_thumbnail'] = '/' + demo_dir + '.thumbnail.png' data['demo_link'] = '/' + demo_dir + '/demo/' conf_sample = os.path.join(pkg_dir, 'conf.py.sample') engine = os.path.join(pkg_dir, 'engine') parent = os.path.join(pkg_dir, 'parent') if os.path.exists(conf_sample): post.add_dependency(conf_sample) with io.open(conf_sample, 'r', encoding='utf-8') as f: data['confpy'] = pygments.highlight( f.read(), PythonLexer(), utils.NikolaPygmentsHTML(theme + '_conf_sample', linenos=False)) else: data['confpy'] = None if os.path.exists(engine): post.add_dependency(engine) with io.open(engine, 'r', encoding='utf-8') as f: data['engine'] = f.read().strip() else: data['engine'] = 'mako' if os.path.exists(parent): post.add_dependency(parent) with io.open(parent, 'r', encoding='utf-8') as f: data['parent'] = f.read().strip() elif theme == 'base': pass else: raise ValueError("Theme {0} has no parent.".format(theme)) data['chain'] = utils.get_theme_chain(theme, [os.path.dirname(pkg_dir), 'themes']) data['chain'] = [os.path.basename(i) for i in reversed(data['chain'])] data['bootswatch'] = (('bootstrap' in data['chain'] or 'bootstrap-jinja' in data['chain'] or 'bootstrap3-jinja' in data['chain'] or 'bootstrap3' in data['chain']) and 'bootstrap3-gradients' not in data['chain']) data['tags'] = 'theme,' + data['engine'] return data
def sanity_check(theme=None): if theme is None: # Check them all for theme in theme_list(): sanity_check(theme) return themes = utils.get_theme_chain(theme, themes_dirs=['v7']) themes_bn = [os.path.basename(i) for i in themes] engine = utils.get_template_engine(themes) # Inheritance checks # All themes must inherit from base if themes_bn[-1] != 'base': error("theme {0} doesn't inherit from base".format(theme)) # All jinja themes must inherit from base-jinja if engine == "jinja" and "base-jinja" not in themes_bn: error("theme {0} is jinja-based and doesn't inherit from base-jinja".format(theme)) # All mako themes must NOT inherit from base-jinja if engine == "mako" and "base-jinja" in themes_bn: error("theme {0} is mako-based and inherits from base-jinja".format(theme)) # Detect exact asset duplication in theme chain for root, dirs, files in os.walk("v7/"+theme): for f in files: path = "/".join([root, f]) asset = path.split("/", 2)[-1] r, p1, p2 = is_asset_duplicated(asset, themes) if r: error("duplicated asset: {0} {1}".format(p1, p2)) # Detect deprecated names and anonymous namespaces for root, dirs, files in os.walk("v7/"+theme+"/templates"): for f in files: path = "/".join([root, f]) with io.open(path, "r", encoding="utf-8") as inf: data = inf.read() for k, exceptions in blacklist: if k in data and f not in exceptions: error("theme '{0}' contains deprecated name '{1}' in {2}".format(theme, k, path)) # Ensure the theme has a README.md if utils.get_asset_path('README.md', themes) is None: error("theme '{0}' has no README.md".format(theme)) # Ensure the theme has a meta file if utils.get_asset_path(theme + '.theme', themes) is None: warning("theme '{0}' has no {0}.theme meta file".format(theme))
def get_data(theme): data = {} data['name'] = theme readme = utils.get_asset_path('README', [theme]) if readme: data['readme'] = open(readme).read() else: data['readme'] = 'No readme file available' data['chain'] = utils.get_theme_chain(theme) data['bootswatch'] = ('bootstrap' in data['chain'] or 'bootstrap-jinja' in data['chain'] or 'bootstrap3-jinja' in data['chain'] or 'bootstrap3' in data['chain']) and \ 'bootstrap3-gradients' not in data['chain'] data['engine'] = utils.get_template_engine(data['chain']) data['chain'] = data['chain'][::-1] return data
def new_theme(self, name, engine, parent): """Create a new theme.""" base = 'themes' themedir = os.path.join(base, name) LOGGER.info( "Creating theme {0} with parent {1} and engine {2} in {3}".format( name, parent, engine, themedir)) if not os.path.exists(base): os.mkdir(base) LOGGER.info("Created directory {0}".format(base)) # Check if engine and parent match engine_file = utils.get_asset_path( 'engine', utils.get_theme_chain(parent, self.site.themes_dirs)) with io.open(engine_file, 'r', encoding='utf-8') as fh: parent_engine = fh.read().strip() if parent_engine != engine: LOGGER.error( "Cannot use engine {0} because parent theme '{1}' uses {2}". format(engine, parent, parent_engine)) return 2 # Create theme if not os.path.exists(themedir): os.mkdir(themedir) LOGGER.info("Created directory {0}".format(themedir)) else: LOGGER.error("Theme already exists") return 2 with io.open(os.path.join(themedir, 'parent'), 'w', encoding='utf-8') as fh: fh.write(parent + '\n') LOGGER.info("Created file {0}".format( os.path.join(themedir, 'parent'))) with io.open(os.path.join(themedir, 'engine'), 'w', encoding='utf-8') as fh: fh.write(engine + '\n') LOGGER.info("Created file {0}".format( os.path.join(themedir, 'engine'))) LOGGER.info("Theme {0} created successfully.".format(themedir)) LOGGER.notice( 'Remember to set THEME="{0}" in conf.py to use this theme.'.format( name))
def new_theme(self, name, engine, parent, create_legacy_meta=False): """Create a new theme.""" base = 'themes' themedir = os.path.join(base, name) LOGGER.info("Creating theme {0} with parent {1} and engine {2} in {3}".format(name, parent, engine, themedir)) if not os.path.exists(base): os.mkdir(base) LOGGER.info("Created directory {0}".format(base)) # Check if engine and parent match parent_engine = utils.get_template_engine(utils.get_theme_chain(parent, self.site.themes_dirs)) if parent_engine != engine: LOGGER.error("Cannot use engine {0} because parent theme '{1}' uses {2}".format(engine, parent, parent_engine)) return 2 # Create theme if not os.path.exists(themedir): os.mkdir(themedir) LOGGER.info("Created directory {0}".format(themedir)) else: LOGGER.error("Theme already exists") return 2 cp = configparser.ConfigParser() cp['Theme'] = { 'engine': engine, 'parent': parent } theme_meta_path = os.path.join(themedir, name + '.theme') with io.open(theme_meta_path, 'w', encoding='utf-8') as fh: cp.write(fh) LOGGER.info("Created file {0}".format(theme_meta_path)) if create_legacy_meta: with io.open(os.path.join(themedir, 'parent'), 'w', encoding='utf-8') as fh: fh.write(parent + '\n') LOGGER.info("Created file {0}".format(os.path.join(themedir, 'parent'))) with io.open(os.path.join(themedir, 'engine'), 'w', encoding='utf-8') as fh: fh.write(engine + '\n') LOGGER.info("Created file {0}".format(os.path.join(themedir, 'engine'))) LOGGER.info("Theme {0} created successfully.".format(themedir)) LOGGER.notice('Remember to set THEME="{0}" in conf.py to use this theme.'.format(name))
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" name = options['name'] swatch = options['swatch'] if not swatch: LOGGER.error('The -s option is mandatory') return 1 parent = options['parent'] version = '4' # Check which Bootstrap version to use themes = utils.get_theme_chain(parent, self.site.themes_dirs) if _check_for_theme('bootstrap', themes) or _check_for_theme('bootstrap-jinja', themes): version = '2' elif _check_for_theme('bootstrap3', themes) or _check_for_theme('bootstrap3-jinja', themes): version = '3' elif _check_for_theme('bootstrap4', themes) or _check_for_theme('bootstrap4-jinja', themes): version = '4' elif not _check_for_theme('bootstrap4', themes) and not _check_for_theme('bootstrap4-jinja', themes): LOGGER.warn('"bootswatch_theme" only makes sense for themes that use bootstrap') elif _check_for_theme('bootstrap3-gradients', themes) or _check_for_theme('bootstrap3-gradients-jinja', themes): LOGGER.warn('"bootswatch_theme" doesn\'t work well with the bootstrap3-gradients family') LOGGER.info("Creating '{0}' theme from '{1}' and '{2}'".format(name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): url = 'https://bootswatch.com' if version: url += '/' + version url = '/'.join((url, swatch, fname)) LOGGER.info("Downloading: " + url) r = requests.get(url) if r.status_code > 299: LOGGER.error('Error {} getting {}', r.status_code, url) exit(1) data = r.text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data.encode('utf-8')) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent.encode('utf-8')) LOGGER.notice('Theme created. Change the THEME setting to "{0}" to use it.'.format(name))
def init_theme(theme): t_path = "/".join(["sites", theme]) o_path = os.path.abspath("/".join(["output", "v6", theme])) if os.path.isdir(t_path): shutil.rmtree(t_path) if os.path.isdir(o_path): shutil.rmtree(o_path) subprocess.check_call(["nikola", "init", "--demo", t_path], stdout=subprocess.PIPE) os.symlink(os.path.abspath("themes"), os.path.abspath("/".join([t_path, "themes"]))) conf_path = "/".join([t_path,"conf.py"]) # Get custom required settings from the theme themes = utils.get_theme_chain(theme) extra_conf_path = utils.get_asset_path('conf.py.sample', themes) extra_conf = '' if extra_conf_path: extra_conf = open(extra_conf_path, 'r').read() with codecs.open(conf_path, "a", "utf-8") as conf: conf.write("\n\n{2}\n\nTHEME = '{0}'\n\nOUTPUT_FOLDER = '{1}'\n\nSOCIAL_BUTTONS_CODE = ''\n".format(theme, o_path, extra_conf))
def read_theme(theme): # Gather this theme's data theme_name = os.path.basename(theme) data = {} data['name'] = theme_name readme = os.path.join(theme, 'README.md') if os.path.isfile(readme): with codecs.open(readme, 'r', 'utf8') as inf: data['readme'] = inf.read() else: data['readme'] = '' themes = utils.get_theme_chain(theme_name) data['engine'] = utils.get_template_engine(themes) if 'bootstrap3' in themes: data['bs_version'] = 3 elif 'bootstrap' in themes: data['bs_version'] = 2 else: data['bs_version'] = 0
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" if requests is None: print( 'To use the bootswatch_theme command, you need to install the ' '"requests" package.') return name = options['name'] swatch = options['swatch'] parent = options['parent'] # See if we need bootswatch v2 or v3 themes = utils.get_theme_chain(parent) version = '2' if 'bootstrap3' in themes: version = '' elif 'bootstrap' not in themes: print( 'WARNING: bootswatch_theme only makes sense for themes that use bootstrap' ) print("Creating '{0}' theme from '{1}' and '{2}'".format( name, swatch, parent)) try: os.makedirs(os.path.join('themes', name, 'assets', 'css')) except: pass for fname in ('bootstrap.min.css', 'bootstrap.css'): url = '/'.join(('http://bootswatch.com', version, swatch, fname)) print("Downloading: ", url) data = requests.get(url).text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent) print('Theme created. Change the THEME setting to "{0}" to use ' 'it.'.format(name))
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" if requests is None: print('To use the bootswatch_theme command, you need to install the ' '"requests" package.') return name = options['name'] swatch = options['swatch'] parent = options['parent'] version = '' # See if we need bootswatch for bootstrap v2 or v3 themes = utils.get_theme_chain(parent) if 'bootstrap3' not in themes: version = '2' elif 'bootstrap' not in themes: print('WARNING: bootswatch_theme only makes sense for themes that use bootstrap') print("Creating '{0}' theme from '{1}' and '{2}'".format(name, swatch, parent)) try: os.makedirs(os.path.join('themes', name, 'assets', 'css')) except: pass for fname in ('bootstrap.min.css', 'bootstrap.css'): url = '/'.join(('http://bootswatch.com', version, swatch, fname)) print("Downloading: ", url) data = requests.get(url).text with open(os.path.join('themes', name, 'assets', 'css', fname), 'wb+') as output: output.write(data.encode('utf-8')) with open(os.path.join('themes', name, 'parent'), 'wb+') as output: output.write(parent.encode('utf-8')) print('Theme created. Change the THEME setting to "{0}" to use ' 'it.'.format(name))
def init_theme(theme): t_path = "/".join(["sites", theme]) o_path = os.path.abspath("/".join(["output", "v7", theme])) if os.path.isdir(t_path): shutil.rmtree(t_path) if os.path.isdir(o_path): shutil.rmtree(o_path) subprocess.check_call(["nikola", "init", "-qd", t_path], stdout=subprocess.PIPE) os.symlink(os.path.abspath("v7"), os.path.abspath("/".join([t_path, "themes"]))) conf_path = "/".join([t_path, "conf.py"]) # Get custom required settings from the theme themes = utils.get_theme_chain(theme, _themes_dir="v7") extra_conf_path = utils.get_asset_path("conf.py.sample", themes, _themes_dir="v7") extra_conf = "" if extra_conf_path: extra_conf = io.open(extra_conf_path, "r", encoding="utf-8").read() with io.open(conf_path, "a", encoding="utf-8") as conf: conf.write( "\n\n{2}\n\nTHEME = '{0}'\n\nUSE_BUNDLES = False\n\nOUTPUT_FOLDER = '{1}'\n\nSOCIAL_BUTTONS_CODE = ''\nUSE_BASE_TAG = False\n".format( theme, o_path, extra_conf ) )
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" name = options['name'] swatch = options['swatch'] if not swatch: LOGGER.error('The -s option is mandatory') return 1 parent = options['parent'] version = '4' # Check which Bootstrap version to use themes = utils.get_theme_chain(parent, self.site.themes_dirs) if _check_for_theme('bootstrap', themes) or _check_for_theme('bootstrap-jinja', themes): version = '2' elif _check_for_theme('bootstrap3', themes) or _check_for_theme('bootstrap3-jinja', themes): version = '3' elif _check_for_theme('bootstrap4', themes) or _check_for_theme('bootstrap4-jinja', themes): version = '4' elif not _check_for_theme('bootstrap4', themes) and not _check_for_theme('bootstrap4-jinja', themes): LOGGER.warning( '"subtheme" only makes sense for themes that use bootstrap') elif _check_for_theme('bootstrap3-gradients', themes) or _check_for_theme('bootstrap3-gradients-jinja', themes): LOGGER.warning( '"subtheme" doesn\'t work well with the bootstrap3-gradients family') LOGGER.info("Creating '{0}' theme from '{1}' and '{2}'".format( name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): if swatch in [ 'bubblegum', 'business-tycoon', 'charming', 'daydream', 'executive-suite', 'good-news', 'growth', 'harbor', 'hello-world', 'neon-glow', 'pleasant', 'retro', 'vibrant-sea', 'wizardry']: # Hackerthemes LOGGER.info( 'Hackertheme-based subthemes often require you use a custom font for full effect.') if version != '4': LOGGER.error( 'The hackertheme subthemes are only available for Bootstrap 4.') return 1 if fname == 'bootstrap.css': url = 'https://raw.githubusercontent.com/HackerThemes/theme-machine/master/dist/{swatch}/css/bootstrap4-{swatch}.css'.format( swatch=swatch) else: url = 'https://raw.githubusercontent.com/HackerThemes/theme-machine/master/dist/{swatch}/css/bootstrap4-{swatch}.min.css'.format( swatch=swatch) else: # Bootswatch url = 'https://bootswatch.com' if version: url += '/' + version url = '/'.join((url, swatch, fname)) LOGGER.info("Downloading: " + url) r = requests.get(url) if r.status_code > 299: LOGGER.error('Error {} getting {}', r.status_code, url) return 1 data = r.text with open(os.path.join('themes', name, 'assets', 'css', fname), 'w+') as output: output.write(data) with open(os.path.join('themes', name, '%s.theme' % name), 'w+') as output: parent_theme_data_path = utils.get_asset_path( '%s.theme' % parent, themes) cp = configparser.ConfigParser() cp.read(parent_theme_data_path) cp['Theme']['parent'] = parent cp['Family'] = {'family': cp['Family']['family']} cp.write(output) LOGGER.info( 'Theme created. Change the THEME setting to "{0}" to use it.'.format(name))
def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" name = options['name'] swatch = options['swatch'] if not swatch: LOGGER.error('The -s option is mandatory') return 1 parent = options['parent'] version = '4' # Check which Bootstrap version to use themes = utils.get_theme_chain(parent, self.site.themes_dirs) if _check_for_theme('bootstrap', themes) or _check_for_theme('bootstrap-jinja', themes): version = '2' elif _check_for_theme('bootstrap3', themes) or _check_for_theme('bootstrap3-jinja', themes): version = '3' elif _check_for_theme('bootstrap4', themes) or _check_for_theme('bootstrap4-jinja', themes): version = '4' elif not _check_for_theme('bootstrap4', themes) and not _check_for_theme('bootstrap4-jinja', themes): LOGGER.warn( '"subtheme" only makes sense for themes that use bootstrap') elif _check_for_theme('bootstrap3-gradients', themes) or _check_for_theme('bootstrap3-gradients-jinja', themes): LOGGER.warn( '"subtheme" doesn\'t work well with the bootstrap3-gradients family') LOGGER.info("Creating '{0}' theme from '{1}' and '{2}'".format( name, swatch, parent)) utils.makedirs(os.path.join('themes', name, 'assets', 'css')) for fname in ('bootstrap.min.css', 'bootstrap.css'): if swatch in [ 'bubblegum', 'business-tycoon', 'charming', 'daydream', 'executive-suite', 'good-news', 'growth', 'harbor', 'hello-world', 'neon-glow', 'pleasant', 'retro', 'vibrant-sea', 'wizardry']: # Hackerthemes LOGGER.info( 'Hackertheme-based subthemes often require you use a custom font for full effect.') if version != '4': LOGGER.error( 'The hackertheme subthemes are only available for Bootstrap 4.') return 1 if fname == 'bootstrap.css': url = 'https://raw.githubusercontent.com/HackerThemes/theme-machine/master/dist/{swatch}/css/bootstrap4-{swatch}.css'.format( swatch=swatch) else: url = 'https://raw.githubusercontent.com/HackerThemes/theme-machine/master/dist/{swatch}/css/bootstrap4-{swatch}.min.css'.format( swatch=swatch) else: # Bootswatch url = 'https://bootswatch.com' if version: url += '/' + version url = '/'.join((url, swatch, fname)) LOGGER.info("Downloading: " + url) r = requests.get(url) if r.status_code > 299: LOGGER.error('Error {} getting {}', r.status_code, url) return 1 data = r.text with open(os.path.join('themes', name, 'assets', 'css', fname), 'w+') as output: output.write(data) with open(os.path.join('themes', name, '%s.theme' % name), 'w+') as output: parent_theme_data_path = utils.get_asset_path( '%s.theme' % parent, themes) cp = configparser.ConfigParser() cp.read(parent_theme_data_path) cp['Theme']['parent'] = parent cp['Family'] = {'family': cp['Family']['family']} cp.write(output) LOGGER.notice( 'Theme created. Change the THEME setting to "{0}" to use it.'.format(name))
def parse_theme_info(post, pkg_dir, config): theme = os.path.basename(pkg_dir) data = {} data['name'] = theme out_path = post.folder_relative + '/' + theme demo_dir = config['demo_screenshots_map'].get(out_path, out_path) data['previewimage'] = '/' + demo_dir + '.png' data['previewimage_thumbnail'] = '/' + demo_dir + '.thumbnail.png' data['demo_link'] = '/' + demo_dir + '/demo/' conf_sample = os.path.join(pkg_dir, 'conf.py.sample') ini = os.path.join(pkg_dir, theme + '.theme') engine = os.path.join(pkg_dir, 'engine') parent = os.path.join(pkg_dir, 'parent') data['chain'] = utils.get_theme_chain(theme, [os.path.dirname(pkg_dir), 'themes']) data['chain'] = [os.path.basename(i) for i in reversed(data['chain'])] if os.path.exists(conf_sample): post.add_dependency(conf_sample) with io.open(conf_sample, 'r', encoding='utf-8') as f: data['confpy'] = pygments.highlight( f.read(), PythonLexer(), utils.NikolaPygmentsHTML(theme + '_conf_sample', linenos=False)) else: data['confpy'] = None if os.path.exists(ini): post.add_dependency(ini) c = configparser.ConfigParser() c.read(ini) data['parent'] = c.get('Theme', 'parent', fallback=None) data['engine'] = c.get('Theme', 'engine', fallback='mako') data['bootswatch'] = c.getboolean('Nikola', 'bootswatch', fallback=False) data['tags'] = 'theme,' + data['engine'] theme_tags = c.get('Theme', 'tags', fallback='') if theme_tags: data['tags'] += ',' + theme_tags if data['parent'] is None and theme != 'base': raise ValueError("Theme {0} has no parent.".format(theme)) else: if os.path.exists(engine): post.add_dependency(engine) with io.open(engine, 'r', encoding='utf-8') as f: data['engine'] = f.read().strip() else: data['engine'] = 'mako' if os.path.exists(parent): post.add_dependency(parent) with io.open(parent, 'r', encoding='utf-8') as f: data['parent'] = f.read().strip() elif theme == 'base': pass else: raise ValueError("Theme {0} has no parent.".format(theme)) data['bootswatch'] = (('bootstrap' in data['chain'] or 'bootstrap-jinja' in data['chain'] or 'bootstrap3-jinja' in data['chain'] or 'bootstrap3' in data['chain']) and 'bootstrap3-gradients' not in data['chain']) data['tags'] = 'theme,' + data['engine'] return data
def parse_theme_info(post, pkg_dir, config): theme = os.path.basename(pkg_dir) data = {} data['name'] = theme out_path = post.folder_relative + '/' + theme demo_dir = config['demo_screenshots_map'].get(out_path, out_path) data['previewimage'] = '/' + demo_dir + '.png' data['previewimage_thumbnail'] = '/' + demo_dir + '.thumbnail.png' data['demo_link'] = '/' + demo_dir + '/demo/' conf_sample = os.path.join(pkg_dir, 'conf.py.sample') ini = os.path.join(pkg_dir, theme + '.theme') engine = os.path.join(pkg_dir, 'engine') parent = os.path.join(pkg_dir, 'parent') data['chain'] = utils.get_theme_chain(theme, [os.path.dirname(pkg_dir), 'themes']) data['chain'] = [os.path.basename(i) for i in reversed(data['chain'])] if os.path.exists(conf_sample): post.add_dependency(conf_sample) with io.open(conf_sample, 'r', encoding='utf-8') as f: data['confpy'] = pygments.highlight( f.read(), PythonLexer(), utils.NikolaPygmentsHTML(theme + '_conf_sample', linenos=False)) else: data['confpy'] = None if os.path.exists(ini): post.add_dependency(ini) c = configparser.ConfigParser() c.read(ini) data['parent'] = c.get('Theme', 'parent', fallback=None) data['engine'] = c.get('Theme', 'engine', fallback='mako') data['family'] = c.get('Family', 'family', fallback=theme) data['family_head'] = data['family'] == theme if data['engine'] == 'mako': data['family_mako_version'] = theme _other = c.get('Family', 'jinja_version', fallback=None) data['family_jinja_version'] = _other data['show_family_data'] = bool(_other) else: data['family_jinja_version'] = theme _other = c.get('Family', 'mako_version', fallback=None) data['family_mako_version'] = _other data['show_family_data'] = bool(_other) data['family_variants'] = [ i.strip() for i in c.get('Family', 'variants', fallback='').split(',') ] data['family_variants'] = [i for i in data['family_variants'] if i] # remove empty strings _variants_count = len(data['family_variants']) data[ 'family_variants_text'] = '1 variant' if _variants_count == 1 else '{0} variants'.format( _variants_count) data['show_family_data'] = data['show_family_data'] or bool( data['family_variants']) data['bootswatch'] = c.getboolean('Nikola', 'bootswatch', fallback=False) data['tags'] = 'newmeta,theme,' + data['engine'] data['license'] = c.get('Theme', 'license', fallback=None) data['author'] = c.get('Theme', 'author', fallback=None) data['author_url'] = c.get('Theme', 'author_url', fallback=None) data['author_url'] = c.get('Theme', 'author_url', fallback=None) based_on = c.get('Theme', 'based_on', fallback=None) based_on_list = [] if based_on: for i in based_on.split(','): i = i.strip() m = re.match("(.*?) ?<(.*?)>", i) if m: based_on_list.append('<a href="{0[1]}">{0[0]}</a>'.format( m.groups())) else: based_on_list.append(i) data['based_on'] = ', '.join(based_on_list) theme_tags = c.get('Theme', 'tags', fallback='') if theme_tags: data['tags'] += ',' + theme_tags if data['parent'] is None and theme != 'base': raise ValueError("Theme {0} has no parent.".format(theme)) else: # Old-style metadata if os.path.exists(engine): post.add_dependency(engine) with io.open(engine, 'r', encoding='utf-8') as f: data['engine'] = f.read().strip() else: data['engine'] = 'mako' if os.path.exists(parent): post.add_dependency(parent) with io.open(parent, 'r', encoding='utf-8') as f: data['parent'] = f.read().strip() elif theme == 'base': pass else: raise ValueError("Theme {0} has no parent.".format(theme)) data['bootswatch'] = (('bootstrap' in data['chain'] or 'bootstrap-jinja' in data['chain'] or 'bootstrap3-jinja' in data['chain'] or 'bootstrap3' in data['chain']) and 'bootstrap3-gradients' not in data['chain']) data['tags'] = 'theme,' + data['engine'] data['family'] = theme data['family_head'] = True data['family_{0}_version'.format(data['engine'])] = theme return data
def parse_theme_info(post, pkg_dir, config): theme = os.path.basename(pkg_dir) data = {} data['name'] = theme out_path = post.folder_relative + '/' + theme demo_dir = config['demo_screenshots_map'].get(out_path, out_path) data['previewimage'] = '/' + demo_dir + '.png' data['previewimage_thumbnail'] = '/' + demo_dir + '.thumbnail.png' data['demo_link'] = '/' + demo_dir + '/demo/' conf_sample = os.path.join(pkg_dir, 'conf.py.sample') ini = os.path.join(pkg_dir, theme + '.theme') engine = os.path.join(pkg_dir, 'engine') parent = os.path.join(pkg_dir, 'parent') data['chain'] = utils.get_theme_chain(theme, [os.path.dirname(pkg_dir), 'themes']) data['chain'] = [os.path.basename(i) for i in reversed(data['chain'])] try: data['dirver'] = _version_from_path(pkg_dir) except Exception: data['dirver'] = config['versions_supported'][-1] data['slug_versioned'] = 'v{0}/{1}'.format(data['dirver'], theme) data['slug_sortable'] = '{1} v{0}'.format(data['dirver'], theme) data['allver'] = range(data['dirver'], config['versions_supported'][-1] + 1) if os.path.exists(conf_sample): post.add_dependency(conf_sample) with io.open(conf_sample, 'r', encoding='utf-8') as f: data['confpy'] = pygments.highlight( f.read(), PythonLexer(), utils.NikolaPygmentsHTML(theme + '_conf_sample', linenos=False)) else: data['confpy'] = None if os.path.exists(ini): post.add_dependency(ini) c = configparser.ConfigParser() c.read(ini) data['parent'] = c.get('Theme', 'parent', fallback=None) data['engine'] = c.get('Theme', 'engine', fallback='mako') data['family'] = c.get('Family', 'family', fallback=theme) data['family_head'] = data['family'] == theme if data['engine'] == 'mako': data['family_mako_version'] = theme _other = c.get('Family', 'jinja_version', fallback=None) data['family_jinja_version'] = _other data['show_family_data'] = bool(_other) else: data['family_jinja_version'] = theme _other = c.get('Family', 'mako_version', fallback=None) data['family_mako_version'] = _other data['show_family_data'] = bool(_other) data['family_variants'] = [i.strip() for i in c.get('Family', 'variants', fallback='').split(',')] data['family_variants'] = [i for i in data['family_variants'] if i] # remove empty strings _variants_count = len(data['family_variants']) data['family_variants_text'] = '1 variant' if _variants_count == 1 else '{0} variants'.format(_variants_count) data['show_family_data'] = data['show_family_data'] or bool(data['family_variants']) or not data['family_head'] data['bootswatch'] = c.getboolean('Nikola', 'bootswatch', fallback=False) data['tags'] = 'newmeta,theme,' + data['engine'] + ',v{0}'.format(data['dirver']) data['license'] = c.get('Theme', 'license', fallback=None) data['author'] = c.get('Theme', 'author', fallback=None) data['author_url'] = c.get('Theme', 'author_url', fallback=None) data['author_url'] = c.get('Theme', 'author_url', fallback=None) based_on = c.get('Theme', 'based_on', fallback=None) based_on_list = [] if based_on: for i in based_on.split(','): i = i.strip() m = re.match("(.*?) ?<(.*?)>", i) if m: based_on_list.append('<a href="{0[1]}">{0[0]}</a>'.format( m.groups())) else: based_on_list.append(i) data['based_on'] = ', '.join(based_on_list) theme_tags = c.get('Theme', 'tags', fallback='') if theme_tags: data['tags'] += ',' + theme_tags if data['parent'] is None and theme != 'base': raise ValueError("Theme {0} has no parent.".format(theme)) else: # Old-style metadata if os.path.exists(engine): post.add_dependency(engine) with io.open(engine, 'r', encoding='utf-8') as f: data['engine'] = f.read().strip() else: data['engine'] = 'mako' if os.path.exists(parent): post.add_dependency(parent) with io.open(parent, 'r', encoding='utf-8') as f: data['parent'] = f.read().strip() elif theme == 'base': pass else: raise ValueError("Theme {0} has no parent.".format(theme)) data['bootswatch'] = (('bootstrap' in data['chain'] or 'bootstrap-jinja' in data['chain'] or 'bootstrap3-jinja' in data['chain'] or 'bootstrap3' in data['chain']) and 'bootstrap3-gradients' not in data['chain']) data['tags'] = 'theme,' + data['engine'] + ',v{0}'.format(data['dirver']) data['family'] = theme data['family_head'] = True data['family_{0}_version'.format(data['engine'])] = theme return data