From b119f8228d2fddde3665446913d8bc31c1d5ef0a Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Wed, 11 Dec 2019 12:02:36 +0100 Subject: [PATCH 01/14] Fixed django and sqlalchemy requirements --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index fc27f40..e140e62 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django +django==2.2.5 jmespath gunicorn pandas From cb2a864437be1dc425735a93e898cc8b14b04edf Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Thu, 12 Dec 2019 16:29:44 +0100 Subject: [PATCH 02/14] Assumptions and sources are removed if category (ie. source) is deleted --- meta/migrations/0006_auto_20191212_1617.py | 29 ++++++++++++++++++++++ meta/models.py | 6 ++--- 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 meta/migrations/0006_auto_20191212_1617.py diff --git a/meta/migrations/0006_auto_20191212_1617.py b/meta/migrations/0006_auto_20191212_1617.py new file mode 100644 index 0000000..9c221e5 --- /dev/null +++ b/meta/migrations/0006_auto_20191212_1617.py @@ -0,0 +1,29 @@ +# Generated by Django 2.2.5 on 2019-12-12 15:17 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('meta', '0005_auto_20190211_1125'), + ] + + operations = [ + migrations.AlterField( + model_name='assumption', + name='category', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='meta.Category'), + ), + migrations.AlterField( + model_name='assumption', + name='source', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='meta.Source'), + ), + migrations.AlterField( + model_name='source', + name='category', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='meta.Category'), + ), + ] diff --git a/meta/models.py b/meta/models.py index 6ccab42..41c1188 100644 --- a/meta/models.py +++ b/meta/models.py @@ -20,8 +20,8 @@ class Assumption(models.Model): app_name = models.CharField(max_length=255) - source = models.ForeignKey('Source', on_delete=models.DO_NOTHING) - category = models.ForeignKey('Category', on_delete=models.DO_NOTHING) + source = models.ForeignKey('Source', on_delete=models.CASCADE) + category = models.ForeignKey('Category', on_delete=models.CASCADE) def __str__(self): return self.name @@ -37,7 +37,7 @@ class Source(models.Model): app_name = models.CharField(max_length=255) - category = models.ForeignKey('Category', on_delete=models.DO_NOTHING) + category = models.ForeignKey('Category', on_delete=models.CASCADE) def json(self): return JsonWidget(self.meta_data).render() From 8965ff9ceff4a88c7e012463dd6a4110d33ba84d Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Thu, 12 Dec 2019 16:38:56 +0100 Subject: [PATCH 03/14] Added dynamic title for meta app lists --- meta/templates/meta/app_list.html | 2 +- meta/views.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/meta/templates/meta/app_list.html b/meta/templates/meta/app_list.html index 237e70b..d458d06 100644 --- a/meta/templates/meta/app_list.html +++ b/meta/templates/meta/app_list.html @@ -7,7 +7,7 @@
-

Quellen

+

{{title}}

{% for category in categories %} diff --git a/meta/views.py b/meta/views.py index 6dfec3c..de52f23 100644 --- a/meta/views.py +++ b/meta/views.py @@ -39,6 +39,7 @@ class AppListView(ListView): default_template_name = 'meta/app_list.html' app_name = None ordering = ['category__name'] + title = "Quellen" def __init__(self, *args, **kwargs): super(AppListView, self).__init__(*args, **kwargs) @@ -53,6 +54,8 @@ def get_context_data(self, *, object_list=None, **kwargs): context = super(AppListView, self).get_context_data( object_list=object_list, **kwargs) + context['title'] = self.title + # Try to load base.html template from app: base_template = 'meta/base.html' if self.app_name is not None: @@ -94,6 +97,7 @@ def get_template_names(self): class AssumptionsView(AppListView): source_url = None model = Assumption + title = "Annahmen" def get_context_data(self, *, object_list=None, **kwargs): context = super(AssumptionsView, self).get_context_data( From a4ec0f2a0c47f1f6cdc1493b4592fd333f1599b5 Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Thu, 12 Dec 2019 16:54:48 +0100 Subject: [PATCH 04/14] Fixed github security alert (django requirement set to 2.2.8) --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index e140e62..8820464 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django==2.2.5 +django==2.2.8 jmespath gunicorn pandas From a53f0e8ede7cea48ffdbfad44dd3b10e777349af Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Fri, 13 Dec 2019 12:57:20 +0100 Subject: [PATCH 05/14] Added missing Makefile for sphinx --- doc/Makefile | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100755 doc/Makefile diff --git a/doc/Makefile b/doc/Makefile new file mode 100755 index 0000000..298ea9e --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,19 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +SOURCEDIR = . +BUILDDIR = _build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file From 18eeba6ca4196f483d67b976e898c82aaded7e20 Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Fri, 13 Dec 2019 13:32:01 +0100 Subject: [PATCH 06/14] Blacked --- db_apps/oemof_results.py | 175 +++--- doc/_static/run_tasks.py | 1 - doc/_static/tasks.py | 1 - doc/conf.py | 69 +-- install_requirements.py | 10 +- meta/admin.py | 1 - meta/apps.py | 2 +- meta/migrations/0001_initial.py | 81 ++- meta/migrations/0002_auto_20181130_1141.py | 6 +- meta/migrations/0003_source_meta_data.py | 6 +- meta/migrations/0004_auto_20190207_1139.py | 17 +- meta/migrations/0005_auto_20190211_1125.py | 27 +- meta/migrations/0006_auto_20191212_1617.py | 26 +- meta/models.py | 32 +- meta/views.py | 49 +- meta/widgets.py | 29 +- setup.py | 21 +- static/ionicons-2.0.1/builder/generate.py | 521 +++++++++--------- .../builder/scripts/eotlitetool.py | 398 +++++++------ .../builder/scripts/generate_font.py | 291 +++++----- templatetags/labels.py | 11 +- templatetags/simple.py | 1 - user_sessions/__init__.py | 2 +- user_sessions/apps.py | 4 +- user_sessions/sessions.py | 7 +- user_sessions/urls.py | 7 +- user_sessions/utils.py | 16 +- user_sessions/views.py | 5 +- utils/constants.py | 24 +- utils/forms.py | 20 +- utils/highcharts.py | 93 ++-- utils/mail.py | 36 +- utils/permissions.py | 5 +- utils/shortcuts.py | 11 +- utils/views.py | 95 ++-- utils/visualizations.py | 7 +- utils/widgets.py | 93 ++-- wam/admin.py | 5 +- wam/celery.py | 31 +- wam/settings.py | 155 +++--- wam/urls.py | 36 +- wam/views.py | 42 +- 42 files changed, 1238 insertions(+), 1231 deletions(-) diff --git a/db_apps/oemof_results.py b/db_apps/oemof_results.py index 606c932..0782660 100644 --- a/db_apps/oemof_results.py +++ b/db_apps/oemof_results.py @@ -1,9 +1,7 @@ - import re import pandas import transaction -from sqlalchemy import ( - Column, Integer, String, ARRAY, ForeignKey) +from sqlalchemy import Column, Integer, String, ARRAY, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import DOUBLE_PRECISION from sqlalchemy.ext.declarative import declarative_base @@ -48,90 +46,49 @@ class OemofInputResult(Base): - __tablename__ = 'stemp_oemof_input_result' + __tablename__ = "stemp_oemof_input_result" - input_result_id = Column( - Integer, - primary_key=True - ) - input_id = Column(Integer, ForeignKey('stemp_oemof_data.data_id')) - result_id = Column(Integer, ForeignKey('stemp_oemof_data.data_id')) + input_result_id = Column(Integer, primary_key=True) + input_id = Column(Integer, ForeignKey("stemp_oemof_data.data_id")) + result_id = Column(Integer, ForeignKey("stemp_oemof_data.data_id")) input = relationship( - "OemofData", - backref="input", - uselist=False, - foreign_keys=[input_id], + "OemofData", backref="input", uselist=False, foreign_keys=[input_id], ) result = relationship( - "OemofData", - backref="result", - uselist=False, - foreign_keys=[result_id], + "OemofData", backref="result", uselist=False, foreign_keys=[result_id], ) class OemofData(Base): - __tablename__ = 'stemp_oemof_data' + __tablename__ = "stemp_oemof_data" - data_id = Column( - Integer, - primary_key=True - ) + data_id = Column(Integer, primary_key=True) scalars = relationship("OemofScalar", cascade="delete") sequences = relationship("OemofSequence", cascade="delete") class OemofScalar(Base): - __tablename__ = 'stemp_oemof_scalar' + __tablename__ = "stemp_oemof_scalar" - scalar_id = Column( - Integer, - primary_key=True - ) - data_id = Column( - Integer, ForeignKey('stemp_oemof_data.data_id')) - from_node = Column( - String - ) - to_node = Column( - String - ) - attribute = Column( - String - ) - value = Column( - String - ) - type = Column( - String - ) + scalar_id = Column(Integer, primary_key=True) + data_id = Column(Integer, ForeignKey("stemp_oemof_data.data_id")) + from_node = Column(String) + to_node = Column(String) + attribute = Column(String) + value = Column(String) + type = Column(String) class OemofSequence(Base): - __tablename__ = 'stemp_oemof_sequence' + __tablename__ = "stemp_oemof_sequence" - sequence_id = Column( - Integer, - primary_key=True - ) - data_id = Column( - Integer, ForeignKey('stemp_oemof_data.data_id')) - from_node = Column( - String - ) - to_node = Column( - String, - nullable=True - ) - attribute = Column( - String - ) - value = Column( - ARRAY(DOUBLE_PRECISION) - ) - type = Column( - String - ) + sequence_id = Column(Integer, primary_key=True) + data_id = Column(Integer, ForeignKey("stemp_oemof_data.data_id")) + from_node = Column(String) + to_node = Column(String, nullable=True) + attribute = Column(String) + value = Column(ARRAY(DOUBLE_PRECISION)) + type = Column(String) def store_results(session, input_data, result_data): @@ -166,34 +123,33 @@ def store_results(session, input_data, result_data): result_data = convert_keys_to_strings(result_data) input_result = OemofInputResult() - for input_result_attr, data in ( - ('input', input_data), ('result', result_data)): + for input_result_attr, data in (("input", input_data), ("result", result_data)): scalars = [] sequences = [] for (from_node, to_node), sc_sq_dict in data.items(): - for key, value in sc_sq_dict['scalars'].items(): + for key, value in sc_sq_dict["scalars"].items(): scalars.append( OemofScalar( from_node=from_node, to_node=to_node, attribute=key, value=value, - type=type(value).__name__ + type=type(value).__name__, ) ) session.add_all(scalars) - for key, series in sc_sq_dict['sequences'].items(): - list_type = 'list' + for key, series in sc_sq_dict["sequences"].items(): + list_type = "list" if isinstance(series, pandas.Series): series = series.values.tolist() - list_type = 'series' + list_type = "series" sequences.append( OemofSequence( from_node=from_node, to_node=to_node, attribute=key, value=series, - type=list_type + type=list_type, ) ) session.add_all(sequences) @@ -208,8 +164,9 @@ def store_results(session, input_data, result_data): return result_id -def restore_results(session, input_result_id, restore_none_type=False, - advanced_label=None): +def restore_results( + session, input_result_id, restore_none_type=False, advanced_label=None +): """ Restores input and result data from OemofInputResult from DB @@ -229,49 +186,47 @@ def restore_results(session, input_result_id, restore_none_type=False, (dict, dict): Restored input- and result-data """ + def type_conversion(value_str, value_type): - if value_type == 'str': + if value_type == "str": return value_str - elif value_type == 'float': + elif value_type == "float": return float(value_str) - elif value_type == 'int': + elif value_type == "int": return int(value_str) - elif value_type == 'bool': + elif value_type == "bool": return bool(value_str) else: raise TypeError('Unknown conversion type "' + value_type + '"') def convert_label_to_namedtuple(label): def unpack_tuples(value): - if value.startswith('(') and value.endswith(')'): - value_list = value[1:-1].split(', ') + if value.startswith("(") and value.endswith(")"): + value_list = value[1:-1].split(", ") if len(value_list) == 1: single = value_list[0][:-1] - return (None, ) if single == 'None' else (single, ) + return (None,) if single == "None" else (single,) else: - return (None if v == 'None' else v for v in value_list) + return (None if v == "None" else v for v in value_list) else: - return None if value == 'None' else value + return None if value == "None" else value pattern = ( - f"{advanced_label.__name__}\(" + - ', '.join( + f"{advanced_label.__name__}\(" + + ", ".join( [ f"{field}=(?P<{field}>[\(\)A-Za-z0-9#._\-,\ ']*)" for field in advanced_label._fields ] - ) + - "\)" + ) + + "\)" ) try: - match = re.match(pattern, label.replace('\'', '')) + match = re.match(pattern, label.replace("'", "")) except AttributeError: return label if match is not None: - fields = { - k: unpack_tuples(v) - for k, v in match.groupdict().items() - } + fields = {k: unpack_tuples(v) for k, v in match.groupdict().items()} return advanced_label(**fields) else: return label @@ -281,35 +236,39 @@ def get_nodes(scalar_or_sequence): if advanced_label is not None: raw_nodes = tuple(map(convert_label_to_namedtuple, raw_nodes)) if restore_none_type: - return tuple(map(lambda x: None if x == 'None' else x, raw_nodes)) + return tuple(map(lambda x: None if x == "None" else x, raw_nodes)) else: return raw_nodes # Find results: - input_result = session.query(OemofInputResult).filter( - OemofInputResult.input_result_id == input_result_id).first() + input_result = ( + session.query(OemofInputResult) + .filter(OemofInputResult.input_result_id == input_result_id) + .first() + ) if input_result is None: raise IndexError( - 'Could not find OemofInputResult with ID #' + str(input_result_id)) + "Could not find OemofInputResult with ID #" + str(input_result_id) + ) input_data = {} result_data = {} - for input_result_attr, data in ( - ('input', input_data), ('result', result_data)): + for input_result_attr, data in (("input", input_data), ("result", result_data)): ir_attr = getattr(input_result, input_result_attr) for scalar in ir_attr.scalars: nodes = get_nodes(scalar) if nodes not in data: - data[nodes] = {'scalars': {}, 'sequences': {}} - data[nodes]['scalars'][scalar.attribute] = type_conversion( - scalar.value, scalar.type) + data[nodes] = {"scalars": {}, "sequences": {}} + data[nodes]["scalars"][scalar.attribute] = type_conversion( + scalar.value, scalar.type + ) for sequence in ir_attr.sequences: nodes = get_nodes(sequence) if nodes not in data: - data[nodes] = {'scalars': {}, 'sequences': {}} - if sequence.type == 'series': + data[nodes] = {"scalars": {}, "sequences": {}} + if sequence.type == "series": series = pandas.Series(sequence.value) else: series = sequence.value - data[nodes]['sequences'][sequence.attribute] = series + data[nodes]["sequences"][sequence.attribute] = series return input_data, result_data diff --git a/doc/_static/run_tasks.py b/doc/_static/run_tasks.py index 3b590f0..1bf1165 100644 --- a/doc/_static/run_tasks.py +++ b/doc/_static/run_tasks.py @@ -1,4 +1,3 @@ - from app_name import tasks diff --git a/doc/_static/tasks.py b/doc/_static/tasks.py index 8092883..8b6d4dc 100644 --- a/doc/_static/tasks.py +++ b/doc/_static/tasks.py @@ -1,4 +1,3 @@ - from wam.celery import app diff --git a/doc/conf.py b/doc/conf.py index b9ea50f..54175ac 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -19,14 +19,14 @@ # -- Project information ----------------------------------------------------- -project = 'WAM-Server' -copyright = '2018, Hendrik Huyskens' -author = 'Hendrik Huyskens' +project = "WAM-Server" +copyright = "2018, Hendrik Huyskens" +author = "Hendrik Huyskens" # The short X.Y version -version = '' +version = "" # The full version, including alpha/beta/rc tags -release = '' +release = "" # -- General configuration --------------------------------------------------- @@ -39,25 +39,25 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.doctest', - 'sphinx.ext.intersphinx', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.viewcode', + "sphinx.ext.autodoc", + "sphinx.ext.doctest", + "sphinx.ext.intersphinx", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx.ext.viewcode", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The master toctree document. -master_doc = 'index' +master_doc = "index" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -80,7 +80,7 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = 'alabaster' +html_theme = "alabaster" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -91,7 +91,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Custom sidebar templates, must be a dictionary that maps document names # to template names. @@ -107,7 +107,7 @@ # -- Options for HTMLHelp output --------------------------------------------- # Output file base name for HTML help builder. -htmlhelp_basename = 'WAM-Serverdoc' +htmlhelp_basename = "WAM-Serverdoc" # -- Options for LaTeX output ------------------------------------------------ @@ -116,15 +116,12 @@ # The paper size ('letterpaper' or 'a4paper'). # # 'papersize': 'letterpaper', - # The font size ('10pt', '11pt' or '12pt'). # # 'pointsize': '10pt', - # Additional stuff for the LaTeX preamble. # # 'preamble': '', - # Latex figure (float) alignment # # 'figure_align': 'htbp', @@ -134,8 +131,13 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'WAM-Server.tex', 'WAM-Server Documentation', - 'Hendrik Huyskens', 'manual'), + ( + master_doc, + "WAM-Server.tex", + "WAM-Server Documentation", + "Hendrik Huyskens", + "manual", + ), ] @@ -143,10 +145,7 @@ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'wam-server', 'WAM-Server Documentation', - [author], 1) -] +man_pages = [(master_doc, "wam-server", "WAM-Server Documentation", [author], 1)] # -- Options for Texinfo output ---------------------------------------------- @@ -155,9 +154,15 @@ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'WAM-Server', 'WAM-Server Documentation', - author, 'WAM-Server', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "WAM-Server", + "WAM-Server Documentation", + author, + "WAM-Server", + "One line description of project.", + "Miscellaneous", + ), ] @@ -176,7 +181,7 @@ # epub_uid = '' # A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] +epub_exclude_files = ["search.html"] # -- Extension configuration ------------------------------------------------- @@ -184,9 +189,9 @@ # -- Options for intersphinx extension --------------------------------------- # Example configuration for intersphinx: refer to the Python standard library. -intersphinx_mapping = {'https://docs.python.org/': None} +intersphinx_mapping = {"https://docs.python.org/": None} # -- Options for todo extension ---------------------------------------------- # If true, `todo` and `todoList` produce output, else they produce nothing. -todo_include_todos = True \ No newline at end of file +todo_include_todos = True diff --git a/install_requirements.py b/install_requirements.py index 2854758..f2d00b4 100644 --- a/install_requirements.py +++ b/install_requirements.py @@ -2,11 +2,9 @@ import subprocess base_dir = os.path.abspath(os.path.curdir) -pip_path = subprocess.check_output(['which', 'pip']).decode().strip('\n') -apps = os.environ['WAM_APPS'].split(',') +pip_path = subprocess.check_output(["which", "pip"]).decode().strip("\n") +apps = os.environ["WAM_APPS"].split(",") for app in apps: - req_file = os.path.join(base_dir, app, 'requirements.txt') + req_file = os.path.join(base_dir, app, "requirements.txt") if os.path.isfile(req_file): - subprocess.call( - [pip_path, 'install', '-r', req_file] - ) + subprocess.call([pip_path, "install", "-r", req_file]) diff --git a/meta/admin.py b/meta/admin.py index 457fab9..6527fa7 100644 --- a/meta/admin.py +++ b/meta/admin.py @@ -1,4 +1,3 @@ - from wam.admin import wam_admin_site from meta import models diff --git a/meta/apps.py b/meta/apps.py index 13f6832..1767574 100644 --- a/meta/apps.py +++ b/meta/apps.py @@ -2,4 +2,4 @@ class MetaConfig(AppConfig): - name = 'meta' + name = "meta" diff --git a/meta/migrations/0001_initial.py b/meta/migrations/0001_initial.py index 1849d75..c53b444 100644 --- a/meta/migrations/0001_initial.py +++ b/meta/migrations/0001_initial.py @@ -8,49 +8,76 @@ class Migration(migrations.Migration): initial = True - dependencies = [ - ] + dependencies = [] operations = [ migrations.CreateModel( - name='Assumption', + name="Assumption", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('description', models.TextField()), - ('value', models.CharField(max_length=64)), - ('value_type', models.CharField(max_length=32)), - ('app_name', models.CharField(max_length=255)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255)), + ("description", models.TextField()), + ("value", models.CharField(max_length=64)), + ("value_type", models.CharField(max_length=32)), + ("app_name", models.CharField(max_length=255)), ], ), migrations.CreateModel( - name='Source', + name="Source", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('author', models.CharField(max_length=255)), - ('url', models.URLField()), - ('description', models.TextField()), - ('year', models.IntegerField()), - ('license', models.CharField(max_length=255)), - ('app_name', models.CharField(max_length=255)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("author", models.CharField(max_length=255)), + ("url", models.URLField()), + ("description", models.TextField()), + ("year", models.IntegerField()), + ("license", models.CharField(max_length=255)), + ("app_name", models.CharField(max_length=255)), ], ), migrations.CreateModel( - name='SourceCategory', + name="SourceCategory", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('description', models.TextField()), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=255)), + ("description", models.TextField()), ], ), migrations.AddField( - model_name='source', - name='category', - field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='meta.SourceCategory'), + model_name="source", + name="category", + field=models.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, to="meta.SourceCategory" + ), ), migrations.AddField( - model_name='assumption', - name='source', - field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='meta.Source'), + model_name="assumption", + name="source", + field=models.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, to="meta.Source" + ), ), ] diff --git a/meta/migrations/0002_auto_20181130_1141.py b/meta/migrations/0002_auto_20181130_1141.py index 67e61bd..251c35b 100644 --- a/meta/migrations/0002_auto_20181130_1141.py +++ b/meta/migrations/0002_auto_20181130_1141.py @@ -6,13 +6,11 @@ class Migration(migrations.Migration): dependencies = [ - ('meta', '0001_initial'), + ("meta", "0001_initial"), ] operations = [ migrations.RenameField( - model_name='assumption', - old_name='value_type', - new_name='unit', + model_name="assumption", old_name="value_type", new_name="unit", ), ] diff --git a/meta/migrations/0003_source_meta_data.py b/meta/migrations/0003_source_meta_data.py index 1c9c5b2..d392e9b 100644 --- a/meta/migrations/0003_source_meta_data.py +++ b/meta/migrations/0003_source_meta_data.py @@ -7,13 +7,13 @@ class Migration(migrations.Migration): dependencies = [ - ('meta', '0002_auto_20181130_1141'), + ("meta", "0002_auto_20181130_1141"), ] operations = [ migrations.AddField( - model_name='source', - name='meta_data', + model_name="source", + name="meta_data", field=django.contrib.postgres.fields.jsonb.JSONField(null=True), ), ] diff --git a/meta/migrations/0004_auto_20190207_1139.py b/meta/migrations/0004_auto_20190207_1139.py index 354a78a..7d048bc 100644 --- a/meta/migrations/0004_auto_20190207_1139.py +++ b/meta/migrations/0004_auto_20190207_1139.py @@ -7,18 +7,19 @@ class Migration(migrations.Migration): dependencies = [ - ('meta', '0003_source_meta_data'), + ("meta", "0003_source_meta_data"), ] operations = [ - migrations.RenameModel( - old_name='SourceCategory', - new_name='Category', - ), + migrations.RenameModel(old_name="SourceCategory", new_name="Category",), migrations.AddField( - model_name='assumption', - name='category', - field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.DO_NOTHING, to='meta.Category'), + model_name="assumption", + name="category", + field=models.ForeignKey( + default=None, + on_delete=django.db.models.deletion.DO_NOTHING, + to="meta.Category", + ), preserve_default=False, ), ] diff --git a/meta/migrations/0005_auto_20190211_1125.py b/meta/migrations/0005_auto_20190211_1125.py index 88ba2e8..128a367 100644 --- a/meta/migrations/0005_auto_20190211_1125.py +++ b/meta/migrations/0005_auto_20190211_1125.py @@ -6,28 +6,13 @@ class Migration(migrations.Migration): dependencies = [ - ('meta', '0004_auto_20190207_1139'), + ("meta", "0004_auto_20190207_1139"), ] operations = [ - migrations.RemoveField( - model_name='source', - name='author', - ), - migrations.RemoveField( - model_name='source', - name='description', - ), - migrations.RemoveField( - model_name='source', - name='license', - ), - migrations.RemoveField( - model_name='source', - name='url', - ), - migrations.RemoveField( - model_name='source', - name='year', - ), + migrations.RemoveField(model_name="source", name="author",), + migrations.RemoveField(model_name="source", name="description",), + migrations.RemoveField(model_name="source", name="license",), + migrations.RemoveField(model_name="source", name="url",), + migrations.RemoveField(model_name="source", name="year",), ] diff --git a/meta/migrations/0006_auto_20191212_1617.py b/meta/migrations/0006_auto_20191212_1617.py index 9c221e5..9a79ab7 100644 --- a/meta/migrations/0006_auto_20191212_1617.py +++ b/meta/migrations/0006_auto_20191212_1617.py @@ -7,23 +7,29 @@ class Migration(migrations.Migration): dependencies = [ - ('meta', '0005_auto_20190211_1125'), + ("meta", "0005_auto_20190211_1125"), ] operations = [ migrations.AlterField( - model_name='assumption', - name='category', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='meta.Category'), + model_name="assumption", + name="category", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="meta.Category" + ), ), migrations.AlterField( - model_name='assumption', - name='source', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='meta.Source'), + model_name="assumption", + name="source", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="meta.Source" + ), ), migrations.AlterField( - model_name='source', - name='category', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='meta.Category'), + model_name="source", + name="category", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, to="meta.Category" + ), ), ] diff --git a/meta/models.py b/meta/models.py index 41c1188..283b865 100644 --- a/meta/models.py +++ b/meta/models.py @@ -1,4 +1,3 @@ - import jmespath from django.db import models @@ -13,6 +12,7 @@ class Assumption(models.Model): A source must be assigned to exactly one :class:`Source` defined in `source`. """ + name = models.CharField(max_length=255) description = models.TextField() value = models.CharField(max_length=64) @@ -20,8 +20,8 @@ class Assumption(models.Model): app_name = models.CharField(max_length=255) - source = models.ForeignKey('Source', on_delete=models.CASCADE) - category = models.ForeignKey('Category', on_delete=models.CASCADE) + source = models.ForeignKey("Source", on_delete=models.CASCADE) + category = models.ForeignKey("Category", on_delete=models.CASCADE) def __str__(self): return self.name @@ -33,30 +33,31 @@ class Source(models.Model): A source must be assigned to exactly one :class:`Category` defined in `category`. """ + meta_data = JSONField(null=True) app_name = models.CharField(max_length=255) - category = models.ForeignKey('Category', on_delete=models.CASCADE) + category = models.ForeignKey("Category", on_delete=models.CASCADE) def json(self): return JsonWidget(self.meta_data).render() def infos(self): infos = jmespath.search( - '{' - 'url: identifier, ' - 'title: title, ' - 'description: description, ' - 'licenses: licenses[*].name' - '}', - self.meta_data + "{" + "url: identifier, " + "title: title, " + "description: description, " + "licenses: licenses[*].name" + "}", + self.meta_data, ) - if infos.get('url') is not None: - if infos.get('url') == '': - infos.pop('url') + if infos.get("url") is not None: + if infos.get("url") == "": + infos.pop("url") else: - infos.pop('url') + infos.pop("url") return infos @@ -65,6 +66,7 @@ class Category(models.Model): A category subsumes one or multiple sources, see :class:`Source`. """ + name = models.CharField(max_length=255) description = models.TextField() diff --git a/meta/views.py b/meta/views.py index de52f23..61ff53c 100644 --- a/meta/views.py +++ b/meta/views.py @@ -36,56 +36,52 @@ class AppListView(ListView): * The template displays all items of a model in a table, each row has a unique id """ - default_template_name = 'meta/app_list.html' + + default_template_name = "meta/app_list.html" app_name = None - ordering = ['category__name'] + ordering = ["category__name"] title = "Quellen" def __init__(self, *args, **kwargs): super(AppListView, self).__init__(*args, **kwargs) if self.app_name is not None: - self.queryset = self.model.objects.filter( - app_name=self.app_name) + self.queryset = self.model.objects.filter(app_name=self.app_name) else: self.queryset = self.model.objects.all() def get_context_data(self, *, object_list=None, **kwargs): # pylint: disable=protected-access context = super(AppListView, self).get_context_data( - object_list=object_list, **kwargs) + object_list=object_list, **kwargs + ) - context['title'] = self.title + context["title"] = self.title # Try to load base.html template from app: - base_template = 'meta/base.html' + base_template = "meta/base.html" if self.app_name is not None: base_template_file = os.path.join( - BASE_DIR, - self.app_name, - 'templates', - self.app_name, - 'base.html' + BASE_DIR, self.app_name, "templates", self.app_name, "base.html" ) if os.path.exists(base_template_file): - base_template = self.app_name + '/base.html' - context['base_template'] = base_template + base_template = self.app_name + "/base.html" + context["base_template"] = base_template # Highlight specific id: highlight_id = self.request.GET.get(self.model._meta.model_name, None) if ( - highlight_id is not None and - context['object_list'].filter(pk=highlight_id).exists() + highlight_id is not None + and context["object_list"].filter(pk=highlight_id).exists() ): - context['highlight'] = str(highlight_id) + context["highlight"] = str(highlight_id) # Highlight category: - category_id = self.request.GET.get('category', None) + category_id = self.request.GET.get("category", None) if ( - category_id is not None and - context['object_list'].filter( - category__pk=category_id).exists() + category_id is not None + and context["object_list"].filter(category__pk=category_id).exists() ): - context['category'] = str(category_id) + context["category"] = str(category_id) return context @@ -101,12 +97,13 @@ class AssumptionsView(AppListView): def get_context_data(self, *, object_list=None, **kwargs): context = super(AssumptionsView, self).get_context_data( - object_list=object_list, **kwargs) + object_list=object_list, **kwargs + ) if self.source_url is not None: - context['source_url'] = self.source_url + context["source_url"] = self.source_url else: if self.app_name is not None: - context['source_url'] = self.app_name + ':sources' + context["source_url"] = self.app_name + ":sources" else: - context['source_url'] = 'sources' + context["source_url"] = "sources" return context diff --git a/meta/widgets.py b/meta/widgets.py index 2b6bcfa..0acb118 100644 --- a/meta/widgets.py +++ b/meta/widgets.py @@ -1,32 +1,35 @@ from django.utils.safestring import mark_safe -class JsonWidget(): +class JsonWidget: def __init__(self, json): self.json = json def __convert_to_html(self, data, level=0): - html = '' + html = "" if isinstance(data, dict): - html += f'
'\ - if level > 0 else '
' + html += ( + f'
' + if level > 0 + else "
" + ) for key, value in data.items(): - html += f'{key}: {self.__convert_to_html(value, level+1)}' - html += '
' + html += f"{key}: {self.__convert_to_html(value, level+1)}" + html += "
" elif isinstance(data, list): html += f'
' for item in data: - html += f'{self.__convert_to_html(item, level+1)}' - html += '
' + html += f"{self.__convert_to_html(item, level+1)}" + html += "
" else: - html += f'{data}
' + html += f"{data}
" return html def render(self): - header = '' + header = "" if self.json["title"] != "": header += f'

{self.json["title"]}

' if self.json["description"] != "": diff --git a/setup.py b/setup.py index 90d7c39..89b81b8 100644 --- a/setup.py +++ b/setup.py @@ -2,22 +2,23 @@ from setuptools import setup, find_packages -with open('requirements.txt') as f: +with open("requirements.txt") as f: requirements = f.read().splitlines() git_requirements = [ f"{req.split('#egg=')[1]} @ {req}" - for req in requirements if req.startswith('git') + for req in requirements + if req.startswith("git") ] - normal_requirements = [req for req in requirements if not req.startswith('git')] + normal_requirements = [req for req in requirements if not req.startswith("git")] setup( - name='wam', - version='0.1.3', + name="wam", + version="0.1.3", packages=find_packages(), - license='GNU Affero General Public License v3.0', - author='henhuy, nesnoj, Bachibouzouk, christian-rli, 4lm', - description='WAM - Web Applications & Maps', - url='https://github.com/rl-institut/WAM', + license="GNU Affero General Public License v3.0", + author="henhuy, nesnoj, Bachibouzouk, christian-rli, 4lm", + description="WAM - Web Applications & Maps", + url="https://github.com/rl-institut/WAM", install_requires=normal_requirements + git_requirements, - scripts=['manage.py'] + scripts=["manage.py"], ) diff --git a/static/ionicons-2.0.1/builder/generate.py b/static/ionicons-2.0.1/builder/generate.py index 8bfff53..39ae07c 100644 --- a/static/ionicons-2.0.1/builder/generate.py +++ b/static/ionicons-2.0.1/builder/generate.py @@ -4,315 +4,316 @@ BUILDER_PATH = os.path.dirname(os.path.abspath(__file__)) -ROOT_PATH = os.path.join(BUILDER_PATH, '..') -FONTS_FOLDER_PATH = os.path.join(ROOT_PATH, 'fonts') -CSS_FOLDER_PATH = os.path.join(ROOT_PATH, 'css') -SCSS_FOLDER_PATH = os.path.join(ROOT_PATH, 'scss') -LESS_FOLDER_PATH = os.path.join(ROOT_PATH, 'less') +ROOT_PATH = os.path.join(BUILDER_PATH, "..") +FONTS_FOLDER_PATH = os.path.join(ROOT_PATH, "fonts") +CSS_FOLDER_PATH = os.path.join(ROOT_PATH, "css") +SCSS_FOLDER_PATH = os.path.join(ROOT_PATH, "scss") +LESS_FOLDER_PATH = os.path.join(ROOT_PATH, "less") def main(): - generate_font_files() + generate_font_files() - data = get_build_data() + data = get_build_data() - rename_svg_glyph_names(data) - generate_scss(data) - generate_less(data) - generate_cheatsheet(data) - generate_component_json(data) - generate_composer_json(data) - generate_bower_json(data) + rename_svg_glyph_names(data) + generate_scss(data) + generate_less(data) + generate_cheatsheet(data) + generate_component_json(data) + generate_composer_json(data) + generate_bower_json(data) def generate_font_files(): - print "Generate Fonts" - cmd = "fontforge -script %s/scripts/generate_font.py" % (BUILDER_PATH) - call(cmd, shell=True) + print "Generate Fonts" + cmd = "fontforge -script %s/scripts/generate_font.py" % (BUILDER_PATH) + call(cmd, shell=True) def rename_svg_glyph_names(data): - # hacky and slow (but safe) way to rename glyph-name attributes - svg_path = os.path.join(FONTS_FOLDER_PATH, 'ionicons.svg') - svg_file = open(svg_path, 'r+') - svg_text = svg_file.read() - svg_file.seek(0) + # hacky and slow (but safe) way to rename glyph-name attributes + svg_path = os.path.join(FONTS_FOLDER_PATH, "ionicons.svg") + svg_file = open(svg_path, "r+") + svg_text = svg_file.read() + svg_file.seek(0) - for ionicon in data['icons']: - # uniF2CA - org_name = 'uni%s' % (ionicon['code'].replace('0x', '').upper()) - ion_name = 'ion-%s' % (ionicon['name']) - svg_text = svg_text.replace(org_name, ion_name) + for ionicon in data["icons"]: + # uniF2CA + org_name = "uni%s" % (ionicon["code"].replace("0x", "").upper()) + ion_name = "ion-%s" % (ionicon["name"]) + svg_text = svg_text.replace(org_name, ion_name) - svg_file.write(svg_text) - svg_file.close() + svg_file.write(svg_text) + svg_file.close() def generate_less(data): - print "Generate LESS" - font_name = data['name'] - font_version = data['version'] - css_prefix = data['prefix'] - variables_file_path = os.path.join(LESS_FOLDER_PATH, '_ionicons-variables.less') - icons_file_path = os.path.join(LESS_FOLDER_PATH, '_ionicons-icons.less') - - d = [] - d.append('/*!'); - d.append('Ionicons, v%s' % (font_version) ); - d.append('Created by Ben Sperry for the Ionic Framework, http://ionicons.com/'); - d.append('https://twitter.com/benjsperry https://twitter.com/ionicframework'); - d.append('MIT License: https://github.com/driftyco/ionicons'); - d.append('*/'); - d.append('// Ionicons Variables') - d.append('// --------------------------\n') - d.append('@ionicons-font-path: "../fonts";') - d.append('@ionicons-font-family: "%s";' % (font_name) ) - d.append('@ionicons-version: "%s";' % (font_version) ) - d.append('@ionicons-prefix: %s;' % (css_prefix) ) - d.append('') - for ionicon in data['icons']: - chr_code = ionicon['code'].replace('0x', '\\') - d.append('@ionicon-var-%s: "%s";' % (ionicon['name'], chr_code) ) - f = open(variables_file_path, 'w') - f.write( '\n'.join(d) ) - f.close() - - d = [] - d.append('// Ionicons Icons') - d.append('// --------------------------\n') - - group = [ '.%s' % (data['name'].lower()) ] - for ionicon in data['icons']: - group.append('.@{ionicons-prefix}%s:before' % (ionicon['name']) ) - - d.append( ',\n'.join(group) ) - - d.append('{') - d.append(' &:extend(.ion);') - d.append('}') - - for ionicon in data['icons']: - chr_code = ionicon['code'].replace('0x', '\\') - d.append('.@{ionicons-prefix}%s:before { content: @ionicon-var-%s; }' % (ionicon['name'], ionicon['name']) ) - - f = open(icons_file_path, 'w') - f.write( '\n'.join(d) ) - f.close() + print "Generate LESS" + font_name = data["name"] + font_version = data["version"] + css_prefix = data["prefix"] + variables_file_path = os.path.join(LESS_FOLDER_PATH, "_ionicons-variables.less") + icons_file_path = os.path.join(LESS_FOLDER_PATH, "_ionicons-icons.less") + + d = [] + d.append("/*!") + d.append("Ionicons, v%s" % (font_version)) + d.append("Created by Ben Sperry for the Ionic Framework, http://ionicons.com/") + d.append("https://twitter.com/benjsperry https://twitter.com/ionicframework") + d.append("MIT License: https://github.com/driftyco/ionicons") + d.append("*/") + d.append("// Ionicons Variables") + d.append("// --------------------------\n") + d.append('@ionicons-font-path: "../fonts";') + d.append('@ionicons-font-family: "%s";' % (font_name)) + d.append('@ionicons-version: "%s";' % (font_version)) + d.append("@ionicons-prefix: %s;" % (css_prefix)) + d.append("") + for ionicon in data["icons"]: + chr_code = ionicon["code"].replace("0x", "\\") + d.append('@ionicon-var-%s: "%s";' % (ionicon["name"], chr_code)) + f = open(variables_file_path, "w") + f.write("\n".join(d)) + f.close() + + d = [] + d.append("// Ionicons Icons") + d.append("// --------------------------\n") + + group = [".%s" % (data["name"].lower())] + for ionicon in data["icons"]: + group.append(".@{ionicons-prefix}%s:before" % (ionicon["name"])) + + d.append(",\n".join(group)) + + d.append("{") + d.append(" &:extend(.ion);") + d.append("}") + + for ionicon in data["icons"]: + chr_code = ionicon["code"].replace("0x", "\\") + d.append( + ".@{ionicons-prefix}%s:before { content: @ionicon-var-%s; }" + % (ionicon["name"], ionicon["name"]) + ) + + f = open(icons_file_path, "w") + f.write("\n".join(d)) + f.close() def generate_scss(data): - print "Generate SCSS" - font_name = data['name'] - font_version = data['version'] - css_prefix = data['prefix'] - variables_file_path = os.path.join(SCSS_FOLDER_PATH, '_ionicons-variables.scss') - icons_file_path = os.path.join(SCSS_FOLDER_PATH, '_ionicons-icons.scss') - - d = [] - d.append('// Ionicons Variables') - d.append('// --------------------------\n') - d.append('$ionicons-font-path: "../fonts" !default;') - d.append('$ionicons-font-family: "%s" !default;' % (font_name) ) - d.append('$ionicons-version: "%s" !default;' % (font_version) ) - d.append('$ionicons-prefix: %s !default;' % (css_prefix) ) - d.append('') - for ionicon in data['icons']: - chr_code = ionicon['code'].replace('0x', '\\') - d.append('$ionicon-var-%s: "%s";' % (ionicon['name'], chr_code) ) - f = open(variables_file_path, 'w') - f.write( '\n'.join(d) ) - f.close() - - d = [] - d.append('// Ionicons Icons') - d.append('// --------------------------\n') - - group = [ '.%s' % (data['name'].lower()) ] - for ionicon in data['icons']: - group.append('.#{$ionicons-prefix}%s:before' % (ionicon['name']) ) - - d.append( ',\n'.join(group) ) - - d.append('{') - d.append(' @extend .ion;') - d.append('}') - - for ionicon in data['icons']: - chr_code = ionicon['code'].replace('0x', '\\') - d.append('.#{$ionicons-prefix}%s:before { content: $ionicon-var-%s; }' % (ionicon['name'], ionicon['name']) ) - - f = open(icons_file_path, 'w') - f.write( '\n'.join(d) ) - f.close() - - generate_css_from_scss(data) + print "Generate SCSS" + font_name = data["name"] + font_version = data["version"] + css_prefix = data["prefix"] + variables_file_path = os.path.join(SCSS_FOLDER_PATH, "_ionicons-variables.scss") + icons_file_path = os.path.join(SCSS_FOLDER_PATH, "_ionicons-icons.scss") + + d = [] + d.append("// Ionicons Variables") + d.append("// --------------------------\n") + d.append('$ionicons-font-path: "../fonts" !default;') + d.append('$ionicons-font-family: "%s" !default;' % (font_name)) + d.append('$ionicons-version: "%s" !default;' % (font_version)) + d.append("$ionicons-prefix: %s !default;" % (css_prefix)) + d.append("") + for ionicon in data["icons"]: + chr_code = ionicon["code"].replace("0x", "\\") + d.append('$ionicon-var-%s: "%s";' % (ionicon["name"], chr_code)) + f = open(variables_file_path, "w") + f.write("\n".join(d)) + f.close() + + d = [] + d.append("// Ionicons Icons") + d.append("// --------------------------\n") + + group = [".%s" % (data["name"].lower())] + for ionicon in data["icons"]: + group.append(".#{$ionicons-prefix}%s:before" % (ionicon["name"])) + + d.append(",\n".join(group)) + + d.append("{") + d.append(" @extend .ion;") + d.append("}") + + for ionicon in data["icons"]: + chr_code = ionicon["code"].replace("0x", "\\") + d.append( + ".#{$ionicons-prefix}%s:before { content: $ionicon-var-%s; }" + % (ionicon["name"], ionicon["name"]) + ) + + f = open(icons_file_path, "w") + f.write("\n".join(d)) + f.close() + + generate_css_from_scss(data) def generate_css_from_scss(data): - print "Generate CSS From SCSS" + print "Generate CSS From SCSS" - scss_file_path = os.path.join(SCSS_FOLDER_PATH, 'ionicons.scss') - css_file_path = os.path.join(CSS_FOLDER_PATH, 'ionicons.css') - css_min_file_path = os.path.join(CSS_FOLDER_PATH, 'ionicons.min.css') + scss_file_path = os.path.join(SCSS_FOLDER_PATH, "ionicons.scss") + css_file_path = os.path.join(CSS_FOLDER_PATH, "ionicons.css") + css_min_file_path = os.path.join(CSS_FOLDER_PATH, "ionicons.min.css") - cmd = "sass %s %s --style compact" % (scss_file_path, css_file_path) - call(cmd, shell=True) + cmd = "sass %s %s --style compact" % (scss_file_path, css_file_path) + call(cmd, shell=True) - print "Generate Minified CSS From SCSS" - cmd = "sass %s %s --style compressed" % (scss_file_path, css_min_file_path) - call(cmd, shell=True) + print "Generate Minified CSS From SCSS" + cmd = "sass %s %s --style compressed" % (scss_file_path, css_min_file_path) + call(cmd, shell=True) def generate_cheatsheet(data): - print "Generate Cheatsheet" + print "Generate Cheatsheet" - cheatsheet_file_path = os.path.join(ROOT_PATH, 'cheatsheet.html') - template_path = os.path.join(BUILDER_PATH, 'cheatsheet', 'template.html') - icon_row_path = os.path.join(BUILDER_PATH, 'cheatsheet', 'icon-row.html') + cheatsheet_file_path = os.path.join(ROOT_PATH, "cheatsheet.html") + template_path = os.path.join(BUILDER_PATH, "cheatsheet", "template.html") + icon_row_path = os.path.join(BUILDER_PATH, "cheatsheet", "icon-row.html") - f = open(template_path, 'r') - template_html = f.read() - f.close() + f = open(template_path, "r") + template_html = f.read() + f.close() - f = open(icon_row_path, 'r') - icon_row_template = f.read() - f.close() + f = open(icon_row_path, "r") + icon_row_template = f.read() + f.close() - content = [] + content = [] - for ionicon in data['icons']: - css_code = ionicon['code'].replace('0x', '\\') - escaped_html_code = ionicon['code'].replace('0x', '&#x') + ';' - html_code = ionicon['code'].replace('0x', '&#x') + ';' - item_row = icon_row_template + for ionicon in data["icons"]: + css_code = ionicon["code"].replace("0x", "\\") + escaped_html_code = ionicon["code"].replace("0x", "&#x") + ";" + html_code = ionicon["code"].replace("0x", "&#x") + ";" + item_row = icon_row_template - item_row = item_row.replace('{{name}}', ionicon['name']) - item_row = item_row.replace('{{prefix}}', data['prefix']) - item_row = item_row.replace('{{css_code}}', css_code) - item_row = item_row.replace('{{escaped_html_code}}', escaped_html_code) - item_row = item_row.replace('{{html_code}}', html_code) + item_row = item_row.replace("{{name}}", ionicon["name"]) + item_row = item_row.replace("{{prefix}}", data["prefix"]) + item_row = item_row.replace("{{css_code}}", css_code) + item_row = item_row.replace("{{escaped_html_code}}", escaped_html_code) + item_row = item_row.replace("{{html_code}}", html_code) - content.append(item_row) + content.append(item_row) - template_html = template_html.replace("{{font_name}}", data["name"]) - template_html = template_html.replace("{{font_version}}", data["version"]) - template_html = template_html.replace("{{icon_count}}", str(len(data["icons"])) ) - template_html = template_html.replace("{{content}}", '\n'.join(content) ) + template_html = template_html.replace("{{font_name}}", data["name"]) + template_html = template_html.replace("{{font_version}}", data["version"]) + template_html = template_html.replace("{{icon_count}}", str(len(data["icons"]))) + template_html = template_html.replace("{{content}}", "\n".join(content)) - f = open(cheatsheet_file_path, 'w') - f.write(template_html) - f.close() + f = open(cheatsheet_file_path, "w") + f.write(template_html) + f.close() def generate_component_json(data): - print "Generate component.json" - d = { - "name": data['name'], - "repo": "driftyco/ionicons", - "description": "The premium icon font for Ionic Framework.", - "version": data['version'], - "keywords": [], - "dependencies": {}, - "development": {}, - "license": "MIT", - "styles": [ - "css/%s.css" % (data['name'].lower()) - ], - "fonts": [ - "fonts/%s.eot" % (data['name'].lower()), - "fonts/%s.svg" % (data['name'].lower()), - "fonts/%s.ttf" % (data['name'].lower()), - "fonts/%s.woff" % (data['name'].lower()) - ] - } - txt = json.dumps(d, indent=4, separators=(',', ': ')) - - component_file_path = os.path.join(ROOT_PATH, 'component.json') - f = open(component_file_path, 'w') - f.write(txt) - f.close() + print "Generate component.json" + d = { + "name": data["name"], + "repo": "driftyco/ionicons", + "description": "The premium icon font for Ionic Framework.", + "version": data["version"], + "keywords": [], + "dependencies": {}, + "development": {}, + "license": "MIT", + "styles": ["css/%s.css" % (data["name"].lower())], + "fonts": [ + "fonts/%s.eot" % (data["name"].lower()), + "fonts/%s.svg" % (data["name"].lower()), + "fonts/%s.ttf" % (data["name"].lower()), + "fonts/%s.woff" % (data["name"].lower()), + ], + } + txt = json.dumps(d, indent=4, separators=(",", ": ")) + + component_file_path = os.path.join(ROOT_PATH, "component.json") + f = open(component_file_path, "w") + f.write(txt) + f.close() def generate_composer_json(data): - print "Generate composer.json" - d = { - "name": "driftyco/ionicons", - "description": "The premium icon font for Ionic Framework.", - "keywords": [ "fonts", "icon font", "icons", "ionic", "web font"], - "homepage": "http://ionicons.com/", - "authors": [ - { - "name": "Ben Sperry", - "email": "ben@drifty.com", - "role": "Designer", - "homepage": "https://twitter.com/benjsperry" - }, - { - "name": "Adam Bradley", - "email": "adam@drifty.com", - "role": "Developer", - "homepage": "https://twitter.com/adamdbradley" - }, - { - "name": "Max Lynch", - "email": "max@drifty.com", - "role": "Developer", - "homepage": "https://twitter.com/maxlynch" - } - ], - "extra": {}, - "license": [ "MIT" ] - } - txt = json.dumps(d, indent=4, separators=(',', ': ')) - - composer_file_path = os.path.join(ROOT_PATH, 'composer.json') - f = open(composer_file_path, 'w') - f.write(txt) - f.close() + print "Generate composer.json" + d = { + "name": "driftyco/ionicons", + "description": "The premium icon font for Ionic Framework.", + "keywords": ["fonts", "icon font", "icons", "ionic", "web font"], + "homepage": "http://ionicons.com/", + "authors": [ + { + "name": "Ben Sperry", + "email": "ben@drifty.com", + "role": "Designer", + "homepage": "https://twitter.com/benjsperry", + }, + { + "name": "Adam Bradley", + "email": "adam@drifty.com", + "role": "Developer", + "homepage": "https://twitter.com/adamdbradley", + }, + { + "name": "Max Lynch", + "email": "max@drifty.com", + "role": "Developer", + "homepage": "https://twitter.com/maxlynch", + }, + ], + "extra": {}, + "license": ["MIT"], + } + txt = json.dumps(d, indent=4, separators=(",", ": ")) + + composer_file_path = os.path.join(ROOT_PATH, "composer.json") + f = open(composer_file_path, "w") + f.write(txt) + f.close() def generate_bower_json(data): - print "Generate bower.json" - d = { - "name": data['name'], - "version": data['version'], - "homepage": "https://github.com/driftyco/ionicons", - "authors": [ - "Ben Sperry ", - "Adam Bradley ", - "Max Lynch " - ], - "description": "Ionicons - free and beautiful icons from the creators of Ionic Framework", - "main": [ - "css/%s.css" % (data['name'].lower()), - "fonts/*" - ], - "keywords": [ "fonts", "icon font", "icons", "ionic", "web font"], - "license": "MIT", - "ignore": [ - "**/.*", - "builder", - "node_modules", - "bower_components", - "test", - "tests" - ] - } - txt = json.dumps(d, indent=4, separators=(',', ': ')) - - bower_file_path = os.path.join(ROOT_PATH, 'bower.json') - f = open(bower_file_path, 'w') - f.write(txt) - f.close() + print "Generate bower.json" + d = { + "name": data["name"], + "version": data["version"], + "homepage": "https://github.com/driftyco/ionicons", + "authors": [ + "Ben Sperry ", + "Adam Bradley ", + "Max Lynch ", + ], + "description": "Ionicons - free and beautiful icons from the creators of Ionic Framework", + "main": ["css/%s.css" % (data["name"].lower()), "fonts/*"], + "keywords": ["fonts", "icon font", "icons", "ionic", "web font"], + "license": "MIT", + "ignore": [ + "**/.*", + "builder", + "node_modules", + "bower_components", + "test", + "tests", + ], + } + txt = json.dumps(d, indent=4, separators=(",", ": ")) + + bower_file_path = os.path.join(ROOT_PATH, "bower.json") + f = open(bower_file_path, "w") + f.write(txt) + f.close() def get_build_data(): - build_data_path = os.path.join(BUILDER_PATH, 'build_data.json') - f = open(build_data_path, 'r') - data = json.loads(f.read()) - f.close() - return data + build_data_path = os.path.join(BUILDER_PATH, "build_data.json") + f = open(build_data_path, "r") + data = json.loads(f.read()) + f.close() + return data if __name__ == "__main__": - main() + main() diff --git a/static/ionicons-2.0.1/builder/scripts/eotlitetool.py b/static/ionicons-2.0.1/builder/scripts/eotlitetool.py index d3e253b..1898312 100644 --- a/static/ionicons-2.0.1/builder/scripts/eotlitetool.py +++ b/static/ionicons-2.0.1/builder/scripts/eotlitetool.py @@ -42,9 +42,9 @@ # OpenType file structure # http://www.microsoft.com/typography/otspec/otff.htm -# +# # Types: -# +# # BYTE 8-bit unsigned integer. # CHAR 8-bit signed integer. # USHORT 16-bit unsigned integer. @@ -52,111 +52,111 @@ # ULONG 32-bit unsigned integer. # Fixed 32-bit signed fixed-point number (16.16) # LONGDATETIME Date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a signed 64-bit integer. -# +# # SFNT Header -# +# # Fixed sfnt version // 0x00010000 for version 1.0. # USHORT numTables // Number of tables. # USHORT searchRange // (Maximum power of 2 <= numTables) x 16. # USHORT entrySelector // Log2(maximum power of 2 <= numTables). # USHORT rangeShift // NumTables x 16-searchRange. -# +# # Table Directory -# +# # ULONG tag // 4-byte identifier. # ULONG checkSum // CheckSum for this table. # ULONG offset // Offset from beginning of TrueType font file. # ULONG length // Length of this table. -# +# # OS/2 Table (Version 4) -# +# # USHORT version // 0x0004 -# SHORT xAvgCharWidth -# USHORT usWeightClass -# USHORT usWidthClass -# USHORT fsType -# SHORT ySubscriptXSize -# SHORT ySubscriptYSize -# SHORT ySubscriptXOffset -# SHORT ySubscriptYOffset -# SHORT ySuperscriptXSize -# SHORT ySuperscriptYSize -# SHORT ySuperscriptXOffset -# SHORT ySuperscriptYOffset -# SHORT yStrikeoutSize -# SHORT yStrikeoutPosition -# SHORT sFamilyClass -# BYTE panose[10] +# SHORT xAvgCharWidth +# USHORT usWeightClass +# USHORT usWidthClass +# USHORT fsType +# SHORT ySubscriptXSize +# SHORT ySubscriptYSize +# SHORT ySubscriptXOffset +# SHORT ySubscriptYOffset +# SHORT ySuperscriptXSize +# SHORT ySuperscriptYSize +# SHORT ySuperscriptXOffset +# SHORT ySuperscriptYOffset +# SHORT yStrikeoutSize +# SHORT yStrikeoutPosition +# SHORT sFamilyClass +# BYTE panose[10] # ULONG ulUnicodeRange1 // Bits 0-31 # ULONG ulUnicodeRange2 // Bits 32-63 # ULONG ulUnicodeRange3 // Bits 64-95 # ULONG ulUnicodeRange4 // Bits 96-127 -# CHAR achVendID[4] -# USHORT fsSelection -# USHORT usFirstCharIndex -# USHORT usLastCharIndex -# SHORT sTypoAscender -# SHORT sTypoDescender -# SHORT sTypoLineGap -# USHORT usWinAscent -# USHORT usWinDescent +# CHAR achVendID[4] +# USHORT fsSelection +# USHORT usFirstCharIndex +# USHORT usLastCharIndex +# SHORT sTypoAscender +# SHORT sTypoDescender +# SHORT sTypoLineGap +# USHORT usWinAscent +# USHORT usWinDescent # ULONG ulCodePageRange1 // Bits 0-31 # ULONG ulCodePageRange2 // Bits 32-63 -# SHORT sxHeight -# SHORT sCapHeight -# USHORT usDefaultChar -# USHORT usBreakChar -# USHORT usMaxContext -# -# +# SHORT sxHeight +# SHORT sCapHeight +# USHORT usDefaultChar +# USHORT usBreakChar +# USHORT usMaxContext +# +# # The Naming Table is organized as follows: -# +# # [name table header] # [name records] # [string data] -# +# # Name Table Header -# +# # USHORT format // Format selector (=0). # USHORT count // Number of name records. # USHORT stringOffset // Offset to start of string storage (from start of table). -# +# # Name Record -# +# # USHORT platformID // Platform ID. # USHORT encodingID // Platform-specific encoding ID. # USHORT languageID // Language ID. # USHORT nameID // Name ID. # USHORT length // String length (in bytes). # USHORT offset // String offset from start of storage area (in bytes). -# +# # head Table -# +# # Fixed tableVersion // Table version number 0x00010000 for version 1.0. # Fixed fontRevision // Set by font manufacturer. # ULONG checkSumAdjustment // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum. # ULONG magicNumber // Set to 0x5F0F3CF5. -# USHORT flags +# USHORT flags # USHORT unitsPerEm // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines. # LONGDATETIME created // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer # LONGDATETIME modified // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer # SHORT xMin // For all glyph bounding boxes. -# SHORT yMin -# SHORT xMax -# SHORT yMax +# SHORT yMin +# SHORT xMax +# SHORT yMax # USHORT macStyle # USHORT lowestRecPPEM // Smallest readable size in pixels. # SHORT fontDirectionHint # SHORT indexToLocFormat // 0 for short offsets, 1 for long. # SHORT glyphDataFormat // 0 for current format. -# -# -# +# +# +# # Embedded OpenType (EOT) file format # http://www.w3.org/Submission/EOT/ -# +# # EOT version 0x00020001 -# +# # An EOT font consists of a header with the original OpenType font # appended at the end. Most of the data in the EOT header is simply a # copy of data from specific tables within the font data. The exceptions @@ -165,15 +165,15 @@ # used. A null root string implies the font data can be used anywhere. # The EOT header is in little-endian byte order but the font data remains # in big-endian order as specified by the OpenType spec. -# +# # Overall structure: -# +# # [EOT header] # [EOT name records] # [font data] -# +# # EOT header -# +# # ULONG eotSize // Total structure length in bytes (including string and font data) # ULONG fontDataSize // Length of the OpenType font (FontData) in bytes # ULONG version // Version number of this format - 0x00020001 @@ -193,274 +193,318 @@ # ULONG checkSumAdjustment // head Table CheckSumAdjustment # ULONG reserved[4] // Reserved - must be 0 # USHORT padding1 // Padding - must be 0 -# +# # EOT name records -# +# # USHORT FamilyNameSize // Font family name size in bytes # BYTE FamilyName[FamilyNameSize] // Font family name (name ID = 1), little-endian UTF-16 # USHORT Padding2 // Padding - must be 0 -# +# # USHORT StyleNameSize // Style name size in bytes # BYTE StyleName[StyleNameSize] // Style name (name ID = 2), little-endian UTF-16 # USHORT Padding3 // Padding - must be 0 -# +# # USHORT VersionNameSize // Version name size in bytes # bytes VersionName[VersionNameSize] // Version name (name ID = 5), little-endian UTF-16 # USHORT Padding4 // Padding - must be 0 -# +# # USHORT FullNameSize // Full name size in bytes # BYTE FullName[FullNameSize] // Full name (name ID = 4), little-endian UTF-16 # USHORT Padding5 // Padding - must be 0 -# +# # USHORT RootStringSize // Root string size in bytes # BYTE RootString[RootStringSize] // Root string, little-endian UTF-16 - import optparse import struct + class FontError(Exception): """Error related to font handling""" + pass + def multichar(str): - vals = struct.unpack('4B', str[:4]) + vals = struct.unpack("4B", str[:4]) return (vals[0] << 24) + (vals[1] << 16) + (vals[2] << 8) + vals[3] + def multicharval(v): - return struct.pack('4B', (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF) + return struct.pack( + "4B", (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF + ) + class EOT: EOT_VERSION = 0x00020001 - EOT_MAGIC_NUMBER = 0x504c + EOT_MAGIC_NUMBER = 0x504C EOT_DEFAULT_CHARSET = 0x01 - EOT_FAMILY_NAME_INDEX = 0 # order of names in variable portion of EOT header + EOT_FAMILY_NAME_INDEX = 0 # order of names in variable portion of EOT header EOT_STYLE_NAME_INDEX = 1 EOT_VERSION_NAME_INDEX = 2 EOT_FULL_NAME_INDEX = 3 EOT_NUM_NAMES = 4 - - EOT_HEADER_PACK = '<4L10B2BL2H7L18x' + + EOT_HEADER_PACK = "<4L10B2BL2H7L18x" + class OpenType: - SFNT_CFF = multichar('OTTO') # Postscript CFF SFNT version - SFNT_TRUE = 0x10000 # Standard TrueType version - SFNT_APPLE = multichar('true') # Apple TrueType version - - SFNT_UNPACK = '>I4H' - TABLE_DIR_UNPACK = '>4I' - - TABLE_HEAD = multichar('head') # TrueType table tags - TABLE_NAME = multichar('name') - TABLE_OS2 = multichar('OS/2') - TABLE_GLYF = multichar('glyf') - TABLE_CFF = multichar('CFF ') - + SFNT_CFF = multichar("OTTO") # Postscript CFF SFNT version + SFNT_TRUE = 0x10000 # Standard TrueType version + SFNT_APPLE = multichar("true") # Apple TrueType version + + SFNT_UNPACK = ">I4H" + TABLE_DIR_UNPACK = ">4I" + + TABLE_HEAD = multichar("head") # TrueType table tags + TABLE_NAME = multichar("name") + TABLE_OS2 = multichar("OS/2") + TABLE_GLYF = multichar("glyf") + TABLE_CFF = multichar("CFF ") + OS2_FSSELECTION_ITALIC = 0x1 - OS2_UNPACK = '>4xH2xH22x10B4L4xH14x2L' - - HEAD_UNPACK = '>8xL' - - NAME_RECORD_UNPACK = '>6H' + OS2_UNPACK = ">4xH2xH22x10B4L4xH14x2L" + + HEAD_UNPACK = ">8xL" + + NAME_RECORD_UNPACK = ">6H" NAME_ID_FAMILY = 1 NAME_ID_STYLE = 2 NAME_ID_UNIQUE = 3 NAME_ID_FULL = 4 NAME_ID_VERSION = 5 NAME_ID_POSTSCRIPT = 6 - PLATFORM_ID_UNICODE = 0 # Mac OS uses this typically + PLATFORM_ID_UNICODE = 0 # Mac OS uses this typically PLATFORM_ID_MICROSOFT = 3 - ENCODING_ID_MICROSOFT_UNICODEBMP = 1 # with Microsoft platformID BMP-only Unicode encoding - LANG_ID_MICROSOFT_EN_US = 0x0409 # with Microsoft platformID EN US lang code + ENCODING_ID_MICROSOFT_UNICODEBMP = ( + 1 # with Microsoft platformID BMP-only Unicode encoding + ) + LANG_ID_MICROSOFT_EN_US = 0x0409 # with Microsoft platformID EN US lang code + def eotname(ttf): - i = ttf.rfind('.') + i = ttf.rfind(".") if i != -1: ttf = ttf[:i] - return ttf + '.eotlite' + return ttf + ".eotlite" + def readfont(f): - data = open(f, 'rb').read() + data = open(f, "rb").read() return data + def get_table_directory(data): """read the SFNT header and table directory""" datalen = len(data) sfntsize = struct.calcsize(OpenType.SFNT_UNPACK) if sfntsize > datalen: - raise FontError, 'truncated font data' + raise FontError, "truncated font data" sfntvers, numTables = struct.unpack(OpenType.SFNT_UNPACK, data[:sfntsize])[:2] if sfntvers != OpenType.SFNT_CFF and sfntvers != OpenType.SFNT_TRUE: - raise FontError, 'invalid font type'; - + raise FontError, "invalid font type" + font = {} - font['version'] = sfntvers - font['numTables'] = numTables - + font["version"] = sfntvers + font["numTables"] = numTables + # create set of offsets, lengths for tables table_dir_size = struct.calcsize(OpenType.TABLE_DIR_UNPACK) if sfntsize + table_dir_size * numTables > datalen: - raise FontError, 'truncated font data, table directory extends past end of data' + raise FontError, "truncated font data, table directory extends past end of data" table_dir = {} for i in range(0, numTables): start = sfntsize + i * table_dir_size end = start + table_dir_size - tag, check, bongo, dirlen = struct.unpack(OpenType.TABLE_DIR_UNPACK, data[start:end]) - table_dir[tag] = {'offset': bongo, 'length': dirlen, 'checksum': check} - - font['tableDir'] = table_dir - + tag, check, bongo, dirlen = struct.unpack( + OpenType.TABLE_DIR_UNPACK, data[start:end] + ) + table_dir[tag] = {"offset": bongo, "length": dirlen, "checksum": check} + + font["tableDir"] = table_dir + return font + def get_name_records(nametable): """reads through the name records within name table""" name = {} # read the header headersize = 6 - count, strOffset = struct.unpack('>2H', nametable[2:6]) + count, strOffset = struct.unpack(">2H", nametable[2:6]) namerecsize = struct.calcsize(OpenType.NAME_RECORD_UNPACK) if count * namerecsize + headersize > len(nametable): - raise FontError, 'names exceed size of name table' - name['count'] = count - name['strOffset'] = strOffset - + raise FontError, "names exceed size of name table" + name["count"] = count + name["strOffset"] = strOffset + # read through the name records namerecs = {} for i in range(0, count): start = headersize + i * namerecsize end = start + namerecsize - platformID, encodingID, languageID, nameID, namelen, offset = struct.unpack(OpenType.NAME_RECORD_UNPACK, nametable[start:end]) - if platformID != OpenType.PLATFORM_ID_MICROSOFT or \ - encodingID != OpenType.ENCODING_ID_MICROSOFT_UNICODEBMP or \ - languageID != OpenType.LANG_ID_MICROSOFT_EN_US: + platformID, encodingID, languageID, nameID, namelen, offset = struct.unpack( + OpenType.NAME_RECORD_UNPACK, nametable[start:end] + ) + if ( + platformID != OpenType.PLATFORM_ID_MICROSOFT + or encodingID != OpenType.ENCODING_ID_MICROSOFT_UNICODEBMP + or languageID != OpenType.LANG_ID_MICROSOFT_EN_US + ): continue - namerecs[nameID] = {'offset': offset, 'length': namelen} - - name['namerecords'] = namerecs + namerecs[nameID] = {"offset": offset, "length": namelen} + + name["namerecords"] = namerecs return name + def make_eot_name_headers(fontdata, nameTableDir): """extracts names from the name table and generates the names header portion of the EOT header""" - nameoffset = nameTableDir['offset'] - namelen = nameTableDir['length'] + nameoffset = nameTableDir["offset"] + namelen = nameTableDir["length"] name = get_name_records(fontdata[nameoffset : nameoffset + namelen]) - namestroffset = name['strOffset'] - namerecs = name['namerecords'] - - eotnames = (OpenType.NAME_ID_FAMILY, OpenType.NAME_ID_STYLE, OpenType.NAME_ID_VERSION, OpenType.NAME_ID_FULL) + namestroffset = name["strOffset"] + namerecs = name["namerecords"] + + eotnames = ( + OpenType.NAME_ID_FAMILY, + OpenType.NAME_ID_STYLE, + OpenType.NAME_ID_VERSION, + OpenType.NAME_ID_FULL, + ) nameheaders = [] for nameid in eotnames: if nameid in namerecs: namerecord = namerecs[nameid] - noffset = namerecord['offset'] - nlen = namerecord['length'] - nformat = '%dH' % (nlen / 2) # length is in number of bytes + noffset = namerecord["offset"] + nlen = namerecord["length"] + nformat = "%dH" % (nlen / 2) # length is in number of bytes start = nameoffset + namestroffset + noffset end = start + nlen - nstr = struct.unpack('>' + nformat, fontdata[start:end]) - nameheaders.append(struct.pack('" + nformat, fontdata[start:end]) + nameheaders.append(struct.pack(" os2Dir['length']: - raise FontError, 'OS/2 table invalid length' - - os2fields = struct.unpack(OpenType.OS2_UNPACK, fontdata[os2offset : os2offset + os2size]) - + + if os2size > os2Dir["length"]: + raise FontError, "OS/2 table invalid length" + + os2fields = struct.unpack( + OpenType.OS2_UNPACK, fontdata[os2offset : os2offset + os2size] + ) + panose = [] urange = [] codepage = [] - + weight, fsType = os2fields[:2] panose[:10] = os2fields[2:12] urange[:4] = os2fields[12:16] fsSelection = os2fields[16] codepage[:2] = os2fields[17:19] - + italic = fsSelection & OpenType.OS2_FSSELECTION_ITALIC - + # read in values from head table headDir = tableDir[OpenType.TABLE_HEAD] - headoffset = headDir['offset'] + headoffset = headDir["offset"] headsize = struct.calcsize(OpenType.HEAD_UNPACK) - - if headsize > headDir['length']: - raise FontError, 'head table invalid length' - - headfields = struct.unpack(OpenType.HEAD_UNPACK, fontdata[headoffset : headoffset + headsize]) + + if headsize > headDir["length"]: + raise FontError, "head table invalid length" + + headfields = struct.unpack( + OpenType.HEAD_UNPACK, fontdata[headoffset : headoffset + headsize] + ) checkSumAdjustment = headfields[0] - + # make name headers nameheaders = make_eot_name_headers(fontdata, tableDir[OpenType.TABLE_NAME]) rootstring = make_root_string() - + # calculate the total eot size - eotSize = struct.calcsize(EOT.EOT_HEADER_PACK) + len(nameheaders) + len(rootstring) + fontDataSize - fixed = struct.pack(EOT.EOT_HEADER_PACK, - *([eotSize, fontDataSize, version, flags] + panose + [charset, italic] + - [weight, fsType, magicNumber] + urange + codepage + [checkSumAdjustment])) - - return ''.join((fixed, nameheaders, rootstring)) - - + eotSize = ( + struct.calcsize(EOT.EOT_HEADER_PACK) + + len(nameheaders) + + len(rootstring) + + fontDataSize + ) + fixed = struct.pack( + EOT.EOT_HEADER_PACK, + *( + [eotSize, fontDataSize, version, flags] + + panose + + [charset, italic] + + [weight, fsType, magicNumber] + + urange + + codepage + + [checkSumAdjustment] + ) + ) + + return "".join((fixed, nameheaders, rootstring)) + + def write_eot_font(eot, header, data): - open(eot,'wb').write(''.join((header, data))) + open(eot, "wb").write("".join((header, data))) return + def main(): # deal with options p = optparse.OptionParser() - p.add_option('--output', '-o', default="world") + p.add_option("--output", "-o", default="world") options, args = p.parse_args() - + # iterate over font files for f in args: data = readfont(f) if len(data) == 0: - print 'Error reading %s' % f + print "Error reading %s" % f else: eot = eotname(f) header = make_eot_header(data) write_eot_font(eot, header, data) - -if __name__ == '__main__': + +if __name__ == "__main__": main() - - \ No newline at end of file diff --git a/static/ionicons-2.0.1/builder/scripts/generate_font.py b/static/ionicons-2.0.1/builder/scripts/generate_font.py index 8e0bed2..2987942 100755 --- a/static/ionicons-2.0.1/builder/scripts/generate_font.py +++ b/static/ionicons-2.0.1/builder/scripts/generate_font.py @@ -11,163 +11,180 @@ import copy SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) -INPUT_SVG_DIR = os.path.join(SCRIPT_PATH, '..', '..', 'src') -OUTPUT_FONT_DIR = os.path.join(SCRIPT_PATH, '..', '..', 'fonts') -MANIFEST_PATH = os.path.join(SCRIPT_PATH, '..', 'manifest.json') -BUILD_DATA_PATH = os.path.join(SCRIPT_PATH, '..', 'build_data.json') +INPUT_SVG_DIR = os.path.join(SCRIPT_PATH, "..", "..", "src") +OUTPUT_FONT_DIR = os.path.join(SCRIPT_PATH, "..", "..", "fonts") +MANIFEST_PATH = os.path.join(SCRIPT_PATH, "..", "manifest.json") +BUILD_DATA_PATH = os.path.join(SCRIPT_PATH, "..", "build_data.json") AUTO_WIDTH = True KERNING = 15 -cp = 0xf100 +cp = 0xF100 m = md5.new() f = fontforge.font() -f.encoding = 'UnicodeFull' +f.encoding = "UnicodeFull" f.design_size = 16 f.em = 512 f.ascent = 448 f.descent = 64 -manifest_file = open(MANIFEST_PATH, 'r') +manifest_file = open(MANIFEST_PATH, "r") manifest_data = json.loads(manifest_file.read()) manifest_file.close() -print "Load Manifest, Icons: %s" % ( len(manifest_data['icons']) ) +print "Load Manifest, Icons: %s" % (len(manifest_data["icons"])) build_data = copy.deepcopy(manifest_data) -build_data['icons'] = [] +build_data["icons"] = [] -font_name = manifest_data['name'] -m.update(font_name + ';') -m.update(manifest_data['prefix'] + ';') +font_name = manifest_data["name"] +m.update(font_name + ";") +m.update(manifest_data["prefix"] + ";") for dirname, dirnames, filenames in os.walk(INPUT_SVG_DIR): - for filename in filenames: - name, ext = os.path.splitext(filename) - filePath = os.path.join(dirname, filename) - size = os.path.getsize(filePath) - - if ext in ['.svg', '.eps']: - - # see if this file is already in the manifest - chr_code = None - for ionicon in manifest_data['icons']: - if ionicon['name'] == name: - chr_code = ionicon['code'] - break - - if chr_code is None: - # this is a new src icon - print 'New Icon: \n - %s' % (name) - - while True: - chr_code = '0x%x' % (cp) - already_exists = False - for ionicon in manifest_data['icons']: - if ionicon.get('code') == chr_code: - already_exists = True - cp += 1 - chr_code = '0x%x' % (cp) - continue - if not already_exists: - break - - print ' - %s' % chr_code - manifest_data['icons'].append({ - 'name': name, - 'code': chr_code - }) - - build_data['icons'].append({ - 'name': name, - 'code': chr_code - }) - - if ext in ['.svg']: - # hack removal of tags - svgfile = open(filePath, 'r+') - tmpsvgfile = tempfile.NamedTemporaryFile(suffix=ext, delete=False) - svgtext = svgfile.read() - svgfile.seek(0) - - # replace the tags with 'nothing' - svgtext = svgtext.replace('', '') - svgtext = svgtext.replace('', '') - - tmpsvgfile.file.write(svgtext) - - svgfile.close() - tmpsvgfile.file.close() - - filePath = tmpsvgfile.name - # end hack - - m.update(name + str(size) + ';') - glyph = f.createChar( int(chr_code, 16) ) - glyph.importOutlines(filePath) - - # if we created a temporary file, let's clean it up - if tmpsvgfile: - os.unlink(tmpsvgfile.name) - - # set glyph size explicitly or automatically depending on autowidth - if AUTO_WIDTH: - glyph.left_side_bearing = glyph.right_side_bearing = 0 - glyph.round() - - # resize glyphs if autowidth is enabled - if AUTO_WIDTH: - f.autoWidth(0, 0, 512) - - fontfile = '%s/ionicons' % (OUTPUT_FONT_DIR) + for filename in filenames: + name, ext = os.path.splitext(filename) + filePath = os.path.join(dirname, filename) + size = os.path.getsize(filePath) + + if ext in [".svg", ".eps"]: + + # see if this file is already in the manifest + chr_code = None + for ionicon in manifest_data["icons"]: + if ionicon["name"] == name: + chr_code = ionicon["code"] + break + + if chr_code is None: + # this is a new src icon + print "New Icon: \n - %s" % (name) + + while True: + chr_code = "0x%x" % (cp) + already_exists = False + for ionicon in manifest_data["icons"]: + if ionicon.get("code") == chr_code: + already_exists = True + cp += 1 + chr_code = "0x%x" % (cp) + continue + if not already_exists: + break + + print " - %s" % chr_code + manifest_data["icons"].append({"name": name, "code": chr_code}) + + build_data["icons"].append({"name": name, "code": chr_code}) + + if ext in [".svg"]: + # hack removal of tags + svgfile = open(filePath, "r+") + tmpsvgfile = tempfile.NamedTemporaryFile(suffix=ext, delete=False) + svgtext = svgfile.read() + svgfile.seek(0) + + # replace the tags with 'nothing' + svgtext = svgtext.replace("", "") + svgtext = svgtext.replace("", "") + + tmpsvgfile.file.write(svgtext) + + svgfile.close() + tmpsvgfile.file.close() + + filePath = tmpsvgfile.name + # end hack + + m.update(name + str(size) + ";") + glyph = f.createChar(int(chr_code, 16)) + glyph.importOutlines(filePath) + + # if we created a temporary file, let's clean it up + if tmpsvgfile: + os.unlink(tmpsvgfile.name) + + # set glyph size explicitly or automatically depending on autowidth + if AUTO_WIDTH: + glyph.left_side_bearing = glyph.right_side_bearing = 0 + glyph.round() + + # resize glyphs if autowidth is enabled + if AUTO_WIDTH: + f.autoWidth(0, 0, 512) + + fontfile = "%s/ionicons" % (OUTPUT_FONT_DIR) build_hash = m.hexdigest() -if build_hash == manifest_data.get('build_hash'): - print "Source files unchanged, did not rebuild fonts" +if build_hash == manifest_data.get("build_hash"): + print "Source files unchanged, did not rebuild fonts" else: - manifest_data['build_hash'] = build_hash - - f.fontname = font_name - f.familyname = font_name - f.fullname = font_name - f.generate(fontfile + '.ttf') - f.generate(fontfile + '.svg') - - # Fix SVG header for webkit - # from: https://github.com/fontello/font-builder/blob/master/bin/fontconvert.py - svgfile = open(fontfile + '.svg', 'r+') - svgtext = svgfile.read() - svgfile.seek(0) - svgfile.write(svgtext.replace('''''', '''''')) - svgfile.close() - - scriptPath = os.path.dirname(os.path.realpath(__file__)) - try: - subprocess.Popen([scriptPath + '/sfnt2woff', fontfile + '.ttf'], stdout=subprocess.PIPE) - except OSError: - # If the local version of sfnt2woff fails (i.e., on Linux), try to use the - # global version. This allows us to avoid forcing OS X users to compile - # sfnt2woff from source, simplifying install. - subprocess.call(['sfnt2woff', fontfile + '.ttf']) - - # eotlitetool.py script to generate IE7-compatible .eot fonts - subprocess.call('python ' + scriptPath + '/eotlitetool.py ' + fontfile + '.ttf -o ' + fontfile + '.eot', shell=True) - subprocess.call('mv ' + fontfile + '.eotlite ' + fontfile + '.eot', shell=True) - - # Hint the TTF file - subprocess.call('ttfautohint -s -f -n ' + fontfile + '.ttf ' + fontfile + '-hinted.ttf > /dev/null 2>&1 && mv ' + fontfile + '-hinted.ttf ' + fontfile + '.ttf', shell=True) - - manifest_data['icons'] = sorted(manifest_data['icons'], key=lambda k: k['name']) - build_data['icons'] = sorted(build_data['icons'], key=lambda k: k['name']) - - print "Save Manifest, Icons: %s" % ( len(manifest_data['icons']) ) - f = open(MANIFEST_PATH, 'w') - f.write( json.dumps(manifest_data, indent=2, separators=(',', ': ')) ) - f.close() - - print "Save Build, Icons: %s" % ( len(build_data['icons']) ) - f = open(BUILD_DATA_PATH, 'w') - f.write( json.dumps(build_data, indent=2, separators=(',', ': ')) ) - f.close() - + manifest_data["build_hash"] = build_hash + + f.fontname = font_name + f.familyname = font_name + f.fullname = font_name + f.generate(fontfile + ".ttf") + f.generate(fontfile + ".svg") + + # Fix SVG header for webkit + # from: https://github.com/fontello/font-builder/blob/master/bin/fontconvert.py + svgfile = open(fontfile + ".svg", "r+") + svgtext = svgfile.read() + svgfile.seek(0) + svgfile.write( + svgtext.replace("""""", """""") + ) + svgfile.close() + + scriptPath = os.path.dirname(os.path.realpath(__file__)) + try: + subprocess.Popen( + [scriptPath + "/sfnt2woff", fontfile + ".ttf"], stdout=subprocess.PIPE + ) + except OSError: + # If the local version of sfnt2woff fails (i.e., on Linux), try to use the + # global version. This allows us to avoid forcing OS X users to compile + # sfnt2woff from source, simplifying install. + subprocess.call(["sfnt2woff", fontfile + ".ttf"]) + + # eotlitetool.py script to generate IE7-compatible .eot fonts + subprocess.call( + "python " + + scriptPath + + "/eotlitetool.py " + + fontfile + + ".ttf -o " + + fontfile + + ".eot", + shell=True, + ) + subprocess.call("mv " + fontfile + ".eotlite " + fontfile + ".eot", shell=True) + + # Hint the TTF file + subprocess.call( + "ttfautohint -s -f -n " + + fontfile + + ".ttf " + + fontfile + + "-hinted.ttf > /dev/null 2>&1 && mv " + + fontfile + + "-hinted.ttf " + + fontfile + + ".ttf", + shell=True, + ) + + manifest_data["icons"] = sorted(manifest_data["icons"], key=lambda k: k["name"]) + build_data["icons"] = sorted(build_data["icons"], key=lambda k: k["name"]) + + print "Save Manifest, Icons: %s" % (len(manifest_data["icons"])) + f = open(MANIFEST_PATH, "w") + f.write(json.dumps(manifest_data, indent=2, separators=(",", ": "))) + f.close() + + print "Save Build, Icons: %s" % (len(build_data["icons"])) + f = open(BUILD_DATA_PATH, "w") + f.write(json.dumps(build_data, indent=2, separators=(",", ": "))) + f.close() diff --git a/templatetags/labels.py b/templatetags/labels.py index 5a8139b..b9c9e48 100644 --- a/templatetags/labels.py +++ b/templatetags/labels.py @@ -1,4 +1,3 @@ - from django import template from django.utils.safestring import mark_safe @@ -21,17 +20,17 @@ def label(context, value, safe=False, app=None): app = get_app_from_request(context.request) except AttributeError: raise AttributeError( - 'Current app could not be found. ' - 'This may occur in widget templates as they do not return ' - 'request object. In this case, you can set app manually.' + "Current app could not be found. " + "This may occur in widget templates as they do not return " + "request object. In this case, you can set app manually." ) - if app == '': + if app == "": return None current = APP_LABELS.get(app) if current is None: return None - keys = value.split(':') + keys = value.split(":") for key in keys: current = current.get(key) if current is None: diff --git a/templatetags/simple.py b/templatetags/simple.py index e6430f7..2ce6b85 100644 --- a/templatetags/simple.py +++ b/templatetags/simple.py @@ -1,4 +1,3 @@ - from django import template register = template.Library() diff --git a/user_sessions/__init__.py b/user_sessions/__init__.py index accd9c2..232944c 100644 --- a/user_sessions/__init__.py +++ b/user_sessions/__init__.py @@ -1 +1 @@ -default_app_config = 'user_sessions.apps.UserSessionsConfig' +default_app_config = "user_sessions.apps.UserSessionsConfig" diff --git a/user_sessions/apps.py b/user_sessions/apps.py index 618f5eb..02b47ba 100644 --- a/user_sessions/apps.py +++ b/user_sessions/apps.py @@ -1,15 +1,15 @@ - from django.apps import AppConfig from wam import settings class UserSessionsConfig(AppConfig): - name = 'user_sessions' + name = "user_sessions" def ready(self): """This function is executed right after project settings""" # Initialize user sessions: from user_sessions.sessions import SessionData + settings.SESSION_DATA = SessionData() diff --git a/user_sessions/sessions.py b/user_sessions/sessions.py index 41014be..5e0e40d 100644 --- a/user_sessions/sessions.py +++ b/user_sessions/sessions.py @@ -2,7 +2,7 @@ from utils.shortcuts import get_app_from_request -class SessionData(): +class SessionData: def __init__(self): self.sessions = defaultdict(dict) @@ -16,9 +16,8 @@ def start_session(self, request, session_obj): def get_session(self, request): # pylint: disable=no-else-raise app = get_app_from_request(request) - user_session = self.sessions[app].get( - request.session.session_key, None) + user_session = self.sessions[app].get(request.session.session_key, None) if user_session is None: - raise KeyError('Session not found') + raise KeyError("Session not found") else: return user_session diff --git a/user_sessions/urls.py b/user_sessions/urls.py index 517d520..ef860a5 100644 --- a/user_sessions/urls.py +++ b/user_sessions/urls.py @@ -1,4 +1,3 @@ - from django.urls import path from wam.admin import wam_admin_site @@ -6,14 +5,14 @@ from user_sessions import views -app_name = 'user_sessions' +app_name = "user_sessions" url_patterns = [] admin_url_patterns = [ path( - 'sessions/manage', + "sessions/manage", wam_admin_site.admin_view(views.ManageView.as_view()), - name='manage' + name="manage", ), ] diff --git a/user_sessions/utils.py b/user_sessions/utils.py index 8ca9328..8f8228f 100644 --- a/user_sessions/utils.py +++ b/user_sessions/utils.py @@ -12,13 +12,15 @@ def check_session_method(func): This method is for class-based views """ + def func_wrapper(self, request, *args, **kwargs): try: session = SESSION_DATA.get_session(request) except KeyError: log_session_error(request) - return render(request, 'stemp/session_not_found.html') + return render(request, "stemp/session_not_found.html") return func(self, request, session=session, *args, **kwargs) + return func_wrapper @@ -28,13 +30,15 @@ def check_session(func): This function is for function-based views """ + def func_wrapper(request, *args, **kwargs): try: session = SESSION_DATA.get_session(request) except KeyError: log_session_error(request) - return render(request, 'stemp/session_not_found.html') + return render(request, "stemp/session_not_found.html") return func(request, session=session, *args, **kwargs) + return func_wrapper @@ -42,10 +46,8 @@ def log_session_error(request): app = get_app_from_request(request) err_msg = ( f'Session error for app "{app}":\n' - f'Session-Key: {request.session.session_key}\n' - f'Current session data:\n' + - '\n'.join( - [f'{k}: {str(v)}' for k, v in SESSION_DATA.sessions[app].items()] - ) + f"Session-Key: {request.session.session_key}\n" + f"Current session data:\n" + + "\n".join([f"{k}: {str(v)}" for k, v in SESSION_DATA.sessions[app].items()]) ) logging.error(err_msg) diff --git a/user_sessions/views.py b/user_sessions/views.py index 120b216..f20bb6c 100644 --- a/user_sessions/views.py +++ b/user_sessions/views.py @@ -1,11 +1,10 @@ - from django.views.generic import TemplateView from wam.settings import SESSION_DATA class ManageView(TemplateView): - template_name = 'user_sessions/manage.html' + template_name = "user_sessions/manage.html" def get_context_data(self, **kwargs): - return {'session_keys': SESSION_DATA.sessions.keys()} + return {"session_keys": SESSION_DATA.sessions.keys()} diff --git a/utils/constants.py b/utils/constants.py index c58e38f..0994e04 100644 --- a/utils/constants.py +++ b/utils/constants.py @@ -1,34 +1,32 @@ - from enum import Enum from collections import namedtuple AppInfo = namedtuple( - 'AppInfo', - ['category', 'name', 'url', 'closed', 'icon', 'url_arg'], + "AppInfo", ["category", "name", "url", "closed", "icon", "url_arg"], ) AppInfo.__new__.__defaults__ = (False, None, None) class AppCategory(Enum): - Web = 'web' - App = 'app' - Map = 'map' + Web = "web" + App = "app" + Map = "map" def label(self): return { - AppCategory.Web: 'Websites', - AppCategory.App: 'Applications', - AppCategory.Map: 'Maps' + AppCategory.Web: "Websites", + AppCategory.App: "Applications", + AppCategory.Map: "Maps", }.get(self) def goto(self): return { - AppCategory.Web: 'Zur Seite', - AppCategory.App: 'Zum Tool', - AppCategory.Map: 'Zur Karte' + AppCategory.Web: "Zur Seite", + AppCategory.App: "Zum Tool", + AppCategory.Map: "Zur Karte", }.get(self) class AppIcon(Enum): - Map = 'img/icons_custom/Icon_map_w.png' + Map = "img/icons_custom/Icon_map_w.png" diff --git a/utils/forms.py b/utils/forms.py index 34e4326..c63f4f2 100644 --- a/utils/forms.py +++ b/utils/forms.py @@ -3,17 +3,15 @@ class FeedbackForm(forms.Form): """Input form for feedback page""" - from_name = forms.CharField(required=False, - max_length=100, - label='Your Name (optional)') - from_email = forms.EmailField(required=False, - label='Email Address (optional)') - subject = forms.CharField(required=True, - max_length=100, - label='Subject') - message = forms.CharField(widget=forms.Textarea, - required=True, - label='Your Feedback') + + from_name = forms.CharField( + required=False, max_length=100, label="Your Name (optional)" + ) + from_email = forms.EmailField(required=False, label="Email Address (optional)") + subject = forms.CharField(required=True, max_length=100, label="Subject") + message = forms.CharField( + widget=forms.Textarea, required=True, label="Your Feedback" + ) def submit(self): pass diff --git a/utils/highcharts.py b/utils/highcharts.py index f68ece4..03d121d 100644 --- a/utils/highcharts.py +++ b/utils/highcharts.py @@ -1,4 +1,3 @@ - from itertools import count import pandas from django.utils.safestring import mark_safe @@ -8,102 +7,90 @@ # Full HC API reference: https://api.highcharts.com/highcharts/ RLI_THEME = { - 'credits': { - 'enabled': False - }, - 'colors': [ - '#fc8e65', '#55aae5', '#7fadb7', '#fce288', '#f69c3a', '#c28e5e', - '#a27b82', '#797097' + "credits": {"enabled": False}, + "colors": [ + "#fc8e65", + "#55aae5", + "#7fadb7", + "#fce288", + "#f69c3a", + "#c28e5e", + "#a27b82", + "#797097", ], - 'title': { - 'style': { - 'color': '#002E4F', - 'font': 'bold 1.2rem Roboto, "Trebuchet MS", Verdana, sans-serif' + "title": { + "style": { + "color": "#002E4F", + "font": 'bold 1.2rem Roboto, "Trebuchet MS", Verdana, sans-serif', } }, - 'subtitle': { - 'style': { - 'color': '#666', - 'font': 'bold 12px "Roboto Light", "Trebuchet MS", Verdana, sans-serif' + "subtitle": { + "style": { + "color": "#666", + "font": 'bold 12px "Roboto Light", "Trebuchet MS", Verdana, sans-serif', } }, - 'lang': { - 'decimalPoint': ',', - 'thousandsSep': '.' - }, - 'legend': { - 'itemStyle': { - 'font': '1rem "Roboto Light", Trebuchet MS, Verdana, sans-serif', - 'color': 'black' + "lang": {"decimalPoint": ",", "thousandsSep": "."}, + "legend": { + "itemStyle": { + "font": '1rem "Roboto Light", Trebuchet MS, Verdana, sans-serif', + "color": "black", }, - 'itemHoverStyle': { - 'color': 'gray' - } + "itemHoverStyle": {"color": "gray"}, + }, + "plotOptions": { + "series": {"dataLabels": {"style": {"fontWeight": None, "textOutline": None}}} }, - 'plotOptions': { - 'series': { - 'dataLabels': { - 'style': { - 'fontWeight': None, - 'textOutline': None - } - } - } - } } class Highchart(HC): - media_template = 'includes/highchart_media.html' + media_template = "includes/highchart_media.html" id_counter = count() def __init__(self, use_rli_theme=True, **kwargs): self.id = next(self.id_counter) - if 'renderTo' not in kwargs: - kwargs['renderTo'] = f'hc_{self.id}' + if "renderTo" not in kwargs: + kwargs["renderTo"] = f"hc_{self.id}" super(Highchart, self).__init__(**kwargs) if use_rli_theme: self.set_dict_options(RLI_THEME) def add_pandas_data_set(self, data, series_type=None, **kwargs): if series_type is None: - ValueError('No highcharts type specified.') + ValueError("No highcharts type specified.") if isinstance(data, pandas.Series): - self.add_data_set( - data.values.tolist(), series_type, data.name, **kwargs) + self.add_data_set(data.values.tolist(), series_type, data.name, **kwargs) elif isinstance(data, pandas.DataFrame): for column in data.columns: - if series_type == 'scatter': + if series_type == "scatter": self.add_data_set( data=[data[column].tolist()], series_type=series_type, name=column, - **kwargs + **kwargs, ) else: self.add_data_set( data=data[column].tolist(), series_type=series_type, name=column, - **kwargs + **kwargs, ) else: self.add_data_set(data, series_type) if ( - isinstance(data, pandas.Series) or - isinstance(data, pandas.DataFrame) and - series_type != 'scatter' + isinstance(data, pandas.Series) + or isinstance(data, pandas.DataFrame) + and series_type != "scatter" ): - self.set_options( - 'xAxis', - {'categories': data.index.values.tolist()} - ) + self.set_options("xAxis", {"categories": data.index.values.tolist()}) def __str__(self): self.buildhtml() return mark_safe(self.container) def media(self): - context = {'chart': self} + context = {"chart": self} renderer = get_default_renderer() return mark_safe(renderer.render(self.media_template, context)) diff --git a/utils/mail.py b/utils/mail.py index e86f01f..6d9a6f3 100644 --- a/utils/mail.py +++ b/utils/mail.py @@ -1,7 +1,12 @@ import logging from requests.exceptions import ConnectionError # pylint: disable=import-error -from exchangelib import Credentials, Account, Message, Mailbox # pylint: disable=import-error +from exchangelib import ( + Credentials, + Account, + Message, + Mailbox, +) # pylint: disable=import-error from exchangelib.errors import AutoDiscoverFailed # pylint: disable=import-error from wam.settings import WAM_EXCHANGE_ACCOUNT, WAM_EXCHANGE_EMAIL, WAM_EXCHANGE_PW @@ -24,37 +29,38 @@ def send_email(to_email, subject, message): Success status (True: successful) """ - credentials = Credentials(WAM_EXCHANGE_ACCOUNT, - WAM_EXCHANGE_PW) + credentials = Credentials(WAM_EXCHANGE_ACCOUNT, WAM_EXCHANGE_PW) try: - account = Account(WAM_EXCHANGE_EMAIL, - credentials=credentials, - autodiscover=True) + account = Account( + WAM_EXCHANGE_EMAIL, credentials=credentials, autodiscover=True + ) except ConnectionError: - err_msg = 'Feedback-Form - Verbindungsfehler!' + err_msg = "Feedback-Form - Verbindungsfehler!" logging.error(err_msg) return False except AutoDiscoverFailed: - err_msg = 'Feedback-Form - Konto- oder Authentifizierungsfehler!' + err_msg = "Feedback-Form - Konto- oder Authentifizierungsfehler!" logging.error(err_msg) return False except Exception as err: # pylint: disable=broad-except - err_msg = f'Feedback-Form - Sonstiger Fehler: {err}' + err_msg = f"Feedback-Form - Sonstiger Fehler: {err}" logging.error(err_msg) return False recipients = [Mailbox(email_address=to_email)] - m = Message(account=account, - folder=account.sent, - subject=subject, - body=message, - to_recipients=recipients) + m = Message( + account=account, + folder=account.sent, + subject=subject, + body=message, + to_recipients=recipients, + ) try: m.send_and_save() except Exception as err: # pylint: disable=broad-except - err_msg = f'Feedback-Form - Fehler beim Mailversand: {err}' + err_msg = f"Feedback-Form - Fehler beim Mailversand: {err}" logging.error(err_msg) return False diff --git a/utils/permissions.py b/utils/permissions.py index 2365d92..2f2f6bf 100644 --- a/utils/permissions.py +++ b/utils/permissions.py @@ -4,7 +4,7 @@ class GroupCheckMixin(UserPassesTestMixin): groups_to_check = [] - access_denied_url = 'access_denied' + access_denied_url = "access_denied" def get_login_url(self): # pylint: disable=R1705 @@ -15,7 +15,6 @@ def get_login_url(self): def test_func(self): if len(self.groups_to_check) == 0: - logging.warning( - 'No groups to check - Group check will always fail!') + logging.warning("No groups to check - Group check will always fail!") user_groups = {g.name for g in self.request.user.groups.all()} return len(user_groups.intersection(set(self.groups_to_check))) > 0 diff --git a/utils/shortcuts.py b/utils/shortcuts.py index ea64fbc..8d7a211 100644 --- a/utils/shortcuts.py +++ b/utils/shortcuts.py @@ -4,15 +4,14 @@ def redirect_with_get_parameters(url, **parameters): assert isinstance(parameters, dict) response = redirect(url) - response['Location'] += '?' + '&'.join( - [str(key) + '=' + str(value) for key, value in parameters.items()]) + response["Location"] += "?" + "&".join( + [str(key) + "=" + str(value) for key, value in parameters.items()] + ) return response def get_app_from_request(request): try: - return request.path.split('/')[1] + return request.path.split("/")[1] except AttributeError: - raise AttributeError( - 'Current app could not be found' - ) + raise AttributeError("Current app could not be found") diff --git a/utils/views.py b/utils/views.py index 5830d48..9361782 100644 --- a/utils/views.py +++ b/utils/views.py @@ -7,7 +7,12 @@ from django.core.validators import validate_email, ValidationError from django.shortcuts import redirect -from wam.settings import BASE_DIR, WAM_EXCHANGE_ACCOUNT, WAM_EXCHANGE_EMAIL, WAM_EXCHANGE_PW +from wam.settings import ( + BASE_DIR, + WAM_EXCHANGE_ACCOUNT, + WAM_EXCHANGE_EMAIL, + WAM_EXCHANGE_PW, +) from utils.forms import FeedbackForm from utils.mail import send_email @@ -17,14 +22,12 @@ class FeedbackView(FormView): # pylint: disable=too-many-ancestors app_name = None intro_text = None - template_name = 'feedback.html' + template_name = "feedback.html" form_class = FeedbackForm - success_url = '/feedback_thanks/' - error_url = '/feedback_error/' + success_url = "/feedback_thanks/" + error_url = "/feedback_error/" - def __init__(self, - app_name=None, - intro_text=None): + def __init__(self, app_name=None, intro_text=None): """ Parameters ---------- @@ -40,15 +43,16 @@ def __init__(self, self.app_name = app_name # read and validate app admin's mail address from app.cfg - app_config = ConfigObj(os.path.join(BASE_DIR, app_name, 'app.cfg')) - email = app_config.get('email', None) + app_config = ConfigObj(os.path.join(BASE_DIR, app_name, "app.cfg")) + email = app_config.get("email", None) if email is not None: try: validate_email(email) self.to_email = email except ValidationError: raise ValidationError( - f'E-mail address in {app_name}`s app.cfg is invalid!') + f"E-mail address in {app_name}`s app.cfg is invalid!" + ) else: raise ValueError('Parameter "app_name" must be specified!') @@ -58,72 +62,75 @@ def form_valid(self, form): form.submit() subject, body = self.prepare_message(**form.cleaned_data) - success = send_email(to_email=self.to_email, - subject=subject, - message=body) + success = send_email(to_email=self.to_email, subject=subject, message=body) if success: return super().form_valid(form) - return redirect('feedback_error', err_type='send') + return redirect("feedback_error", err_type="send") def get_context_data(self, **kwargs): context = super(FeedbackView, self).get_context_data(**kwargs) - context['app_name'] = self.app_name - context['intro_text'] = self.intro_text + context["app_name"] = self.app_name + context["intro_text"] = self.intro_text return context def get(self, request, *args, **kwargs): # check if env vars are set, if not redirect to error page - if WAM_EXCHANGE_ACCOUNT is None or \ - WAM_EXCHANGE_EMAIL is None or \ - WAM_EXCHANGE_PW is None: - err_msg = 'Feedback-Form - Konfigurationsfehler: ' \ - 'Umgebungsvariablen nicht gesetzt oder unvollständig!' + if ( + WAM_EXCHANGE_ACCOUNT is None + or WAM_EXCHANGE_EMAIL is None + or WAM_EXCHANGE_PW is None + ): + err_msg = ( + "Feedback-Form - Konfigurationsfehler: " + "Umgebungsvariablen nicht gesetzt oder unvollständig!" + ) logging.error(err_msg) - return redirect('feedback_error', err_type='config') + return redirect("feedback_error", err_type="config") return super().get(request, *args, **kwargs) def prepare_message(self, **kwargs): - subject = f'Nachricht über WAM Feedback-Formular: ' \ - f'App {self.app_name}' - body = f'Sie haben eine Nachricht über das Feedback-Formular der WAM ' \ - f'erhalten.\n\n' \ - f'App: {self.app_name}\n' \ - f'Absender: {kwargs.get("from_name", "")} ' \ - f'({kwargs.get("from_email", "")})\n' \ - f'Betreff: {kwargs.get("subject", "")}\n' \ - f'========================================\n' \ - f'{kwargs.get("message", "")}\n' \ - f'========================================\n' \ - f'Bitte antworte nicht auf diese E-Mail, junger PadaWAM!\n' \ - f'Gez. Obi WAM Kenobi' + subject = f"Nachricht über WAM Feedback-Formular: " f"App {self.app_name}" + body = ( + f"Sie haben eine Nachricht über das Feedback-Formular der WAM " + f"erhalten.\n\n" + f"App: {self.app_name}\n" + f'Absender: {kwargs.get("from_name", "")} ' + f'({kwargs.get("from_email", "")})\n' + f'Betreff: {kwargs.get("subject", "")}\n' + f"========================================\n" + f'{kwargs.get("message", "")}\n' + f"========================================\n" + f"Bitte antworte nicht auf diese E-Mail, junger PadaWAM!\n" + f"Gez. Obi WAM Kenobi" + ) return subject, body class FeedbackSuccessful(TemplateView): - template_name = 'feedback_successful.html' + template_name = "feedback_successful.html" class FeedbackError(TemplateView): """Error page for feedback form""" - template_name = 'feedback_error.html' + template_name = "feedback_error.html" def get(self, request, *args, **kwargs): context = self.get_context_data() # get error type and include corresponding message in context - err_type = kwargs.get('err_type') - if err_type == 'config': - error_text = 'Das Feedback-Formular ist nicht richtig konfiguriert.' - elif err_type == 'send': - error_text = 'Beim Senden ist leider ein Fehler aufgetreten.' + err_type = kwargs.get("err_type") + if err_type == "config": + error_text = "Das Feedback-Formular ist nicht richtig konfiguriert." + elif err_type == "send": + error_text = "Beim Senden ist leider ein Fehler aufgetreten." else: - error_text = 'Das Feedback-Formular funktioniert nicht richtig.' + error_text = "Das Feedback-Formular funktioniert nicht richtig." - context['error_text'] = error_text + context["error_text"] = error_text return self.render_to_response(context) diff --git a/utils/visualizations.py b/utils/visualizations.py index e466f6c..e3f1d83 100644 --- a/utils/visualizations.py +++ b/utils/visualizations.py @@ -1,4 +1,3 @@ - import itertools from abc import ABC, abstractmethod @@ -18,13 +17,13 @@ def __init__(self, data=None): def get_context(self, **kwargs): return { - 'div_id': kwargs.get('div_id', f'rank_{self.id}'), - 'div_kwargs': kwargs.get('div_kwargs', {}) + "div_id": kwargs.get("div_id", f"rank_{self.id}"), + "div_kwargs": kwargs.get("div_kwargs", {}), } def render(self, **kwargs): if self.template_name is None: - raise TemplateDoesNotExist('No template_name set') + raise TemplateDoesNotExist("No template_name set") renderer = get_default_renderer() context = self.get_context(**kwargs) return renderer.render(self.template_name, context) diff --git a/utils/widgets.py b/utils/widgets.py index beb6036..a0140d3 100644 --- a/utils/widgets.py +++ b/utils/widgets.py @@ -1,4 +1,3 @@ - import os from abc import ABC from typing import List, Tuple, Optional @@ -47,18 +46,18 @@ class InfoButton(CustomWidget): showing info text (markdown supported). """ - template_name = 'widgets/info_button.html' + template_name = "widgets/info_button.html" counter = count() def __init__( - self, - text: str = '', - tooltip: str = '', - is_markdown: bool = False, - ionicon_type: str = 'ion-information-circled', - ionicon_size: str = 'small', - ionicon_color: str = None, - info_id: str = None + self, + text: str = "", + tooltip: str = "", + is_markdown: bool = False, + ionicon_type: str = "ion-information-circled", + ionicon_size: str = "small", + ionicon_color: str = None, + info_id: str = None, ): """ @@ -83,9 +82,11 @@ def __init__( prepended by "info_". By default, a counter is used which results in ids "info_0", "info_1" etc. """ - self.text = markdown(text, - extensions=MARKDOWNX_MARKDOWN_EXTENSIONS)\ - if is_markdown else text + self.text = ( + markdown(text, extensions=MARKDOWNX_MARKDOWN_EXTENSIONS) + if is_markdown + else text + ) self.tooltip = tooltip self.ionicon_type = ionicon_type self.ionicon_size = ionicon_size @@ -98,12 +99,12 @@ def __init__( def get_context(self): return { - 'info_id': f'info_{self.id}', - 'text': self.text, - 'tooltip': self.tooltip, - 'ionicon_type': self.ionicon_type, - 'ionicon_size': self.ionicon_size, - 'ionicon_color': self.ionicon_color + "info_id": f"info_{self.id}", + "text": self.text, + "tooltip": self.tooltip, + "ionicon_type": self.ionicon_type, + "ionicon_size": self.ionicon_size, + "ionicon_color": self.ionicon_color, } @@ -114,13 +115,14 @@ class Wizard(CustomWidget): Active steps are hrefs, current step is circled, coming steps are inactive. Optionally, screen reader text for current step can be given. """ - template_name = 'widgets/wizard.html' + + template_name = "widgets/wizard.html" def __init__( - self, - urls: List[Optional[Tuple[str, str]]], - current: int, - screen_reader_for_current: str = None + self, + urls: List[Optional[Tuple[str, str]]], + current: int, + screen_reader_for_current: str = None, ): """ @@ -140,17 +142,18 @@ def __init__( def get_context(self): return { - 'urls': self.urls, - 'current': self.current, - 'screen_reader': self.screen_reader + "urls": self.urls, + "current": self.current, + "screen_reader": self.screen_reader, } class CSVWidget: """Reads in CSV-file and renders it as table""" - def __init__(self, filename, caption, csv_kwargs=None, html_kwargs=None, - links=None): + def __init__( + self, filename, caption, csv_kwargs=None, html_kwargs=None, links=None + ): """ Parameters ---------- @@ -175,9 +178,8 @@ def __init__(self, filename, caption, csv_kwargs=None, html_kwargs=None, csv_kwargs = {} if csv_kwargs is None else csv_kwargs self.data = pandas.read_csv(filename, **csv_kwargs) for link in links: - self.data[link] = self.data[link].apply( - lambda x: f'{x}') - self.data.fillna('-', inplace=True) + self.data[link] = self.data[link].apply(lambda x: f'{x}') + self.data.fillna("-", inplace=True) def __str__(self): style = self.data.style @@ -186,21 +188,18 @@ def __str__(self): class OrbitWidget(CustomWidget): - OrbitItem = namedtuple('OrbitItem', ['name', 'description', 'class_']) + OrbitItem = namedtuple("OrbitItem", ["name", "description", "class_"]) OrbitItem.__new__.__defaults__ = (None,) - template_name = 'widgets/orbit.html' - default_labels = { - 'next': 'Nächster', - 'previous': 'Vorheriger' - } + template_name = "widgets/orbit.html" + default_labels = {"next": "Nächster", "previous": "Vorheriger"} def __init__( - self, - caption: str, - orbits: List[OrbitItem], - labels: dict = None, - orbit_class='orbit' + self, + caption: str, + orbits: List[OrbitItem], + labels: dict = None, + orbit_class="orbit", ): if labels is None: labels = {} @@ -211,8 +210,8 @@ def __init__( def get_context(self): return { - 'caption': self.caption, - 'labels': self.labels, - 'orbits': self.orbits, - 'orbit_class': self.orbit_class + "caption": self.caption, + "labels": self.labels, + "orbits": self.orbits, + "orbit_class": self.orbit_class, } diff --git a/wam/admin.py b/wam/admin.py index ca9bc1d..fd3cbdd 100644 --- a/wam/admin.py +++ b/wam/admin.py @@ -1,4 +1,3 @@ - import importlib from django.contrib.admin import AdminSite @@ -11,8 +10,8 @@ class WamAdminSite(AdminSite): def get_urls(self): admin_urls = super(WamAdminSite, self).get_urls() - for app in settings.WAM_APPS + ['user_sessions']: - urls_module = importlib.import_module(f'{app}.urls') + for app in settings.WAM_APPS + ["user_sessions"]: + urls_module = importlib.import_module(f"{app}.urls") try: admin_urls.extend(urls_module.admin_url_patterns) except AttributeError: diff --git a/wam/celery.py b/wam/celery.py index cd2aa08..a7b6dc0 100644 --- a/wam/celery.py +++ b/wam/celery.py @@ -1,35 +1,28 @@ - from __future__ import absolute_import, unicode_literals import os from celery import Celery from wam.settings import config -os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wam.settings') +os.environ.setdefault("DJANGO_SETTINGS_MODULE", "wam.settings") -if 'READTHEDOCS' in os.environ: +if "READTHEDOCS" in os.environ: url = None else: - url = 'amqp://{user}:{password}@{host}:{port}/{vhost}'.format( - user=config['CELERY']['USER'], - password=config['CELERY']['PASSWORD'], - host=config['CELERY']['HOST'], - port=config['CELERY']['PORT'], - vhost=config['CELERY']['VHOST'], + url = "amqp://{user}:{password}@{host}:{port}/{vhost}".format( + user=config["CELERY"]["USER"], + password=config["CELERY"]["PASSWORD"], + host=config["CELERY"]["HOST"], + port=config["CELERY"]["PORT"], + vhost=config["CELERY"]["VHOST"], ) -app = Celery( - 'wam', - broker=url, - backend=url, -) +app = Celery("wam", broker=url, backend=url,) app.autodiscover_tasks() -app.conf.task_default_queue = 'wam_queue' +app.conf.task_default_queue = "wam_queue" # Optional configuration, see the application user guide. -app.conf.update( - result_expires=3600, -) +app.conf.update(result_expires=3600,) -if __name__ == '__main__': +if __name__ == "__main__": app.start() diff --git a/wam/settings.py b/wam/settings.py index a28ab18..5f17d9d 100644 --- a/wam/settings.py +++ b/wam/settings.py @@ -15,12 +15,12 @@ import logging from configobj import ConfigObj -config_file_path = os.environ.get('WAM_CONFIG_PATH') +config_file_path = os.environ.get("WAM_CONFIG_PATH") if config_file_path is None: raise KeyError( - 'Please add WAM_CONFIG_PATH as an environment variable, see ' - 'https://wam.readthedocs.io/en/latest/getting_started.html#environment-variables' + "Please add WAM_CONFIG_PATH as an environment variable, see " + "https://wam.readthedocs.io/en/latest/getting_started.html#environment-variables" ) config = ConfigObj(config_file_path) @@ -31,98 +31,93 @@ # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = config['WAM']['SECRET_KEY'] +SECRET_KEY = config["WAM"]["SECRET_KEY"] # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = config['WAM'].as_bool('DEBUG') +DEBUG = config["WAM"].as_bool("DEBUG") logging_level = logging.DEBUG if DEBUG else logging.INFO logging.getLogger().setLevel(logging_level) -ALLOWED_HOSTS = config['WAM'].as_list('ALLOWED_HOSTS') +ALLOWED_HOSTS = config["WAM"].as_list("ALLOWED_HOSTS") # Additional apps are loaded from environment variable -WAM_APPS = os.environ.get('WAM_APPS') +WAM_APPS = os.environ.get("WAM_APPS") if WAM_APPS is None: raise KeyError( - 'Please add WAM_APPS as an environment variable, see ' - 'https://wam.readthedocs.io/en/latest/getting_started.html#environment-variables' + "Please add WAM_APPS as an environment variable, see " + "https://wam.readthedocs.io/en/latest/getting_started.html#environment-variables" ) -if WAM_APPS == '': +if WAM_APPS == "": # The environment variable exists but no apps are defined WAM_APPS = [] else: # Apps name are retrieved - WAM_APPS = WAM_APPS.split(',') + WAM_APPS = WAM_APPS.split(",") APP_LABELS = { - app: ConfigObj(os.path.join(BASE_DIR, app, 'labels.cfg')) - for app in WAM_APPS + app: ConfigObj(os.path.join(BASE_DIR, app, "labels.cfg")) for app in WAM_APPS } # Application definition INSTALLED_APPS = WAM_APPS + [ - 'django.contrib.admin', - 'django.contrib.auth', - 'django.contrib.contenttypes', - 'django.contrib.sessions', - 'django.contrib.messages', - 'django.contrib.staticfiles', - 'django.contrib.gis', - 'django.forms', - 'crispy_forms', - 'meta', - 'user_sessions' + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.gis", + "django.forms", + "crispy_forms", + "meta", + "user_sessions", ] MIDDLEWARE = [ - 'django.middleware.security.SecurityMiddleware', - 'whitenoise.middleware.WhiteNoiseMiddleware', - 'django.contrib.sessions.middleware.SessionMiddleware', - 'django.middleware.locale.LocaleMiddleware', - 'django.middleware.common.CommonMiddleware', - 'django.middleware.csrf.CsrfViewMiddleware', - 'django.contrib.auth.middleware.AuthenticationMiddleware', - 'django.contrib.messages.middleware.MessageMiddleware', - 'django.middleware.clickjacking.XFrameOptionsMiddleware', + "django.middleware.security.SecurityMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", + "django.contrib.sessions.middleware.SessionMiddleware", + "django.middleware.locale.LocaleMiddleware", + "django.middleware.common.CommonMiddleware", + "django.middleware.csrf.CsrfViewMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", + "django.contrib.messages.middleware.MessageMiddleware", + "django.middleware.clickjacking.XFrameOptionsMiddleware", ] -ROOT_URLCONF = 'wam.urls' +ROOT_URLCONF = "wam.urls" TEMPLATES = [ { - 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': ['templates/'], - 'APP_DIRS': True, - 'OPTIONS': { - 'context_processors': [ - 'django.template.context_processors.debug', - 'django.template.context_processors.request', - 'django.contrib.auth.context_processors.auth', - 'django.contrib.messages.context_processors.messages', + "BACKEND": "django.template.backends.django.DjangoTemplates", + "DIRS": ["templates/"], + "APP_DIRS": True, + "OPTIONS": { + "context_processors": [ + "django.template.context_processors.debug", + "django.template.context_processors.request", + "django.contrib.auth.context_processors.auth", + "django.contrib.messages.context_processors.messages", ], - 'libraries': { - 'labels': 'templatetags.labels', - 'simple': 'templatetags.simple', + "libraries": { + "labels": "templatetags.labels", + "simple": "templatetags.simple", }, }, }, ] -FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' +FORM_RENDERER = "django.forms.renderers.TemplatesSetting" -WSGI_APPLICATION = 'wam.wsgi.application' +WSGI_APPLICATION = "wam.wsgi.application" # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases -DJANGO_DB = config['WAM'].get('DJANGO_DB', 'DEFAULT') -DATABASES = { - 'default': { - **config['DATABASES'][DJANGO_DB], - } -} +DJANGO_DB = config["WAM"].get("DJANGO_DB", "DEFAULT") +DATABASES = {"default": {**config["DATABASES"][DJANGO_DB],}} # Password validation @@ -130,25 +125,19 @@ AUTH_PASSWORD_VALIDATORS = [ { - 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', - }, - { - 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, + {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",}, + {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",}, + {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",}, ] # Internationalization # https://docs.djangoproject.com/en/1.11/topics/i18n/ -LANGUAGE_CODE = 'de-DE' +LANGUAGE_CODE = "de-DE" -TIME_ZONE = 'Europe/Berlin' +TIME_ZONE = "Europe/Berlin" USE_I18N = True @@ -164,18 +153,16 @@ # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.11/howto/static-files/ -STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') -STATIC_URL = '/static/' -STATICFILES_DIRS = ( - [ - os.path.join(app, 'static') for app in WAM_APPS - if os.path.exists(os.path.join(app, 'static')) - ] + - [os.path.join(BASE_DIR, "static")] -) -STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage' +STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") +STATIC_URL = "/static/" +STATICFILES_DIRS = [ + os.path.join(app, "static") + for app in WAM_APPS + if os.path.exists(os.path.join(app, "static")) +] + [os.path.join(BASE_DIR, "static")] +STATICFILES_STORAGE = "whitenoise.storage.CompressedStaticFilesStorage" -SESSION_ENGINE = 'django.contrib.sessions.backends.db' +SESSION_ENGINE = "django.contrib.sessions.backends.db" # Contains data under session key: SESSION_DATA = None @@ -184,7 +171,7 @@ for app in WAM_APPS: # Import settings module from app and add constants to wam.settings try: - settings = importlib.import_module(f'{app}.settings', package='wam') + settings = importlib.import_module(f"{app}.settings", package="wam") except ModuleNotFoundError: pass else: @@ -200,16 +187,14 @@ # Import app_settings from app try: - importlib.import_module(f'{app}.app_settings', package='wam') + importlib.import_module(f"{app}.app_settings", package="wam") except ModuleNotFoundError: pass # E-mail config for outgoing mails (used by exchangelib) -WAM_EXCHANGE_ACCOUNT = config['WAM'].get('WAM_EXCHANGE_ACCOUNT') -WAM_EXCHANGE_EMAIL = config['WAM'].get('WAM_EXCHANGE_EMAIL') -WAM_EXCHANGE_PW = config['WAM'].get('WAM_EXCHANGE_PW') +WAM_EXCHANGE_ACCOUNT = config["WAM"].get("WAM_EXCHANGE_ACCOUNT") +WAM_EXCHANGE_EMAIL = config["WAM"].get("WAM_EXCHANGE_EMAIL") +WAM_EXCHANGE_PW = config["WAM"].get("WAM_EXCHANGE_PW") # Extensions for markdownx -MARKDOWNX_MARKDOWN_EXTENSIONS = [ - 'markdown.extensions.extra' -] +MARKDOWNX_MARKDOWN_EXTENSIONS = ["markdown.extensions.extra"] diff --git a/wam/urls.py b/wam/urls.py index c05b7d6..2cb8dbb 100644 --- a/wam/urls.py +++ b/wam/urls.py @@ -28,32 +28,34 @@ urlpatterns = [ - path('', views.IndexView.as_view(), name='index'), - path('contact/', views.ContactView.as_view(), name='contact'), - path('privacy/', views.PrivacyView.as_view(), name='privacy'), - path('impressum/', views.ImpressumView.as_view(), name='impressum'), - path('sources/', AppListView.as_view(model=models.Source), name='sources'), - path('assumptions/', AssumptionsView.as_view()), - path('admin/', wam_admin_site.urls), - path('accounts/login/', LoginView.as_view(template_name='login.html')), - path('access_denied/', TemplateView.as_view( - template_name='access_denied.html'), name='access_denied'), - path('feedback_thanks/', FeedbackSuccessful.as_view(), name='feedback_thanks'), - path('feedback_error//', FeedbackError.as_view(), name='feedback_error') + path("", views.IndexView.as_view(), name="index"), + path("contact/", views.ContactView.as_view(), name="contact"), + path("privacy/", views.PrivacyView.as_view(), name="privacy"), + path("impressum/", views.ImpressumView.as_view(), name="impressum"), + path("sources/", AppListView.as_view(model=models.Source), name="sources"), + path("assumptions/", AssumptionsView.as_view()), + path("admin/", wam_admin_site.urls), + path("accounts/login/", LoginView.as_view(template_name="login.html")), + path( + "access_denied/", + TemplateView.as_view(template_name="access_denied.html"), + name="access_denied", + ), + path("feedback_thanks/", FeedbackSuccessful.as_view(), name="feedback_thanks"), + path("feedback_error//", FeedbackError.as_view(), name="feedback_error"), ] try: - urlpatterns.append(re_path(r'^markdownx/', include('markdownx.urls'))) + urlpatterns.append(re_path(r"^markdownx/", include("markdownx.urls"))) except ImportError: pass for app_name in WAM_APPS: app_url = path( - '{}/'.format(app_name), - include(app_name + '.urls', namespace=app_name) + "{}/".format(app_name), include(app_name + ".urls", namespace=app_name) ) urlpatterns.append(app_url) # error handlers (work in non-debug mode only) -handler404 = 'wam.views.handler404' -handler500 = 'wam.views.handler500' +handler404 = "wam.views.handler404" +handler500 = "wam.views.handler500" diff --git a/wam/views.py b/wam/views.py index a06c31c..dca60c2 100644 --- a/wam/views.py +++ b/wam/views.py @@ -11,19 +11,19 @@ class ContactView(TemplateView): - template_name = 'contact.html' + template_name = "contact.html" class PrivacyView(TemplateView): - template_name = 'privacy_statement.html' + template_name = "privacy_statement.html" class ImpressumView(TemplateView): - template_name = 'impressum.html' + template_name = "impressum.html" class IndexView(TemplateView): - template_name = 'index.html' + template_name = "index.html" def get_context_data(self): context = super(IndexView, self).get_context_data() @@ -32,39 +32,35 @@ def get_context_data(self): for app_info in self.get_app_infos(app): app_infos[app_info.category].append(app_info) app_infos.default_factory = None - context['app_infos'] = app_infos + context["app_infos"] = app_infos return context @staticmethod def get_app_infos(app_name): # First, try to get app infos from app_settings.app_infos() function: try: - app_settings = importlib.import_module(f'{app_name}.app_settings') + app_settings = importlib.import_module(f"{app_name}.app_settings") except ImportError: pass else: - if hasattr(app_settings, 'app_infos'): + if hasattr(app_settings, "app_infos"): return app_settings.app_infos() # Second, try to read app.cfg: - app_config = ConfigObj(os.path.join(BASE_DIR, app_name, 'app.cfg')) + app_config = ConfigObj(os.path.join(BASE_DIR, app_name, "app.cfg")) if len(app_config) > 0: return [ AppInfo( - category=AppCategory(app_config['category']), - name=app_config['name'], - url=f'{app_name}:index', - closed=app_config.get('closed', False), - icon=app_config['icon'] + category=AppCategory(app_config["category"]), + name=app_config["name"], + url=f"{app_name}:index", + closed=app_config.get("closed", False), + icon=app_config["icon"], ) ] # Third, return generic app info: return [ - AppInfo( - category=AppCategory.App, - name=app_name, - url=f'{app_name}:index' - ) + AppInfo(category=AppCategory.App, name=app_name, url=f"{app_name}:index") ] def get(self, request, *args, **kwargs): @@ -72,17 +68,19 @@ def get(self, request, *args, **kwargs): return self.render_to_response(context) -def handler404(request, exception, template_name='error.html'): # pylint: disable=unused-argument +def handler404( + request, exception, template_name="error.html" +): # pylint: disable=unused-argument """A custom 404 page""" - context = {'err_text': 'Die Seite wurde leider nicht gefunden'} + context = {"err_text": "Die Seite wurde leider nicht gefunden"} response = render_to_response(template_name, context=context) response.status_code = 404 return response -def handler500(request, template_name='error.html'): # pylint: disable=unused-argument +def handler500(request, template_name="error.html"): # pylint: disable=unused-argument """A custom 500 page""" - context = {'err_text': 'Es ist ein Server-Fehler aufgetreten'} + context = {"err_text": "Es ist ein Server-Fehler aufgetreten"} response = render_to_response(template_name, context=context) response.status_code = 500 return response From 9cf0796496ae2cc52128b421e8af9ac8ee780a78 Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Fri, 13 Dec 2019 13:34:14 +0100 Subject: [PATCH 07/14] Removed ionicon builder --- static/ionicons-2.0.1/builder/build_data.json | 2940 ----------------- .../builder/cheatsheet/icon-row.html | 38 - .../builder/cheatsheet/template.html | 156 - static/ionicons-2.0.1/builder/generate.py | 319 -- static/ionicons-2.0.1/builder/manifest.json | 2940 ----------------- .../builder/scripts/eotlitetool.py | 510 --- .../builder/scripts/generate_font.py | 190 -- .../ionicons-2.0.1/builder/scripts/sfnt2woff | Bin 71204 -> 0 bytes 8 files changed, 7093 deletions(-) delete mode 100644 static/ionicons-2.0.1/builder/build_data.json delete mode 100644 static/ionicons-2.0.1/builder/cheatsheet/icon-row.html delete mode 100644 static/ionicons-2.0.1/builder/cheatsheet/template.html delete mode 100644 static/ionicons-2.0.1/builder/generate.py delete mode 100644 static/ionicons-2.0.1/builder/manifest.json delete mode 100644 static/ionicons-2.0.1/builder/scripts/eotlitetool.py delete mode 100755 static/ionicons-2.0.1/builder/scripts/generate_font.py delete mode 100755 static/ionicons-2.0.1/builder/scripts/sfnt2woff diff --git a/static/ionicons-2.0.1/builder/build_data.json b/static/ionicons-2.0.1/builder/build_data.json deleted file mode 100644 index e7eecca..0000000 --- a/static/ionicons-2.0.1/builder/build_data.json +++ /dev/null @@ -1,2940 +0,0 @@ -{ - "build_hash": "c9df150ee06f9db1642a5350c56829ae", - "prefix": "ion-", - "version": "2.0.0", - "name": "Ionicons", - "icons": [ - { - "code": "0xf101", - "name": "alert" - }, - { - "code": "0xf100", - "name": "alert-circled" - }, - { - "code": "0xf2c7", - "name": "android-add" - }, - { - "code": "0xf359", - "name": "android-add-circle" - }, - { - "code": "0xf35a", - "name": "android-alarm-clock" - }, - { - "code": "0xf35b", - "name": "android-alert" - }, - { - "code": "0xf35c", - "name": "android-apps" - }, - { - "code": "0xf2c9", - "name": "android-archive" - }, - { - "code": "0xf2ca", - "name": "android-arrow-back" - }, - { - "code": "0xf35d", - "name": "android-arrow-down" - }, - { - "code": "0xf35f", - "name": "android-arrow-dropdown" - }, - { - "code": "0xf35e", - "name": "android-arrow-dropdown-circle" - }, - { - "code": "0xf361", - "name": "android-arrow-dropleft" - }, - { - "code": "0xf360", - "name": "android-arrow-dropleft-circle" - }, - { - "code": "0xf363", - "name": "android-arrow-dropright" - }, - { - "code": "0xf362", - "name": "android-arrow-dropright-circle" - }, - { - "code": "0xf365", - "name": "android-arrow-dropup" - }, - { - "code": "0xf364", - "name": "android-arrow-dropup-circle" - }, - { - "code": "0xf30f", - "name": "android-arrow-forward" - }, - { - "code": "0xf366", - "name": "android-arrow-up" - }, - { - "code": "0xf367", - "name": "android-attach" - }, - { - "code": "0xf368", - "name": "android-bar" - }, - { - "code": "0xf369", - "name": "android-bicycle" - }, - { - "code": "0xf36a", - "name": "android-boat" - }, - { - "code": "0xf36b", - "name": "android-bookmark" - }, - { - "code": "0xf36c", - "name": "android-bulb" - }, - { - "code": "0xf36d", - "name": "android-bus" - }, - { - "code": "0xf2d1", - "name": "android-calendar" - }, - { - "code": "0xf2d2", - "name": "android-call" - }, - { - "code": "0xf2d3", - "name": "android-camera" - }, - { - "code": "0xf36e", - "name": "android-cancel" - }, - { - "code": "0xf36f", - "name": "android-car" - }, - { - "code": "0xf370", - "name": "android-cart" - }, - { - "code": "0xf2d4", - "name": "android-chat" - }, - { - "code": "0xf374", - "name": "android-checkbox" - }, - { - "code": "0xf371", - "name": "android-checkbox-blank" - }, - { - "code": "0xf373", - "name": "android-checkbox-outline" - }, - { - "code": "0xf372", - "name": "android-checkbox-outline-blank" - }, - { - "code": "0xf375", - "name": "android-checkmark-circle" - }, - { - "code": "0xf376", - "name": "android-clipboard" - }, - { - "code": "0xf2d7", - "name": "android-close" - }, - { - "code": "0xf37a", - "name": "android-cloud" - }, - { - "code": "0xf377", - "name": "android-cloud-circle" - }, - { - "code": "0xf378", - "name": "android-cloud-done" - }, - { - "code": "0xf379", - "name": "android-cloud-outline" - }, - { - "code": "0xf37b", - "name": "android-color-palette" - }, - { - "code": "0xf37c", - "name": "android-compass" - }, - { - "code": "0xf2d8", - "name": "android-contact" - }, - { - "code": "0xf2d9", - "name": "android-contacts" - }, - { - "code": "0xf37d", - "name": "android-contract" - }, - { - "code": "0xf37e", - "name": "android-create" - }, - { - "code": "0xf37f", - "name": "android-delete" - }, - { - "code": "0xf380", - "name": "android-desktop" - }, - { - "code": "0xf381", - "name": "android-document" - }, - { - "code": "0xf383", - "name": "android-done" - }, - { - "code": "0xf382", - "name": "android-done-all" - }, - { - "code": "0xf2dd", - "name": "android-download" - }, - { - "code": "0xf384", - "name": "android-drafts" - }, - { - "code": "0xf385", - "name": "android-exit" - }, - { - "code": "0xf386", - "name": "android-expand" - }, - { - "code": "0xf388", - "name": "android-favorite" - }, - { - "code": "0xf387", - "name": "android-favorite-outline" - }, - { - "code": "0xf389", - "name": "android-film" - }, - { - "code": "0xf2e0", - "name": "android-folder" - }, - { - "code": "0xf38a", - "name": "android-folder-open" - }, - { - "code": "0xf38b", - "name": "android-funnel" - }, - { - "code": "0xf38c", - "name": "android-globe" - }, - { - "code": "0xf2e3", - "name": "android-hand" - }, - { - "code": "0xf38d", - "name": "android-hangout" - }, - { - "code": "0xf38e", - "name": "android-happy" - }, - { - "code": "0xf38f", - "name": "android-home" - }, - { - "code": "0xf2e4", - "name": "android-image" - }, - { - "code": "0xf390", - "name": "android-laptop" - }, - { - "code": "0xf391", - "name": "android-list" - }, - { - "code": "0xf2e9", - "name": "android-locate" - }, - { - "code": "0xf392", - "name": "android-lock" - }, - { - "code": "0xf2eb", - "name": "android-mail" - }, - { - "code": "0xf393", - "name": "android-map" - }, - { - "code": "0xf394", - "name": "android-menu" - }, - { - "code": "0xf2ec", - "name": "android-microphone" - }, - { - "code": "0xf395", - "name": "android-microphone-off" - }, - { - "code": "0xf396", - "name": "android-more-horizontal" - }, - { - "code": "0xf397", - "name": "android-more-vertical" - }, - { - "code": "0xf398", - "name": "android-navigate" - }, - { - "code": "0xf39b", - "name": "android-notifications" - }, - { - "code": "0xf399", - "name": "android-notifications-none" - }, - { - "code": "0xf39a", - "name": "android-notifications-off" - }, - { - "code": "0xf39c", - "name": "android-open" - }, - { - "code": "0xf39d", - "name": "android-options" - }, - { - "code": "0xf39e", - "name": "android-people" - }, - { - "code": "0xf3a0", - "name": "android-person" - }, - { - "code": "0xf39f", - "name": "android-person-add" - }, - { - "code": "0xf3a1", - "name": "android-phone-landscape" - }, - { - "code": "0xf3a2", - "name": "android-phone-portrait" - }, - { - "code": "0xf3a3", - "name": "android-pin" - }, - { - "code": "0xf3a4", - "name": "android-plane" - }, - { - "code": "0xf2f0", - "name": "android-playstore" - }, - { - "code": "0xf3a5", - "name": "android-print" - }, - { - "code": "0xf3a6", - "name": "android-radio-button-off" - }, - { - "code": "0xf3a7", - "name": "android-radio-button-on" - }, - { - "code": "0xf3a8", - "name": "android-refresh" - }, - { - "code": "0xf2f4", - "name": "android-remove" - }, - { - "code": "0xf3a9", - "name": "android-remove-circle" - }, - { - "code": "0xf3aa", - "name": "android-restaurant" - }, - { - "code": "0xf3ab", - "name": "android-sad" - }, - { - "code": "0xf2f5", - "name": "android-search" - }, - { - "code": "0xf2f6", - "name": "android-send" - }, - { - "code": "0xf2f7", - "name": "android-settings" - }, - { - "code": "0xf2f8", - "name": "android-share" - }, - { - "code": "0xf3ac", - "name": "android-share-alt" - }, - { - "code": "0xf2fc", - "name": "android-star" - }, - { - "code": "0xf3ad", - "name": "android-star-half" - }, - { - "code": "0xf3ae", - "name": "android-star-outline" - }, - { - "code": "0xf2fd", - "name": "android-stopwatch" - }, - { - "code": "0xf3af", - "name": "android-subway" - }, - { - "code": "0xf3b0", - "name": "android-sunny" - }, - { - "code": "0xf3b1", - "name": "android-sync" - }, - { - "code": "0xf3b2", - "name": "android-textsms" - }, - { - "code": "0xf3b3", - "name": "android-time" - }, - { - "code": "0xf3b4", - "name": "android-train" - }, - { - "code": "0xf3b5", - "name": "android-unlock" - }, - { - "code": "0xf3b6", - "name": "android-upload" - }, - { - "code": "0xf3b7", - "name": "android-volume-down" - }, - { - "code": "0xf3b8", - "name": "android-volume-mute" - }, - { - "code": "0xf3b9", - "name": "android-volume-off" - }, - { - "code": "0xf3ba", - "name": "android-volume-up" - }, - { - "code": "0xf3bb", - "name": "android-walk" - }, - { - "code": "0xf3bc", - "name": "android-warning" - }, - { - "code": "0xf3bd", - "name": "android-watch" - }, - { - "code": "0xf305", - "name": "android-wifi" - }, - { - "code": "0xf313", - "name": "aperture" - }, - { - "code": "0xf102", - "name": "archive" - }, - { - "code": "0xf103", - "name": "arrow-down-a" - }, - { - "code": "0xf104", - "name": "arrow-down-b" - }, - { - "code": "0xf105", - "name": "arrow-down-c" - }, - { - "code": "0xf25e", - "name": "arrow-expand" - }, - { - "code": "0xf25f", - "name": "arrow-graph-down-left" - }, - { - "code": "0xf260", - "name": "arrow-graph-down-right" - }, - { - "code": "0xf261", - "name": "arrow-graph-up-left" - }, - { - "code": "0xf262", - "name": "arrow-graph-up-right" - }, - { - "code": "0xf106", - "name": "arrow-left-a" - }, - { - "code": "0xf107", - "name": "arrow-left-b" - }, - { - "code": "0xf108", - "name": "arrow-left-c" - }, - { - "code": "0xf263", - "name": "arrow-move" - }, - { - "code": "0xf264", - "name": "arrow-resize" - }, - { - "code": "0xf265", - "name": "arrow-return-left" - }, - { - "code": "0xf266", - "name": "arrow-return-right" - }, - { - "code": "0xf109", - "name": "arrow-right-a" - }, - { - "code": "0xf10a", - "name": "arrow-right-b" - }, - { - "code": "0xf10b", - "name": "arrow-right-c" - }, - { - "code": "0xf267", - "name": "arrow-shrink" - }, - { - "code": "0xf268", - "name": "arrow-swap" - }, - { - "code": "0xf10c", - "name": "arrow-up-a" - }, - { - "code": "0xf10d", - "name": "arrow-up-b" - }, - { - "code": "0xf10e", - "name": "arrow-up-c" - }, - { - "code": "0xf314", - "name": "asterisk" - }, - { - "code": "0xf10f", - "name": "at" - }, - { - "code": "0xf3bf", - "name": "backspace" - }, - { - "code": "0xf3be", - "name": "backspace-outline" - }, - { - "code": "0xf110", - "name": "bag" - }, - { - "code": "0xf111", - "name": "battery-charging" - }, - { - "code": "0xf112", - "name": "battery-empty" - }, - { - "code": "0xf113", - "name": "battery-full" - }, - { - "code": "0xf114", - "name": "battery-half" - }, - { - "code": "0xf115", - "name": "battery-low" - }, - { - "code": "0xf269", - "name": "beaker" - }, - { - "code": "0xf26a", - "name": "beer" - }, - { - "code": "0xf116", - "name": "bluetooth" - }, - { - "code": "0xf315", - "name": "bonfire" - }, - { - "code": "0xf26b", - "name": "bookmark" - }, - { - "code": "0xf3c0", - "name": "bowtie" - }, - { - "code": "0xf26c", - "name": "briefcase" - }, - { - "code": "0xf2be", - "name": "bug" - }, - { - "code": "0xf26d", - "name": "calculator" - }, - { - "code": "0xf117", - "name": "calendar" - }, - { - "code": "0xf118", - "name": "camera" - }, - { - "code": "0xf119", - "name": "card" - }, - { - "code": "0xf316", - "name": "cash" - }, - { - "code": "0xf11b", - "name": "chatbox" - }, - { - "code": "0xf11a", - "name": "chatbox-working" - }, - { - "code": "0xf11c", - "name": "chatboxes" - }, - { - "code": "0xf11e", - "name": "chatbubble" - }, - { - "code": "0xf11d", - "name": "chatbubble-working" - }, - { - "code": "0xf11f", - "name": "chatbubbles" - }, - { - "code": "0xf122", - "name": "checkmark" - }, - { - "code": "0xf120", - "name": "checkmark-circled" - }, - { - "code": "0xf121", - "name": "checkmark-round" - }, - { - "code": "0xf123", - "name": "chevron-down" - }, - { - "code": "0xf124", - "name": "chevron-left" - }, - { - "code": "0xf125", - "name": "chevron-right" - }, - { - "code": "0xf126", - "name": "chevron-up" - }, - { - "code": "0xf127", - "name": "clipboard" - }, - { - "code": "0xf26e", - "name": "clock" - }, - { - "code": "0xf12a", - "name": "close" - }, - { - "code": "0xf128", - "name": "close-circled" - }, - { - "code": "0xf129", - "name": "close-round" - }, - { - "code": "0xf317", - "name": "closed-captioning" - }, - { - "code": "0xf12b", - "name": "cloud" - }, - { - "code": "0xf271", - "name": "code" - }, - { - "code": "0xf26f", - "name": "code-download" - }, - { - "code": "0xf270", - "name": "code-working" - }, - { - "code": "0xf272", - "name": "coffee" - }, - { - "code": "0xf273", - "name": "compass" - }, - { - "code": "0xf12c", - "name": "compose" - }, - { - "code": "0xf274", - "name": "connection-bars" - }, - { - "code": "0xf275", - "name": "contrast" - }, - { - "code": "0xf3c1", - "name": "crop" - }, - { - "code": "0xf318", - "name": "cube" - }, - { - "code": "0xf12d", - "name": "disc" - }, - { - "code": "0xf12f", - "name": "document" - }, - { - "code": "0xf12e", - "name": "document-text" - }, - { - "code": "0xf130", - "name": "drag" - }, - { - "code": "0xf276", - "name": "earth" - }, - { - "code": "0xf3c2", - "name": "easel" - }, - { - "code": "0xf2bf", - "name": "edit" - }, - { - "code": "0xf277", - "name": "egg" - }, - { - "code": "0xf131", - "name": "eject" - }, - { - "code": "0xf132", - "name": "email" - }, - { - "code": "0xf3c3", - "name": "email-unread" - }, - { - "code": "0xf3c5", - "name": "erlenmeyer-flask" - }, - { - "code": "0xf3c4", - "name": "erlenmeyer-flask-bubbles" - }, - { - "code": "0xf133", - "name": "eye" - }, - { - "code": "0xf306", - "name": "eye-disabled" - }, - { - "code": "0xf278", - "name": "female" - }, - { - "code": "0xf134", - "name": "filing" - }, - { - "code": "0xf135", - "name": "film-marker" - }, - { - "code": "0xf319", - "name": "fireball" - }, - { - "code": "0xf279", - "name": "flag" - }, - { - "code": "0xf31a", - "name": "flame" - }, - { - "code": "0xf137", - "name": "flash" - }, - { - "code": "0xf136", - "name": "flash-off" - }, - { - "code": "0xf139", - "name": "folder" - }, - { - "code": "0xf27a", - "name": "fork" - }, - { - "code": "0xf2c0", - "name": "fork-repo" - }, - { - "code": "0xf13a", - "name": "forward" - }, - { - "code": "0xf31b", - "name": "funnel" - }, - { - "code": "0xf13d", - "name": "gear-a" - }, - { - "code": "0xf13e", - "name": "gear-b" - }, - { - "code": "0xf13f", - "name": "grid" - }, - { - "code": "0xf27b", - "name": "hammer" - }, - { - "code": "0xf31c", - "name": "happy" - }, - { - "code": "0xf3c6", - "name": "happy-outline" - }, - { - "code": "0xf140", - "name": "headphone" - }, - { - "code": "0xf141", - "name": "heart" - }, - { - "code": "0xf31d", - "name": "heart-broken" - }, - { - "code": "0xf143", - "name": "help" - }, - { - "code": "0xf27c", - "name": "help-buoy" - }, - { - "code": "0xf142", - "name": "help-circled" - }, - { - "code": "0xf144", - "name": "home" - }, - { - "code": "0xf27d", - "name": "icecream" - }, - { - "code": "0xf147", - "name": "image" - }, - { - "code": "0xf148", - "name": "images" - }, - { - "code": "0xf14a", - "name": "information" - }, - { - "code": "0xf149", - "name": "information-circled" - }, - { - "code": "0xf14b", - "name": "ionic" - }, - { - "code": "0xf3c8", - "name": "ios-alarm" - }, - { - "code": "0xf3c7", - "name": "ios-alarm-outline" - }, - { - "code": "0xf3ca", - "name": "ios-albums" - }, - { - "code": "0xf3c9", - "name": "ios-albums-outline" - }, - { - "code": "0xf3cc", - "name": "ios-americanfootball" - }, - { - "code": "0xf3cb", - "name": "ios-americanfootball-outline" - }, - { - "code": "0xf3ce", - "name": "ios-analytics" - }, - { - "code": "0xf3cd", - "name": "ios-analytics-outline" - }, - { - "code": "0xf3cf", - "name": "ios-arrow-back" - }, - { - "code": "0xf3d0", - "name": "ios-arrow-down" - }, - { - "code": "0xf3d1", - "name": "ios-arrow-forward" - }, - { - "code": "0xf3d2", - "name": "ios-arrow-left" - }, - { - "code": "0xf3d3", - "name": "ios-arrow-right" - }, - { - "code": "0xf3d4", - "name": "ios-arrow-thin-down" - }, - { - "code": "0xf3d5", - "name": "ios-arrow-thin-left" - }, - { - "code": "0xf3d6", - "name": "ios-arrow-thin-right" - }, - { - "code": "0xf3d7", - "name": "ios-arrow-thin-up" - }, - { - "code": "0xf3d8", - "name": "ios-arrow-up" - }, - { - "code": "0xf3da", - "name": "ios-at" - }, - { - "code": "0xf3d9", - "name": "ios-at-outline" - }, - { - "code": "0xf3dc", - "name": "ios-barcode" - }, - { - "code": "0xf3db", - "name": "ios-barcode-outline" - }, - { - "code": "0xf3de", - "name": "ios-baseball" - }, - { - "code": "0xf3dd", - "name": "ios-baseball-outline" - }, - { - "code": "0xf3e0", - "name": "ios-basketball" - }, - { - "code": "0xf3df", - "name": "ios-basketball-outline" - }, - { - "code": "0xf3e2", - "name": "ios-bell" - }, - { - "code": "0xf3e1", - "name": "ios-bell-outline" - }, - { - "code": "0xf3e4", - "name": "ios-body" - }, - { - "code": "0xf3e3", - "name": "ios-body-outline" - }, - { - "code": "0xf3e6", - "name": "ios-bolt" - }, - { - "code": "0xf3e5", - "name": "ios-bolt-outline" - }, - { - "code": "0xf3e8", - "name": "ios-book" - }, - { - "code": "0xf3e7", - "name": "ios-book-outline" - }, - { - "code": "0xf3ea", - "name": "ios-bookmarks" - }, - { - "code": "0xf3e9", - "name": "ios-bookmarks-outline" - }, - { - "code": "0xf3ec", - "name": "ios-box" - }, - { - "code": "0xf3eb", - "name": "ios-box-outline" - }, - { - "code": "0xf3ee", - "name": "ios-briefcase" - }, - { - "code": "0xf3ed", - "name": "ios-briefcase-outline" - }, - { - "code": "0xf3f0", - "name": "ios-browsers" - }, - { - "code": "0xf3ef", - "name": "ios-browsers-outline" - }, - { - "code": "0xf3f2", - "name": "ios-calculator" - }, - { - "code": "0xf3f1", - "name": "ios-calculator-outline" - }, - { - "code": "0xf3f4", - "name": "ios-calendar" - }, - { - "code": "0xf3f3", - "name": "ios-calendar-outline" - }, - { - "code": "0xf3f6", - "name": "ios-camera" - }, - { - "code": "0xf3f5", - "name": "ios-camera-outline" - }, - { - "code": "0xf3f8", - "name": "ios-cart" - }, - { - "code": "0xf3f7", - "name": "ios-cart-outline" - }, - { - "code": "0xf3fa", - "name": "ios-chatboxes" - }, - { - "code": "0xf3f9", - "name": "ios-chatboxes-outline" - }, - { - "code": "0xf3fc", - "name": "ios-chatbubble" - }, - { - "code": "0xf3fb", - "name": "ios-chatbubble-outline" - }, - { - "code": "0xf3ff", - "name": "ios-checkmark" - }, - { - "code": "0xf3fd", - "name": "ios-checkmark-empty" - }, - { - "code": "0xf3fe", - "name": "ios-checkmark-outline" - }, - { - "code": "0xf400", - "name": "ios-circle-filled" - }, - { - "code": "0xf401", - "name": "ios-circle-outline" - }, - { - "code": "0xf403", - "name": "ios-clock" - }, - { - "code": "0xf402", - "name": "ios-clock-outline" - }, - { - "code": "0xf406", - "name": "ios-close" - }, - { - "code": "0xf404", - "name": "ios-close-empty" - }, - { - "code": "0xf405", - "name": "ios-close-outline" - }, - { - "code": "0xf40c", - "name": "ios-cloud" - }, - { - "code": "0xf408", - "name": "ios-cloud-download" - }, - { - "code": "0xf407", - "name": "ios-cloud-download-outline" - }, - { - "code": "0xf409", - "name": "ios-cloud-outline" - }, - { - "code": "0xf40b", - "name": "ios-cloud-upload" - }, - { - "code": "0xf40a", - "name": "ios-cloud-upload-outline" - }, - { - "code": "0xf410", - "name": "ios-cloudy" - }, - { - "code": "0xf40e", - "name": "ios-cloudy-night" - }, - { - "code": "0xf40d", - "name": "ios-cloudy-night-outline" - }, - { - "code": "0xf40f", - "name": "ios-cloudy-outline" - }, - { - "code": "0xf412", - "name": "ios-cog" - }, - { - "code": "0xf411", - "name": "ios-cog-outline" - }, - { - "code": "0xf414", - "name": "ios-color-filter" - }, - { - "code": "0xf413", - "name": "ios-color-filter-outline" - }, - { - "code": "0xf416", - "name": "ios-color-wand" - }, - { - "code": "0xf415", - "name": "ios-color-wand-outline" - }, - { - "code": "0xf418", - "name": "ios-compose" - }, - { - "code": "0xf417", - "name": "ios-compose-outline" - }, - { - "code": "0xf41a", - "name": "ios-contact" - }, - { - "code": "0xf419", - "name": "ios-contact-outline" - }, - { - "code": "0xf41c", - "name": "ios-copy" - }, - { - "code": "0xf41b", - "name": "ios-copy-outline" - }, - { - "code": "0xf41e", - "name": "ios-crop" - }, - { - "code": "0xf41d", - "name": "ios-crop-strong" - }, - { - "code": "0xf420", - "name": "ios-download" - }, - { - "code": "0xf41f", - "name": "ios-download-outline" - }, - { - "code": "0xf421", - "name": "ios-drag" - }, - { - "code": "0xf423", - "name": "ios-email" - }, - { - "code": "0xf422", - "name": "ios-email-outline" - }, - { - "code": "0xf425", - "name": "ios-eye" - }, - { - "code": "0xf424", - "name": "ios-eye-outline" - }, - { - "code": "0xf427", - "name": "ios-fastforward" - }, - { - "code": "0xf426", - "name": "ios-fastforward-outline" - }, - { - "code": "0xf429", - "name": "ios-filing" - }, - { - "code": "0xf428", - "name": "ios-filing-outline" - }, - { - "code": "0xf42b", - "name": "ios-film" - }, - { - "code": "0xf42a", - "name": "ios-film-outline" - }, - { - "code": "0xf42d", - "name": "ios-flag" - }, - { - "code": "0xf42c", - "name": "ios-flag-outline" - }, - { - "code": "0xf42f", - "name": "ios-flame" - }, - { - "code": "0xf42e", - "name": "ios-flame-outline" - }, - { - "code": "0xf431", - "name": "ios-flask" - }, - { - "code": "0xf430", - "name": "ios-flask-outline" - }, - { - "code": "0xf433", - "name": "ios-flower" - }, - { - "code": "0xf432", - "name": "ios-flower-outline" - }, - { - "code": "0xf435", - "name": "ios-folder" - }, - { - "code": "0xf434", - "name": "ios-folder-outline" - }, - { - "code": "0xf437", - "name": "ios-football" - }, - { - "code": "0xf436", - "name": "ios-football-outline" - }, - { - "code": "0xf439", - "name": "ios-game-controller-a" - }, - { - "code": "0xf438", - "name": "ios-game-controller-a-outline" - }, - { - "code": "0xf43b", - "name": "ios-game-controller-b" - }, - { - "code": "0xf43a", - "name": "ios-game-controller-b-outline" - }, - { - "code": "0xf43d", - "name": "ios-gear" - }, - { - "code": "0xf43c", - "name": "ios-gear-outline" - }, - { - "code": "0xf43f", - "name": "ios-glasses" - }, - { - "code": "0xf43e", - "name": "ios-glasses-outline" - }, - { - "code": "0xf441", - "name": "ios-grid-view" - }, - { - "code": "0xf440", - "name": "ios-grid-view-outline" - }, - { - "code": "0xf443", - "name": "ios-heart" - }, - { - "code": "0xf442", - "name": "ios-heart-outline" - }, - { - "code": "0xf446", - "name": "ios-help" - }, - { - "code": "0xf444", - "name": "ios-help-empty" - }, - { - "code": "0xf445", - "name": "ios-help-outline" - }, - { - "code": "0xf448", - "name": "ios-home" - }, - { - "code": "0xf447", - "name": "ios-home-outline" - }, - { - "code": "0xf44a", - "name": "ios-infinite" - }, - { - "code": "0xf449", - "name": "ios-infinite-outline" - }, - { - "code": "0xf44d", - "name": "ios-information" - }, - { - "code": "0xf44b", - "name": "ios-information-empty" - }, - { - "code": "0xf44c", - "name": "ios-information-outline" - }, - { - "code": "0xf44e", - "name": "ios-ionic-outline" - }, - { - "code": "0xf450", - "name": "ios-keypad" - }, - { - "code": "0xf44f", - "name": "ios-keypad-outline" - }, - { - "code": "0xf452", - "name": "ios-lightbulb" - }, - { - "code": "0xf451", - "name": "ios-lightbulb-outline" - }, - { - "code": "0xf454", - "name": "ios-list" - }, - { - "code": "0xf453", - "name": "ios-list-outline" - }, - { - "code": "0xf456", - "name": "ios-location" - }, - { - "code": "0xf455", - "name": "ios-location-outline" - }, - { - "code": "0xf458", - "name": "ios-locked" - }, - { - "code": "0xf457", - "name": "ios-locked-outline" - }, - { - "code": "0xf45a", - "name": "ios-loop" - }, - { - "code": "0xf459", - "name": "ios-loop-strong" - }, - { - "code": "0xf45c", - "name": "ios-medical" - }, - { - "code": "0xf45b", - "name": "ios-medical-outline" - }, - { - "code": "0xf45e", - "name": "ios-medkit" - }, - { - "code": "0xf45d", - "name": "ios-medkit-outline" - }, - { - "code": "0xf461", - "name": "ios-mic" - }, - { - "code": "0xf45f", - "name": "ios-mic-off" - }, - { - "code": "0xf460", - "name": "ios-mic-outline" - }, - { - "code": "0xf464", - "name": "ios-minus" - }, - { - "code": "0xf462", - "name": "ios-minus-empty" - }, - { - "code": "0xf463", - "name": "ios-minus-outline" - }, - { - "code": "0xf466", - "name": "ios-monitor" - }, - { - "code": "0xf465", - "name": "ios-monitor-outline" - }, - { - "code": "0xf468", - "name": "ios-moon" - }, - { - "code": "0xf467", - "name": "ios-moon-outline" - }, - { - "code": "0xf46a", - "name": "ios-more" - }, - { - "code": "0xf469", - "name": "ios-more-outline" - }, - { - "code": "0xf46b", - "name": "ios-musical-note" - }, - { - "code": "0xf46c", - "name": "ios-musical-notes" - }, - { - "code": "0xf46e", - "name": "ios-navigate" - }, - { - "code": "0xf46d", - "name": "ios-navigate-outline" - }, - { - "code": "0xf470", - "name": "ios-nutrition" - }, - { - "code": "0xf46f", - "name": "ios-nutrition-outline" - }, - { - "code": "0xf472", - "name": "ios-paper" - }, - { - "code": "0xf471", - "name": "ios-paper-outline" - }, - { - "code": "0xf474", - "name": "ios-paperplane" - }, - { - "code": "0xf473", - "name": "ios-paperplane-outline" - }, - { - "code": "0xf476", - "name": "ios-partlysunny" - }, - { - "code": "0xf475", - "name": "ios-partlysunny-outline" - }, - { - "code": "0xf478", - "name": "ios-pause" - }, - { - "code": "0xf477", - "name": "ios-pause-outline" - }, - { - "code": "0xf47a", - "name": "ios-paw" - }, - { - "code": "0xf479", - "name": "ios-paw-outline" - }, - { - "code": "0xf47c", - "name": "ios-people" - }, - { - "code": "0xf47b", - "name": "ios-people-outline" - }, - { - "code": "0xf47e", - "name": "ios-person" - }, - { - "code": "0xf47d", - "name": "ios-person-outline" - }, - { - "code": "0xf480", - "name": "ios-personadd" - }, - { - "code": "0xf47f", - "name": "ios-personadd-outline" - }, - { - "code": "0xf482", - "name": "ios-photos" - }, - { - "code": "0xf481", - "name": "ios-photos-outline" - }, - { - "code": "0xf484", - "name": "ios-pie" - }, - { - "code": "0xf483", - "name": "ios-pie-outline" - }, - { - "code": "0xf486", - "name": "ios-pint" - }, - { - "code": "0xf485", - "name": "ios-pint-outline" - }, - { - "code": "0xf488", - "name": "ios-play" - }, - { - "code": "0xf487", - "name": "ios-play-outline" - }, - { - "code": "0xf48b", - "name": "ios-plus" - }, - { - "code": "0xf489", - "name": "ios-plus-empty" - }, - { - "code": "0xf48a", - "name": "ios-plus-outline" - }, - { - "code": "0xf48d", - "name": "ios-pricetag" - }, - { - "code": "0xf48c", - "name": "ios-pricetag-outline" - }, - { - "code": "0xf48f", - "name": "ios-pricetags" - }, - { - "code": "0xf48e", - "name": "ios-pricetags-outline" - }, - { - "code": "0xf491", - "name": "ios-printer" - }, - { - "code": "0xf490", - "name": "ios-printer-outline" - }, - { - "code": "0xf493", - "name": "ios-pulse" - }, - { - "code": "0xf492", - "name": "ios-pulse-strong" - }, - { - "code": "0xf495", - "name": "ios-rainy" - }, - { - "code": "0xf494", - "name": "ios-rainy-outline" - }, - { - "code": "0xf497", - "name": "ios-recording" - }, - { - "code": "0xf496", - "name": "ios-recording-outline" - }, - { - "code": "0xf499", - "name": "ios-redo" - }, - { - "code": "0xf498", - "name": "ios-redo-outline" - }, - { - "code": "0xf49c", - "name": "ios-refresh" - }, - { - "code": "0xf49a", - "name": "ios-refresh-empty" - }, - { - "code": "0xf49b", - "name": "ios-refresh-outline" - }, - { - "code": "0xf49d", - "name": "ios-reload" - }, - { - "code": "0xf49f", - "name": "ios-reverse-camera" - }, - { - "code": "0xf49e", - "name": "ios-reverse-camera-outline" - }, - { - "code": "0xf4a1", - "name": "ios-rewind" - }, - { - "code": "0xf4a0", - "name": "ios-rewind-outline" - }, - { - "code": "0xf4a3", - "name": "ios-rose" - }, - { - "code": "0xf4a2", - "name": "ios-rose-outline" - }, - { - "code": "0xf4a5", - "name": "ios-search" - }, - { - "code": "0xf4a4", - "name": "ios-search-strong" - }, - { - "code": "0xf4a7", - "name": "ios-settings" - }, - { - "code": "0xf4a6", - "name": "ios-settings-strong" - }, - { - "code": "0xf4a9", - "name": "ios-shuffle" - }, - { - "code": "0xf4a8", - "name": "ios-shuffle-strong" - }, - { - "code": "0xf4ab", - "name": "ios-skipbackward" - }, - { - "code": "0xf4aa", - "name": "ios-skipbackward-outline" - }, - { - "code": "0xf4ad", - "name": "ios-skipforward" - }, - { - "code": "0xf4ac", - "name": "ios-skipforward-outline" - }, - { - "code": "0xf4ae", - "name": "ios-snowy" - }, - { - "code": "0xf4b0", - "name": "ios-speedometer" - }, - { - "code": "0xf4af", - "name": "ios-speedometer-outline" - }, - { - "code": "0xf4b3", - "name": "ios-star" - }, - { - "code": "0xf4b1", - "name": "ios-star-half" - }, - { - "code": "0xf4b2", - "name": "ios-star-outline" - }, - { - "code": "0xf4b5", - "name": "ios-stopwatch" - }, - { - "code": "0xf4b4", - "name": "ios-stopwatch-outline" - }, - { - "code": "0xf4b7", - "name": "ios-sunny" - }, - { - "code": "0xf4b6", - "name": "ios-sunny-outline" - }, - { - "code": "0xf4b9", - "name": "ios-telephone" - }, - { - "code": "0xf4b8", - "name": "ios-telephone-outline" - }, - { - "code": "0xf4bb", - "name": "ios-tennisball" - }, - { - "code": "0xf4ba", - "name": "ios-tennisball-outline" - }, - { - "code": "0xf4bd", - "name": "ios-thunderstorm" - }, - { - "code": "0xf4bc", - "name": "ios-thunderstorm-outline" - }, - { - "code": "0xf4bf", - "name": "ios-time" - }, - { - "code": "0xf4be", - "name": "ios-time-outline" - }, - { - "code": "0xf4c1", - "name": "ios-timer" - }, - { - "code": "0xf4c0", - "name": "ios-timer-outline" - }, - { - "code": "0xf4c3", - "name": "ios-toggle" - }, - { - "code": "0xf4c2", - "name": "ios-toggle-outline" - }, - { - "code": "0xf4c5", - "name": "ios-trash" - }, - { - "code": "0xf4c4", - "name": "ios-trash-outline" - }, - { - "code": "0xf4c7", - "name": "ios-undo" - }, - { - "code": "0xf4c6", - "name": "ios-undo-outline" - }, - { - "code": "0xf4c9", - "name": "ios-unlocked" - }, - { - "code": "0xf4c8", - "name": "ios-unlocked-outline" - }, - { - "code": "0xf4cb", - "name": "ios-upload" - }, - { - "code": "0xf4ca", - "name": "ios-upload-outline" - }, - { - "code": "0xf4cd", - "name": "ios-videocam" - }, - { - "code": "0xf4cc", - "name": "ios-videocam-outline" - }, - { - "code": "0xf4ce", - "name": "ios-volume-high" - }, - { - "code": "0xf4cf", - "name": "ios-volume-low" - }, - { - "code": "0xf4d1", - "name": "ios-wineglass" - }, - { - "code": "0xf4d0", - "name": "ios-wineglass-outline" - }, - { - "code": "0xf4d3", - "name": "ios-world" - }, - { - "code": "0xf4d2", - "name": "ios-world-outline" - }, - { - "code": "0xf1f9", - "name": "ipad" - }, - { - "code": "0xf1fa", - "name": "iphone" - }, - { - "code": "0xf1fb", - "name": "ipod" - }, - { - "code": "0xf295", - "name": "jet" - }, - { - "code": "0xf296", - "name": "key" - }, - { - "code": "0xf297", - "name": "knife" - }, - { - "code": "0xf1fc", - "name": "laptop" - }, - { - "code": "0xf1fd", - "name": "leaf" - }, - { - "code": "0xf298", - "name": "levels" - }, - { - "code": "0xf299", - "name": "lightbulb" - }, - { - "code": "0xf1fe", - "name": "link" - }, - { - "code": "0xf29a", - "name": "load-a" - }, - { - "code": "0xf29b", - "name": "load-b" - }, - { - "code": "0xf29c", - "name": "load-c" - }, - { - "code": "0xf29d", - "name": "load-d" - }, - { - "code": "0xf1ff", - "name": "location" - }, - { - "code": "0xf4d4", - "name": "lock-combination" - }, - { - "code": "0xf200", - "name": "locked" - }, - { - "code": "0xf29e", - "name": "log-in" - }, - { - "code": "0xf29f", - "name": "log-out" - }, - { - "code": "0xf201", - "name": "loop" - }, - { - "code": "0xf2a0", - "name": "magnet" - }, - { - "code": "0xf2a1", - "name": "male" - }, - { - "code": "0xf202", - "name": "man" - }, - { - "code": "0xf203", - "name": "map" - }, - { - "code": "0xf2a2", - "name": "medkit" - }, - { - "code": "0xf33f", - "name": "merge" - }, - { - "code": "0xf204", - "name": "mic-a" - }, - { - "code": "0xf205", - "name": "mic-b" - }, - { - "code": "0xf206", - "name": "mic-c" - }, - { - "code": "0xf209", - "name": "minus" - }, - { - "code": "0xf207", - "name": "minus-circled" - }, - { - "code": "0xf208", - "name": "minus-round" - }, - { - "code": "0xf2c1", - "name": "model-s" - }, - { - "code": "0xf20a", - "name": "monitor" - }, - { - "code": "0xf20b", - "name": "more" - }, - { - "code": "0xf340", - "name": "mouse" - }, - { - "code": "0xf20c", - "name": "music-note" - }, - { - "code": "0xf20e", - "name": "navicon" - }, - { - "code": "0xf20d", - "name": "navicon-round" - }, - { - "code": "0xf2a3", - "name": "navigate" - }, - { - "code": "0xf341", - "name": "network" - }, - { - "code": "0xf2c2", - "name": "no-smoking" - }, - { - "code": "0xf2a4", - "name": "nuclear" - }, - { - "code": "0xf342", - "name": "outlet" - }, - { - "code": "0xf4d5", - "name": "paintbrush" - }, - { - "code": "0xf4d6", - "name": "paintbucket" - }, - { - "code": "0xf2c3", - "name": "paper-airplane" - }, - { - "code": "0xf20f", - "name": "paperclip" - }, - { - "code": "0xf210", - "name": "pause" - }, - { - "code": "0xf213", - "name": "person" - }, - { - "code": "0xf211", - "name": "person-add" - }, - { - "code": "0xf212", - "name": "person-stalker" - }, - { - "code": "0xf2a5", - "name": "pie-graph" - }, - { - "code": "0xf2a6", - "name": "pin" - }, - { - "code": "0xf2a7", - "name": "pinpoint" - }, - { - "code": "0xf2a8", - "name": "pizza" - }, - { - "code": "0xf214", - "name": "plane" - }, - { - "code": "0xf343", - "name": "planet" - }, - { - "code": "0xf215", - "name": "play" - }, - { - "code": "0xf30a", - "name": "playstation" - }, - { - "code": "0xf218", - "name": "plus" - }, - { - "code": "0xf216", - "name": "plus-circled" - }, - { - "code": "0xf217", - "name": "plus-round" - }, - { - "code": "0xf344", - "name": "podium" - }, - { - "code": "0xf219", - "name": "pound" - }, - { - "code": "0xf2a9", - "name": "power" - }, - { - "code": "0xf2aa", - "name": "pricetag" - }, - { - "code": "0xf2ab", - "name": "pricetags" - }, - { - "code": "0xf21a", - "name": "printer" - }, - { - "code": "0xf345", - "name": "pull-request" - }, - { - "code": "0xf346", - "name": "qr-scanner" - }, - { - "code": "0xf347", - "name": "quote" - }, - { - "code": "0xf2ac", - "name": "radio-waves" - }, - { - "code": "0xf21b", - "name": "record" - }, - { - "code": "0xf21c", - "name": "refresh" - }, - { - "code": "0xf21e", - "name": "reply" - }, - { - "code": "0xf21d", - "name": "reply-all" - }, - { - "code": "0xf348", - "name": "ribbon-a" - }, - { - "code": "0xf349", - "name": "ribbon-b" - }, - { - "code": "0xf34a", - "name": "sad" - }, - { - "code": "0xf4d7", - "name": "sad-outline" - }, - { - "code": "0xf34b", - "name": "scissors" - }, - { - "code": "0xf21f", - "name": "search" - }, - { - "code": "0xf2ad", - "name": "settings" - }, - { - "code": "0xf220", - "name": "share" - }, - { - "code": "0xf221", - "name": "shuffle" - }, - { - "code": "0xf222", - "name": "skip-backward" - }, - { - "code": "0xf223", - "name": "skip-forward" - }, - { - "code": "0xf225", - "name": "social-android" - }, - { - "code": "0xf224", - "name": "social-android-outline" - }, - { - "code": "0xf4d9", - "name": "social-angular" - }, - { - "code": "0xf4d8", - "name": "social-angular-outline" - }, - { - "code": "0xf227", - "name": "social-apple" - }, - { - "code": "0xf226", - "name": "social-apple-outline" - }, - { - "code": "0xf2af", - "name": "social-bitcoin" - }, - { - "code": "0xf2ae", - "name": "social-bitcoin-outline" - }, - { - "code": "0xf229", - "name": "social-buffer" - }, - { - "code": "0xf228", - "name": "social-buffer-outline" - }, - { - "code": "0xf4db", - "name": "social-chrome" - }, - { - "code": "0xf4da", - "name": "social-chrome-outline" - }, - { - "code": "0xf4dd", - "name": "social-codepen" - }, - { - "code": "0xf4dc", - "name": "social-codepen-outline" - }, - { - "code": "0xf4df", - "name": "social-css3" - }, - { - "code": "0xf4de", - "name": "social-css3-outline" - }, - { - "code": "0xf22b", - "name": "social-designernews" - }, - { - "code": "0xf22a", - "name": "social-designernews-outline" - }, - { - "code": "0xf22d", - "name": "social-dribbble" - }, - { - "code": "0xf22c", - "name": "social-dribbble-outline" - }, - { - "code": "0xf22f", - "name": "social-dropbox" - }, - { - "code": "0xf22e", - "name": "social-dropbox-outline" - }, - { - "code": "0xf4e1", - "name": "social-euro" - }, - { - "code": "0xf4e0", - "name": "social-euro-outline" - }, - { - "code": "0xf231", - "name": "social-facebook" - }, - { - "code": "0xf230", - "name": "social-facebook-outline" - }, - { - "code": "0xf34d", - "name": "social-foursquare" - }, - { - "code": "0xf34c", - "name": "social-foursquare-outline" - }, - { - "code": "0xf2c4", - "name": "social-freebsd-devil" - }, - { - "code": "0xf233", - "name": "social-github" - }, - { - "code": "0xf232", - "name": "social-github-outline" - }, - { - "code": "0xf34f", - "name": "social-google" - }, - { - "code": "0xf34e", - "name": "social-google-outline" - }, - { - "code": "0xf235", - "name": "social-googleplus" - }, - { - "code": "0xf234", - "name": "social-googleplus-outline" - }, - { - "code": "0xf237", - "name": "social-hackernews" - }, - { - "code": "0xf236", - "name": "social-hackernews-outline" - }, - { - "code": "0xf4e3", - "name": "social-html5" - }, - { - "code": "0xf4e2", - "name": "social-html5-outline" - }, - { - "code": "0xf351", - "name": "social-instagram" - }, - { - "code": "0xf350", - "name": "social-instagram-outline" - }, - { - "code": "0xf4e5", - "name": "social-javascript" - }, - { - "code": "0xf4e4", - "name": "social-javascript-outline" - }, - { - "code": "0xf239", - "name": "social-linkedin" - }, - { - "code": "0xf238", - "name": "social-linkedin-outline" - }, - { - "code": "0xf4e6", - "name": "social-markdown" - }, - { - "code": "0xf4e7", - "name": "social-nodejs" - }, - { - "code": "0xf4e8", - "name": "social-octocat" - }, - { - "code": "0xf2b1", - "name": "social-pinterest" - }, - { - "code": "0xf2b0", - "name": "social-pinterest-outline" - }, - { - "code": "0xf4e9", - "name": "social-python" - }, - { - "code": "0xf23b", - "name": "social-reddit" - }, - { - "code": "0xf23a", - "name": "social-reddit-outline" - }, - { - "code": "0xf23d", - "name": "social-rss" - }, - { - "code": "0xf23c", - "name": "social-rss-outline" - }, - { - "code": "0xf4ea", - "name": "social-sass" - }, - { - "code": "0xf23f", - "name": "social-skype" - }, - { - "code": "0xf23e", - "name": "social-skype-outline" - }, - { - "code": "0xf4ec", - "name": "social-snapchat" - }, - { - "code": "0xf4eb", - "name": "social-snapchat-outline" - }, - { - "code": "0xf241", - "name": "social-tumblr" - }, - { - "code": "0xf240", - "name": "social-tumblr-outline" - }, - { - "code": "0xf2c5", - "name": "social-tux" - }, - { - "code": "0xf4ee", - "name": "social-twitch" - }, - { - "code": "0xf4ed", - "name": "social-twitch-outline" - }, - { - "code": "0xf243", - "name": "social-twitter" - }, - { - "code": "0xf242", - "name": "social-twitter-outline" - }, - { - "code": "0xf353", - "name": "social-usd" - }, - { - "code": "0xf352", - "name": "social-usd-outline" - }, - { - "code": "0xf245", - "name": "social-vimeo" - }, - { - "code": "0xf244", - "name": "social-vimeo-outline" - }, - { - "code": "0xf4f0", - "name": "social-whatsapp" - }, - { - "code": "0xf4ef", - "name": "social-whatsapp-outline" - }, - { - "code": "0xf247", - "name": "social-windows" - }, - { - "code": "0xf246", - "name": "social-windows-outline" - }, - { - "code": "0xf249", - "name": "social-wordpress" - }, - { - "code": "0xf248", - "name": "social-wordpress-outline" - }, - { - "code": "0xf24b", - "name": "social-yahoo" - }, - { - "code": "0xf24a", - "name": "social-yahoo-outline" - }, - { - "code": "0xf4f2", - "name": "social-yen" - }, - { - "code": "0xf4f1", - "name": "social-yen-outline" - }, - { - "code": "0xf24d", - "name": "social-youtube" - }, - { - "code": "0xf24c", - "name": "social-youtube-outline" - }, - { - "code": "0xf4f4", - "name": "soup-can" - }, - { - "code": "0xf4f3", - "name": "soup-can-outline" - }, - { - "code": "0xf2b2", - "name": "speakerphone" - }, - { - "code": "0xf2b3", - "name": "speedometer" - }, - { - "code": "0xf2b4", - "name": "spoon" - }, - { - "code": "0xf24e", - "name": "star" - }, - { - "code": "0xf2b5", - "name": "stats-bars" - }, - { - "code": "0xf30b", - "name": "steam" - }, - { - "code": "0xf24f", - "name": "stop" - }, - { - "code": "0xf2b6", - "name": "thermometer" - }, - { - "code": "0xf250", - "name": "thumbsdown" - }, - { - "code": "0xf251", - "name": "thumbsup" - }, - { - "code": "0xf355", - "name": "toggle" - }, - { - "code": "0xf354", - "name": "toggle-filled" - }, - { - "code": "0xf4f5", - "name": "transgender" - }, - { - "code": "0xf252", - "name": "trash-a" - }, - { - "code": "0xf253", - "name": "trash-b" - }, - { - "code": "0xf356", - "name": "trophy" - }, - { - "code": "0xf4f7", - "name": "tshirt" - }, - { - "code": "0xf4f6", - "name": "tshirt-outline" - }, - { - "code": "0xf2b7", - "name": "umbrella" - }, - { - "code": "0xf357", - "name": "university" - }, - { - "code": "0xf254", - "name": "unlocked" - }, - { - "code": "0xf255", - "name": "upload" - }, - { - "code": "0xf2b8", - "name": "usb" - }, - { - "code": "0xf256", - "name": "videocamera" - }, - { - "code": "0xf257", - "name": "volume-high" - }, - { - "code": "0xf258", - "name": "volume-low" - }, - { - "code": "0xf259", - "name": "volume-medium" - }, - { - "code": "0xf25a", - "name": "volume-mute" - }, - { - "code": "0xf358", - "name": "wand" - }, - { - "code": "0xf25b", - "name": "waterdrop" - }, - { - "code": "0xf25c", - "name": "wifi" - }, - { - "code": "0xf2b9", - "name": "wineglass" - }, - { - "code": "0xf25d", - "name": "woman" - }, - { - "code": "0xf2ba", - "name": "wrench" - }, - { - "code": "0xf30c", - "name": "xbox" - } - ] -} \ No newline at end of file diff --git a/static/ionicons-2.0.1/builder/cheatsheet/icon-row.html b/static/ionicons-2.0.1/builder/cheatsheet/icon-row.html deleted file mode 100644 index a542767..0000000 --- a/static/ionicons-2.0.1/builder/cheatsheet/icon-row.html +++ /dev/null @@ -1,38 +0,0 @@ -
-
- - - - - - - - - - - - - - - - - - - - -
-
12141618212432486496
-
- - - - - {{html_code}} - - - - - - -
-
\ No newline at end of file diff --git a/static/ionicons-2.0.1/builder/cheatsheet/template.html b/static/ionicons-2.0.1/builder/cheatsheet/template.html deleted file mode 100644 index 74d0dc7..0000000 --- a/static/ionicons-2.0.1/builder/cheatsheet/template.html +++ /dev/null @@ -1,156 +0,0 @@ - - - - {{font_name}} v{{font_version}} Cheatsheet - - - - - -
-
-

{{font_name}} v{{font_version}} Cheatsheet, {{icon_count}} icons:

-

Ionicons Homepage

-
-
- {{content}} -
- -
- - \ No newline at end of file diff --git a/static/ionicons-2.0.1/builder/generate.py b/static/ionicons-2.0.1/builder/generate.py deleted file mode 100644 index 39ae07c..0000000 --- a/static/ionicons-2.0.1/builder/generate.py +++ /dev/null @@ -1,319 +0,0 @@ -from subprocess import call -import os -import json - - -BUILDER_PATH = os.path.dirname(os.path.abspath(__file__)) -ROOT_PATH = os.path.join(BUILDER_PATH, "..") -FONTS_FOLDER_PATH = os.path.join(ROOT_PATH, "fonts") -CSS_FOLDER_PATH = os.path.join(ROOT_PATH, "css") -SCSS_FOLDER_PATH = os.path.join(ROOT_PATH, "scss") -LESS_FOLDER_PATH = os.path.join(ROOT_PATH, "less") - - -def main(): - generate_font_files() - - data = get_build_data() - - rename_svg_glyph_names(data) - generate_scss(data) - generate_less(data) - generate_cheatsheet(data) - generate_component_json(data) - generate_composer_json(data) - generate_bower_json(data) - - -def generate_font_files(): - print "Generate Fonts" - cmd = "fontforge -script %s/scripts/generate_font.py" % (BUILDER_PATH) - call(cmd, shell=True) - - -def rename_svg_glyph_names(data): - # hacky and slow (but safe) way to rename glyph-name attributes - svg_path = os.path.join(FONTS_FOLDER_PATH, "ionicons.svg") - svg_file = open(svg_path, "r+") - svg_text = svg_file.read() - svg_file.seek(0) - - for ionicon in data["icons"]: - # uniF2CA - org_name = "uni%s" % (ionicon["code"].replace("0x", "").upper()) - ion_name = "ion-%s" % (ionicon["name"]) - svg_text = svg_text.replace(org_name, ion_name) - - svg_file.write(svg_text) - svg_file.close() - - -def generate_less(data): - print "Generate LESS" - font_name = data["name"] - font_version = data["version"] - css_prefix = data["prefix"] - variables_file_path = os.path.join(LESS_FOLDER_PATH, "_ionicons-variables.less") - icons_file_path = os.path.join(LESS_FOLDER_PATH, "_ionicons-icons.less") - - d = [] - d.append("/*!") - d.append("Ionicons, v%s" % (font_version)) - d.append("Created by Ben Sperry for the Ionic Framework, http://ionicons.com/") - d.append("https://twitter.com/benjsperry https://twitter.com/ionicframework") - d.append("MIT License: https://github.com/driftyco/ionicons") - d.append("*/") - d.append("// Ionicons Variables") - d.append("// --------------------------\n") - d.append('@ionicons-font-path: "../fonts";') - d.append('@ionicons-font-family: "%s";' % (font_name)) - d.append('@ionicons-version: "%s";' % (font_version)) - d.append("@ionicons-prefix: %s;" % (css_prefix)) - d.append("") - for ionicon in data["icons"]: - chr_code = ionicon["code"].replace("0x", "\\") - d.append('@ionicon-var-%s: "%s";' % (ionicon["name"], chr_code)) - f = open(variables_file_path, "w") - f.write("\n".join(d)) - f.close() - - d = [] - d.append("// Ionicons Icons") - d.append("// --------------------------\n") - - group = [".%s" % (data["name"].lower())] - for ionicon in data["icons"]: - group.append(".@{ionicons-prefix}%s:before" % (ionicon["name"])) - - d.append(",\n".join(group)) - - d.append("{") - d.append(" &:extend(.ion);") - d.append("}") - - for ionicon in data["icons"]: - chr_code = ionicon["code"].replace("0x", "\\") - d.append( - ".@{ionicons-prefix}%s:before { content: @ionicon-var-%s; }" - % (ionicon["name"], ionicon["name"]) - ) - - f = open(icons_file_path, "w") - f.write("\n".join(d)) - f.close() - - -def generate_scss(data): - print "Generate SCSS" - font_name = data["name"] - font_version = data["version"] - css_prefix = data["prefix"] - variables_file_path = os.path.join(SCSS_FOLDER_PATH, "_ionicons-variables.scss") - icons_file_path = os.path.join(SCSS_FOLDER_PATH, "_ionicons-icons.scss") - - d = [] - d.append("// Ionicons Variables") - d.append("// --------------------------\n") - d.append('$ionicons-font-path: "../fonts" !default;') - d.append('$ionicons-font-family: "%s" !default;' % (font_name)) - d.append('$ionicons-version: "%s" !default;' % (font_version)) - d.append("$ionicons-prefix: %s !default;" % (css_prefix)) - d.append("") - for ionicon in data["icons"]: - chr_code = ionicon["code"].replace("0x", "\\") - d.append('$ionicon-var-%s: "%s";' % (ionicon["name"], chr_code)) - f = open(variables_file_path, "w") - f.write("\n".join(d)) - f.close() - - d = [] - d.append("// Ionicons Icons") - d.append("// --------------------------\n") - - group = [".%s" % (data["name"].lower())] - for ionicon in data["icons"]: - group.append(".#{$ionicons-prefix}%s:before" % (ionicon["name"])) - - d.append(",\n".join(group)) - - d.append("{") - d.append(" @extend .ion;") - d.append("}") - - for ionicon in data["icons"]: - chr_code = ionicon["code"].replace("0x", "\\") - d.append( - ".#{$ionicons-prefix}%s:before { content: $ionicon-var-%s; }" - % (ionicon["name"], ionicon["name"]) - ) - - f = open(icons_file_path, "w") - f.write("\n".join(d)) - f.close() - - generate_css_from_scss(data) - - -def generate_css_from_scss(data): - print "Generate CSS From SCSS" - - scss_file_path = os.path.join(SCSS_FOLDER_PATH, "ionicons.scss") - css_file_path = os.path.join(CSS_FOLDER_PATH, "ionicons.css") - css_min_file_path = os.path.join(CSS_FOLDER_PATH, "ionicons.min.css") - - cmd = "sass %s %s --style compact" % (scss_file_path, css_file_path) - call(cmd, shell=True) - - print "Generate Minified CSS From SCSS" - cmd = "sass %s %s --style compressed" % (scss_file_path, css_min_file_path) - call(cmd, shell=True) - - -def generate_cheatsheet(data): - print "Generate Cheatsheet" - - cheatsheet_file_path = os.path.join(ROOT_PATH, "cheatsheet.html") - template_path = os.path.join(BUILDER_PATH, "cheatsheet", "template.html") - icon_row_path = os.path.join(BUILDER_PATH, "cheatsheet", "icon-row.html") - - f = open(template_path, "r") - template_html = f.read() - f.close() - - f = open(icon_row_path, "r") - icon_row_template = f.read() - f.close() - - content = [] - - for ionicon in data["icons"]: - css_code = ionicon["code"].replace("0x", "\\") - escaped_html_code = ionicon["code"].replace("0x", "&#x") + ";" - html_code = ionicon["code"].replace("0x", "&#x") + ";" - item_row = icon_row_template - - item_row = item_row.replace("{{name}}", ionicon["name"]) - item_row = item_row.replace("{{prefix}}", data["prefix"]) - item_row = item_row.replace("{{css_code}}", css_code) - item_row = item_row.replace("{{escaped_html_code}}", escaped_html_code) - item_row = item_row.replace("{{html_code}}", html_code) - - content.append(item_row) - - template_html = template_html.replace("{{font_name}}", data["name"]) - template_html = template_html.replace("{{font_version}}", data["version"]) - template_html = template_html.replace("{{icon_count}}", str(len(data["icons"]))) - template_html = template_html.replace("{{content}}", "\n".join(content)) - - f = open(cheatsheet_file_path, "w") - f.write(template_html) - f.close() - - -def generate_component_json(data): - print "Generate component.json" - d = { - "name": data["name"], - "repo": "driftyco/ionicons", - "description": "The premium icon font for Ionic Framework.", - "version": data["version"], - "keywords": [], - "dependencies": {}, - "development": {}, - "license": "MIT", - "styles": ["css/%s.css" % (data["name"].lower())], - "fonts": [ - "fonts/%s.eot" % (data["name"].lower()), - "fonts/%s.svg" % (data["name"].lower()), - "fonts/%s.ttf" % (data["name"].lower()), - "fonts/%s.woff" % (data["name"].lower()), - ], - } - txt = json.dumps(d, indent=4, separators=(",", ": ")) - - component_file_path = os.path.join(ROOT_PATH, "component.json") - f = open(component_file_path, "w") - f.write(txt) - f.close() - - -def generate_composer_json(data): - print "Generate composer.json" - d = { - "name": "driftyco/ionicons", - "description": "The premium icon font for Ionic Framework.", - "keywords": ["fonts", "icon font", "icons", "ionic", "web font"], - "homepage": "http://ionicons.com/", - "authors": [ - { - "name": "Ben Sperry", - "email": "ben@drifty.com", - "role": "Designer", - "homepage": "https://twitter.com/benjsperry", - }, - { - "name": "Adam Bradley", - "email": "adam@drifty.com", - "role": "Developer", - "homepage": "https://twitter.com/adamdbradley", - }, - { - "name": "Max Lynch", - "email": "max@drifty.com", - "role": "Developer", - "homepage": "https://twitter.com/maxlynch", - }, - ], - "extra": {}, - "license": ["MIT"], - } - txt = json.dumps(d, indent=4, separators=(",", ": ")) - - composer_file_path = os.path.join(ROOT_PATH, "composer.json") - f = open(composer_file_path, "w") - f.write(txt) - f.close() - - -def generate_bower_json(data): - print "Generate bower.json" - d = { - "name": data["name"], - "version": data["version"], - "homepage": "https://github.com/driftyco/ionicons", - "authors": [ - "Ben Sperry ", - "Adam Bradley ", - "Max Lynch ", - ], - "description": "Ionicons - free and beautiful icons from the creators of Ionic Framework", - "main": ["css/%s.css" % (data["name"].lower()), "fonts/*"], - "keywords": ["fonts", "icon font", "icons", "ionic", "web font"], - "license": "MIT", - "ignore": [ - "**/.*", - "builder", - "node_modules", - "bower_components", - "test", - "tests", - ], - } - txt = json.dumps(d, indent=4, separators=(",", ": ")) - - bower_file_path = os.path.join(ROOT_PATH, "bower.json") - f = open(bower_file_path, "w") - f.write(txt) - f.close() - - -def get_build_data(): - build_data_path = os.path.join(BUILDER_PATH, "build_data.json") - f = open(build_data_path, "r") - data = json.loads(f.read()) - f.close() - return data - - -if __name__ == "__main__": - main() diff --git a/static/ionicons-2.0.1/builder/manifest.json b/static/ionicons-2.0.1/builder/manifest.json deleted file mode 100644 index e280be3..0000000 --- a/static/ionicons-2.0.1/builder/manifest.json +++ /dev/null @@ -1,2940 +0,0 @@ -{ - "build_hash": "a2c6f31123a3cc8385d45bf46c5dde82", - "prefix": "ion-", - "version": "2.0.0", - "name": "Ionicons", - "icons": [ - { - "code": "0xf101", - "name": "alert" - }, - { - "code": "0xf100", - "name": "alert-circled" - }, - { - "code": "0xf2c7", - "name": "android-add" - }, - { - "code": "0xf359", - "name": "android-add-circle" - }, - { - "code": "0xf35a", - "name": "android-alarm-clock" - }, - { - "code": "0xf35b", - "name": "android-alert" - }, - { - "code": "0xf35c", - "name": "android-apps" - }, - { - "code": "0xf2c9", - "name": "android-archive" - }, - { - "code": "0xf2ca", - "name": "android-arrow-back" - }, - { - "code": "0xf35d", - "name": "android-arrow-down" - }, - { - "code": "0xf35f", - "name": "android-arrow-dropdown" - }, - { - "code": "0xf35e", - "name": "android-arrow-dropdown-circle" - }, - { - "code": "0xf361", - "name": "android-arrow-dropleft" - }, - { - "code": "0xf360", - "name": "android-arrow-dropleft-circle" - }, - { - "code": "0xf363", - "name": "android-arrow-dropright" - }, - { - "code": "0xf362", - "name": "android-arrow-dropright-circle" - }, - { - "code": "0xf365", - "name": "android-arrow-dropup" - }, - { - "code": "0xf364", - "name": "android-arrow-dropup-circle" - }, - { - "code": "0xf30f", - "name": "android-arrow-forward" - }, - { - "code": "0xf366", - "name": "android-arrow-up" - }, - { - "code": "0xf367", - "name": "android-attach" - }, - { - "code": "0xf368", - "name": "android-bar" - }, - { - "code": "0xf369", - "name": "android-bicycle" - }, - { - "code": "0xf36a", - "name": "android-boat" - }, - { - "code": "0xf36b", - "name": "android-bookmark" - }, - { - "code": "0xf36c", - "name": "android-bulb" - }, - { - "code": "0xf36d", - "name": "android-bus" - }, - { - "code": "0xf2d1", - "name": "android-calendar" - }, - { - "code": "0xf2d2", - "name": "android-call" - }, - { - "code": "0xf2d3", - "name": "android-camera" - }, - { - "code": "0xf36e", - "name": "android-cancel" - }, - { - "code": "0xf36f", - "name": "android-car" - }, - { - "code": "0xf370", - "name": "android-cart" - }, - { - "code": "0xf2d4", - "name": "android-chat" - }, - { - "code": "0xf374", - "name": "android-checkbox" - }, - { - "code": "0xf371", - "name": "android-checkbox-blank" - }, - { - "code": "0xf373", - "name": "android-checkbox-outline" - }, - { - "code": "0xf372", - "name": "android-checkbox-outline-blank" - }, - { - "code": "0xf375", - "name": "android-checkmark-circle" - }, - { - "code": "0xf376", - "name": "android-clipboard" - }, - { - "code": "0xf2d7", - "name": "android-close" - }, - { - "code": "0xf37a", - "name": "android-cloud" - }, - { - "code": "0xf377", - "name": "android-cloud-circle" - }, - { - "code": "0xf378", - "name": "android-cloud-done" - }, - { - "code": "0xf379", - "name": "android-cloud-outline" - }, - { - "code": "0xf37b", - "name": "android-color-palette" - }, - { - "code": "0xf37c", - "name": "android-compass" - }, - { - "code": "0xf2d8", - "name": "android-contact" - }, - { - "code": "0xf2d9", - "name": "android-contacts" - }, - { - "code": "0xf37d", - "name": "android-contract" - }, - { - "code": "0xf37e", - "name": "android-create" - }, - { - "code": "0xf37f", - "name": "android-delete" - }, - { - "code": "0xf380", - "name": "android-desktop" - }, - { - "code": "0xf381", - "name": "android-document" - }, - { - "code": "0xf383", - "name": "android-done" - }, - { - "code": "0xf382", - "name": "android-done-all" - }, - { - "code": "0xf2dd", - "name": "android-download" - }, - { - "code": "0xf384", - "name": "android-drafts" - }, - { - "code": "0xf385", - "name": "android-exit" - }, - { - "code": "0xf386", - "name": "android-expand" - }, - { - "code": "0xf388", - "name": "android-favorite" - }, - { - "code": "0xf387", - "name": "android-favorite-outline" - }, - { - "code": "0xf389", - "name": "android-film" - }, - { - "code": "0xf2e0", - "name": "android-folder" - }, - { - "code": "0xf38a", - "name": "android-folder-open" - }, - { - "code": "0xf38b", - "name": "android-funnel" - }, - { - "code": "0xf38c", - "name": "android-globe" - }, - { - "code": "0xf2e3", - "name": "android-hand" - }, - { - "code": "0xf38d", - "name": "android-hangout" - }, - { - "code": "0xf38e", - "name": "android-happy" - }, - { - "code": "0xf38f", - "name": "android-home" - }, - { - "code": "0xf2e4", - "name": "android-image" - }, - { - "code": "0xf390", - "name": "android-laptop" - }, - { - "code": "0xf391", - "name": "android-list" - }, - { - "code": "0xf2e9", - "name": "android-locate" - }, - { - "code": "0xf392", - "name": "android-lock" - }, - { - "code": "0xf2eb", - "name": "android-mail" - }, - { - "code": "0xf393", - "name": "android-map" - }, - { - "code": "0xf394", - "name": "android-menu" - }, - { - "code": "0xf2ec", - "name": "android-microphone" - }, - { - "code": "0xf395", - "name": "android-microphone-off" - }, - { - "code": "0xf396", - "name": "android-more-horizontal" - }, - { - "code": "0xf397", - "name": "android-more-vertical" - }, - { - "code": "0xf398", - "name": "android-navigate" - }, - { - "code": "0xf39b", - "name": "android-notifications" - }, - { - "code": "0xf399", - "name": "android-notifications-none" - }, - { - "code": "0xf39a", - "name": "android-notifications-off" - }, - { - "code": "0xf39c", - "name": "android-open" - }, - { - "code": "0xf39d", - "name": "android-options" - }, - { - "code": "0xf39e", - "name": "android-people" - }, - { - "code": "0xf3a0", - "name": "android-person" - }, - { - "code": "0xf39f", - "name": "android-person-add" - }, - { - "code": "0xf3a1", - "name": "android-phone-landscape" - }, - { - "code": "0xf3a2", - "name": "android-phone-portrait" - }, - { - "code": "0xf3a3", - "name": "android-pin" - }, - { - "code": "0xf3a4", - "name": "android-plane" - }, - { - "code": "0xf2f0", - "name": "android-playstore" - }, - { - "code": "0xf3a5", - "name": "android-print" - }, - { - "code": "0xf3a6", - "name": "android-radio-button-off" - }, - { - "code": "0xf3a7", - "name": "android-radio-button-on" - }, - { - "code": "0xf3a8", - "name": "android-refresh" - }, - { - "code": "0xf2f4", - "name": "android-remove" - }, - { - "code": "0xf3a9", - "name": "android-remove-circle" - }, - { - "code": "0xf3aa", - "name": "android-restaurant" - }, - { - "code": "0xf3ab", - "name": "android-sad" - }, - { - "code": "0xf2f5", - "name": "android-search" - }, - { - "code": "0xf2f6", - "name": "android-send" - }, - { - "code": "0xf2f7", - "name": "android-settings" - }, - { - "code": "0xf2f8", - "name": "android-share" - }, - { - "code": "0xf3ac", - "name": "android-share-alt" - }, - { - "code": "0xf2fc", - "name": "android-star" - }, - { - "code": "0xf3ad", - "name": "android-star-half" - }, - { - "code": "0xf3ae", - "name": "android-star-outline" - }, - { - "code": "0xf2fd", - "name": "android-stopwatch" - }, - { - "code": "0xf3af", - "name": "android-subway" - }, - { - "code": "0xf3b0", - "name": "android-sunny" - }, - { - "code": "0xf3b1", - "name": "android-sync" - }, - { - "code": "0xf3b2", - "name": "android-textsms" - }, - { - "code": "0xf3b3", - "name": "android-time" - }, - { - "code": "0xf3b4", - "name": "android-train" - }, - { - "code": "0xf3b5", - "name": "android-unlock" - }, - { - "code": "0xf3b6", - "name": "android-upload" - }, - { - "code": "0xf3b7", - "name": "android-volume-down" - }, - { - "code": "0xf3b8", - "name": "android-volume-mute" - }, - { - "code": "0xf3b9", - "name": "android-volume-off" - }, - { - "code": "0xf3ba", - "name": "android-volume-up" - }, - { - "code": "0xf3bb", - "name": "android-walk" - }, - { - "code": "0xf3bc", - "name": "android-warning" - }, - { - "code": "0xf3bd", - "name": "android-watch" - }, - { - "code": "0xf305", - "name": "android-wifi" - }, - { - "code": "0xf313", - "name": "aperture" - }, - { - "code": "0xf102", - "name": "archive" - }, - { - "code": "0xf103", - "name": "arrow-down-a" - }, - { - "code": "0xf104", - "name": "arrow-down-b" - }, - { - "code": "0xf105", - "name": "arrow-down-c" - }, - { - "code": "0xf25e", - "name": "arrow-expand" - }, - { - "code": "0xf25f", - "name": "arrow-graph-down-left" - }, - { - "code": "0xf260", - "name": "arrow-graph-down-right" - }, - { - "code": "0xf261", - "name": "arrow-graph-up-left" - }, - { - "code": "0xf262", - "name": "arrow-graph-up-right" - }, - { - "code": "0xf106", - "name": "arrow-left-a" - }, - { - "code": "0xf107", - "name": "arrow-left-b" - }, - { - "code": "0xf108", - "name": "arrow-left-c" - }, - { - "code": "0xf263", - "name": "arrow-move" - }, - { - "code": "0xf264", - "name": "arrow-resize" - }, - { - "code": "0xf265", - "name": "arrow-return-left" - }, - { - "code": "0xf266", - "name": "arrow-return-right" - }, - { - "code": "0xf109", - "name": "arrow-right-a" - }, - { - "code": "0xf10a", - "name": "arrow-right-b" - }, - { - "code": "0xf10b", - "name": "arrow-right-c" - }, - { - "code": "0xf267", - "name": "arrow-shrink" - }, - { - "code": "0xf268", - "name": "arrow-swap" - }, - { - "code": "0xf10c", - "name": "arrow-up-a" - }, - { - "code": "0xf10d", - "name": "arrow-up-b" - }, - { - "code": "0xf10e", - "name": "arrow-up-c" - }, - { - "code": "0xf314", - "name": "asterisk" - }, - { - "code": "0xf10f", - "name": "at" - }, - { - "code": "0xf3bf", - "name": "backspace" - }, - { - "code": "0xf3be", - "name": "backspace-outline" - }, - { - "code": "0xf110", - "name": "bag" - }, - { - "code": "0xf111", - "name": "battery-charging" - }, - { - "code": "0xf112", - "name": "battery-empty" - }, - { - "code": "0xf113", - "name": "battery-full" - }, - { - "code": "0xf114", - "name": "battery-half" - }, - { - "code": "0xf115", - "name": "battery-low" - }, - { - "code": "0xf269", - "name": "beaker" - }, - { - "code": "0xf26a", - "name": "beer" - }, - { - "code": "0xf116", - "name": "bluetooth" - }, - { - "code": "0xf315", - "name": "bonfire" - }, - { - "code": "0xf26b", - "name": "bookmark" - }, - { - "code": "0xf3c0", - "name": "bowtie" - }, - { - "code": "0xf26c", - "name": "briefcase" - }, - { - "code": "0xf2be", - "name": "bug" - }, - { - "code": "0xf26d", - "name": "calculator" - }, - { - "code": "0xf117", - "name": "calendar" - }, - { - "code": "0xf118", - "name": "camera" - }, - { - "code": "0xf119", - "name": "card" - }, - { - "code": "0xf316", - "name": "cash" - }, - { - "code": "0xf11b", - "name": "chatbox" - }, - { - "code": "0xf11a", - "name": "chatbox-working" - }, - { - "code": "0xf11c", - "name": "chatboxes" - }, - { - "code": "0xf11e", - "name": "chatbubble" - }, - { - "code": "0xf11d", - "name": "chatbubble-working" - }, - { - "code": "0xf11f", - "name": "chatbubbles" - }, - { - "code": "0xf122", - "name": "checkmark" - }, - { - "code": "0xf120", - "name": "checkmark-circled" - }, - { - "code": "0xf121", - "name": "checkmark-round" - }, - { - "code": "0xf123", - "name": "chevron-down" - }, - { - "code": "0xf124", - "name": "chevron-left" - }, - { - "code": "0xf125", - "name": "chevron-right" - }, - { - "code": "0xf126", - "name": "chevron-up" - }, - { - "code": "0xf127", - "name": "clipboard" - }, - { - "code": "0xf26e", - "name": "clock" - }, - { - "code": "0xf12a", - "name": "close" - }, - { - "code": "0xf128", - "name": "close-circled" - }, - { - "code": "0xf129", - "name": "close-round" - }, - { - "code": "0xf317", - "name": "closed-captioning" - }, - { - "code": "0xf12b", - "name": "cloud" - }, - { - "code": "0xf271", - "name": "code" - }, - { - "code": "0xf26f", - "name": "code-download" - }, - { - "code": "0xf270", - "name": "code-working" - }, - { - "code": "0xf272", - "name": "coffee" - }, - { - "code": "0xf273", - "name": "compass" - }, - { - "code": "0xf12c", - "name": "compose" - }, - { - "code": "0xf274", - "name": "connection-bars" - }, - { - "code": "0xf275", - "name": "contrast" - }, - { - "code": "0xf3c1", - "name": "crop" - }, - { - "code": "0xf318", - "name": "cube" - }, - { - "code": "0xf12d", - "name": "disc" - }, - { - "code": "0xf12f", - "name": "document" - }, - { - "code": "0xf12e", - "name": "document-text" - }, - { - "code": "0xf130", - "name": "drag" - }, - { - "code": "0xf276", - "name": "earth" - }, - { - "code": "0xf3c2", - "name": "easel" - }, - { - "code": "0xf2bf", - "name": "edit" - }, - { - "code": "0xf277", - "name": "egg" - }, - { - "code": "0xf131", - "name": "eject" - }, - { - "code": "0xf132", - "name": "email" - }, - { - "code": "0xf3c3", - "name": "email-unread" - }, - { - "code": "0xf3c5", - "name": "erlenmeyer-flask" - }, - { - "code": "0xf3c4", - "name": "erlenmeyer-flask-bubbles" - }, - { - "code": "0xf133", - "name": "eye" - }, - { - "code": "0xf306", - "name": "eye-disabled" - }, - { - "code": "0xf278", - "name": "female" - }, - { - "code": "0xf134", - "name": "filing" - }, - { - "code": "0xf135", - "name": "film-marker" - }, - { - "code": "0xf319", - "name": "fireball" - }, - { - "code": "0xf279", - "name": "flag" - }, - { - "code": "0xf31a", - "name": "flame" - }, - { - "code": "0xf137", - "name": "flash" - }, - { - "code": "0xf136", - "name": "flash-off" - }, - { - "code": "0xf139", - "name": "folder" - }, - { - "code": "0xf27a", - "name": "fork" - }, - { - "code": "0xf2c0", - "name": "fork-repo" - }, - { - "code": "0xf13a", - "name": "forward" - }, - { - "code": "0xf31b", - "name": "funnel" - }, - { - "code": "0xf13d", - "name": "gear-a" - }, - { - "code": "0xf13e", - "name": "gear-b" - }, - { - "code": "0xf13f", - "name": "grid" - }, - { - "code": "0xf27b", - "name": "hammer" - }, - { - "code": "0xf31c", - "name": "happy" - }, - { - "code": "0xf3c6", - "name": "happy-outline" - }, - { - "code": "0xf140", - "name": "headphone" - }, - { - "code": "0xf141", - "name": "heart" - }, - { - "code": "0xf31d", - "name": "heart-broken" - }, - { - "code": "0xf143", - "name": "help" - }, - { - "code": "0xf27c", - "name": "help-buoy" - }, - { - "code": "0xf142", - "name": "help-circled" - }, - { - "code": "0xf144", - "name": "home" - }, - { - "code": "0xf27d", - "name": "icecream" - }, - { - "code": "0xf147", - "name": "image" - }, - { - "code": "0xf148", - "name": "images" - }, - { - "code": "0xf14a", - "name": "information" - }, - { - "code": "0xf149", - "name": "information-circled" - }, - { - "code": "0xf14b", - "name": "ionic" - }, - { - "code": "0xf3c8", - "name": "ios-alarm" - }, - { - "code": "0xf3c7", - "name": "ios-alarm-outline" - }, - { - "code": "0xf3ca", - "name": "ios-albums" - }, - { - "code": "0xf3c9", - "name": "ios-albums-outline" - }, - { - "code": "0xf3cc", - "name": "ios-americanfootball" - }, - { - "code": "0xf3cb", - "name": "ios-americanfootball-outline" - }, - { - "code": "0xf3ce", - "name": "ios-analytics" - }, - { - "code": "0xf3cd", - "name": "ios-analytics-outline" - }, - { - "code": "0xf3cf", - "name": "ios-arrow-back" - }, - { - "code": "0xf3d0", - "name": "ios-arrow-down" - }, - { - "code": "0xf3d1", - "name": "ios-arrow-forward" - }, - { - "code": "0xf3d2", - "name": "ios-arrow-left" - }, - { - "code": "0xf3d3", - "name": "ios-arrow-right" - }, - { - "code": "0xf3d4", - "name": "ios-arrow-thin-down" - }, - { - "code": "0xf3d5", - "name": "ios-arrow-thin-left" - }, - { - "code": "0xf3d6", - "name": "ios-arrow-thin-right" - }, - { - "code": "0xf3d7", - "name": "ios-arrow-thin-up" - }, - { - "code": "0xf3d8", - "name": "ios-arrow-up" - }, - { - "code": "0xf3da", - "name": "ios-at" - }, - { - "code": "0xf3d9", - "name": "ios-at-outline" - }, - { - "code": "0xf3dc", - "name": "ios-barcode" - }, - { - "code": "0xf3db", - "name": "ios-barcode-outline" - }, - { - "code": "0xf3de", - "name": "ios-baseball" - }, - { - "code": "0xf3dd", - "name": "ios-baseball-outline" - }, - { - "code": "0xf3e0", - "name": "ios-basketball" - }, - { - "code": "0xf3df", - "name": "ios-basketball-outline" - }, - { - "code": "0xf3e2", - "name": "ios-bell" - }, - { - "code": "0xf3e1", - "name": "ios-bell-outline" - }, - { - "code": "0xf3e4", - "name": "ios-body" - }, - { - "code": "0xf3e3", - "name": "ios-body-outline" - }, - { - "code": "0xf3e6", - "name": "ios-bolt" - }, - { - "code": "0xf3e5", - "name": "ios-bolt-outline" - }, - { - "code": "0xf3e8", - "name": "ios-book" - }, - { - "code": "0xf3e7", - "name": "ios-book-outline" - }, - { - "code": "0xf3ea", - "name": "ios-bookmarks" - }, - { - "code": "0xf3e9", - "name": "ios-bookmarks-outline" - }, - { - "code": "0xf3ec", - "name": "ios-box" - }, - { - "code": "0xf3eb", - "name": "ios-box-outline" - }, - { - "code": "0xf3ee", - "name": "ios-briefcase" - }, - { - "code": "0xf3ed", - "name": "ios-briefcase-outline" - }, - { - "code": "0xf3f0", - "name": "ios-browsers" - }, - { - "code": "0xf3ef", - "name": "ios-browsers-outline" - }, - { - "code": "0xf3f2", - "name": "ios-calculator" - }, - { - "code": "0xf3f1", - "name": "ios-calculator-outline" - }, - { - "code": "0xf3f4", - "name": "ios-calendar" - }, - { - "code": "0xf3f3", - "name": "ios-calendar-outline" - }, - { - "code": "0xf3f6", - "name": "ios-camera" - }, - { - "code": "0xf3f5", - "name": "ios-camera-outline" - }, - { - "code": "0xf3f8", - "name": "ios-cart" - }, - { - "code": "0xf3f7", - "name": "ios-cart-outline" - }, - { - "code": "0xf3fa", - "name": "ios-chatboxes" - }, - { - "code": "0xf3f9", - "name": "ios-chatboxes-outline" - }, - { - "code": "0xf3fc", - "name": "ios-chatbubble" - }, - { - "code": "0xf3fb", - "name": "ios-chatbubble-outline" - }, - { - "code": "0xf3ff", - "name": "ios-checkmark" - }, - { - "code": "0xf3fd", - "name": "ios-checkmark-empty" - }, - { - "code": "0xf3fe", - "name": "ios-checkmark-outline" - }, - { - "code": "0xf400", - "name": "ios-circle-filled" - }, - { - "code": "0xf401", - "name": "ios-circle-outline" - }, - { - "code": "0xf403", - "name": "ios-clock" - }, - { - "code": "0xf402", - "name": "ios-clock-outline" - }, - { - "code": "0xf406", - "name": "ios-close" - }, - { - "code": "0xf404", - "name": "ios-close-empty" - }, - { - "code": "0xf405", - "name": "ios-close-outline" - }, - { - "code": "0xf40c", - "name": "ios-cloud" - }, - { - "code": "0xf408", - "name": "ios-cloud-download" - }, - { - "code": "0xf407", - "name": "ios-cloud-download-outline" - }, - { - "code": "0xf409", - "name": "ios-cloud-outline" - }, - { - "code": "0xf40b", - "name": "ios-cloud-upload" - }, - { - "code": "0xf40a", - "name": "ios-cloud-upload-outline" - }, - { - "code": "0xf410", - "name": "ios-cloudy" - }, - { - "code": "0xf40e", - "name": "ios-cloudy-night" - }, - { - "code": "0xf40d", - "name": "ios-cloudy-night-outline" - }, - { - "code": "0xf40f", - "name": "ios-cloudy-outline" - }, - { - "code": "0xf412", - "name": "ios-cog" - }, - { - "code": "0xf411", - "name": "ios-cog-outline" - }, - { - "code": "0xf414", - "name": "ios-color-filter" - }, - { - "code": "0xf413", - "name": "ios-color-filter-outline" - }, - { - "code": "0xf416", - "name": "ios-color-wand" - }, - { - "code": "0xf415", - "name": "ios-color-wand-outline" - }, - { - "code": "0xf418", - "name": "ios-compose" - }, - { - "code": "0xf417", - "name": "ios-compose-outline" - }, - { - "code": "0xf41a", - "name": "ios-contact" - }, - { - "code": "0xf419", - "name": "ios-contact-outline" - }, - { - "code": "0xf41c", - "name": "ios-copy" - }, - { - "code": "0xf41b", - "name": "ios-copy-outline" - }, - { - "code": "0xf41e", - "name": "ios-crop" - }, - { - "code": "0xf41d", - "name": "ios-crop-strong" - }, - { - "code": "0xf420", - "name": "ios-download" - }, - { - "code": "0xf41f", - "name": "ios-download-outline" - }, - { - "code": "0xf421", - "name": "ios-drag" - }, - { - "code": "0xf423", - "name": "ios-email" - }, - { - "code": "0xf422", - "name": "ios-email-outline" - }, - { - "code": "0xf425", - "name": "ios-eye" - }, - { - "code": "0xf424", - "name": "ios-eye-outline" - }, - { - "code": "0xf427", - "name": "ios-fastforward" - }, - { - "code": "0xf426", - "name": "ios-fastforward-outline" - }, - { - "code": "0xf429", - "name": "ios-filing" - }, - { - "code": "0xf428", - "name": "ios-filing-outline" - }, - { - "code": "0xf42b", - "name": "ios-film" - }, - { - "code": "0xf42a", - "name": "ios-film-outline" - }, - { - "code": "0xf42d", - "name": "ios-flag" - }, - { - "code": "0xf42c", - "name": "ios-flag-outline" - }, - { - "code": "0xf42f", - "name": "ios-flame" - }, - { - "code": "0xf42e", - "name": "ios-flame-outline" - }, - { - "code": "0xf431", - "name": "ios-flask" - }, - { - "code": "0xf430", - "name": "ios-flask-outline" - }, - { - "code": "0xf433", - "name": "ios-flower" - }, - { - "code": "0xf432", - "name": "ios-flower-outline" - }, - { - "code": "0xf435", - "name": "ios-folder" - }, - { - "code": "0xf434", - "name": "ios-folder-outline" - }, - { - "code": "0xf437", - "name": "ios-football" - }, - { - "code": "0xf436", - "name": "ios-football-outline" - }, - { - "code": "0xf439", - "name": "ios-game-controller-a" - }, - { - "code": "0xf438", - "name": "ios-game-controller-a-outline" - }, - { - "code": "0xf43b", - "name": "ios-game-controller-b" - }, - { - "code": "0xf43a", - "name": "ios-game-controller-b-outline" - }, - { - "code": "0xf43d", - "name": "ios-gear" - }, - { - "code": "0xf43c", - "name": "ios-gear-outline" - }, - { - "code": "0xf43f", - "name": "ios-glasses" - }, - { - "code": "0xf43e", - "name": "ios-glasses-outline" - }, - { - "code": "0xf441", - "name": "ios-grid-view" - }, - { - "code": "0xf440", - "name": "ios-grid-view-outline" - }, - { - "code": "0xf443", - "name": "ios-heart" - }, - { - "code": "0xf442", - "name": "ios-heart-outline" - }, - { - "code": "0xf446", - "name": "ios-help" - }, - { - "code": "0xf444", - "name": "ios-help-empty" - }, - { - "code": "0xf445", - "name": "ios-help-outline" - }, - { - "code": "0xf448", - "name": "ios-home" - }, - { - "code": "0xf447", - "name": "ios-home-outline" - }, - { - "code": "0xf44a", - "name": "ios-infinite" - }, - { - "code": "0xf449", - "name": "ios-infinite-outline" - }, - { - "code": "0xf44d", - "name": "ios-information" - }, - { - "code": "0xf44b", - "name": "ios-information-empty" - }, - { - "code": "0xf44c", - "name": "ios-information-outline" - }, - { - "code": "0xf44e", - "name": "ios-ionic-outline" - }, - { - "code": "0xf450", - "name": "ios-keypad" - }, - { - "code": "0xf44f", - "name": "ios-keypad-outline" - }, - { - "code": "0xf452", - "name": "ios-lightbulb" - }, - { - "code": "0xf451", - "name": "ios-lightbulb-outline" - }, - { - "code": "0xf454", - "name": "ios-list" - }, - { - "code": "0xf453", - "name": "ios-list-outline" - }, - { - "code": "0xf456", - "name": "ios-location" - }, - { - "code": "0xf455", - "name": "ios-location-outline" - }, - { - "code": "0xf458", - "name": "ios-locked" - }, - { - "code": "0xf457", - "name": "ios-locked-outline" - }, - { - "code": "0xf45a", - "name": "ios-loop" - }, - { - "code": "0xf459", - "name": "ios-loop-strong" - }, - { - "code": "0xf45c", - "name": "ios-medical" - }, - { - "code": "0xf45b", - "name": "ios-medical-outline" - }, - { - "code": "0xf45e", - "name": "ios-medkit" - }, - { - "code": "0xf45d", - "name": "ios-medkit-outline" - }, - { - "code": "0xf461", - "name": "ios-mic" - }, - { - "code": "0xf45f", - "name": "ios-mic-off" - }, - { - "code": "0xf460", - "name": "ios-mic-outline" - }, - { - "code": "0xf464", - "name": "ios-minus" - }, - { - "code": "0xf462", - "name": "ios-minus-empty" - }, - { - "code": "0xf463", - "name": "ios-minus-outline" - }, - { - "code": "0xf466", - "name": "ios-monitor" - }, - { - "code": "0xf465", - "name": "ios-monitor-outline" - }, - { - "code": "0xf468", - "name": "ios-moon" - }, - { - "code": "0xf467", - "name": "ios-moon-outline" - }, - { - "code": "0xf46a", - "name": "ios-more" - }, - { - "code": "0xf469", - "name": "ios-more-outline" - }, - { - "code": "0xf46b", - "name": "ios-musical-note" - }, - { - "code": "0xf46c", - "name": "ios-musical-notes" - }, - { - "code": "0xf46e", - "name": "ios-navigate" - }, - { - "code": "0xf46d", - "name": "ios-navigate-outline" - }, - { - "code": "0xf470", - "name": "ios-nutrition" - }, - { - "code": "0xf46f", - "name": "ios-nutrition-outline" - }, - { - "code": "0xf472", - "name": "ios-paper" - }, - { - "code": "0xf471", - "name": "ios-paper-outline" - }, - { - "code": "0xf474", - "name": "ios-paperplane" - }, - { - "code": "0xf473", - "name": "ios-paperplane-outline" - }, - { - "code": "0xf476", - "name": "ios-partlysunny" - }, - { - "code": "0xf475", - "name": "ios-partlysunny-outline" - }, - { - "code": "0xf478", - "name": "ios-pause" - }, - { - "code": "0xf477", - "name": "ios-pause-outline" - }, - { - "code": "0xf47a", - "name": "ios-paw" - }, - { - "code": "0xf479", - "name": "ios-paw-outline" - }, - { - "code": "0xf47c", - "name": "ios-people" - }, - { - "code": "0xf47b", - "name": "ios-people-outline" - }, - { - "code": "0xf47e", - "name": "ios-person" - }, - { - "code": "0xf47d", - "name": "ios-person-outline" - }, - { - "code": "0xf480", - "name": "ios-personadd" - }, - { - "code": "0xf47f", - "name": "ios-personadd-outline" - }, - { - "code": "0xf482", - "name": "ios-photos" - }, - { - "code": "0xf481", - "name": "ios-photos-outline" - }, - { - "code": "0xf484", - "name": "ios-pie" - }, - { - "code": "0xf483", - "name": "ios-pie-outline" - }, - { - "code": "0xf486", - "name": "ios-pint" - }, - { - "code": "0xf485", - "name": "ios-pint-outline" - }, - { - "code": "0xf488", - "name": "ios-play" - }, - { - "code": "0xf487", - "name": "ios-play-outline" - }, - { - "code": "0xf48b", - "name": "ios-plus" - }, - { - "code": "0xf489", - "name": "ios-plus-empty" - }, - { - "code": "0xf48a", - "name": "ios-plus-outline" - }, - { - "code": "0xf48d", - "name": "ios-pricetag" - }, - { - "code": "0xf48c", - "name": "ios-pricetag-outline" - }, - { - "code": "0xf48f", - "name": "ios-pricetags" - }, - { - "code": "0xf48e", - "name": "ios-pricetags-outline" - }, - { - "code": "0xf491", - "name": "ios-printer" - }, - { - "code": "0xf490", - "name": "ios-printer-outline" - }, - { - "code": "0xf493", - "name": "ios-pulse" - }, - { - "code": "0xf492", - "name": "ios-pulse-strong" - }, - { - "code": "0xf495", - "name": "ios-rainy" - }, - { - "code": "0xf494", - "name": "ios-rainy-outline" - }, - { - "code": "0xf497", - "name": "ios-recording" - }, - { - "code": "0xf496", - "name": "ios-recording-outline" - }, - { - "code": "0xf499", - "name": "ios-redo" - }, - { - "code": "0xf498", - "name": "ios-redo-outline" - }, - { - "code": "0xf49c", - "name": "ios-refresh" - }, - { - "code": "0xf49a", - "name": "ios-refresh-empty" - }, - { - "code": "0xf49b", - "name": "ios-refresh-outline" - }, - { - "code": "0xf49d", - "name": "ios-reload" - }, - { - "code": "0xf49f", - "name": "ios-reverse-camera" - }, - { - "code": "0xf49e", - "name": "ios-reverse-camera-outline" - }, - { - "code": "0xf4a1", - "name": "ios-rewind" - }, - { - "code": "0xf4a0", - "name": "ios-rewind-outline" - }, - { - "code": "0xf4a3", - "name": "ios-rose" - }, - { - "code": "0xf4a2", - "name": "ios-rose-outline" - }, - { - "code": "0xf4a5", - "name": "ios-search" - }, - { - "code": "0xf4a4", - "name": "ios-search-strong" - }, - { - "code": "0xf4a7", - "name": "ios-settings" - }, - { - "code": "0xf4a6", - "name": "ios-settings-strong" - }, - { - "code": "0xf4a9", - "name": "ios-shuffle" - }, - { - "code": "0xf4a8", - "name": "ios-shuffle-strong" - }, - { - "code": "0xf4ab", - "name": "ios-skipbackward" - }, - { - "code": "0xf4aa", - "name": "ios-skipbackward-outline" - }, - { - "code": "0xf4ad", - "name": "ios-skipforward" - }, - { - "code": "0xf4ac", - "name": "ios-skipforward-outline" - }, - { - "code": "0xf4ae", - "name": "ios-snowy" - }, - { - "code": "0xf4b0", - "name": "ios-speedometer" - }, - { - "code": "0xf4af", - "name": "ios-speedometer-outline" - }, - { - "code": "0xf4b3", - "name": "ios-star" - }, - { - "code": "0xf4b1", - "name": "ios-star-half" - }, - { - "code": "0xf4b2", - "name": "ios-star-outline" - }, - { - "code": "0xf4b5", - "name": "ios-stopwatch" - }, - { - "code": "0xf4b4", - "name": "ios-stopwatch-outline" - }, - { - "code": "0xf4b7", - "name": "ios-sunny" - }, - { - "code": "0xf4b6", - "name": "ios-sunny-outline" - }, - { - "code": "0xf4b9", - "name": "ios-telephone" - }, - { - "code": "0xf4b8", - "name": "ios-telephone-outline" - }, - { - "code": "0xf4bb", - "name": "ios-tennisball" - }, - { - "code": "0xf4ba", - "name": "ios-tennisball-outline" - }, - { - "code": "0xf4bd", - "name": "ios-thunderstorm" - }, - { - "code": "0xf4bc", - "name": "ios-thunderstorm-outline" - }, - { - "code": "0xf4bf", - "name": "ios-time" - }, - { - "code": "0xf4be", - "name": "ios-time-outline" - }, - { - "code": "0xf4c1", - "name": "ios-timer" - }, - { - "code": "0xf4c0", - "name": "ios-timer-outline" - }, - { - "code": "0xf4c3", - "name": "ios-toggle" - }, - { - "code": "0xf4c2", - "name": "ios-toggle-outline" - }, - { - "code": "0xf4c5", - "name": "ios-trash" - }, - { - "code": "0xf4c4", - "name": "ios-trash-outline" - }, - { - "code": "0xf4c7", - "name": "ios-undo" - }, - { - "code": "0xf4c6", - "name": "ios-undo-outline" - }, - { - "code": "0xf4c9", - "name": "ios-unlocked" - }, - { - "code": "0xf4c8", - "name": "ios-unlocked-outline" - }, - { - "code": "0xf4cb", - "name": "ios-upload" - }, - { - "code": "0xf4ca", - "name": "ios-upload-outline" - }, - { - "code": "0xf4cd", - "name": "ios-videocam" - }, - { - "code": "0xf4cc", - "name": "ios-videocam-outline" - }, - { - "code": "0xf4ce", - "name": "ios-volume-high" - }, - { - "code": "0xf4cf", - "name": "ios-volume-low" - }, - { - "code": "0xf4d1", - "name": "ios-wineglass" - }, - { - "code": "0xf4d0", - "name": "ios-wineglass-outline" - }, - { - "code": "0xf4d3", - "name": "ios-world" - }, - { - "code": "0xf4d2", - "name": "ios-world-outline" - }, - { - "code": "0xf1f9", - "name": "ipad" - }, - { - "code": "0xf1fa", - "name": "iphone" - }, - { - "code": "0xf1fb", - "name": "ipod" - }, - { - "code": "0xf295", - "name": "jet" - }, - { - "code": "0xf296", - "name": "key" - }, - { - "code": "0xf297", - "name": "knife" - }, - { - "code": "0xf1fc", - "name": "laptop" - }, - { - "code": "0xf1fd", - "name": "leaf" - }, - { - "code": "0xf298", - "name": "levels" - }, - { - "code": "0xf299", - "name": "lightbulb" - }, - { - "code": "0xf1fe", - "name": "link" - }, - { - "code": "0xf29a", - "name": "load-a" - }, - { - "code": "0xf29b", - "name": "load-b" - }, - { - "code": "0xf29c", - "name": "load-c" - }, - { - "code": "0xf29d", - "name": "load-d" - }, - { - "code": "0xf1ff", - "name": "location" - }, - { - "code": "0xf4d4", - "name": "lock-combination" - }, - { - "code": "0xf200", - "name": "locked" - }, - { - "code": "0xf29e", - "name": "log-in" - }, - { - "code": "0xf29f", - "name": "log-out" - }, - { - "code": "0xf201", - "name": "loop" - }, - { - "code": "0xf2a0", - "name": "magnet" - }, - { - "code": "0xf2a1", - "name": "male" - }, - { - "code": "0xf202", - "name": "man" - }, - { - "code": "0xf203", - "name": "map" - }, - { - "code": "0xf2a2", - "name": "medkit" - }, - { - "code": "0xf33f", - "name": "merge" - }, - { - "code": "0xf204", - "name": "mic-a" - }, - { - "code": "0xf205", - "name": "mic-b" - }, - { - "code": "0xf206", - "name": "mic-c" - }, - { - "code": "0xf209", - "name": "minus" - }, - { - "code": "0xf207", - "name": "minus-circled" - }, - { - "code": "0xf208", - "name": "minus-round" - }, - { - "code": "0xf2c1", - "name": "model-s" - }, - { - "code": "0xf20a", - "name": "monitor" - }, - { - "code": "0xf20b", - "name": "more" - }, - { - "code": "0xf340", - "name": "mouse" - }, - { - "code": "0xf20c", - "name": "music-note" - }, - { - "code": "0xf20e", - "name": "navicon" - }, - { - "code": "0xf20d", - "name": "navicon-round" - }, - { - "code": "0xf2a3", - "name": "navigate" - }, - { - "code": "0xf341", - "name": "network" - }, - { - "code": "0xf2c2", - "name": "no-smoking" - }, - { - "code": "0xf2a4", - "name": "nuclear" - }, - { - "code": "0xf342", - "name": "outlet" - }, - { - "code": "0xf4d5", - "name": "paintbrush" - }, - { - "code": "0xf4d6", - "name": "paintbucket" - }, - { - "code": "0xf2c3", - "name": "paper-airplane" - }, - { - "code": "0xf20f", - "name": "paperclip" - }, - { - "code": "0xf210", - "name": "pause" - }, - { - "code": "0xf213", - "name": "person" - }, - { - "code": "0xf211", - "name": "person-add" - }, - { - "code": "0xf212", - "name": "person-stalker" - }, - { - "code": "0xf2a5", - "name": "pie-graph" - }, - { - "code": "0xf2a6", - "name": "pin" - }, - { - "code": "0xf2a7", - "name": "pinpoint" - }, - { - "code": "0xf2a8", - "name": "pizza" - }, - { - "code": "0xf214", - "name": "plane" - }, - { - "code": "0xf343", - "name": "planet" - }, - { - "code": "0xf215", - "name": "play" - }, - { - "code": "0xf30a", - "name": "playstation" - }, - { - "code": "0xf218", - "name": "plus" - }, - { - "code": "0xf216", - "name": "plus-circled" - }, - { - "code": "0xf217", - "name": "plus-round" - }, - { - "code": "0xf344", - "name": "podium" - }, - { - "code": "0xf219", - "name": "pound" - }, - { - "code": "0xf2a9", - "name": "power" - }, - { - "code": "0xf2aa", - "name": "pricetag" - }, - { - "code": "0xf2ab", - "name": "pricetags" - }, - { - "code": "0xf21a", - "name": "printer" - }, - { - "code": "0xf345", - "name": "pull-request" - }, - { - "code": "0xf346", - "name": "qr-scanner" - }, - { - "code": "0xf347", - "name": "quote" - }, - { - "code": "0xf2ac", - "name": "radio-waves" - }, - { - "code": "0xf21b", - "name": "record" - }, - { - "code": "0xf21c", - "name": "refresh" - }, - { - "code": "0xf21e", - "name": "reply" - }, - { - "code": "0xf21d", - "name": "reply-all" - }, - { - "code": "0xf348", - "name": "ribbon-a" - }, - { - "code": "0xf349", - "name": "ribbon-b" - }, - { - "code": "0xf34a", - "name": "sad" - }, - { - "code": "0xf4d7", - "name": "sad-outline" - }, - { - "code": "0xf34b", - "name": "scissors" - }, - { - "code": "0xf21f", - "name": "search" - }, - { - "code": "0xf2ad", - "name": "settings" - }, - { - "code": "0xf220", - "name": "share" - }, - { - "code": "0xf221", - "name": "shuffle" - }, - { - "code": "0xf222", - "name": "skip-backward" - }, - { - "code": "0xf223", - "name": "skip-forward" - }, - { - "code": "0xf225", - "name": "social-android" - }, - { - "code": "0xf224", - "name": "social-android-outline" - }, - { - "code": "0xf4d9", - "name": "social-angular" - }, - { - "code": "0xf4d8", - "name": "social-angular-outline" - }, - { - "code": "0xf227", - "name": "social-apple" - }, - { - "code": "0xf226", - "name": "social-apple-outline" - }, - { - "code": "0xf2af", - "name": "social-bitcoin" - }, - { - "code": "0xf2ae", - "name": "social-bitcoin-outline" - }, - { - "code": "0xf229", - "name": "social-buffer" - }, - { - "code": "0xf228", - "name": "social-buffer-outline" - }, - { - "code": "0xf4db", - "name": "social-chrome" - }, - { - "code": "0xf4da", - "name": "social-chrome-outline" - }, - { - "code": "0xf4dd", - "name": "social-codepen" - }, - { - "code": "0xf4dc", - "name": "social-codepen-outline" - }, - { - "code": "0xf4df", - "name": "social-css3" - }, - { - "code": "0xf4de", - "name": "social-css3-outline" - }, - { - "code": "0xf22b", - "name": "social-designernews" - }, - { - "code": "0xf22a", - "name": "social-designernews-outline" - }, - { - "code": "0xf22d", - "name": "social-dribbble" - }, - { - "code": "0xf22c", - "name": "social-dribbble-outline" - }, - { - "code": "0xf22f", - "name": "social-dropbox" - }, - { - "code": "0xf22e", - "name": "social-dropbox-outline" - }, - { - "code": "0xf4e1", - "name": "social-euro" - }, - { - "code": "0xf4e0", - "name": "social-euro-outline" - }, - { - "code": "0xf231", - "name": "social-facebook" - }, - { - "code": "0xf230", - "name": "social-facebook-outline" - }, - { - "code": "0xf34d", - "name": "social-foursquare" - }, - { - "code": "0xf34c", - "name": "social-foursquare-outline" - }, - { - "code": "0xf2c4", - "name": "social-freebsd-devil" - }, - { - "code": "0xf233", - "name": "social-github" - }, - { - "code": "0xf232", - "name": "social-github-outline" - }, - { - "code": "0xf34f", - "name": "social-google" - }, - { - "code": "0xf34e", - "name": "social-google-outline" - }, - { - "code": "0xf235", - "name": "social-googleplus" - }, - { - "code": "0xf234", - "name": "social-googleplus-outline" - }, - { - "code": "0xf237", - "name": "social-hackernews" - }, - { - "code": "0xf236", - "name": "social-hackernews-outline" - }, - { - "code": "0xf4e3", - "name": "social-html5" - }, - { - "code": "0xf4e2", - "name": "social-html5-outline" - }, - { - "code": "0xf351", - "name": "social-instagram" - }, - { - "code": "0xf350", - "name": "social-instagram-outline" - }, - { - "code": "0xf4e5", - "name": "social-javascript" - }, - { - "code": "0xf4e4", - "name": "social-javascript-outline" - }, - { - "code": "0xf239", - "name": "social-linkedin" - }, - { - "code": "0xf238", - "name": "social-linkedin-outline" - }, - { - "code": "0xf4e6", - "name": "social-markdown" - }, - { - "code": "0xf4e7", - "name": "social-nodejs" - }, - { - "code": "0xf4e8", - "name": "social-octocat" - }, - { - "code": "0xf2b1", - "name": "social-pinterest" - }, - { - "code": "0xf2b0", - "name": "social-pinterest-outline" - }, - { - "code": "0xf4e9", - "name": "social-python" - }, - { - "code": "0xf23b", - "name": "social-reddit" - }, - { - "code": "0xf23a", - "name": "social-reddit-outline" - }, - { - "code": "0xf23d", - "name": "social-rss" - }, - { - "code": "0xf23c", - "name": "social-rss-outline" - }, - { - "code": "0xf4ea", - "name": "social-sass" - }, - { - "code": "0xf23f", - "name": "social-skype" - }, - { - "code": "0xf23e", - "name": "social-skype-outline" - }, - { - "code": "0xf4ec", - "name": "social-snapchat" - }, - { - "code": "0xf4eb", - "name": "social-snapchat-outline" - }, - { - "code": "0xf241", - "name": "social-tumblr" - }, - { - "code": "0xf240", - "name": "social-tumblr-outline" - }, - { - "code": "0xf2c5", - "name": "social-tux" - }, - { - "code": "0xf4ee", - "name": "social-twitch" - }, - { - "code": "0xf4ed", - "name": "social-twitch-outline" - }, - { - "code": "0xf243", - "name": "social-twitter" - }, - { - "code": "0xf242", - "name": "social-twitter-outline" - }, - { - "code": "0xf353", - "name": "social-usd" - }, - { - "code": "0xf352", - "name": "social-usd-outline" - }, - { - "code": "0xf245", - "name": "social-vimeo" - }, - { - "code": "0xf244", - "name": "social-vimeo-outline" - }, - { - "code": "0xf4f0", - "name": "social-whatsapp" - }, - { - "code": "0xf4ef", - "name": "social-whatsapp-outline" - }, - { - "code": "0xf247", - "name": "social-windows" - }, - { - "code": "0xf246", - "name": "social-windows-outline" - }, - { - "code": "0xf249", - "name": "social-wordpress" - }, - { - "code": "0xf248", - "name": "social-wordpress-outline" - }, - { - "code": "0xf24b", - "name": "social-yahoo" - }, - { - "code": "0xf24a", - "name": "social-yahoo-outline" - }, - { - "code": "0xf4f2", - "name": "social-yen" - }, - { - "code": "0xf4f1", - "name": "social-yen-outline" - }, - { - "code": "0xf24d", - "name": "social-youtube" - }, - { - "code": "0xf24c", - "name": "social-youtube-outline" - }, - { - "code": "0xf4f4", - "name": "soup-can" - }, - { - "code": "0xf4f3", - "name": "soup-can-outline" - }, - { - "code": "0xf2b2", - "name": "speakerphone" - }, - { - "code": "0xf2b3", - "name": "speedometer" - }, - { - "code": "0xf2b4", - "name": "spoon" - }, - { - "code": "0xf24e", - "name": "star" - }, - { - "code": "0xf2b5", - "name": "stats-bars" - }, - { - "code": "0xf30b", - "name": "steam" - }, - { - "code": "0xf24f", - "name": "stop" - }, - { - "code": "0xf2b6", - "name": "thermometer" - }, - { - "code": "0xf250", - "name": "thumbsdown" - }, - { - "code": "0xf251", - "name": "thumbsup" - }, - { - "code": "0xf355", - "name": "toggle" - }, - { - "code": "0xf354", - "name": "toggle-filled" - }, - { - "code": "0xf4f5", - "name": "transgender" - }, - { - "code": "0xf252", - "name": "trash-a" - }, - { - "code": "0xf253", - "name": "trash-b" - }, - { - "code": "0xf356", - "name": "trophy" - }, - { - "code": "0xf4f7", - "name": "tshirt" - }, - { - "code": "0xf4f6", - "name": "tshirt-outline" - }, - { - "code": "0xf2b7", - "name": "umbrella" - }, - { - "code": "0xf357", - "name": "university" - }, - { - "code": "0xf254", - "name": "unlocked" - }, - { - "code": "0xf255", - "name": "upload" - }, - { - "code": "0xf2b8", - "name": "usb" - }, - { - "code": "0xf256", - "name": "videocamera" - }, - { - "code": "0xf257", - "name": "volume-high" - }, - { - "code": "0xf258", - "name": "volume-low" - }, - { - "code": "0xf259", - "name": "volume-medium" - }, - { - "code": "0xf25a", - "name": "volume-mute" - }, - { - "code": "0xf358", - "name": "wand" - }, - { - "code": "0xf25b", - "name": "waterdrop" - }, - { - "code": "0xf25c", - "name": "wifi" - }, - { - "code": "0xf2b9", - "name": "wineglass" - }, - { - "code": "0xf25d", - "name": "woman" - }, - { - "code": "0xf2ba", - "name": "wrench" - }, - { - "code": "0xf30c", - "name": "xbox" - } - ] -} \ No newline at end of file diff --git a/static/ionicons-2.0.1/builder/scripts/eotlitetool.py b/static/ionicons-2.0.1/builder/scripts/eotlitetool.py deleted file mode 100644 index 1898312..0000000 --- a/static/ionicons-2.0.1/builder/scripts/eotlitetool.py +++ /dev/null @@ -1,510 +0,0 @@ -#!/usr/bin/env python -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is font utility code. -# -# The Initial Developer of the Original Code is Mozilla Corporation. -# Portions created by the Initial Developer are Copyright (C) 2009 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# John Daggett -# -# Alternatively, the contents of this file may be used under the terms of -# either the GNU General Public License Version 2 or later (the "GPL"), or -# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** */ - -# eotlitetool.py - create EOT version of OpenType font for use with IE -# -# Usage: eotlitetool.py [-o output-filename] font1 [font2 ...] -# - -# OpenType file structure -# http://www.microsoft.com/typography/otspec/otff.htm -# -# Types: -# -# BYTE 8-bit unsigned integer. -# CHAR 8-bit signed integer. -# USHORT 16-bit unsigned integer. -# SHORT 16-bit signed integer. -# ULONG 32-bit unsigned integer. -# Fixed 32-bit signed fixed-point number (16.16) -# LONGDATETIME Date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a signed 64-bit integer. -# -# SFNT Header -# -# Fixed sfnt version // 0x00010000 for version 1.0. -# USHORT numTables // Number of tables. -# USHORT searchRange // (Maximum power of 2 <= numTables) x 16. -# USHORT entrySelector // Log2(maximum power of 2 <= numTables). -# USHORT rangeShift // NumTables x 16-searchRange. -# -# Table Directory -# -# ULONG tag // 4-byte identifier. -# ULONG checkSum // CheckSum for this table. -# ULONG offset // Offset from beginning of TrueType font file. -# ULONG length // Length of this table. -# -# OS/2 Table (Version 4) -# -# USHORT version // 0x0004 -# SHORT xAvgCharWidth -# USHORT usWeightClass -# USHORT usWidthClass -# USHORT fsType -# SHORT ySubscriptXSize -# SHORT ySubscriptYSize -# SHORT ySubscriptXOffset -# SHORT ySubscriptYOffset -# SHORT ySuperscriptXSize -# SHORT ySuperscriptYSize -# SHORT ySuperscriptXOffset -# SHORT ySuperscriptYOffset -# SHORT yStrikeoutSize -# SHORT yStrikeoutPosition -# SHORT sFamilyClass -# BYTE panose[10] -# ULONG ulUnicodeRange1 // Bits 0-31 -# ULONG ulUnicodeRange2 // Bits 32-63 -# ULONG ulUnicodeRange3 // Bits 64-95 -# ULONG ulUnicodeRange4 // Bits 96-127 -# CHAR achVendID[4] -# USHORT fsSelection -# USHORT usFirstCharIndex -# USHORT usLastCharIndex -# SHORT sTypoAscender -# SHORT sTypoDescender -# SHORT sTypoLineGap -# USHORT usWinAscent -# USHORT usWinDescent -# ULONG ulCodePageRange1 // Bits 0-31 -# ULONG ulCodePageRange2 // Bits 32-63 -# SHORT sxHeight -# SHORT sCapHeight -# USHORT usDefaultChar -# USHORT usBreakChar -# USHORT usMaxContext -# -# -# The Naming Table is organized as follows: -# -# [name table header] -# [name records] -# [string data] -# -# Name Table Header -# -# USHORT format // Format selector (=0). -# USHORT count // Number of name records. -# USHORT stringOffset // Offset to start of string storage (from start of table). -# -# Name Record -# -# USHORT platformID // Platform ID. -# USHORT encodingID // Platform-specific encoding ID. -# USHORT languageID // Language ID. -# USHORT nameID // Name ID. -# USHORT length // String length (in bytes). -# USHORT offset // String offset from start of storage area (in bytes). -# -# head Table -# -# Fixed tableVersion // Table version number 0x00010000 for version 1.0. -# Fixed fontRevision // Set by font manufacturer. -# ULONG checkSumAdjustment // To compute: set it to 0, sum the entire font as ULONG, then store 0xB1B0AFBA - sum. -# ULONG magicNumber // Set to 0x5F0F3CF5. -# USHORT flags -# USHORT unitsPerEm // Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines. -# LONGDATETIME created // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer -# LONGDATETIME modified // Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer -# SHORT xMin // For all glyph bounding boxes. -# SHORT yMin -# SHORT xMax -# SHORT yMax -# USHORT macStyle -# USHORT lowestRecPPEM // Smallest readable size in pixels. -# SHORT fontDirectionHint -# SHORT indexToLocFormat // 0 for short offsets, 1 for long. -# SHORT glyphDataFormat // 0 for current format. -# -# -# -# Embedded OpenType (EOT) file format -# http://www.w3.org/Submission/EOT/ -# -# EOT version 0x00020001 -# -# An EOT font consists of a header with the original OpenType font -# appended at the end. Most of the data in the EOT header is simply a -# copy of data from specific tables within the font data. The exceptions -# are the 'Flags' field and the root string name field. The root string -# is a set of names indicating domains for which the font data can be -# used. A null root string implies the font data can be used anywhere. -# The EOT header is in little-endian byte order but the font data remains -# in big-endian order as specified by the OpenType spec. -# -# Overall structure: -# -# [EOT header] -# [EOT name records] -# [font data] -# -# EOT header -# -# ULONG eotSize // Total structure length in bytes (including string and font data) -# ULONG fontDataSize // Length of the OpenType font (FontData) in bytes -# ULONG version // Version number of this format - 0x00020001 -# ULONG flags // Processing Flags (0 == no special processing) -# BYTE fontPANOSE[10] // OS/2 Table panose -# BYTE charset // DEFAULT_CHARSET (0x01) -# BYTE italic // 0x01 if ITALIC in OS/2 Table fsSelection is set, 0 otherwise -# ULONG weight // OS/2 Table usWeightClass -# USHORT fsType // OS/2 Table fsType (specifies embedding permission flags) -# USHORT magicNumber // Magic number for EOT file - 0x504C. -# ULONG unicodeRange1 // OS/2 Table ulUnicodeRange1 -# ULONG unicodeRange2 // OS/2 Table ulUnicodeRange2 -# ULONG unicodeRange3 // OS/2 Table ulUnicodeRange3 -# ULONG unicodeRange4 // OS/2 Table ulUnicodeRange4 -# ULONG codePageRange1 // OS/2 Table ulCodePageRange1 -# ULONG codePageRange2 // OS/2 Table ulCodePageRange2 -# ULONG checkSumAdjustment // head Table CheckSumAdjustment -# ULONG reserved[4] // Reserved - must be 0 -# USHORT padding1 // Padding - must be 0 -# -# EOT name records -# -# USHORT FamilyNameSize // Font family name size in bytes -# BYTE FamilyName[FamilyNameSize] // Font family name (name ID = 1), little-endian UTF-16 -# USHORT Padding2 // Padding - must be 0 -# -# USHORT StyleNameSize // Style name size in bytes -# BYTE StyleName[StyleNameSize] // Style name (name ID = 2), little-endian UTF-16 -# USHORT Padding3 // Padding - must be 0 -# -# USHORT VersionNameSize // Version name size in bytes -# bytes VersionName[VersionNameSize] // Version name (name ID = 5), little-endian UTF-16 -# USHORT Padding4 // Padding - must be 0 -# -# USHORT FullNameSize // Full name size in bytes -# BYTE FullName[FullNameSize] // Full name (name ID = 4), little-endian UTF-16 -# USHORT Padding5 // Padding - must be 0 -# -# USHORT RootStringSize // Root string size in bytes -# BYTE RootString[RootStringSize] // Root string, little-endian UTF-16 - - -import optparse -import struct - - -class FontError(Exception): - """Error related to font handling""" - - pass - - -def multichar(str): - vals = struct.unpack("4B", str[:4]) - return (vals[0] << 24) + (vals[1] << 16) + (vals[2] << 8) + vals[3] - - -def multicharval(v): - return struct.pack( - "4B", (v >> 24) & 0xFF, (v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF - ) - - -class EOT: - EOT_VERSION = 0x00020001 - EOT_MAGIC_NUMBER = 0x504C - EOT_DEFAULT_CHARSET = 0x01 - EOT_FAMILY_NAME_INDEX = 0 # order of names in variable portion of EOT header - EOT_STYLE_NAME_INDEX = 1 - EOT_VERSION_NAME_INDEX = 2 - EOT_FULL_NAME_INDEX = 3 - EOT_NUM_NAMES = 4 - - EOT_HEADER_PACK = "<4L10B2BL2H7L18x" - - -class OpenType: - SFNT_CFF = multichar("OTTO") # Postscript CFF SFNT version - SFNT_TRUE = 0x10000 # Standard TrueType version - SFNT_APPLE = multichar("true") # Apple TrueType version - - SFNT_UNPACK = ">I4H" - TABLE_DIR_UNPACK = ">4I" - - TABLE_HEAD = multichar("head") # TrueType table tags - TABLE_NAME = multichar("name") - TABLE_OS2 = multichar("OS/2") - TABLE_GLYF = multichar("glyf") - TABLE_CFF = multichar("CFF ") - - OS2_FSSELECTION_ITALIC = 0x1 - OS2_UNPACK = ">4xH2xH22x10B4L4xH14x2L" - - HEAD_UNPACK = ">8xL" - - NAME_RECORD_UNPACK = ">6H" - NAME_ID_FAMILY = 1 - NAME_ID_STYLE = 2 - NAME_ID_UNIQUE = 3 - NAME_ID_FULL = 4 - NAME_ID_VERSION = 5 - NAME_ID_POSTSCRIPT = 6 - PLATFORM_ID_UNICODE = 0 # Mac OS uses this typically - PLATFORM_ID_MICROSOFT = 3 - ENCODING_ID_MICROSOFT_UNICODEBMP = ( - 1 # with Microsoft platformID BMP-only Unicode encoding - ) - LANG_ID_MICROSOFT_EN_US = 0x0409 # with Microsoft platformID EN US lang code - - -def eotname(ttf): - i = ttf.rfind(".") - if i != -1: - ttf = ttf[:i] - return ttf + ".eotlite" - - -def readfont(f): - data = open(f, "rb").read() - return data - - -def get_table_directory(data): - """read the SFNT header and table directory""" - datalen = len(data) - sfntsize = struct.calcsize(OpenType.SFNT_UNPACK) - if sfntsize > datalen: - raise FontError, "truncated font data" - sfntvers, numTables = struct.unpack(OpenType.SFNT_UNPACK, data[:sfntsize])[:2] - if sfntvers != OpenType.SFNT_CFF and sfntvers != OpenType.SFNT_TRUE: - raise FontError, "invalid font type" - - font = {} - font["version"] = sfntvers - font["numTables"] = numTables - - # create set of offsets, lengths for tables - table_dir_size = struct.calcsize(OpenType.TABLE_DIR_UNPACK) - if sfntsize + table_dir_size * numTables > datalen: - raise FontError, "truncated font data, table directory extends past end of data" - table_dir = {} - for i in range(0, numTables): - start = sfntsize + i * table_dir_size - end = start + table_dir_size - tag, check, bongo, dirlen = struct.unpack( - OpenType.TABLE_DIR_UNPACK, data[start:end] - ) - table_dir[tag] = {"offset": bongo, "length": dirlen, "checksum": check} - - font["tableDir"] = table_dir - - return font - - -def get_name_records(nametable): - """reads through the name records within name table""" - name = {} - # read the header - headersize = 6 - count, strOffset = struct.unpack(">2H", nametable[2:6]) - namerecsize = struct.calcsize(OpenType.NAME_RECORD_UNPACK) - if count * namerecsize + headersize > len(nametable): - raise FontError, "names exceed size of name table" - name["count"] = count - name["strOffset"] = strOffset - - # read through the name records - namerecs = {} - for i in range(0, count): - start = headersize + i * namerecsize - end = start + namerecsize - platformID, encodingID, languageID, nameID, namelen, offset = struct.unpack( - OpenType.NAME_RECORD_UNPACK, nametable[start:end] - ) - if ( - platformID != OpenType.PLATFORM_ID_MICROSOFT - or encodingID != OpenType.ENCODING_ID_MICROSOFT_UNICODEBMP - or languageID != OpenType.LANG_ID_MICROSOFT_EN_US - ): - continue - namerecs[nameID] = {"offset": offset, "length": namelen} - - name["namerecords"] = namerecs - return name - - -def make_eot_name_headers(fontdata, nameTableDir): - """extracts names from the name table and generates the names header portion of the EOT header""" - nameoffset = nameTableDir["offset"] - namelen = nameTableDir["length"] - name = get_name_records(fontdata[nameoffset : nameoffset + namelen]) - namestroffset = name["strOffset"] - namerecs = name["namerecords"] - - eotnames = ( - OpenType.NAME_ID_FAMILY, - OpenType.NAME_ID_STYLE, - OpenType.NAME_ID_VERSION, - OpenType.NAME_ID_FULL, - ) - nameheaders = [] - for nameid in eotnames: - if nameid in namerecs: - namerecord = namerecs[nameid] - noffset = namerecord["offset"] - nlen = namerecord["length"] - nformat = "%dH" % (nlen / 2) # length is in number of bytes - start = nameoffset + namestroffset + noffset - end = start + nlen - nstr = struct.unpack(">" + nformat, fontdata[start:end]) - nameheaders.append(struct.pack(" os2Dir["length"]: - raise FontError, "OS/2 table invalid length" - - os2fields = struct.unpack( - OpenType.OS2_UNPACK, fontdata[os2offset : os2offset + os2size] - ) - - panose = [] - urange = [] - codepage = [] - - weight, fsType = os2fields[:2] - panose[:10] = os2fields[2:12] - urange[:4] = os2fields[12:16] - fsSelection = os2fields[16] - codepage[:2] = os2fields[17:19] - - italic = fsSelection & OpenType.OS2_FSSELECTION_ITALIC - - # read in values from head table - headDir = tableDir[OpenType.TABLE_HEAD] - headoffset = headDir["offset"] - headsize = struct.calcsize(OpenType.HEAD_UNPACK) - - if headsize > headDir["length"]: - raise FontError, "head table invalid length" - - headfields = struct.unpack( - OpenType.HEAD_UNPACK, fontdata[headoffset : headoffset + headsize] - ) - checkSumAdjustment = headfields[0] - - # make name headers - nameheaders = make_eot_name_headers(fontdata, tableDir[OpenType.TABLE_NAME]) - rootstring = make_root_string() - - # calculate the total eot size - eotSize = ( - struct.calcsize(EOT.EOT_HEADER_PACK) - + len(nameheaders) - + len(rootstring) - + fontDataSize - ) - fixed = struct.pack( - EOT.EOT_HEADER_PACK, - *( - [eotSize, fontDataSize, version, flags] - + panose - + [charset, italic] - + [weight, fsType, magicNumber] - + urange - + codepage - + [checkSumAdjustment] - ) - ) - - return "".join((fixed, nameheaders, rootstring)) - - -def write_eot_font(eot, header, data): - open(eot, "wb").write("".join((header, data))) - return - - -def main(): - - # deal with options - p = optparse.OptionParser() - p.add_option("--output", "-o", default="world") - options, args = p.parse_args() - - # iterate over font files - for f in args: - data = readfont(f) - if len(data) == 0: - print "Error reading %s" % f - else: - eot = eotname(f) - header = make_eot_header(data) - write_eot_font(eot, header, data) - - -if __name__ == "__main__": - main() diff --git a/static/ionicons-2.0.1/builder/scripts/generate_font.py b/static/ionicons-2.0.1/builder/scripts/generate_font.py deleted file mode 100755 index 2987942..0000000 --- a/static/ionicons-2.0.1/builder/scripts/generate_font.py +++ /dev/null @@ -1,190 +0,0 @@ -# Font generation script from FontCustom -# https://github.com/FontCustom/fontcustom/ -# http://fontcustom.com/ - -import fontforge -import os -import md5 -import subprocess -import tempfile -import json -import copy - -SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__)) -INPUT_SVG_DIR = os.path.join(SCRIPT_PATH, "..", "..", "src") -OUTPUT_FONT_DIR = os.path.join(SCRIPT_PATH, "..", "..", "fonts") -MANIFEST_PATH = os.path.join(SCRIPT_PATH, "..", "manifest.json") -BUILD_DATA_PATH = os.path.join(SCRIPT_PATH, "..", "build_data.json") -AUTO_WIDTH = True -KERNING = 15 - -cp = 0xF100 -m = md5.new() - -f = fontforge.font() -f.encoding = "UnicodeFull" -f.design_size = 16 -f.em = 512 -f.ascent = 448 -f.descent = 64 - -manifest_file = open(MANIFEST_PATH, "r") -manifest_data = json.loads(manifest_file.read()) -manifest_file.close() -print "Load Manifest, Icons: %s" % (len(manifest_data["icons"])) - -build_data = copy.deepcopy(manifest_data) -build_data["icons"] = [] - -font_name = manifest_data["name"] -m.update(font_name + ";") -m.update(manifest_data["prefix"] + ";") - -for dirname, dirnames, filenames in os.walk(INPUT_SVG_DIR): - for filename in filenames: - name, ext = os.path.splitext(filename) - filePath = os.path.join(dirname, filename) - size = os.path.getsize(filePath) - - if ext in [".svg", ".eps"]: - - # see if this file is already in the manifest - chr_code = None - for ionicon in manifest_data["icons"]: - if ionicon["name"] == name: - chr_code = ionicon["code"] - break - - if chr_code is None: - # this is a new src icon - print "New Icon: \n - %s" % (name) - - while True: - chr_code = "0x%x" % (cp) - already_exists = False - for ionicon in manifest_data["icons"]: - if ionicon.get("code") == chr_code: - already_exists = True - cp += 1 - chr_code = "0x%x" % (cp) - continue - if not already_exists: - break - - print " - %s" % chr_code - manifest_data["icons"].append({"name": name, "code": chr_code}) - - build_data["icons"].append({"name": name, "code": chr_code}) - - if ext in [".svg"]: - # hack removal of tags - svgfile = open(filePath, "r+") - tmpsvgfile = tempfile.NamedTemporaryFile(suffix=ext, delete=False) - svgtext = svgfile.read() - svgfile.seek(0) - - # replace the tags with 'nothing' - svgtext = svgtext.replace("", "") - svgtext = svgtext.replace("", "") - - tmpsvgfile.file.write(svgtext) - - svgfile.close() - tmpsvgfile.file.close() - - filePath = tmpsvgfile.name - # end hack - - m.update(name + str(size) + ";") - glyph = f.createChar(int(chr_code, 16)) - glyph.importOutlines(filePath) - - # if we created a temporary file, let's clean it up - if tmpsvgfile: - os.unlink(tmpsvgfile.name) - - # set glyph size explicitly or automatically depending on autowidth - if AUTO_WIDTH: - glyph.left_side_bearing = glyph.right_side_bearing = 0 - glyph.round() - - # resize glyphs if autowidth is enabled - if AUTO_WIDTH: - f.autoWidth(0, 0, 512) - - fontfile = "%s/ionicons" % (OUTPUT_FONT_DIR) - -build_hash = m.hexdigest() - -if build_hash == manifest_data.get("build_hash"): - print "Source files unchanged, did not rebuild fonts" - -else: - manifest_data["build_hash"] = build_hash - - f.fontname = font_name - f.familyname = font_name - f.fullname = font_name - f.generate(fontfile + ".ttf") - f.generate(fontfile + ".svg") - - # Fix SVG header for webkit - # from: https://github.com/fontello/font-builder/blob/master/bin/fontconvert.py - svgfile = open(fontfile + ".svg", "r+") - svgtext = svgfile.read() - svgfile.seek(0) - svgfile.write( - svgtext.replace("""""", """""") - ) - svgfile.close() - - scriptPath = os.path.dirname(os.path.realpath(__file__)) - try: - subprocess.Popen( - [scriptPath + "/sfnt2woff", fontfile + ".ttf"], stdout=subprocess.PIPE - ) - except OSError: - # If the local version of sfnt2woff fails (i.e., on Linux), try to use the - # global version. This allows us to avoid forcing OS X users to compile - # sfnt2woff from source, simplifying install. - subprocess.call(["sfnt2woff", fontfile + ".ttf"]) - - # eotlitetool.py script to generate IE7-compatible .eot fonts - subprocess.call( - "python " - + scriptPath - + "/eotlitetool.py " - + fontfile - + ".ttf -o " - + fontfile - + ".eot", - shell=True, - ) - subprocess.call("mv " + fontfile + ".eotlite " + fontfile + ".eot", shell=True) - - # Hint the TTF file - subprocess.call( - "ttfautohint -s -f -n " - + fontfile - + ".ttf " - + fontfile - + "-hinted.ttf > /dev/null 2>&1 && mv " - + fontfile - + "-hinted.ttf " - + fontfile - + ".ttf", - shell=True, - ) - - manifest_data["icons"] = sorted(manifest_data["icons"], key=lambda k: k["name"]) - build_data["icons"] = sorted(build_data["icons"], key=lambda k: k["name"]) - - print "Save Manifest, Icons: %s" % (len(manifest_data["icons"])) - f = open(MANIFEST_PATH, "w") - f.write(json.dumps(manifest_data, indent=2, separators=(",", ": "))) - f.close() - - print "Save Build, Icons: %s" % (len(build_data["icons"])) - f = open(BUILD_DATA_PATH, "w") - f.write(json.dumps(build_data, indent=2, separators=(",", ": "))) - f.close() diff --git a/static/ionicons-2.0.1/builder/scripts/sfnt2woff b/static/ionicons-2.0.1/builder/scripts/sfnt2woff deleted file mode 100755 index 1a16944044ecd26a678ba51691674226e6b871dc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 71204 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 Z(L26L81D|Uk9WAGjmm~0QK4%g{y*c|pVa^W From 703a1a470ad1eed3746f7450cd5e5bf9c1ca8236 Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Tue, 7 Apr 2020 15:51:58 +0200 Subject: [PATCH 08/14] Added "Kurzbeschreibung" to WAM-landing page under "Applications" --- templates/index.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/templates/index.html b/templates/index.html index 5dab0dc..37796a1 100644 --- a/templates/index.html +++ b/templates/index.html @@ -19,8 +19,13 @@
{% for category, apps in app_infos.items %} -
+

{{category.label|safe}}

+ {% if category.value == "app" %} + + Kurzbeschreibung Dialog- und Visualisierungswerkzeuge für Energie und Infrastruktur (pdf) + + {% endif %}
{% for app in apps %}
From 93d98765f6fd558c2dea3a471bc660b322773f7e Mon Sep 17 00:00:00 2001 From: nesnoj Date: Thu, 9 Apr 2020 10:25:39 +0200 Subject: [PATCH 09/14] fix flake8 --- wam/settings.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wam/settings.py b/wam/settings.py index 5f17d9d..bbb4ba0 100644 --- a/wam/settings.py +++ b/wam/settings.py @@ -117,7 +117,7 @@ # Database # https://docs.djangoproject.com/en/1.11/ref/settings/#databases DJANGO_DB = config["WAM"].get("DJANGO_DB", "DEFAULT") -DATABASES = {"default": {**config["DATABASES"][DJANGO_DB],}} +DATABASES = {"default": {**config["DATABASES"][DJANGO_DB], }} # Password validation @@ -127,9 +127,9 @@ { "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator", }, - {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",}, - {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",}, - {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",}, + {"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator", }, + {"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator", }, + {"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator", }, ] From edecc87f0ae9f61cb138938c64501cefc87e4e32 Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Mon, 20 Apr 2020 13:50:27 +0200 Subject: [PATCH 10/14] Added "Kurzbeschreibung" to CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20fc7ac..445adf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,9 +19,9 @@ Here is a template for new release sections ## [Unreleased] ### Added +- Short link to Stemp-Tools on landing page ### Changed - - WAM installation instructions improved (esp. for Windows) #95 ## [0.1.3] 2019-09-19 From 2aafa233a07234bd04c3a0c7ee2bc199012ca600 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 20 Apr 2020 11:51:19 +0000 Subject: [PATCH 11/14] Bump django from 2.2.8 to 2.2.10 Bumps [django](https://github.com/django/django) from 2.2.8 to 2.2.10. - [Release notes](https://github.com/django/django/releases) - [Commits](https://github.com/django/django/compare/2.2.8...2.2.10) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index d10334b..041afd7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -django==2.2.9 +django==2.2.10 jmespath gunicorn pandas From b1f78a2b2a50889d2c08f3676a8d5078a6c31c76 Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Mon, 20 Apr 2020 13:52:56 +0200 Subject: [PATCH 12/14] Added version number to release v0.1.4 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 445adf8..3f87c47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ Here is a template for new release sections ### Removed - ``` -## [Unreleased] +## [0.1.4] 2020-04-20 ### Added - Short link to Stemp-Tools on landing page From c858be0a7d5e56fe019ea746b4a239d37502d61f Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Wed, 22 Apr 2020 13:47:34 +0200 Subject: [PATCH 13/14] Added missing entries to CHANGELOG.md --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 445adf8..4506f64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,9 +20,14 @@ Here is a template for new release sections ### Added - Short link to Stemp-Tools on landing page +- Sphinx Makefile +- dynamic title for meta app lists ### Changed +- Removed unnecessary ionicon files +- Black style - WAM installation instructions improved (esp. for Windows) #95 +- Assumptions and sources are deleted if category is deleted (cascade) ## [0.1.3] 2019-09-19 From d82de91a13cb8886349b1807a4b42935c8709b0c Mon Sep 17 00:00:00 2001 From: "RL-INSTITUT\\hendrik.huyskens" Date: Wed, 22 Apr 2020 13:53:04 +0200 Subject: [PATCH 14/14] Adapted security entry for django version in CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4506f64..acbb4b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,9 @@ Here is a template for new release sections - WAM installation instructions improved (esp. for Windows) #95 - Assumptions and sources are deleted if category is deleted (cascade) +### Security +- set django version to 2.2.10 + ## [0.1.3] 2019-09-19 ### Added