Ejemplo n.º 1
0
def cusacklab():
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'kD%CwAWo#D&F5n07'  # Replace this value.
    app.config['KERKO_ZOTERO_API_KEY'] = '2jTxk56Cboj4CI0a1x6HI62y'  # Replace this value.
    app.config['KERKO_ZOTERO_LIBRARY_ID'] = '180445'  # Replace this value.
    app.config['KERKO_ZOTERO_LIBRARY_TYPE'] = 'group'  # Replace this value if necessary.
    app.config['KERKO_DATA_DIR'] = str(pathlib.Path(__file__).parent / 'data' / 'kerko')
    app.config['KERKO_COMPOSER'] = Composer()

    from flask_babelex import Babel
    from flask_bootstrap import Bootstrap

    babel = Babel(app)
    bootstrap = Bootstrap(app)

    from kerko import blueprint as kerko_blueprint

    app.register_blueprint(kerko_blueprint, url_prefix='/bibliography')
from flask import Flask
from kerko.composer import Composer
from flask_babelex import Babel
from flask_bootstrap import Bootstrap
from flask import redirect, url_for
from kerko import blueprint as kerko_blueprint

app = Flask(__name__)


@app.route('/')
def home():
    return redirect(url_for('kerko.search'))


app.config['KERKO_TITLE'] = 'Positive Deviance Collaborative'
app.config['SECRET_KEY'] = 'K#d{c^#KgD=s.Kq'  # Replace this value.
app.config[
    'KERKO_ZOTERO_API_KEY'] = 'DUTwl21GgxVc74bGODObxDut'  # Replace this value.
app.config['KERKO_ZOTERO_LIBRARY_ID'] = '5778088'  # Replace this value.
app.config[
    'KERKO_ZOTERO_LIBRARY_TYPE'] = 'user'  # Replace this value if necessary.
app.config['KERKO_DATA_DIR'] = 'data/kerko'
app.config['KERKO_COMPOSER'] = Composer()
# app.config['KERKOAPP_COLLECTION_FACETS']= 'LKGKEMQ6:110:Positive Deviance Publications;'
# app.config['KERKOAPP_EXCLUDE_DEFAULT_FACETS'] = 'facet_tag'
# app.config['KERKO_ZOTERO_WAIT'] = '20'

babel = Babel(app)
bootstrap = Bootstrap(app)
app.register_blueprint(kerko_blueprint, url_prefix='/bibliography')
Ejemplo n.º 3
0
    def __init__(self):
        app_dir = pathlib.Path(env.str('FLASK_APP')).parent.absolute()

        self.check_deprecated_options()

        self.SECRET_KEY = env.str('SECRET_KEY')
        self.EXPLAIN_TEMPLATE_LOADING = False
        self.PROXY_FIX = env.bool('PROXY_FIX', False)
        self.BABEL_DEFAULT_LOCALE = env.str('BABEL_DEFAULT_LOCALE', 'en')
        self.BABEL_DEFAULT_TIMEZONE = env.str('BABEL_DEFAULT_TIMEZONE', 'UTC')

        # Set Kerko variables from the environment. Some are deliberately omitted
        # because it would make more sense to set them in the app's Config object
        # directly.
        self.KERKO_TITLE = env.str('KERKO_TITLE', _("Kerko App"))
        self.KERKO_DATA_DIR = env.path('KERKO_DATA_DIR',
                                       str(app_dir / 'data' / 'kerko'))
        self.KERKO_WHOOSH_LANGUAGE = env.str('KERKO_WHOOSH_LANGUAGE', 'en')
        self.KERKO_ZOTERO_LOCALE = env.str('KERKO_ZOTERO_LOCALE', 'en-US')
        self.KERKO_ZOTERO_API_KEY = env.str('KERKO_ZOTERO_API_KEY')
        self.KERKO_ZOTERO_LIBRARY_ID = env.str('KERKO_ZOTERO_LIBRARY_ID')
        self.KERKO_ZOTERO_LIBRARY_TYPE = env.str('KERKO_ZOTERO_LIBRARY_TYPE')
        self.KERKO_ZOTERO_MAX_ATTEMPTS = env.int('KERKO_ZOTERO_MAX_ATTEMPTS',
                                                 10)
        self.KERKO_ZOTERO_WAIT = env.int('KERKO_ZOTERO_WAIT',
                                         120)  # In seconds.
        self.KERKO_ZOTERO_BATCH_SIZE = env.int('KERKO_ZOTERO_BATCH_SIZE', 100)
        self.KERKO_PAGE_LEN = env.int('KERKO_PAGE_LEN', 20)
        self.KERKO_PAGER_LINKS = env.int('KERKO_PAGER_LINKS', 4)
        self.KERKO_CSL_STYLE = env.str('KERKO_CSL_STYLE', 'apa')
        self.KERKO_RESULTS_ABSTRACTS = env.bool('KERKO_RESULTS_ABSTRACTS',
                                                False)
        self.KERKO_RESULTS_ABSTRACTS_TOGGLER = env.bool(
            'KERKO_RESULTS_ABSTRACTS_TOGGLER', True)
        self.KERKO_FACET_COLLAPSING = env.bool('KERKO_FACET_COLLAPSING', False)
        self.KERKO_PRINT_ITEM_LINK = env.bool('KERKO_PRINT_ITEM_LINK', False)
        self.KERKO_PRINT_CITATIONS_LINK = env.bool(
            'KERKO_PRINT_CITATIONS_LINK', False)
        self.KERKO_PRINT_CITATIONS_MAX_COUNT = env.int(
            'KERKO_PRINT_CITATIONS_MAX_COUNT', 0)
        self.KERKO_DOWNLOAD_CITATIONS_LINK = env.bool(
            'KERKO_DOWNLOAD_CITATIONS_LINK', True)
        self.KERKO_DOWNLOAD_CITATIONS_MAX_COUNT = env.int(
            'KERKO_DOWNLOAD_CITATIONS_MAX_COUNT', 0)
        self.KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW = env.bool(
            'KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW', False)
        self.KERKO_RELATIONS_INITIAL_LIMIT = env.int(
            'KERKO_RELATIONS_INITIAL_LIMIT', 5)

        self.KERKO_COMPOSER = Composer(
            whoosh_language=self.KERKO_WHOOSH_LANGUAGE,
            exclude_default_scopes=env.list('KERKOAPP_EXCLUDE_DEFAULT_SCOPES',
                                            []),
            exclude_default_fields=env.list('KERKOAPP_EXCLUDE_DEFAULT_FIELDS',
                                            []),
            exclude_default_facets=env.list('KERKOAPP_EXCLUDE_DEFAULT_FACETS',
                                            []),
            exclude_default_sorts=env.list('KERKOAPP_EXCLUDE_DEFAULT_SORTS',
                                           []),
            exclude_default_citation_formats=env.list(
                'KERKOAPP_EXCLUDE_DEFAULT_CITATION_FORMATS', []),
            exclude_default_badges=env.list('KERKOAPP_EXCLUDE_DEFAULT_BADGES',
                                            []),
            default_item_include_re=env.str('KERKOAPP_ITEM_INCLUDE_RE', ''),
            default_item_exclude_re=env.str('KERKOAPP_ITEM_EXCLUDE_RE', ''),
            default_tag_include_re=env.str(
                'KERKOAPP_TAG_INCLUDE_RE',
                env.str('KERKOAPP_TAG_WHITELIST_RE', '')),
            default_tag_exclude_re=env.str(
                'KERKOAPP_TAG_EXCLUDE_RE',
                env.str('KERKOAPP_TAG_BLACKLIST_RE', r'^_')),
            default_child_include_re=env.str(
                'KERKOAPP_CHILD_INCLUDE_RE',
                env.str('KERKOAPP_CHILD_WHITELIST_RE', '')),
            default_child_exclude_re=env.str(
                'KERKOAPP_CHILD_EXCLUDE_RE',
                env.str('KERKOAPP_CHILD_BLACKLIST_RE', r'^_')),
            mime_types=env.list('KERKOAPP_MIME_TYPES', ['application/pdf']),
        )

        # Add collection facets.
        collection_spec = env.collection_spec('KERKOAPP_COLLECTION_FACETS',
                                              None)
        if collection_spec:
            for collection_key, weight, title in collection_spec:
                self.KERKO_COMPOSER.add_facet(
                    CollectionFacetSpec(
                        title=title,
                        weight=int(weight),
                        collection_key=collection_key,
                    ))
Ejemplo n.º 4
0
class Config():
    app_dir = pathlib.Path(env.str('FLASK_APP')).parent.absolute()

    # Get configuration values from the environment.
    SECRET_KEY = env.str('SECRET_KEY')
    KERKO_ZOTERO_API_KEY = env.str('KERKO_ZOTERO_API_KEY')
    KERKO_ZOTERO_LIBRARY_ID = env.str('KERKO_ZOTERO_LIBRARY_ID')
    KERKO_ZOTERO_LIBRARY_TYPE = env.str('KERKO_ZOTERO_LIBRARY_TYPE')
    KERKO_DATA_DIR = env.str('KERKO_DATA_DIR', str(app_dir / 'data' / 'kerko'))

    # Set other configuration variables.
    LOGGING_HANDLER = 'default'
    EXPLAIN_TEMPLATE_LOADING = False

    LIBSASS_INCLUDES = [
        str(pathlib.Path(__file__).parent.parent / 'static' / 'src' / 'vendor' / 'bootstrap' / 'scss'),
        str(pathlib.Path(__file__).parent.parent / 'static' / 'src' / 'vendor' / '@fortawesome' / 'fontawesome-free' / 'scss'),
    ]

    BABEL_DEFAULT_LOCALE = 'en_GB'
    KERKO_WHOOSH_LANGUAGE = 'en'
    KERKO_ZOTERO_LOCALE = 'en-GB'

    HOME_URL = 'https://adaptdev.info'
    HOME_TITLE = _("Adaptive Management in International Development")
    # HOME_SUBTITLE = _("...")
    # ABOUT_URL = 'https://example.com'

    NAV_TITLE = _("Library")
    KERKO_TITLE = _("Library – Adaptive Management in International Development")

    KERKO_PRINT_ITEM_LINK = True
    KERKO_PRINT_CITATIONS_LINK = True
    KERKO_RESULTS_FIELDS = ['id', 'attachments', 'bib', 'coins', 'data', 'preview', 'url']
    KERKO_RESULTS_ABSTRACTS = True
    KERKO_RESULTS_ABSTRACTS_MAX_LENGTH = 500
    KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY = 40
    KERKO_TEMPLATE_BASE = 'app/base.html.jinja2'
    KERKO_TEMPLATE_LAYOUT = 'app/layout.html.jinja2'
    KERKO_TEMPLATE_SEARCH = 'app/search.html.jinja2'
    KERKO_TEMPLATE_SEARCH_ITEM = 'app/search-item.html.jinja2'
    KERKO_TEMPLATE_ITEM = 'app/item.html.jinja2'
    KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW = True
    KERKO_RELATIONS_INITIAL_LIMIT = 50

    # CAUTION: The URL's query string must be changed after any edit to the CSL
    # style, otherwise zotero.org might still use a previously cached version of
    # the file.
    KERKO_CSL_STYLE = 'https://docs.edtechhub.org/static/dist/csl/eth_apa.xml?202012301815'

    KERKO_COMPOSER = Composer(
        whoosh_language=KERKO_WHOOSH_LANGUAGE,
        exclude_default_facets=['facet_tag', 'facet_link'],
        exclude_default_fields=['data', 'text_docs'],
        exclude_default_scopes=['metadata', 'fulltext'],
        default_child_include_re='^(_publish|publishPDF)$',
        default_child_exclude_re='',
    )

    # Replace the default 'data' extractor to strip unwanted data from the Extra field.
    KERKO_COMPOSER.add_field(
        FieldSpec(
            key='data',
            field_type=STORED,
            extractor=extractors.TransformerExtractor(
                extractor=extractors.RawDataExtractor(),
                transformers=[extra_field_cleaner]
            ),
            codec=codecs.JSONFieldCodec()
        )
    )

    # Add field for storing the formatted item preview used on search result
    # pages. This relies on the CSL style's in-text citation formatting and only
    # makes sense using our custom CSL style!
    KERKO_COMPOSER.add_field(
        FieldSpec(
            key='preview',
            field_type=STORED,
            extractor=extractors.TransformerExtractor(
                extractor=extractors.ItemExtractor(key='citation', format_='citation'),
                # Zotero wraps the citation in a <span> element (most probably
                # because it expects the 'citation' format to be used in-text),
                # but that <span> has to be removed because our custom CSL style
                # causes <div>s to be nested within. Let's replace that <span>
                # with the same markup that the 'bib' format usually provides.
                transformers=[
                    lambda value: re.sub(r'^<span>', '<div class="csl-entry">', value, count=1),
                    lambda value: re.sub(r'</span>$', '</div>', value, count=1),
                ]
            )
        )
    )

    # Add extractors for the 'alternateId' field.
    KERKO_COMPOSER.fields['alternateId'].extractor.extractors.append(
        extractors.TransformerExtractor(
            extractor=extractors.ItemDataExtractor(key='extra'),
            transformers=[
                transformers.find(
                    regex=r'^\s*EdTechHub.ItemAlsoKnownAs\s*:\s*(.*)$',
                    flags=re.IGNORECASE | re.MULTILINE,
                    max_matches=1,
                ),
                transformers.split(sep=';'),
            ]
        )
    )
    KERKO_COMPOSER.fields['alternateId'].extractor.extractors.append(
        extractors.TransformerExtractor(
            extractor=extractors.ItemDataExtractor(key='extra'),
            transformers=[
                transformers.find(
                    regex=r'^\s*KerkoCite.ItemAlsoKnownAs\s*:\s*(.*)$',
                    flags=re.IGNORECASE | re.MULTILINE,
                    max_matches=1,
                ),
                transformers.split(sep=' '),
            ]
        )
    )
    KERKO_COMPOSER.fields['alternateId'].extractor.extractors.append(
        extractors.TransformerExtractor(
            extractor=extractors.ItemDataExtractor(key='extra'),
            transformers=[
                transformers.find(
                    regex=r'^\s*shortDOI\s*:\s*(\S+)\s*$',
                    flags=re.IGNORECASE | re.MULTILINE,
                    max_matches=0,
                ),
            ]
        )
    )

    # Themes facet.
    KERKO_COMPOSER.add_facet(
        CollectionFacetSpec(
            key='facet_theme',
            filter_key='theme',
            title=_('Theme'),
            weight=40,
            collection_key='Z7A9H37R',
        )
    )
Ejemplo n.º 5
0
    def __init__(self):
        app_dir = pathlib.Path(env.str('FLASK_APP')).parent.absolute()

        # Get configuration values from the environment.
        self.SECRET_KEY = env.str('SECRET_KEY')
        self.KERKO_ZOTERO_API_KEY = env.str('KERKO_ZOTERO_API_KEY')
        self.KERKO_ZOTERO_LIBRARY_ID = env.str('KERKO_ZOTERO_LIBRARY_ID')
        self.KERKO_ZOTERO_LIBRARY_TYPE = env.str('KERKO_ZOTERO_LIBRARY_TYPE')
        self.KERKO_DATA_DIR = env.str('KERKO_DATA_DIR',
                                      str(app_dir / 'data' / 'kerko'))

        # Set other configuration variables.
        self.LOGGING_HANDLER = 'default'
        self.EXPLAIN_TEMPLATE_LOADING = False

        self.LIBSASS_INCLUDES = [
            str(
                pathlib.Path(__file__).parent.parent / 'static' / 'src' /
                'vendor' / 'bootstrap' / 'scss'),
            str(
                pathlib.Path(__file__).parent.parent / 'static' / 'src' /
                'vendor' / '@fortawesome' / 'fontawesome-free' / 'scss'),
        ]

        self.BABEL_DEFAULT_LOCALE = 'en_GB'
        self.KERKO_WHOOSH_LANGUAGE = 'en'
        self.KERKO_ZOTERO_LOCALE = 'en-GB'

        self.HOME_URL = 'https://opendeved.net'
        self.HOME_TITLE = _("Open Development & Education")
        # self.HOME_SUBTITLE = _("...")

        self.ABOUT_URL = 'https://opendeved.net/about/'
        self.BLOG_URL = 'https://opendeved.net/'
        self.JOBS_URL = 'https://opendeved.net/jobs/'
        self.PROGRAMMES_URL = 'https://opendeved.net/programmes/'
        self.CONTACTUS_URL = 'https://opendeved.net/contact-us/'

        self.NAV_TITLE = _("Evidence Library")
        self.KERKO_TITLE = _("Evidence Library – Open Development & Education")
        self.KERKO_PRINT_ITEM_LINK = True
        self.KERKO_PRINT_CITATIONS_LINK = True
        self.KERKO_RESULTS_FIELDS = [
            'id', 'attachments', 'bib', 'coins', 'data', 'preview', 'url'
        ]
        self.KERKO_RESULTS_ABSTRACTS = True
        self.KERKO_RESULTS_ABSTRACTS_MAX_LENGTH = 500
        self.KERKO_RESULTS_ABSTRACTS_MAX_LENGTH_LEEWAY = 40
        self.KERKO_TEMPLATE_LAYOUT = 'app/layout.html.jinja2'
        self.KERKO_TEMPLATE_SEARCH = 'app/search.html.jinja2'
        self.KERKO_TEMPLATE_SEARCH_ITEM = 'app/search-item.html.jinja2'
        self.KERKO_TEMPLATE_ITEM = 'app/item.html.jinja2'
        self.KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW = True
        self.KERKO_RELATIONS_INITIAL_LIMIT = 50

        # CAUTION: The URL's query string must be changed after any edit to the CSL
        # style, otherwise zotero.org might still use a previously cached version of
        # the file.
        self.KERKO_CSL_STYLE = 'https://docs.opendeved.net/static/dist/csl/eth_apa.xml?202012301815'

        self.KERKO_COMPOSER = Composer(
            whoosh_language=self.KERKO_WHOOSH_LANGUAGE,
            exclude_default_facets=[
                'facet_tag', 'facet_link', 'facet_item_type'
            ],
            exclude_default_fields=['data'],
            default_item_exclude_re=r'^_exclude$',
            default_child_include_re=r'^(_publish|publishPDF)$',
            default_child_exclude_re=r'',
        )

        # Replace the default 'data' extractor to strip unwanted data from the Extra field.
        self.KERKO_COMPOSER.add_field(
            FieldSpec(
                key='data',
                field_type=STORED,
                extractor=extractors.TransformerExtractor(
                    extractor=extractors.RawDataExtractor(),
                    transformers=[extra_field_cleaner]),
            ))

        # Add field for storing the formatted item preview used on search result
        # pages. This relies on the CSL style's in-text citation formatting and only
        # makes sense using our custom CSL style!
        self.KERKO_COMPOSER.add_field(
            FieldSpec(
                key='preview',
                field_type=STORED,
                extractor=extractors.TransformerExtractor(
                    extractor=extractors.ItemExtractor(key='citation',
                                                       format_='citation'),
                    # Zotero wraps the citation in a <span> element (most probably
                    # because it expects the 'citation' format to be used in-text),
                    # but that <span> has to be removed because our custom CSL style
                    # causes <div>s to be nested within. Let's replace that <span>
                    # with the same markup that the 'bib' format usually provides.
                    transformers=[
                        lambda value: re.sub(r'^<span>',
                                             '<div class="csl-entry">',
                                             value,
                                             count=1),
                        lambda value: re.sub(
                            r'</span>$', '</div>', value, count=1),
                    ])))

        # Add extractors for the 'alternate_id' field.
        self.KERKO_COMPOSER.fields['alternate_id'].extractor.extractors.append(
            extractors.TransformerExtractor(
                extractor=extractors.ItemDataExtractor(key='extra'),
                transformers=[
                    transformers.find(
                        regex=r'^\s*EdTechHub.ItemAlsoKnownAs\s*:\s*(.*)$',
                        flags=re.IGNORECASE | re.MULTILINE,
                        max_matches=1,
                    ),
                    transformers.split(sep=';'),
                ]))
        self.KERKO_COMPOSER.fields['alternate_id'].extractor.extractors.append(
            extractors.TransformerExtractor(
                extractor=extractors.ItemDataExtractor(key='extra'),
                transformers=[
                    transformers.find(
                        regex=r'^\s*KerkoCite.ItemAlsoKnownAs\s*:\s*(.*)$',
                        flags=re.IGNORECASE | re.MULTILINE,
                        max_matches=1,
                    ),
                    transformers.split(sep=' '),
                ]))
        self.KERKO_COMPOSER.fields['alternate_id'].extractor.extractors.append(
            extractors.TransformerExtractor(
                extractor=extractors.ItemDataExtractor(key='extra'),
                transformers=[
                    transformers.find(
                        regex=r'^\s*shortDOI\s*:\s*(\S+)\s*$',
                        flags=re.IGNORECASE | re.MULTILINE,
                        max_matches=0,
                    ),
                ]))

        self.KERKO_COMPOSER.add_facet(
            CollectionFacetSpec(
                key='facet_featured',
                filter_key='featured',
                title=_('Featured publisher'),
                weight=10,
                collection_key='JUDM2WBF',
            ))

        self.KERKO_COMPOSER.add_facet(
            CollectionFacetSpec(
                key='facet_pubtype',
                filter_key='pubtype',
                title=_('Publication type'),
                weight=20,
                collection_key='NEH6ARC4',
            ))

        self.KERKO_COMPOSER.add_facet(
            CollectionFacetSpec(
                key='facet_theme',
                filter_key='theme',
                title=_('Theme'),
                weight=30,
                collection_key='QK8NXPKZ',
            ))

        self.KERKO_COMPOSER.add_facet(
            CollectionFacetSpec(
                key='facet_location',
                filter_key='location',
                title=_('Location'),
                weight=50,
                collection_key='94GNF2EB',
            ))

        # OpenDevEd flag and badge.
        self.KERKO_COMPOSER.add_field(
            FieldSpec(
                key='opendeved',
                field_type=BOOLEAN(stored=True),
                extractor=extractors.InCollectionExtractor(
                    collection_key='JG6T4YVA'),
            ))
        self.KERKO_COMPOSER.add_badge(
            BadgeSpec(
                key='opendeved',
                field=self.KERKO_COMPOSER.fields['opendeved'],
                activator=lambda field, item: bool(item.get(field.key)),
                renderer=TemplateRenderer(
                    'app/_ode-badge.html.jinja2',
                    badge_title=_(
                        'Published by Open Development & Education')),
                weight=100,
            ))
        # "Internal document" flag and badge.
        self.KERKO_COMPOSER.add_field(
            FieldSpec(
                key='internal',
                field_type=BOOLEAN(stored=True),
                extractor=MatchesTagExtractor(pattern=r'^_internal$'),
            ))
        self.KERKO_COMPOSER.add_badge(
            BadgeSpec(
                key='internal',
                field=self.KERKO_COMPOSER.fields['internal'],
                activator=lambda field, item: item.get(field.key, False),
                renderer=TemplateRenderer('app/_text-badge.html.jinja2',
                                          text=_('Internal<br />document')),
                weight=10,
            ))
        # "Coming soon" flag and badge.
        self.KERKO_COMPOSER.add_field(
            FieldSpec(
                key='comingsoon',
                field_type=BOOLEAN(stored=True),
                extractor=MatchesTagExtractor(pattern=r'^_comingsoon$'),
            ))
        self.KERKO_COMPOSER.add_badge(
            BadgeSpec(
                key='comingsoon',
                field=self.KERKO_COMPOSER.fields['comingsoon'],
                activator=lambda field, item: item.get(field.key, False),
                renderer=TemplateRenderer('app/_text-badge.html.jinja2',
                                          text=_('Coming<br >soon')),
                weight=20,
            ))

        # Sort option based on the OpenDevEd flag.
        self.KERKO_COMPOSER.add_sort(
            SortSpec(
                key='ode_desc',
                label=_('Open Development & Education first'),
                weight=100,
                fields=[
                    self.KERKO_COMPOSER.fields['opendeved'],
                    self.KERKO_COMPOSER.fields['sort_date'],
                    self.KERKO_COMPOSER.fields['sort_creator'],
                    self.KERKO_COMPOSER.fields['sort_title']
                ],
                reverse=[
                    False,
                    True,
                    False,
                    False,
                ],
            ))
Ejemplo n.º 6
0
class Config():
    app_dir = pathlib.Path(env.str('FLASK_APP')).parent.absolute()

    SECRET_KEY = env.str('SECRET_KEY')
    EXPLAIN_TEMPLATE_LOADING = False
    PROXY_FIX = env.bool('PROXY_FIX', False)
    BABEL_DEFAULT_LOCALE = env.str('BABEL_DEFAULT_LOCALE', 'en')

    # Set Kerko variables from the environment. Some are deliberately omitted
    # because it would make more sense to set them in the app's Config object
    # directly.
    KERKO_TITLE = env.str('KERKO_TITLE', _("Kerko App"))
    KERKO_DATA_DIR = env.path('KERKO_DATA_DIR',
                              str(app_dir / 'data' / 'kerko'))
    KERKO_WHOOSH_LANGUAGE = env.str('KERKO_WHOOSH_LANGUAGE', 'en')
    KERKO_ZOTERO_LOCALE = env.str('KERKO_ZOTERO_LOCALE', 'en-US')
    KERKO_ZOTERO_API_KEY = env.str('KERKO_ZOTERO_API_KEY')
    KERKO_ZOTERO_LIBRARY_ID = env.str('KERKO_ZOTERO_LIBRARY_ID')
    KERKO_ZOTERO_LIBRARY_TYPE = env.str('KERKO_ZOTERO_LIBRARY_TYPE')
    KERKO_ZOTERO_MAX_ATTEMPTS = env.int('KERKO_ZOTERO_MAX_ATTEMPTS', 10)
    KERKO_ZOTERO_WAIT = env.int('KERKO_ZOTERO_WAIT', 120)  # In seconds.
    KERKO_ZOTERO_BATCH_SIZE = env.int('KERKO_ZOTERO_BATCH_SIZE', 100)
    KERKO_PAGE_LEN = env.int('KERKO_PAGE_LEN', 20)
    KERKO_PAGER_LINKS = env.int('KERKO_PAGER_LINKS', 4)
    KERKO_CSL_STYLE = env.str('KERKO_CSL_STYLE', 'apa')
    KERKO_RESULTS_ABSTRACT = env.bool('KERKO_RESULTS_ABSTRACT', False)
    KERKO_FACET_COLLAPSING = env.bool('KERKO_FACET_COLLAPSING', False)
    KERKO_PRINT_ITEM_LINK = env.bool('KERKO_PRINT_ITEM_LINK', False)
    KERKO_PRINT_CITATIONS_LINK = env.bool('KERKO_PRINT_CITATIONS_LINK', False)
    KERKO_PRINT_CITATIONS_MAX_COUNT = env.int(
        'KERKO_PRINT_CITATIONS_MAX_COUNT', 0)
    KERKO_DOWNLOAD_CITATIONS_LINK = env.bool('KERKO_DOWNLOAD_CITATIONS_LINK',
                                             True)
    KERKO_DOWNLOAD_CITATIONS_MAX_COUNT = env.int(
        'KERKO_DOWNLOAD_CITATIONS_MAX_COUNT', 0)
    KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW = env.bool(
        'KERKO_DOWNLOAD_ATTACHMENT_NEW_WINDOW', False)

    if env.str('KERKOAPP_NOTE_WHITELIST_RE', '') or env.str(
            'KERKOAPP_NOTE_BLACKLIST_RE', ''):
        # Obsolete after version 0.4.
        raise SystemExit(
            "ERROR: The 'KERKOAPP_NOTE_WHITELIST_RE' and 'KERKOAPP_NOTE_BLACKLIST_RE'"
            " environment variables are no longer supported. Please use"
            " 'KERKOAPP_CHILD_WHITELIST_RE' and 'KERKOAPP_CHILD_BLACKLIST_RE' instead."
        )

    KERKO_COMPOSER = Composer(
        whoosh_language=KERKO_WHOOSH_LANGUAGE,
        exclude_default_scopes=env.list('KERKOAPP_EXCLUDE_DEFAULT_SCOPES', []),
        exclude_default_fields=env.list('KERKOAPP_EXCLUDE_DEFAULT_FIELDS', []),
        exclude_default_facets=env.list('KERKOAPP_EXCLUDE_DEFAULT_FACETS', []),
        exclude_default_sorts=env.list('KERKOAPP_EXCLUDE_DEFAULT_SORTS', []),
        exclude_default_citation_formats=env.list(
            'KERKOAPP_EXCLUDE_DEFAULT_CITATION_FORMATS', []),
        exclude_default_badges=env.list('KERKOAPP_EXCLUDE_DEFAULT_BADGES', []),
        default_tag_whitelist_re=env.str('KERKOAPP_TAG_WHITELIST_RE', ''),
        default_tag_blacklist_re=env.str('KERKOAPP_TAG_BLACKLIST_RE', r'^_'),
        default_child_whitelist_re=env.str('KERKOAPP_CHILD_WHITELIST_RE', ''),
        default_child_blacklist_re=env.str('KERKOAPP_CHILD_BLACKLIST_RE',
                                           r'^_'),
        mime_types=env.list('KERKOAPP_MIME_TYPES', ['application/pdf']),
    )

    # Add collection facets.
    collection_spec = env.collection_spec('KERKOAPP_COLLECTION_FACETS', None)
    if collection_spec:
        for collection_key, weight, title in collection_spec:
            KERKO_COMPOSER.add_facet(
                CollectionFacetSpec(
                    title=title,
                    weight=int(weight),
                    collection_key=collection_key,
                ))