This commit is contained in:
CreaRobotics committed 2026-03-02 11:34:40 +01:00
1 parent 6ccab0347b
commit 954a2fd6d6
18684 files changed
+601012 -190

No files matched your search

@@ -0,0 +1,5 @@
#!/usr/bin/env python
# For acceptable version formats, see https://www.python.org/dev/peps/pep-0440/
__version__ = '1.6.1'
@@ -0,0 +1,370 @@
#!/usr/bin/env python
from __future__ import annotations
import logging
import os
import shutil
import sys
import textwrap
import traceback
import warnings
import click
from mkdocs import __version__, config, utils
if sys.platform.startswith("win"):
try:
import colorama
except ImportError:
pass
else:
colorama.init()
log = logging.getLogger(__name__)
def _showwarning(message, category, filename, lineno, file=None, line=None):
try:
# Last stack frames:
# * ...
# * Location of call to deprecated function <-- include this
# * Location of call to warn() <-- include this
# * (stdlib) Location of call to showwarning function
# * (this function) Location of call to extract_stack()
stack = [frame for frame in traceback.extract_stack() if frame.line][-4:-2]
# Make sure the actual affected file's name is still present (the case of syntax warning):
if not any(frame.filename == filename for frame in stack):
stack = stack[-1:] + [traceback.FrameSummary(filename, lineno, '')]
tb = ''.join(traceback.format_list(stack))
except Exception:
tb = f' File "{filename}", line {lineno}'
log.info(f'{category.__name__}: {message}\n{tb}')
def _enable_warnings():
# When `python -W...` or `PYTHONWARNINGS` are used, `sys.warnoptions` is set.
# In that case, we skip warnings configuration since
# we don't want to overwrite the user configuration.
if not sys.warnoptions:
from mkdocs.commands import build
build.log.addFilter(utils.DuplicateFilter())
warnings.simplefilter('module', DeprecationWarning)
warnings.showwarning = _showwarning
class ColorFormatter(logging.Formatter):
colors = {
'CRITICAL': 'red',
'ERROR': 'red',
'WARNING': 'yellow',
'DEBUG': 'blue',
}
text_wrapper = textwrap.TextWrapper(
width=shutil.get_terminal_size(fallback=(0, 0)).columns,
replace_whitespace=False,
break_long_words=False,
break_on_hyphens=False,
initial_indent=' ' * 11,
subsequent_indent=' ' * 11,
)
def format(self, record):
message = super().format(record)
prefix = f'{record.levelname:<8}- '
if record.levelname in self.colors:
prefix = click.style(prefix, fg=self.colors[record.levelname])
if self.text_wrapper.width:
# Only wrap text if a terminal width was detected
msg = '\n'.join(self.text_wrapper.fill(line) for line in message.splitlines())
# Prepend prefix after wrapping so that color codes don't affect length
return prefix + msg[11:]
return prefix + message
class State:
"""Maintain logging level."""
def __init__(self, log_name='mkdocs', level=logging.INFO):
self.logger = logging.getLogger(log_name)
self.logger.setLevel(level)
self.logger.propagate = False
self.stream = logging.StreamHandler()
self.stream.setFormatter(ColorFormatter())
self.stream.name = 'MkDocsStreamHandler'
self.logger.addHandler(self.stream)
def __del__(self):
self.logger.removeHandler(self.stream)
pass_state = click.make_pass_decorator(State, ensure=True)
clean_help = "Remove old files from the site_dir before building (the default)."
config_help = (
"Provide a specific MkDocs config. This can be a file name, or '-' to read from stdin."
)
dev_addr_help = "IP address and port to serve documentation locally (default: localhost:8000)"
serve_open_help = "Open the website in a Web browser after the initial build finishes."
strict_help = "Enable strict mode. This will cause MkDocs to abort the build on any warnings."
theme_help = "The theme to use when building your documentation."
theme_choices = sorted(utils.get_theme_names())
site_dir_help = "The directory to output the result of the documentation build."
use_directory_urls_help = "Use directory URLs when building pages (the default)."
reload_help = "Enable the live reloading in the development server (this is the default)"
no_reload_help = "Disable the live reloading in the development server."
serve_dirty_help = "Only re-build files that have changed."
serve_clean_help = (
"Build the site without any effects of `mkdocs serve` - pure `mkdocs build`, then serve."
)
commit_message_help = (
"A commit message to use when committing to the "
"GitHub Pages remote branch. Commit {sha} and MkDocs {version} are available as expansions"
)
remote_branch_help = (
"The remote branch to commit to for GitHub Pages. This "
"overrides the value specified in config"
)
remote_name_help = (
"The remote name to commit to for GitHub Pages. This overrides the value specified in config"
)
force_help = "Force the push to the repository."
no_history_help = "Replace the whole Git history with one new commit."
ignore_version_help = (
"Ignore check that build is not being deployed with an older version of MkDocs."
)
watch_theme_help = (
"Include the theme in list of files to watch for live reloading. "
"Ignored when live reload is not used."
)
shell_help = "Use the shell when invoking Git."
watch_help = "A directory or file to watch for live reloading. Can be supplied multiple times."
projects_file_help = (
"URL or local path of the registry file that declares all known MkDocs-related projects."
)
def add_options(*opts):
def inner(f):
for i in reversed(opts):
f = i(f)
return f
return inner
def verbose_option(f):
def callback(ctx, param, value):
state = ctx.ensure_object(State)
if value:
state.logger.setLevel(logging.DEBUG)
return click.option(
'-v',
'--verbose',
is_flag=True,
expose_value=False,
help='Enable verbose output',
callback=callback,
)(f)
def quiet_option(f):
def callback(ctx, param, value):
state = ctx.ensure_object(State)
if value:
state.logger.setLevel(logging.ERROR)
return click.option(
'-q',
'--quiet',
is_flag=True,
expose_value=False,
help='Silence warnings',
callback=callback,
)(f)
def color_option(f):
def callback(ctx, param, value):
state = ctx.ensure_object(State)
if value is False or (
value is None
and (
not sys.stdout.isatty()
or os.environ.get('NO_COLOR')
or os.environ.get('TERM') == 'dumb'
)
):
state.stream.setFormatter(logging.Formatter('%(levelname)-8s- %(message)s'))
return click.option(
'--color/--no-color',
is_flag=True,
default=None,
expose_value=False,
help="Force enable or disable color and wrapping for the output. Default is auto-detect.",
callback=callback,
)(f)
common_options = add_options(quiet_option, verbose_option)
common_config_options = add_options(
click.option('-f', '--config-file', type=click.File('rb'), help=config_help),
# Don't override config value if user did not specify --strict flag
# Conveniently, load_config drops None values
click.option('-s', '--strict/--no-strict', is_flag=True, default=None, help=strict_help),
click.option('-t', '--theme', type=click.Choice(theme_choices), help=theme_help),
# As with --strict, set the default to None so that this doesn't incorrectly
# override the config file
click.option(
'--use-directory-urls/--no-directory-urls',
is_flag=True,
default=None,
help=use_directory_urls_help,
),
)
PYTHON_VERSION = f"{sys.version_info.major}.{sys.version_info.minor}"
PKG_DIR = os.path.dirname(os.path.abspath(__file__))
@click.group(context_settings=dict(help_option_names=['-h', '--help'], max_content_width=120))
@click.version_option(
__version__,
'-V',
'--version',
message=f'%(prog)s, version %(version)s from { PKG_DIR } (Python { PYTHON_VERSION })',
)
@common_options
@color_option
def cli():
"""MkDocs - Project documentation with Markdown."""
@cli.command(name="serve")
@click.option('-a', '--dev-addr', help=dev_addr_help, metavar='<IP:PORT>')
@click.option('-o', '--open', 'open_in_browser', help=serve_open_help, is_flag=True)
@click.option('--no-livereload', 'livereload', flag_value=False, help=no_reload_help)
@click.option('--livereload', 'livereload', flag_value=True, default=True, hidden=True)
@click.option('--dirtyreload', 'build_type', flag_value='dirty', hidden=True)
@click.option('--dirty', 'build_type', flag_value='dirty', help=serve_dirty_help)
@click.option('-c', '--clean', 'build_type', flag_value='clean', help=serve_clean_help)
@click.option('--watch-theme', help=watch_theme_help, is_flag=True)
@click.option(
'-w', '--watch', help=watch_help, type=click.Path(exists=True), multiple=True, default=[]
)
@common_config_options
@common_options
def serve_command(**kwargs):
"""Run the builtin development server."""
from mkdocs.commands import serve
_enable_warnings()
serve.serve(**kwargs)
@cli.command(name="build")
@click.option('-c', '--clean/--dirty', is_flag=True, default=True, help=clean_help)
@common_config_options
@click.option('-d', '--site-dir', type=click.Path(), help=site_dir_help)
@common_options
def build_command(clean, **kwargs):
"""Build the MkDocs documentation."""
from mkdocs.commands import build
_enable_warnings()
cfg = config.load_config(**kwargs)
cfg.plugins.on_startup(command='build', dirty=not clean)
try:
build.build(cfg, dirty=not clean)
finally:
cfg.plugins.on_shutdown()
@cli.command(name="gh-deploy")
@click.option('-c', '--clean/--dirty', is_flag=True, default=True, help=clean_help)
@click.option('-m', '--message', help=commit_message_help)
@click.option('-b', '--remote-branch', help=remote_branch_help)
@click.option('-r', '--remote-name', help=remote_name_help)
@click.option('--force', is_flag=True, help=force_help)
@click.option('--no-history', is_flag=True, help=no_history_help)
@click.option('--ignore-version', is_flag=True, help=ignore_version_help)
@click.option('--shell', is_flag=True, help=shell_help)
@common_config_options
@click.option('-d', '--site-dir', type=click.Path(), help=site_dir_help)
@common_options
def gh_deploy_command(
clean, message, remote_branch, remote_name, force, no_history, ignore_version, shell, **kwargs
):
"""Deploy your documentation to GitHub Pages."""
from mkdocs.commands import build, gh_deploy
_enable_warnings()
cfg = config.load_config(remote_branch=remote_branch, remote_name=remote_name, **kwargs)
cfg.plugins.on_startup(command='gh-deploy', dirty=not clean)
try:
build.build(cfg, dirty=not clean)
finally:
cfg.plugins.on_shutdown()
gh_deploy.gh_deploy(
cfg,
message=message,
force=force,
no_history=no_history,
ignore_version=ignore_version,
shell=shell,
)
@cli.command(name="get-deps")
@verbose_option
@click.option('-f', '--config-file', type=click.File('rb'), help=config_help)
@click.option(
'-p',
'--projects-file',
default=None,
help=projects_file_help,
show_default=True,
)
def get_deps_command(config_file, projects_file):
"""Show required PyPI packages inferred from plugins in mkdocs.yml."""
from mkdocs_get_deps import get_deps, get_projects_file
from mkdocs.config.base import _open_config_file
warning_counter = utils.CountHandler()
warning_counter.setLevel(logging.WARNING)
logging.getLogger('mkdocs').addHandler(warning_counter)
with get_projects_file(projects_file) as p:
with _open_config_file(config_file) as f:
deps = get_deps(config_file=f, projects_file=p)
for dep in deps:
print(dep) # noqa: T201
if warning_counter.get_counts():
sys.exit(1)
@cli.command(name="new")
@click.argument("project_directory")
@common_options
def new_command(project_directory):
"""Create a new MkDocs project."""
from mkdocs.commands import new
new.new(project_directory)
if __name__ == '__main__': # pragma: no cover
cli()
Whitespace-only changes.
@@ -0,0 +1,369 @@
from __future__ import annotations
import gzip
import logging
import os
import time
from typing import TYPE_CHECKING, Sequence
from urllib.parse import urljoin, urlsplit
import jinja2
from jinja2.exceptions import TemplateNotFound
import mkdocs
from mkdocs import utils
from mkdocs.exceptions import Abort, BuildError
from mkdocs.structure.files import File, Files, InclusionLevel, get_files, set_exclusions
from mkdocs.structure.nav import Navigation, get_navigation
from mkdocs.structure.pages import Page
from mkdocs.utils import DuplicateFilter # noqa: F401 - legacy re-export
from mkdocs.utils import templates
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
log = logging.getLogger(__name__)
def get_context(
nav: Navigation,
files: Sequence[File] | Files,
config: MkDocsConfig,
page: Page | None = None,
base_url: str = '',
) -> templates.TemplateContext:
"""Return the template context for a given page or template."""
if page is not None:
base_url = utils.get_relative_url('.', page.url)
extra_javascript = [
utils.normalize_url(str(script), page, base_url) for script in config.extra_javascript
]
extra_css = [utils.normalize_url(path, page, base_url) for path in config.extra_css]
if isinstance(files, Files):
files = files.documentation_pages()
return templates.TemplateContext(
nav=nav,
pages=files,
base_url=base_url,
extra_css=extra_css,
extra_javascript=extra_javascript,
mkdocs_version=mkdocs.__version__,
build_date_utc=utils.get_build_datetime(),
config=config,
page=page,
)
def _build_template(
name: str, template: jinja2.Template, files: Files, config: MkDocsConfig, nav: Navigation
) -> str:
"""Return rendered output for given template as a string."""
# Run `pre_template` plugin events.
template = config.plugins.on_pre_template(template, template_name=name, config=config)
if utils.is_error_template(name):
# Force absolute URLs in the nav of error pages and account for the
# possibility that the docs root might be different than the server root.
# See https://github.com/mkdocs/mkdocs/issues/77.
# However, if site_url is not set, assume the docs root and server root
# are the same. See https://github.com/mkdocs/mkdocs/issues/1598.
base_url = urlsplit(config.site_url or '/').path
else:
base_url = utils.get_relative_url('.', name)
context = get_context(nav, files, config, base_url=base_url)
# Run `template_context` plugin events.
context = config.plugins.on_template_context(context, template_name=name, config=config)
output = template.render(context)
# Run `post_template` plugin events.
output = config.plugins.on_post_template(output, template_name=name, config=config)
return output
def _build_theme_template(
template_name: str, env: jinja2.Environment, files: Files, config: MkDocsConfig, nav: Navigation
) -> None:
"""Build a template using the theme environment."""
log.debug(f"Building theme template: {template_name}")
try:
template = env.get_template(template_name)
except TemplateNotFound:
log.warning(f"Template skipped: '{template_name}' not found in theme directories.")
return
output = _build_template(template_name, template, files, config, nav)
if output.strip():
output_path = os.path.join(config.site_dir, template_name)
utils.write_file(output.encode('utf-8'), output_path)
if template_name == 'sitemap.xml':
log.debug(f"Gzipping template: {template_name}")
gz_filename = f'{output_path}.gz'
with open(gz_filename, 'wb') as f:
timestamp = utils.get_build_timestamp(
pages=[f.page for f in files.documentation_pages() if f.page is not None]
)
with gzip.GzipFile(
fileobj=f, filename=gz_filename, mode='wb', mtime=timestamp
) as gz_buf:
gz_buf.write(output.encode('utf-8'))
else:
log.info(f"Template skipped: '{template_name}' generated empty output.")
def _build_extra_template(template_name: str, files: Files, config: MkDocsConfig, nav: Navigation):
"""Build user templates which are not part of the theme."""
log.debug(f"Building extra template: {template_name}")
file = files.get_file_from_path(template_name)
if file is None:
log.warning(f"Template skipped: '{template_name}' not found in docs_dir.")
return
try:
template = jinja2.Template(file.content_string)
except Exception as e:
log.warning(f"Error reading template '{template_name}': {e}")
return
output = _build_template(template_name, template, files, config, nav)
if output.strip():
utils.write_file(output.encode('utf-8'), file.abs_dest_path)
else:
log.info(f"Template skipped: '{template_name}' generated empty output.")
def _populate_page(page: Page, config: MkDocsConfig, files: Files, dirty: bool = False) -> None:
"""Read page content from docs_dir and render Markdown."""
config._current_page = page
try:
# When --dirty is used, only read the page if the file has been modified since the
# previous build of the output.
if dirty and not page.file.is_modified():
return
# Run the `pre_page` plugin event
page = config.plugins.on_pre_page(page, config=config, files=files)
page.read_source(config)
assert page.markdown is not None
# Run `page_markdown` plugin events.
page.markdown = config.plugins.on_page_markdown(
page.markdown, page=page, config=config, files=files
)
page.render(config, files)
assert page.content is not None
# Run `page_content` plugin events.
page.content = config.plugins.on_page_content(
page.content, page=page, config=config, files=files
)
except Exception as e:
message = f"Error reading page '{page.file.src_uri}':"
# Prevent duplicated the error message because it will be printed immediately afterwards.
if not isinstance(e, BuildError):
message += f" {e}"
log.error(message)
raise
finally:
config._current_page = None
def _build_page(
page: Page,
config: MkDocsConfig,
doc_files: Sequence[File],
nav: Navigation,
env: jinja2.Environment,
dirty: bool = False,
excluded: bool = False,
) -> None:
"""Pass a Page to theme template and write output to site_dir."""
config._current_page = page
try:
# When --dirty is used, only build the page if the file has been modified since the
# previous build of the output.
if dirty and not page.file.is_modified():
return
log.debug(f"Building page {page.file.src_uri}")
# Activate page. Signals to theme that this is the current page.
page.active = True
context = get_context(nav, doc_files, config, page)
# Allow 'template:' override in md source files.
template = env.get_template(page.meta.get('template', 'main.html'))
# Run `page_context` plugin events.
context = config.plugins.on_page_context(context, page=page, config=config, nav=nav)
if excluded:
page.content = (
'<div class="mkdocs-draft-marker" title="This page will not be included into the built site.">'
'DRAFT'
'</div>' + (page.content or '')
)
# Render the template.
output = template.render(context)
# Run `post_page` plugin events.
output = config.plugins.on_post_page(output, page=page, config=config)
# Write the output file.
if output.strip():
utils.write_file(
output.encode('utf-8', errors='xmlcharrefreplace'), page.file.abs_dest_path
)
else:
log.info(f"Page skipped: '{page.file.src_uri}'. Generated empty output.")
except Exception as e:
message = f"Error building page '{page.file.src_uri}':"
# Prevent duplicated the error message because it will be printed immediately afterwards.
if not isinstance(e, BuildError):
message += f" {e}"
log.error(message)
raise
finally:
# Deactivate page
page.active = False
config._current_page = None
def build(config: MkDocsConfig, *, serve_url: str | None = None, dirty: bool = False) -> None:
"""Perform a full site build."""
logger = logging.getLogger('mkdocs')
# Add CountHandler for strict mode
warning_counter = utils.CountHandler()
warning_counter.setLevel(logging.WARNING)
if config.strict:
logging.getLogger('mkdocs').addHandler(warning_counter)
inclusion = InclusionLevel.is_in_serve if serve_url else InclusionLevel.is_included
try:
start = time.monotonic()
# Run `config` plugin events.
config = config.plugins.on_config(config)
# Run `pre_build` plugin events.
config.plugins.on_pre_build(config=config)
if not dirty:
log.info("Cleaning site directory")
utils.clean_directory(config.site_dir)
else: # pragma: no cover
# Warn user about problems that may occur with --dirty option
log.warning(
"A 'dirty' build is being performed, this will likely lead to inaccurate navigation and other"
" links within your site. This option is designed for site development purposes only."
)
if not serve_url: # pragma: no cover
log.info(f"Building documentation to directory: {config.site_dir}")
if dirty and site_directory_contains_stale_files(config.site_dir):
log.info("The directory contains stale files. Use --clean to remove them.")
# First gather all data from all files/pages to ensure all data is consistent across all pages.
files = get_files(config)
env = config.theme.get_env()
files.add_files_from_theme(env, config)
# Run `files` plugin events.
files = config.plugins.on_files(files, config=config)
# If plugins have added files but haven't set their inclusion level, calculate it again.
set_exclusions(files, config)
nav = get_navigation(files, config)
# Run `nav` plugin events.
nav = config.plugins.on_nav(nav, config=config, files=files)
log.debug("Reading markdown pages.")
excluded = []
for file in files.documentation_pages(inclusion=inclusion):
log.debug(f"Reading: {file.src_uri}")
if file.page is None and file.inclusion.is_not_in_nav():
if serve_url and file.inclusion.is_excluded():
excluded.append(urljoin(serve_url, file.url))
Page(None, file, config)
assert file.page is not None
_populate_page(file.page, config, files, dirty)
if excluded:
log.info(
"The following pages are being built only for the preview "
"but will be excluded from `mkdocs build` per `draft_docs` config:\n - "
+ "\n - ".join(excluded)
)
# Run `env` plugin events.
env = config.plugins.on_env(env, config=config, files=files)
# Start writing files to site_dir now that all data is gathered. Note that order matters. Files
# with lower precedence get written first so that files with higher precedence can overwrite them.
log.debug("Copying static assets.")
files.copy_static_files(dirty=dirty, inclusion=inclusion)
for template in config.theme.static_templates:
_build_theme_template(template, env, files, config, nav)
for template in config.extra_templates:
_build_extra_template(template, files, config, nav)
log.debug("Building markdown pages.")
doc_files = files.documentation_pages(inclusion=inclusion)
for file in doc_files:
assert file.page is not None
_build_page(
file.page, config, doc_files, nav, env, dirty, excluded=file.inclusion.is_excluded()
)
log_level = config.validation.links.anchors
for file in doc_files:
assert file.page is not None
file.page.validate_anchor_links(files=files, log_level=log_level)
# Run `post_build` plugin events.
config.plugins.on_post_build(config=config)
if counts := warning_counter.get_counts():
msg = ', '.join(f'{v} {k.lower()}s' for k, v in counts)
raise Abort(f'Aborted with {msg} in strict mode!')
log.info(f'Documentation built in {time.monotonic() - start:.2f} seconds')
except Exception as e:
# Run `build_error` plugin events.
config.plugins.on_build_error(error=e)
if isinstance(e, BuildError):
log.error(str(e))
raise Abort('Aborted with a BuildError!')
raise
finally:
logger.removeHandler(warning_counter)
def site_directory_contains_stale_files(site_directory: str) -> bool:
"""Check if the site directory contains stale files from a previous build."""
return bool(os.path.exists(site_directory) and os.listdir(site_directory))
@@ -0,0 +1,169 @@
from __future__ import annotations
import logging
import os
import re
import subprocess
from typing import TYPE_CHECKING
import ghp_import # type: ignore
from packaging import version
import mkdocs
from mkdocs.exceptions import Abort
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
log = logging.getLogger(__name__)
default_message = """Deployed {sha} with MkDocs version: {version}"""
def _is_cwd_git_repo() -> bool:
try:
proc = subprocess.Popen(
['git', 'rev-parse', '--is-inside-work-tree'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
except FileNotFoundError:
log.error("Could not find git - is it installed and on your path?")
raise Abort('Deployment Aborted!')
proc.communicate()
return proc.wait() == 0
def _get_current_sha(repo_path) -> str:
proc = subprocess.Popen(
['git', 'rev-parse', '--short', 'HEAD'],
cwd=repo_path or None,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, _ = proc.communicate()
sha = stdout.decode('utf-8').strip()
return sha
def _get_remote_url(remote_name: str) -> tuple[str, str] | tuple[None, None]:
# No CNAME found. We will use the origin URL to determine the GitHub
# Pages location.
remote = f"remote.{remote_name}.url"
proc = subprocess.Popen(
["git", "config", "--get", remote],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, _ = proc.communicate()
url = stdout.decode('utf-8').strip()
if 'github.com/' in url:
host, path = url.split('github.com/', 1)
elif 'github.com:' in url:
host, path = url.split('github.com:', 1)
else:
return None, None
return host, path
def _check_version(branch: str) -> None:
proc = subprocess.Popen(
['git', 'show', '-s', '--format=%s', f'refs/heads/{branch}'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
stdout, _ = proc.communicate()
msg = stdout.decode('utf-8').strip()
m = re.search(r'\d+(\.\d+)+((a|b|rc)\d+)?(\.post\d+)?(\.dev\d+)?', msg, re.X | re.I)
previousv = version.parse(m.group()) if m else None
currentv = version.parse(mkdocs.__version__)
if not previousv:
log.warning('Version check skipped: No version specified in previous deployment.')
elif currentv > previousv:
log.info(
f'Previous deployment was done with MkDocs version {previousv}; '
f'you are deploying with a newer version ({currentv})'
)
elif currentv < previousv:
log.error(
f'Deployment terminated: Previous deployment was made with MkDocs version {previousv}; '
f'you are attempting to deploy with an older version ({currentv}). Use --ignore-version '
'to deploy anyway.'
)
raise Abort('Deployment Aborted!')
def gh_deploy(
config: MkDocsConfig,
message: str | None = None,
force=False,
no_history=False,
ignore_version=False,
shell=False,
) -> None:
if not _is_cwd_git_repo():
log.error('Cannot deploy - this directory does not appear to be a git repository')
remote_branch = config.remote_branch
remote_name = config.remote_name
if not ignore_version:
_check_version(remote_branch)
if message is None:
message = default_message
sha = _get_current_sha(os.path.dirname(config.config_file_path))
message = message.format(version=mkdocs.__version__, sha=sha)
log.info(
"Copying '%s' to '%s' branch and pushing to GitHub.",
config.site_dir,
config.remote_branch,
)
try:
ghp_import.ghp_import(
config.site_dir,
mesg=message,
remote=remote_name,
branch=remote_branch,
push=True,
force=force,
use_shell=shell,
no_history=no_history,
nojekyll=True,
)
except ghp_import.GhpError as e:
log.error(f"Failed to deploy to GitHub with error: \n{e.message}")
raise Abort('Deployment Aborted!')
cname_file = os.path.join(config.site_dir, 'CNAME')
# Does this repository have a CNAME set for GitHub Pages?
if os.path.isfile(cname_file):
# This GitHub Pages repository has a CNAME configured.
with open(cname_file) as f:
cname_host = f.read().strip()
log.info(
f'Based on your CNAME file, your documentation should be '
f'available shortly at: http://{cname_host}'
)
log.info(
'NOTE: Your DNS records must be configured appropriately for your CNAME URL to work.'
)
return
host, path = _get_remote_url(remote_name)
if host is None or path is None:
# This could be a GitHub Enterprise deployment.
log.info('Your documentation should be available shortly.')
else:
username, repo = path.split('/', 1)
if repo.endswith('.git'):
repo = repo[: -len('.git')]
url = f'https://{username}.github.io/{repo}/'
log.info(f"Your documentation should shortly be available at: {url}")
@@ -0,0 +1,53 @@
from __future__ import annotations
import logging
import os
config_text = 'site_name: My Docs\n'
index_text = """# Welcome to MkDocs
For full documentation visit [mkdocs.org](https://www.mkdocs.org).
## Commands
* `mkdocs new [dir-name]` - Create a new project.
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs -h` - Print help message and exit.
## Project layout
mkdocs.yml # The configuration file.
docs/
index.md # The documentation homepage.
... # Other markdown pages, images and other files.
"""
log = logging.getLogger(__name__)
def new(output_dir: str) -> None:
docs_dir = os.path.join(output_dir, 'docs')
config_path = os.path.join(output_dir, 'mkdocs.yml')
index_path = os.path.join(docs_dir, 'index.md')
if os.path.exists(config_path):
log.info('Project already exists.')
return
if not os.path.exists(output_dir):
log.info(f'Creating project directory: {output_dir}')
os.mkdir(output_dir)
log.info(f'Writing config file: {config_path}')
with open(config_path, 'w', encoding='utf-8') as f:
f.write(config_text)
if os.path.exists(index_path):
return
log.info(f'Writing initial docs: {index_path}')
if not os.path.exists(docs_dir):
os.mkdir(docs_dir)
with open(index_path, 'w', encoding='utf-8') as f:
f.write(index_text)
@@ -0,0 +1,112 @@
from __future__ import annotations
import logging
import shutil
import tempfile
from os.path import isdir, isfile, join
from typing import TYPE_CHECKING
from urllib.parse import urlsplit
from mkdocs.commands.build import build
from mkdocs.config import load_config
from mkdocs.livereload import LiveReloadServer, _serve_url
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
log = logging.getLogger(__name__)
def serve(
config_file: str | None = None,
livereload: bool = True,
build_type: str | None = None,
watch_theme: bool = False,
watch: list[str] = [],
*,
open_in_browser: bool = False,
**kwargs,
) -> None:
"""
Start the MkDocs development server.
By default it will serve the documentation on http://localhost:8000/ and
it will rebuild the documentation and refresh the page automatically
whenever a file is edited.
"""
# Create a temporary build directory, and set some options to serve it
# PY2 returns a byte string by default. The Unicode prefix ensures a Unicode
# string is returned. And it makes MkDocs temp dirs easier to identify.
site_dir = tempfile.mkdtemp(prefix='mkdocs_')
def get_config():
config = load_config(
config_file=config_file,
site_dir=site_dir,
**kwargs,
)
config.watch.extend(watch)
return config
is_clean = build_type == 'clean'
is_dirty = build_type == 'dirty'
config = get_config()
config.plugins.on_startup(command=('build' if is_clean else 'serve'), dirty=is_dirty)
host, port = config.dev_addr
mount_path = urlsplit(config.site_url or '/').path
config.site_url = serve_url = _serve_url(host, port, mount_path)
def builder(config: MkDocsConfig | None = None):
log.info("Building documentation...")
if config is None:
config = get_config()
config.site_url = serve_url
build(config, serve_url=None if is_clean else serve_url, dirty=is_dirty)
server = LiveReloadServer(
builder=builder, host=host, port=port, root=site_dir, mount_path=mount_path
)
def error_handler(code) -> bytes | None:
if code in (404, 500):
error_page = join(site_dir, f'{code}.html')
if isfile(error_page):
with open(error_page, 'rb') as f:
return f.read()
return None
server.error_handler = error_handler
try:
# Perform the initial build
builder(config)
if livereload:
# Watch the documentation files, the config file and the theme files.
server.watch(config.docs_dir)
if config.config_file_path:
server.watch(config.config_file_path)
if watch_theme:
for d in config.theme.dirs:
server.watch(d)
# Run `serve` plugin events.
server = config.plugins.on_serve(server, config=config, builder=builder)
for item in config.watch:
server.watch(item)
try:
server.serve(open_in_browser=open_in_browser)
except KeyboardInterrupt:
log.info("Shutting down...")
finally:
server.shutdown()
finally:
config.plugins.on_shutdown()
if isdir(site_dir):
shutil.rmtree(site_dir)
@@ -0,0 +1,3 @@
from mkdocs.config.base import Config, load_config
__all__ = ['load_config', 'Config']
@@ -0,0 +1,392 @@
from __future__ import annotations
import functools
import logging
import os
import sys
import warnings
from collections import UserDict
from contextlib import contextmanager
from typing import (
IO,
TYPE_CHECKING,
Any,
Generic,
Iterator,
List,
Mapping,
Sequence,
Tuple,
TypeVar,
overload,
)
from mkdocs import exceptions, utils
from mkdocs.utils import weak_property
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
log = logging.getLogger('mkdocs.config')
T = TypeVar('T')
class BaseConfigOption(Generic[T]):
def __init__(self) -> None:
self.warnings: list[str] = []
self.default = None
@property
def default(self):
try:
# ensure no mutable values are assigned
return self._default.copy()
except AttributeError:
return self._default
@default.setter
def default(self, value):
self._default = value
def validate(self, value: object, /) -> T:
return self.run_validation(value)
def reset_warnings(self) -> None:
self.warnings = []
def pre_validation(self, config: Config, key_name: str) -> None:
"""
Before all options are validated, perform a pre-validation process.
The pre-validation process method should be implemented by subclasses.
"""
def run_validation(self, value: object, /):
"""
Perform validation for a value.
The run_validation method should be implemented by subclasses.
"""
return value
def post_validation(self, config: Config, key_name: str) -> None:
"""
After all options have passed validation, perform a post-validation
process to do any additional changes dependent on other config values.
The post-validation process method should be implemented by subclasses.
"""
def __set_name__(self, owner, name):
if name.endswith('_') and not name.startswith('_'):
name = name[:-1]
self._name = name
@overload
def __get__(self, obj: Config, type=None) -> T:
...
@overload
def __get__(self, obj, type=None) -> BaseConfigOption:
...
def __get__(self, obj, type=None):
if not isinstance(obj, Config):
return self
return obj[self._name]
def __set__(self, obj, value: T):
if not isinstance(obj, Config):
raise AttributeError(
f"can't set attribute ({self._name}) because the parent is a {type(obj)} not a {Config}"
)
obj[self._name] = value
class ValidationError(Exception):
"""Raised during the validation process of the config on errors."""
def __eq__(self, other):
return type(self) is type(other) and str(self) == str(other)
PlainConfigSchemaItem = Tuple[str, BaseConfigOption]
PlainConfigSchema = Sequence[PlainConfigSchemaItem]
ConfigErrors = List[Tuple[str, Exception]]
ConfigWarnings = List[Tuple[str, str]]
class Config(UserDict):
"""
Base class for MkDocs configuration, plugin configuration (and sub-configuration) objects.
It should be subclassed and have `ConfigOption`s defined as attributes.
For examples, see mkdocs/contrib/search/__init__.py and mkdocs/config/defaults.py.
Behavior as it was prior to MkDocs 1.4 is now handled by LegacyConfig.
"""
_schema: PlainConfigSchema
config_file_path: str
def __init_subclass__(cls):
schema = dict(getattr(cls, '_schema', ()))
for attr_name, attr in cls.__dict__.items():
if isinstance(attr, BaseConfigOption):
schema[getattr(attr, '_name', attr_name)] = attr
cls._schema = tuple(schema.items())
for attr_name, attr in cls._schema:
attr.required = True
if getattr(attr, '_legacy_required', None) is not None:
raise TypeError(
f"{cls.__name__}.{attr_name}: "
"Setting 'required' is unsupported in class-based configs. "
"All values are required, or can be wrapped into config_options.Optional"
)
def __new__(cls, *args, **kwargs) -> Config:
"""Compatibility: allow referring to `LegacyConfig(...)` constructor as `Config(...)`."""
if cls is Config:
return LegacyConfig(*args, **kwargs)
return super().__new__(cls)
def __init__(self, config_file_path: str | bytes | None = None):
super().__init__()
self.__user_configs: list[dict] = []
self.set_defaults()
self._schema_keys = {k for k, v in self._schema}
# Ensure config_file_path is a Unicode string
if config_file_path is not None and not isinstance(config_file_path, str):
try:
# Assume config_file_path is encoded with the file system encoding.
config_file_path = config_file_path.decode(encoding=sys.getfilesystemencoding())
except UnicodeDecodeError:
raise ValidationError("config_file_path is not a Unicode string.")
self.config_file_path = config_file_path or ''
def set_defaults(self) -> None:
"""
Set the base config by going through each validator and getting the
default if it has one.
"""
for key, config_option in self._schema:
self[key] = config_option.default
def _validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed: ConfigErrors = []
warnings: ConfigWarnings = []
for key, config_option in self._schema:
try:
value = self.get(key)
self[key] = config_option.validate(value)
warnings.extend((key, w) for w in config_option.warnings)
config_option.reset_warnings()
except ValidationError as e:
failed.append((key, e))
break
for key in set(self.keys()) - self._schema_keys:
warnings.append((key, f"Unrecognised configuration name: {key}"))
return failed, warnings
def _pre_validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed: ConfigErrors = []
warnings: ConfigWarnings = []
for key, config_option in self._schema:
try:
config_option.pre_validation(self, key_name=key)
warnings.extend((key, w) for w in config_option.warnings)
config_option.reset_warnings()
except ValidationError as e:
failed.append((key, e))
return failed, warnings
def _post_validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed: ConfigErrors = []
warnings: ConfigWarnings = []
for key, config_option in self._schema:
try:
config_option.post_validation(self, key_name=key)
warnings.extend((key, w) for w in config_option.warnings)
config_option.reset_warnings()
except ValidationError as e:
failed.append((key, e))
return failed, warnings
def validate(self) -> tuple[ConfigErrors, ConfigWarnings]:
failed, warnings = self._pre_validate()
run_failed, run_warnings = self._validate()
failed.extend(run_failed)
warnings.extend(run_warnings)
# Only run the post validation steps if there are no failures, warnings
# are okay.
if len(failed) == 0:
post_failed, post_warnings = self._post_validate()
failed.extend(post_failed)
warnings.extend(post_warnings)
return failed, warnings
def load_dict(self, patch: dict) -> None:
"""Load config options from a dictionary."""
if not isinstance(patch, dict):
raise exceptions.ConfigurationError(
"The configuration is invalid. Expected a key-"
f"value mapping (dict) but received: {type(patch)}"
)
self.__user_configs.append(patch)
self.update(patch)
def load_file(self, config_file: IO) -> None:
"""Load config options from the open file descriptor of a YAML file."""
warnings.warn(
"Config.load_file is not used since MkDocs 1.5 and will be removed soon. "
"Use MkDocsConfig.load_file instead",
DeprecationWarning,
)
return self.load_dict(utils.yaml_load(config_file))
@weak_property
def user_configs(self) -> Sequence[Mapping[str, Any]]:
warnings.warn(
"user_configs is never used in MkDocs and will be removed soon.", DeprecationWarning
)
return self.__user_configs
@functools.lru_cache(maxsize=None)
def get_schema(cls: type) -> PlainConfigSchema:
"""Extract ConfigOptions defined in a class (used just as a container) and put them into a schema tuple."""
if issubclass(cls, Config):
return cls._schema
return tuple((k, v) for k, v in cls.__dict__.items() if isinstance(v, BaseConfigOption))
class LegacyConfig(Config):
"""A configuration object for plugins, as just a dict without type-safe attribute access."""
def __init__(self, schema: PlainConfigSchema, config_file_path: str | None = None):
self._schema = tuple((k, v) for k, v in schema) # Re-create just for validation
super().__init__(config_file_path)
@contextmanager
def _open_config_file(config_file: str | IO | None) -> Iterator[IO]:
"""
A context manager which yields an open file descriptor ready to be read.
Accepts a filename as a string, an open or closed file descriptor, or None.
When None, it defaults to `mkdocs.yml` in the CWD. If a closed file descriptor
is received, a new file descriptor is opened for the same file.
The file descriptor is automatically closed when the context manager block is existed.
"""
# Default to the standard config filename.
if config_file is None:
paths_to_try = ['mkdocs.yml', 'mkdocs.yaml']
# If it is a string, we can assume it is a path and attempt to open it.
elif isinstance(config_file, str):
paths_to_try = [config_file]
# If closed file descriptor, get file path to reopen later.
elif getattr(config_file, 'closed', False):
paths_to_try = [config_file.name]
else:
result_config_file = config_file
paths_to_try = None
if paths_to_try:
# config_file is not a file descriptor, so open it as a path.
for path in paths_to_try:
path = os.path.abspath(path)
log.debug(f"Loading configuration file: {path}")
try:
result_config_file = open(path, 'rb')
break
except FileNotFoundError:
continue
else:
raise exceptions.ConfigurationError(f"Config file '{paths_to_try[0]}' does not exist.")
else:
log.debug(f"Loading configuration file: {result_config_file}")
# Ensure file descriptor is at beginning
try:
result_config_file.seek(0)
except OSError:
pass
try:
yield result_config_file
finally:
if hasattr(result_config_file, 'close'):
result_config_file.close()
def load_config(
config_file: str | IO | None = None, *, config_file_path: str | None = None, **kwargs
) -> MkDocsConfig:
"""
Load the configuration for a given file object or name.
The config_file can either be a file object, string or None. If it is None
the default `mkdocs.yml` filename will loaded.
Extra kwargs are passed to the configuration to replace any default values
unless they themselves are None.
"""
options = kwargs.copy()
# Filter None values from the options. This usually happens with optional
# parameters from Click.
for key, value in options.copy().items():
if value is None:
options.pop(key)
with _open_config_file(config_file) as fd:
# Initialize the config with the default schema.
from mkdocs.config.defaults import MkDocsConfig
if config_file_path is None:
if sys.stdin and fd is not sys.stdin.buffer:
config_file_path = getattr(fd, 'name', None)
cfg = MkDocsConfig(config_file_path=config_file_path)
# load the config file
cfg.load_file(fd)
# Then load the options to overwrite anything in the config.
cfg.load_dict(options)
errors, warnings = cfg.validate()
for config_name, warning in warnings:
log.warning(f"Config value '{config_name}': {warning}")
for config_name, error in errors:
log.error(f"Config value '{config_name}': {error}")
for key, value in cfg.items():
log.debug(f"Config value '{key}' = {value!r}")
if len(errors) > 0:
raise exceptions.Abort("Aborted with a configuration error!")
elif cfg.strict and len(warnings) > 0:
raise exceptions.Abort(
f"Aborted with {len(warnings)} configuration warnings in 'strict' mode!"
)
return cfg
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,218 @@
from __future__ import annotations
import logging
from typing import IO, Dict, Mapping
from mkdocs.config import base
from mkdocs.config import config_options as c
from mkdocs.structure.pages import Page, _AbsoluteLinksValidationValue
from mkdocs.utils.yaml import get_yaml_loader, yaml_load
class _LogLevel(c.OptionallyRequired[int]):
levels: Mapping[str, int] = {
"warn": logging.WARNING,
"info": logging.INFO,
"ignore": logging.DEBUG,
}
def run_validation(self, value: object) -> int:
if not isinstance(value, str):
raise base.ValidationError(f"Expected a string, but a {type(value)} was given.")
try:
return self.levels[value]
except KeyError:
raise base.ValidationError(f"Expected one of {list(self.levels)}, got {value!r}")
class _AbsoluteLinksValidation(_LogLevel):
levels: Mapping[str, int] = {
**_LogLevel.levels,
"relative_to_docs": _AbsoluteLinksValidationValue.RELATIVE_TO_DOCS,
}
# NOTE: The order here is important. During validation some config options
# depend on others. So, if config option A depends on B, then A should be
# listed higher in the schema.
class MkDocsConfig(base.Config):
"""The configuration of MkDocs itself (the root object of mkdocs.yml)."""
config_file_path: str = c.Type(str) # type: ignore[assignment]
"""The path to the mkdocs.yml config file. Can't be populated from the config."""
site_name = c.Type(str)
"""The title to use for the documentation."""
nav = c.Optional(c.Nav())
"""Defines the structure of the navigation."""
pages = c.Deprecated(removed=True, moved_to='nav')
exclude_docs = c.Optional(c.PathSpec())
"""Gitignore-like patterns of files (relative to docs dir) to exclude from the site."""
draft_docs = c.Optional(c.PathSpec())
"""Gitignore-like patterns of files (relative to docs dir) to mark as draft."""
not_in_nav = c.Optional(c.PathSpec())
"""Gitignore-like patterns of files (relative to docs dir) that are not intended to be in the nav.
This marks doc files that are expected not to be in the nav, otherwise they will cause a log message
(see also `validation.nav.omitted_files`).
"""
site_url = c.Optional(c.URL(is_dir=True))
"""The full URL to where the documentation will be hosted."""
site_description = c.Optional(c.Type(str))
"""A description for the documentation project that will be added to the
HTML meta tags."""
site_author = c.Optional(c.Type(str))
"""The name of the author to add to the HTML meta tags."""
theme = c.Theme(default='mkdocs')
"""The MkDocs theme for the documentation."""
docs_dir = c.DocsDir(default='docs', exists=True)
"""The directory containing the documentation markdown."""
site_dir = c.SiteDir(default='site')
"""The directory where the site will be built to"""
copyright = c.Optional(c.Type(str))
"""A copyright notice to add to the footer of documentation."""
google_analytics = c.Deprecated(
message=(
'The configuration option {} has been deprecated and '
'will be removed in a future release of MkDocs. See the '
'options available on your theme for an alternative.'
),
option_type=c.Type(list, length=2),
)
"""set of values for Google analytics containing the account IO and domain
this should look like, ['UA-27795084-5', 'mkdocs.org']"""
dev_addr = c.IpAddress(default='127.0.0.1:8000')
"""The address on which to serve the live reloading docs server."""
use_directory_urls = c.Type(bool, default=True)
"""If `True`, use `<page_name>/index.html` style files with hyperlinks to
the directory. If `False`, use `<page_name>.html style file with
hyperlinks to the file.
True generates nicer URLs, but False is useful if browsing the output on
a filesystem."""
repo_url = c.Optional(c.URL())
"""Specify a link to the project source repo to be included
in the documentation pages."""
repo_name = c.Optional(c.RepoName('repo_url'))
"""A name to use for the link to the project source repo.
Default, If repo_url is unset then None, otherwise
"GitHub", "Bitbucket" or "GitLab" for known url or Hostname
for unknown urls."""
edit_uri_template = c.Optional(c.EditURITemplate('edit_uri'))
edit_uri = c.Optional(c.EditURI('repo_url'))
"""Specify a URI to the docs dir in the project source repo, relative to the
repo_url. When set, a link directly to the page in the source repo will
be added to the generated HTML. If repo_url is not set also, this option
is ignored."""
extra_css = c.Type(list, default=[])
extra_javascript = c.ListOfItems(c.ExtraScript(), default=[])
"""Specify which css or javascript files from the docs directory should be
additionally included in the site."""
extra_templates = c.Type(list, default=[])
"""Similar to the above, but each template (HTML or XML) will be build with
Jinja2 and the global context."""
markdown_extensions = c.MarkdownExtensions(
builtins=['toc', 'tables', 'fenced_code'], configkey='mdx_configs'
)
"""PyMarkdown extension names."""
mdx_configs = c.Private[Dict[str, dict]]()
"""PyMarkdown extension configs. Populated from `markdown_extensions`."""
strict = c.Type(bool, default=False)
"""Enabling strict mode causes MkDocs to stop the build when a problem is
encountered rather than display an error."""
remote_branch = c.Type(str, default='gh-pages')
"""The remote branch to commit to when using gh-deploy."""
remote_name = c.Type(str, default='origin')
"""The remote name to push to when using gh-deploy."""
extra = c.SubConfig()
"""extra is a mapping/dictionary of data that is passed to the template.
This allows template authors to require extra configuration that not
relevant to all themes and doesn't need to be explicitly supported by
MkDocs itself. A good example here would be including the current
project version."""
plugins = c.Plugins(theme_key='theme', default=['search'])
"""A list of plugins. Each item may contain a string name or a key value pair.
A key value pair should be the string name (as the key) and a dict of config
options (as the value)."""
hooks = c.Hooks('plugins')
"""A list of filenames that will be imported as Python modules and used as
an instance of a plugin each."""
watch = c.ListOfPaths(default=[])
"""A list of extra paths to watch while running `mkdocs serve`."""
class Validation(base.Config):
class NavValidation(base.Config):
omitted_files = _LogLevel(default='info')
"""Warning level for when a doc file is never mentioned in the navigation.
For granular configuration, see `not_in_nav`."""
not_found = _LogLevel(default='warn')
"""Warning level for when the navigation links to a relative path that isn't an existing page on the site."""
absolute_links = _AbsoluteLinksValidation(default='info')
"""Warning level for when the navigation links to an absolute path (starting with `/`)."""
nav = c.SubConfig(NavValidation)
class LinksValidation(base.Config):
not_found = _LogLevel(default='warn')
"""Warning level for when a Markdown doc links to a relative path that isn't an existing document on the site."""
absolute_links = _AbsoluteLinksValidation(default='info')
"""Warning level for when a Markdown doc links to an absolute path (starting with `/`)."""
unrecognized_links = _LogLevel(default='info')
"""Warning level for when a Markdown doc links to a relative path that doesn't look like
it could be a valid internal link. For example, if the link ends with `/`."""
anchors = _LogLevel(default='info')
"""Warning level for when a Markdown doc links to an anchor that's not present on the target page."""
links = c.SubConfig(LinksValidation)
validation = c.PropagatingSubConfig[Validation]()
_current_page: Page | None = None
"""The currently rendered page. Please do not access this and instead
rely on the `page` argument to event handlers."""
def load_dict(self, patch: dict) -> None:
super().load_dict(patch)
if 'config_file_path' in patch:
raise base.ValidationError("Can't set config_file_path in config")
def load_file(self, config_file: IO) -> None:
"""Load config options from the open file descriptor of a YAML file."""
loader = get_yaml_loader(config=self)
self.load_dict(yaml_load(config_file, loader))
def get_schema() -> base.PlainConfigSchema:
"""Soft-deprecated, do not use."""
return MkDocsConfig._schema
Whitespace-only changes.
@@ -0,0 +1,120 @@
from __future__ import annotations
import logging
import os
from typing import TYPE_CHECKING, List
from mkdocs import utils
from mkdocs.config import base
from mkdocs.config import config_options as c
from mkdocs.contrib.search.search_index import SearchIndex
from mkdocs.plugins import BasePlugin
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.pages import Page
from mkdocs.utils.templates import TemplateContext
log = logging.getLogger(__name__)
base_path = os.path.dirname(os.path.abspath(__file__))
class LangOption(c.OptionallyRequired[List[str]]):
"""Validate Language(s) provided in config are known languages."""
def get_lunr_supported_lang(self, lang):
fallback = {'uk': 'ru'}
for lang_part in lang.split("_"):
lang_part = lang_part.lower()
lang_part = fallback.get(lang_part, lang_part)
if os.path.isfile(os.path.join(base_path, 'lunr-language', f'lunr.{lang_part}.js')):
return lang_part
def run_validation(self, value: object):
if isinstance(value, str):
value = [value]
if not isinstance(value, list):
raise c.ValidationError('Expected a list of language codes.')
for lang in value[:]:
if lang != 'en':
lang_detected = self.get_lunr_supported_lang(lang)
if not lang_detected:
log.info(f"Option search.lang '{lang}' is not supported, falling back to 'en'")
value.remove(lang)
if 'en' not in value:
value.append('en')
elif lang_detected != lang:
value.remove(lang)
value.append(lang_detected)
log.info(f"Option search.lang '{lang}' switched to '{lang_detected}'")
return value
class _PluginConfig(base.Config):
lang = c.Optional(LangOption())
separator = c.Type(str, default=r'[\s\-]+')
min_search_length = c.Type(int, default=3)
prebuild_index = c.Choice((False, True, 'node', 'python'), default=False)
indexing = c.Choice(('full', 'sections', 'titles'), default='full')
class SearchPlugin(BasePlugin[_PluginConfig]):
"""Add a search feature to MkDocs."""
def on_config(self, config: MkDocsConfig, **kwargs) -> MkDocsConfig:
"""Add plugin templates and scripts to config."""
if config.theme.get('include_search_page'):
config.theme.static_templates.add('search.html')
if not config.theme.get('search_index_only'):
path = os.path.join(base_path, 'templates')
config.theme.dirs.append(path)
if 'search/main.js' not in config.extra_javascript:
config.extra_javascript.append('search/main.js') # type: ignore
if self.config.lang is None:
# lang setting undefined. Set default based on theme locale
validate = _PluginConfig.lang.run_validation
self.config.lang = validate(config.theme.locale.language)
# The `python` method of `prebuild_index` is pending deprecation as of version 1.2.
# TODO: Raise a deprecation warning in a future release (1.3?).
if self.config.prebuild_index == 'python':
log.info(
"The 'python' method of the search plugin's 'prebuild_index' config option "
"is pending deprecation and will not be supported in a future release."
)
return config
def on_pre_build(self, config: MkDocsConfig, **kwargs) -> None:
"""Create search index instance for later use."""
self.search_index = SearchIndex(**self.config)
def on_page_context(self, context: TemplateContext, page: Page, **kwargs) -> None:
"""Add page to search index."""
self.search_index.add_entry_from_context(page)
def on_post_build(self, config: MkDocsConfig, **kwargs) -> None:
"""Build search index."""
output_base_path = os.path.join(config.site_dir, 'search')
search_index = self.search_index.generate_search_index()
json_output_path = os.path.join(output_base_path, 'search_index.json')
utils.write_file(search_index.encode('utf-8'), json_output_path)
assert self.config.lang is not None
if not config.theme.get('search_index_only'):
# Include language support files in output. Copy them directly
# so that only the needed files are included.
files = []
if len(self.config.lang) > 1 or 'en' not in self.config.lang:
files.append('lunr.stemmer.support.js')
if len(self.config.lang) > 1:
files.append('lunr.multi.js')
if 'ja' in self.config.lang or 'jp' in self.config.lang:
files.append('tinyseg.js')
for lang in self.config.lang:
if lang != 'en':
files.append(f'lunr.{lang}.js')
for filename in files:
from_path = os.path.join(base_path, 'lunr-language', filename)
to_path = os.path.join(output_base_path, filename)
utils.copy_file(from_path, to_path)
@@ -0,0 +1,381 @@
/*!
* Lunr languages, `Arabic` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2018, Dalia Al-Shahrabi
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Kazem Taghva, Rania Elkhoury, and Jeffrey Coombs (2005)
* Meryeme Hadni, Abdelmonaime Lachkar, and S. Alaoui Ouatik (2012)
*
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.ar = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.ar.trimmer,
lunr.ar.stopWordFilter,
lunr.ar.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.ar.stemmer)
}
};
/* lunr trimmer function */
lunr.ar.wordCharacters = "\u0621-\u065b\u0671\u0640";
lunr.ar.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.ar.wordCharacters);
lunr.Pipeline.registerFunction(lunr.ar.trimmer, 'trimmer-ar');
/* lunr stemmer function */
lunr.ar.stemmer = (function() {
var self = this;
var word = '';
self.result = false;
self.preRemoved = false;
self.sufRemoved = false;
//prefix data
self.pre = {
pre1: 'ف ك ب و س ل ن ا ي ت',
pre2: 'ال لل',
pre3: 'بال وال فال تال كال ولل',
pre4: 'فبال كبال وبال وكال'
};
//suffix data
self.suf = {
suf1: 'ه ك ت ن ا ي',
suf2: 'نك نه ها وك يا اه ون ين تن تم نا وا ان كم كن ني نن ما هم هن تك ته ات يه',
suf3: 'تين كهم نيه نهم ونه وها يهم ونا ونك وني وهم تكم تنا تها تني تهم كما كها ناه نكم هنا تان يها',
suf4: 'كموه ناها ونني ونهم تكما تموه تكاه كماه ناكم ناهم نيها وننا'
}
//arabic language patterns and alternative mapping for patterns
self.patterns = JSON.parse('{"pt43":[{"pt":[{"c":"ا","l":1}]},{"pt":[{"c":"ا,ت,ن,ي","l":0}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"و","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ل","l":2,"m":3}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ي","l":2}],"mPt":[{"c":"ف","l":0,"m":0},{"c":"ع","l":1,"m":1},{"c":"ا","l":2},{"c":"ل","l":3,"m":3}]},{"pt":[{"c":"م","l":0}]}],"pt53":[{"pt":[{"c":"ت","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":3},{"c":"ل","l":3,"m":4},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":0},{"c":"ا","l":3}],"mPt":[{"c":"ف","l":0,"m":1},{"c":"ع","l":1,"m":2},{"c":"ل","l":2,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ن","l":4}]},{"pt":[{"c":"ت","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"م","l":0},{"c":"و","l":3}]},{"pt":[{"c":"ا","l":1},{"c":"و","l":3}]},{"pt":[{"c":"و","l":1},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ي","l":3}]},{"pt":[{"c":"ا","l":2},{"c":"ن","l":3}]},{"pt":[{"c":"م","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"م","l":0},{"c":"ا","l":2}]},{"pt":[{"c":"م","l":1},{"c":"ا","l":3}]},{"pt":[{"c":"ي,ت,ا,ن","l":0},{"c":"ت","l":1}],"mPt":[{"c":"ف","l":0,"m":2},{"c":"ع","l":1,"m":3},{"c":"ا","l":2},{"c":"ل","l":3,"m":4}]},{"pt":[{"c":"ت,ي,ا,ن","l":0},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ت","l":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":2},{"c":"ي","l":3}]},{"pt":[{"c":"ا,ي,ت,ن","l":0},{"c":"ن","l":1}],"mPt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ف","l":2,"m":2},{"c":"ع","l":3,"m":3},{"c":"ا","l":4},{"c":"ل","l":5,"m":4}]},{"pt":[{"c":"ا","l":3},{"c":"ء","l":4}]}],"pt63":[{"pt":[{"c":"ا","l":0},{"c":"ت","l":2},{"c":"ا","l":4}]},{"pt":[{"c":"ا,ت,ن,ي","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ا,ن,ت,ي","l":0},{"c":"و","l":3}]},{"pt":[{"c":"م","l":0},{"c":"س","l":1},{"c":"ت","l":2}],"mPt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ف","l":3,"m":3},{"c":"ع","l":4,"m":4},{"c":"ا","l":5},{"c":"ل","l":6,"m":5}]},{"pt":[{"c":"ي","l":1},{"c":"ي","l":3},{"c":"ا","l":4},{"c":"ء","l":5}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":1},{"c":"ا","l":4}]}],"pt54":[{"pt":[{"c":"ت","l":0}]},{"pt":[{"c":"ا,ي,ت,ن","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"م","l":0}],"mPt":[{"c":"ا","l":0},{"c":"ف","l":1,"m":1},{"c":"ع","l":2,"m":2},{"c":"ل","l":3,"m":3},{"c":"ر","l":4,"m":4},{"c":"ا","l":5},{"c":"ر","l":6,"m":4}]},{"pt":[{"c":"ا","l":2}]},{"pt":[{"c":"ا","l":0},{"c":"ن","l":2}]}],"pt64":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":4}]},{"pt":[{"c":"م","l":0},{"c":"ت","l":1}]}],"pt73":[{"pt":[{"c":"ا","l":0},{"c":"س","l":1},{"c":"ت","l":2},{"c":"ا","l":5}]}],"pt75":[{"pt":[{"c":"ا","l":0},{"c":"ا","l":5}]}]}');
self.execArray = [
'cleanWord',
'removeDiacritics',
'cleanAlef',
'removeStopWords',
'normalizeHamzaAndAlef',
'removeStartWaw',
'removePre432',
'removeEndTaa',
'wordCheck'
];
self.stem = function() {
var counter = 0;
self.result = false;
self.preRemoved = false;
self.sufRemoved = false;
while (counter < self.execArray.length && self.result != true) {
self.result = self[self.execArray[counter]]();
counter++;
}
}
self.setCurrent = function(word) {
self.word = word;
}
self.getCurrent = function() {
return self.word
}
/*remove elongating character and test that the word does not contain non-arabic characters.
If the word contains special characters, don't stem. */
self.cleanWord = function() {
var wordCharacters = "\u0621-\u065b\u0671\u0640";
var testRegex = new RegExp("[^" + wordCharacters + "]");
self.word = self.word
.replace(new RegExp('\u0640', 'g'), '');
if (testRegex.test(word)) {
return true;
}
return false;
}
self.removeDiacritics = function() {
var diacriticsRegex = new RegExp("[\u064b-\u065b]");
self.word = self.word.replace(/[\u064b-\u065b]/gi, '');
return false;
}
/*Replace all variations of alef (آأإٱى) to a plain alef (ا)*/
self.cleanAlef = function() {
var alefRegex = new RegExp("[\u0622\u0623\u0625\u0671\u0649]");
self.word = self.word.replace(alefRegex, "\u0627");
return false;
}
/* if the word is a stop word, don't stem*/
self.removeStopWords = function() {
var stopWords = '، اض امين اه اها اي ا اب اجل اجمع اخ اخذ اصبح اضحى اقبل اقل اكثر الا ام اما امامك امامك امسى اما ان انا انت انتم انتما انتن انت انشا انى او اوشك اولئك اولئكم اولاء اولالك اوه اي ايا اين اينما اي ان اي اف اذ اذا اذا اذما اذن الى اليكم اليكما اليكن اليك اليك الا اما ان انما اي اياك اياكم اياكما اياكن ايانا اياه اياها اياهم اياهما اياهن اياي ايه ان ا ابتدا اثر اجل احد اخرى اخلولق اذا اربعة ارتد استحال اطار اعادة اعلنت اف اكثر اكد الالاء الالى الا الاخيرة الان الاول الاولى التى التي الثاني الثانية الذاتي الذى الذي الذين السابق الف اللائي اللاتي اللتان اللتيا اللتين اللذان اللذين اللواتي الماضي المقبل الوقت الى اليوم اما امام امس ان انبرى انقلب انه انها او اول اي ايار ايام ايضا ب بات باسم بان بخ برس بسبب بس بشكل بضع بطان بعد بعض بك بكم بكما بكن بل بلى بما بماذا بمن بن بنا به بها بي بيد بين بس بله بئس تان تانك تبدل تجاه تحول تلقاء تلك تلكم تلكما تم تينك تين ته تي ثلاثة ثم ثم ثمة ثم جعل جلل جميع جير حار حاشا حاليا حاي حتى حرى حسب حم حوالى حول حيث حيثما حين حي حبذا حتى حذار خلا خلال دون دونك ذا ذات ذاك ذانك ذان ذلك ذلكم ذلكما ذلكن ذو ذوا ذواتا ذواتي ذيت ذينك ذين ذه ذي راح رجع رويدك ريث رب زيارة سبحان سرعان سنة سنوات سوف سوى ساء ساءما شبه شخصا شرع شتان صار صباح صفر صه صه ضد ضمن طاق طالما طفق طق ظل عاد عام عاما عامة عدا عدة عدد عدم عسى عشر عشرة علق على عليك عليه عليها عل عن عند عندما عوض عين عدس عما غدا غير ف فان فلان فو فى في فيم فيما فيه فيها قال قام قبل قد قط قلما قوة كانما كاين كاي كاين كاد كان كانت كذا كذلك كرب كل كلا كلاهما كلتا كلم كليكما كليهما كلما كلا كم كما كي كيت كيف كيفما كان كخ لئن لا لات لاسيما لدن لدى لعمر لقاء لك لكم لكما لكن لكنما لكي لكيلا للامم لم لما لما لن لنا له لها لو لوكالة لولا لوما لي لست لست لستم لستما لستن لست لسن لعل لكن ليت ليس ليسا ليستا ليست ليسوا لسنا ما ماانفك مابرح مادام ماذا مازال مافتئ مايو متى مثل مذ مساء مع معاذ مقابل مكانكم مكانكما مكانكن مكانك مليار مليون مما ممن من منذ منها مه مهما من من نحن نحو نعم نفس نفسه نهاية نخ نعما نعم ها هاؤم هاك هاهنا هب هذا هذه هكذا هل هلم هلا هم هما هن هنا هناك هنالك هو هي هيا هيت هيا هؤلاء هاتان هاتين هاته هاتي هج هذا هذان هذين هذه هذي هيهات و وا واحد واضاف واضافت واكد وان واها واوضح وراءك وفي وقال وقالت وقد وقف وكان وكانت ولا ولم ومن وهو وهي ويكان وي وشكان يكون يمكن يوم ايان'.split(' ');
if (stopWords.indexOf(self.word) >= 0) {
return true;
}
}
/* changes ؤ ئ to ء and removes alef if at the end of the word*/
self.normalizeHamzaAndAlef = function() {
self.word = self.word.replace('\u0624', '\u0621');
self.word = self.word.replace('\u0626', '\u0621');
self.word = self.word.replace(/([\u0627])\1+/gi, '\u0627');
return false;
}
/*remove end taa marboota ة*/
self.removeEndTaa = function() {
if (self.word.length > 2) {
self.word = self.word.replace(/[\u0627]$/, '');
self.word = self.word.replace('\u0629', '');
return false;
} else return true;
}
/* if the word starts with double waw وو keep only one of them */
self.removeStartWaw = function() {
if (self.word.length > 3 && self.word[0] == '\u0648' && self.word[1] == '\u0648') {
self.word = self.word.slice(1);
}
return false;
}
/* remove prefixes of size 4, 3 and 2 characters */
self.removePre432 = function() {
var word = self.word;
if (self.word.length >= 7) {
var pre4Regex = new RegExp('^(' + self.pre.pre4.split(' ').join('|') + ')')
self.word = self.word.replace(pre4Regex, '');
}
if (self.word == word && self.word.length >= 6) {
var pre3Regex = new RegExp('^(' + self.pre.pre3.split(' ').join('|') + ')')
self.word = self.word.replace(pre3Regex, '');
}
if (self.word == word && self.word.length >= 5) {
var pre2Regex = new RegExp('^(' + self.pre.pre2.split(' ').join('|') + ')')
self.word = self.word.replace(pre2Regex, '');
}
if (word != self.word) self.preRemoved = true;
return false;
}
/* check the word against word patterns. If the word matches a pattern, map it to the
alternative pattern if available then stop stemming. */
self.patternCheck = function(pattern) {
var patternMatch = false;
for (var i = 0; i < pattern.length; i++) {
var currentPatternCheck = true;
for (var j = 0; j < pattern[i].pt.length; j++) {
var chars = pattern[i].pt[j].c.split(',');
var charMatch = false;
chars.forEach(function(el) {
if (self.word[pattern[i].pt[j].l] == el) {
charMatch = true;
}
})
if (!charMatch) {
currentPatternCheck = false;
break;
}
}
if (currentPatternCheck == true) {
if (pattern[i].mPt) {
var newWord = [];
for (var k = 0; k < pattern[i].mPt.length; k++) {
if (pattern[i].mPt[k].m != null) {
newWord[pattern[i].mPt[k].l] = self.word[pattern[i].mPt[k].m]
} else {
newWord[pattern[i].mPt[k].l] = pattern[i].mPt[k].c
}
}
self.word = newWord.join('');
}
self.result = true;
break;
}
}
}
/* remove prefixes of size 1 char*/
self.removePre1 = function() {
var word = self.word;
if (self.preRemoved == false)
if (self.word.length > 3) {
var pre1Regex = new RegExp('^(' + self.pre.pre1.split(' ').join('|') + ')')
self.word = self.word.replace(pre1Regex, '');
}
if (word != self.word) self.preRemoved = true;
return false;
}
/*remove suffixes of size 1 char */
self.removeSuf1 = function() {
var word = self.word;
if (self.sufRemoved == false)
if (self.word.length > 3) {
var suf1Regex = new RegExp('(' + self.suf.suf1.split(' ').join('|') + ')$')
self.word = self.word.replace(suf1Regex, '');
}
if (word != self.word) self.sufRemoved = true;
return false;
}
/*remove suffixes of size 4, 3 and 2 chars*/
self.removeSuf432 = function() {
var word = self.word;
if (self.word.length >= 6) {
var suf4Regex = new RegExp('(' + self.suf.suf4.split(' ').join('|') + ')$')
self.word = self.word.replace(suf4Regex, '');
}
if (self.word == word && self.word.length >= 5) {
var suf3Regex = new RegExp('(' + self.suf.suf3.split(' ').join('|') + ')$')
self.word = self.word.replace(suf3Regex, '');
}
if (self.word == word && self.word.length >= 4) {
var suf2Regex = new RegExp('(' + self.suf.suf2.split(' ').join('|') + ')$')
self.word = self.word.replace(suf2Regex, '');
}
if (word != self.word) self.sufRemoved = true;
return false;
}
/*check the word length and decide what is the next step accordingly*/
self.wordCheck = function() {
var word = self.word;
var word7Exec = [self.removeSuf432, self.removeSuf1, self.removePre1]
var counter = 0;
var patternChecked = false;
while (self.word.length >= 7 && !self.result && counter < word7Exec.length) {
if (self.word.length == 7 && !patternChecked) {
self.checkPattern73();
patternChecked = true;
} else {
word7Exec[counter]();
counter++;
patternChecked = false;
}
}
var word6Exec = [self.checkPattern63, self.removeSuf432, self.removeSuf1, self.removePre1, self.checkPattern64];
counter = 0;
while (self.word.length == 6 && !self.result && counter < word6Exec.length) {
word6Exec[counter]();
counter++;
}
var word5Exec = [self.checkPattern53, self.removeSuf432, self.removeSuf1, self.removePre1, self.checkPattern54];
counter = 0;
while (self.word.length == 5 && !self.result && counter < word5Exec.length) {
word5Exec[counter]();
counter++;
}
var word4Exec = [self.checkPattern43, self.removeSuf1, self.removePre1, self.removeSuf432];
counter = 0;
while (self.word.length == 4 && !self.result && counter < word4Exec.length) {
word4Exec[counter]();
counter++;
}
return true;
}
self.checkPattern43 = function() {
self.patternCheck(self.patterns.pt43)
}
self.checkPattern53 = function() {
self.patternCheck(self.patterns.pt53)
}
self.checkPattern54 = function() {
self.patternCheck(self.patterns.pt54)
}
self.checkPattern63 = function() {
self.patternCheck(self.patterns.pt63)
}
self.checkPattern64 = function() {
self.patternCheck(self.patterns.pt64)
}
self.checkPattern73 = function() {
self.patternCheck(self.patterns.pt73)
}
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
self.setCurrent(word);
self.stem();
return self.getCurrent();
})
} else { // for lunr version <= 1
self.setCurrent(token);
self.stem();
return self.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.ar.stemmer, 'stemmer-ar');
lunr.ar.stopWordFilter = lunr.generateStopWordFilter('، اض امين اه اها اي ا اب اجل اجمع اخ اخذ اصبح اضحى اقبل اقل اكثر الا ام اما امامك امامك امسى اما ان انا انت انتم انتما انتن انت انشا انى او اوشك اولئك اولئكم اولاء اولالك اوه اي ايا اين اينما اي ان اي اف اذ اذا اذا اذما اذن الى اليكم اليكما اليكن اليك اليك الا اما ان انما اي اياك اياكم اياكما اياكن ايانا اياه اياها اياهم اياهما اياهن اياي ايه ان ا ابتدا اثر اجل احد اخرى اخلولق اذا اربعة ارتد استحال اطار اعادة اعلنت اف اكثر اكد الالاء الالى الا الاخيرة الان الاول الاولى التى التي الثاني الثانية الذاتي الذى الذي الذين السابق الف اللائي اللاتي اللتان اللتيا اللتين اللذان اللذين اللواتي الماضي المقبل الوقت الى اليوم اما امام امس ان انبرى انقلب انه انها او اول اي ايار ايام ايضا ب بات باسم بان بخ برس بسبب بس بشكل بضع بطان بعد بعض بك بكم بكما بكن بل بلى بما بماذا بمن بن بنا به بها بي بيد بين بس بله بئس تان تانك تبدل تجاه تحول تلقاء تلك تلكم تلكما تم تينك تين ته تي ثلاثة ثم ثم ثمة ثم جعل جلل جميع جير حار حاشا حاليا حاي حتى حرى حسب حم حوالى حول حيث حيثما حين حي حبذا حتى حذار خلا خلال دون دونك ذا ذات ذاك ذانك ذان ذلك ذلكم ذلكما ذلكن ذو ذوا ذواتا ذواتي ذيت ذينك ذين ذه ذي راح رجع رويدك ريث رب زيارة سبحان سرعان سنة سنوات سوف سوى ساء ساءما شبه شخصا شرع شتان صار صباح صفر صه صه ضد ضمن طاق طالما طفق طق ظل عاد عام عاما عامة عدا عدة عدد عدم عسى عشر عشرة علق على عليك عليه عليها عل عن عند عندما عوض عين عدس عما غدا غير ف فان فلان فو فى في فيم فيما فيه فيها قال قام قبل قد قط قلما قوة كانما كاين كاي كاين كاد كان كانت كذا كذلك كرب كل كلا كلاهما كلتا كلم كليكما كليهما كلما كلا كم كما كي كيت كيف كيفما كان كخ لئن لا لات لاسيما لدن لدى لعمر لقاء لك لكم لكما لكن لكنما لكي لكيلا للامم لم لما لما لن لنا له لها لو لوكالة لولا لوما لي لست لست لستم لستما لستن لست لسن لعل لكن ليت ليس ليسا ليستا ليست ليسوا لسنا ما ماانفك مابرح مادام ماذا مازال مافتئ مايو متى مثل مذ مساء مع معاذ مقابل مكانكم مكانكما مكانكن مكانك مليار مليون مما ممن من منذ منها مه مهما من من نحن نحو نعم نفس نفسه نهاية نخ نعما نعم ها هاؤم هاك هاهنا هب هذا هذه هكذا هل هلم هلا هم هما هن هنا هناك هنالك هو هي هيا هيت هيا هؤلاء هاتان هاتين هاته هاتي هج هذا هذان هذين هذه هذي هيهات وا واحد واضاف واضافت واكد وان واها واوضح وراءك وفي وقال وقالت وقد وقف وكان وكانت ولا ولم ومن وهو وهي ويكان وي وشكان يكون يمكن يوم ايان'.split(' '));
lunr.Pipeline.registerFunction(lunr.ar.stopWordFilter, 'stopWordFilter-ar');
};
}))
@@ -0,0 +1,284 @@
/*!
* Lunr languages, `Danish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.da = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.da.trimmer,
lunr.da.stopWordFilter,
lunr.da.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.da.stemmer)
}
};
/* lunr trimmer function */
lunr.da.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.da.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.da.wordCharacters);
lunr.Pipeline.registerFunction(lunr.da.trimmer, 'trimmer-da');
/* lunr stemmer function */
lunr.da.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function DanishStemmer() {
var a_0 = [new Among("hed", -1, 1), new Among("ethed", 0, 1),
new Among("ered", -1, 1), new Among("e", -1, 1),
new Among("erede", 3, 1), new Among("ende", 3, 1),
new Among("erende", 5, 1), new Among("ene", 3, 1),
new Among("erne", 3, 1), new Among("ere", 3, 1),
new Among("en", -1, 1), new Among("heden", 10, 1),
new Among("eren", 10, 1), new Among("er", -1, 1),
new Among("heder", 13, 1), new Among("erer", 13, 1),
new Among("s", -1, 2), new Among("heds", 16, 1),
new Among("es", 16, 1), new Among("endes", 18, 1),
new Among("erendes", 19, 1), new Among("enes", 18, 1),
new Among("ernes", 18, 1), new Among("eres", 18, 1),
new Among("ens", 16, 1), new Among("hedens", 24, 1),
new Among("erens", 24, 1), new Among("ers", 16, 1),
new Among("ets", 16, 1), new Among("erets", 28, 1),
new Among("et", -1, 1), new Among("eret", 30, 1)
],
a_1 = [
new Among("gd", -1, -1), new Among("dt", -1, -1),
new Among("gt", -1, -1), new Among("kt", -1, -1)
],
a_2 = [
new Among("ig", -1, 1), new Among("lig", 0, 1),
new Among("elig", 1, 1), new Among("els", -1, 1),
new Among("l\u00F8st", -1, 2)
],
g_v = [17, 65, 16, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 128
],
g_s_ending = [239, 254, 42, 3,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16
],
I_x, I_p1, S_ch, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_mark_regions() {
var v_1, c = sbp.cursor + 3;
I_p1 = sbp.limit;
if (0 <= c && c <= sbp.limit) {
I_x = c;
while (true) {
v_1 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 248)) {
sbp.cursor = v_1;
break;
}
sbp.cursor = v_1;
if (v_1 >= sbp.limit)
return;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 248)) {
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
I_p1 = sbp.cursor;
if (I_p1 < I_x)
I_p1 = I_x;
}
}
function r_main_suffix() {
var among_var, v_1;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_0, 32);
sbp.limit_backward = v_1;
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
if (sbp.in_grouping_b(g_s_ending, 97, 229))
sbp.slice_del();
break;
}
}
}
}
function r_consonant_pair() {
var v_1 = sbp.limit - sbp.cursor,
v_2;
if (sbp.cursor >= I_p1) {
v_2 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
if (sbp.find_among_b(a_1, 4)) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_2;
sbp.cursor = sbp.limit - v_1;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
} else
sbp.limit_backward = v_2;
}
}
function r_other_suffix() {
var among_var, v_1 = sbp.limit - sbp.cursor,
v_2, v_3;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "st")) {
sbp.bra = sbp.cursor;
if (sbp.eq_s_b(2, "ig"))
sbp.slice_del();
}
sbp.cursor = sbp.limit - v_1;
if (sbp.cursor >= I_p1) {
v_2 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_2, 5);
sbp.limit_backward = v_2;
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_del();
v_3 = sbp.limit - sbp.cursor;
r_consonant_pair();
sbp.cursor = sbp.limit - v_3;
break;
case 2:
sbp.slice_from("l\u00F8s");
break;
}
}
}
}
function r_undouble() {
var v_1;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
if (sbp.out_grouping_b(g_v, 97, 248)) {
sbp.bra = sbp.cursor;
S_ch = sbp.slice_to(S_ch);
sbp.limit_backward = v_1;
if (sbp.eq_v_b(S_ch))
sbp.slice_del();
} else
sbp.limit_backward = v_1;
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_main_suffix();
sbp.cursor = sbp.limit;
r_consonant_pair();
sbp.cursor = sbp.limit;
r_other_suffix();
sbp.cursor = sbp.limit;
r_undouble();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.da.stemmer, 'stemmer-da');
lunr.da.stopWordFilter = lunr.generateStopWordFilter('ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været'.split(' '));
lunr.Pipeline.registerFunction(lunr.da.stopWordFilter, 'stopWordFilter-da');
};
}))
@@ -0,0 +1,384 @@
/*!
* Lunr languages, `German` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.de = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.de.trimmer,
lunr.de.stopWordFilter,
lunr.de.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.de.stemmer)
}
};
/* lunr trimmer function */
lunr.de.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.de.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.de.wordCharacters);
lunr.Pipeline.registerFunction(lunr.de.trimmer, 'trimmer-de');
/* lunr stemmer function */
lunr.de.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function GermanStemmer() {
var a_0 = [new Among("", -1, 6), new Among("U", 0, 2),
new Among("Y", 0, 1), new Among("\u00E4", 0, 3),
new Among("\u00F6", 0, 4), new Among("\u00FC", 0, 5)
],
a_1 = [
new Among("e", -1, 2), new Among("em", -1, 1),
new Among("en", -1, 2), new Among("ern", -1, 1),
new Among("er", -1, 1), new Among("s", -1, 3),
new Among("es", 5, 2)
],
a_2 = [new Among("en", -1, 1),
new Among("er", -1, 1), new Among("st", -1, 2),
new Among("est", 2, 1)
],
a_3 = [new Among("ig", -1, 1),
new Among("lich", -1, 1)
],
a_4 = [new Among("end", -1, 1),
new Among("ig", -1, 2), new Among("ung", -1, 1),
new Among("lich", -1, 3), new Among("isch", -1, 2),
new Among("ik", -1, 2), new Among("heit", -1, 3),
new Among("keit", -1, 4)
],
g_v = [17, 65, 16, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 8, 0, 32, 8
],
g_s_ending = [117, 30, 5],
g_st_ending = [
117, 30, 4
],
I_x, I_p2, I_p1, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function habr1(c1, c2, v_1) {
if (sbp.eq_s(1, c1)) {
sbp.ket = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 252)) {
sbp.slice_from(c2);
sbp.cursor = v_1;
return true;
}
}
return false;
}
function r_prelude() {
var v_1 = sbp.cursor,
v_2, v_3, v_4, v_5;
while (true) {
v_2 = sbp.cursor;
sbp.bra = v_2;
if (sbp.eq_s(1, "\u00DF")) {
sbp.ket = sbp.cursor;
sbp.slice_from("ss");
} else {
if (v_2 >= sbp.limit)
break;
sbp.cursor = v_2 + 1;
}
}
sbp.cursor = v_1;
while (true) {
v_3 = sbp.cursor;
while (true) {
v_4 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 252)) {
v_5 = sbp.cursor;
sbp.bra = v_5;
if (habr1("u", "U", v_4))
break;
sbp.cursor = v_5;
if (habr1("y", "Y", v_4))
break;
}
if (v_4 >= sbp.limit) {
sbp.cursor = v_3;
return;
}
sbp.cursor = v_4 + 1;
}
}
}
function habr2() {
while (!sbp.in_grouping(g_v, 97, 252)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 252)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
function r_mark_regions() {
I_p1 = sbp.limit;
I_p2 = I_p1;
var c = sbp.cursor + 3;
if (0 <= c && c <= sbp.limit) {
I_x = c;
if (!habr2()) {
I_p1 = sbp.cursor;
if (I_p1 < I_x)
I_p1 = I_x;
if (!habr2())
I_p2 = sbp.cursor;
}
}
}
function r_postlude() {
var among_var, v_1;
while (true) {
v_1 = sbp.cursor;
sbp.bra = v_1;
among_var = sbp.find_among(a_0, 6);
if (!among_var)
return;
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("y");
break;
case 2:
case 5:
sbp.slice_from("u");
break;
case 3:
sbp.slice_from("a");
break;
case 4:
sbp.slice_from("o");
break;
case 6:
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
break;
}
}
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_standard_suffix() {
var among_var, v_1 = sbp.limit - sbp.cursor,
v_2, v_3, v_4;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_1, 7);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "s")) {
sbp.bra = sbp.cursor;
if (sbp.eq_s_b(3, "nis"))
sbp.slice_del();
}
break;
case 3:
if (sbp.in_grouping_b(g_s_ending, 98, 116))
sbp.slice_del();
break;
}
}
}
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_2, 4);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
if (sbp.in_grouping_b(g_st_ending, 98, 116)) {
var c = sbp.cursor - 3;
if (sbp.limit_backward <= c && c <= sbp.limit) {
sbp.cursor = c;
sbp.slice_del();
}
}
break;
}
}
}
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 8);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R2()) {
switch (among_var) {
case 1:
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "ig")) {
sbp.bra = sbp.cursor;
v_2 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "e")) {
sbp.cursor = sbp.limit - v_2;
if (r_R2())
sbp.slice_del();
}
}
break;
case 2:
v_3 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "e")) {
sbp.cursor = sbp.limit - v_3;
sbp.slice_del();
}
break;
case 3:
sbp.slice_del();
sbp.ket = sbp.cursor;
v_4 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(2, "er")) {
sbp.cursor = sbp.limit - v_4;
if (!sbp.eq_s_b(2, "en"))
break;
}
sbp.bra = sbp.cursor;
if (r_R1())
sbp.slice_del();
break;
case 4:
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 2);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R2() && among_var == 1)
sbp.slice_del();
}
break;
}
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_prelude();
sbp.cursor = v_1;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_standard_suffix();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.de.stemmer, 'stemmer-de');
lunr.de.stopWordFilter = lunr.generateStopWordFilter('aber alle allem allen aller alles als also am an ander andere anderem anderen anderer anderes anderm andern anderr anders auch auf aus bei bin bis bist da damit dann das dasselbe dazu daß dein deine deinem deinen deiner deines dem demselben den denn denselben der derer derselbe derselben des desselben dessen dich die dies diese dieselbe dieselben diesem diesen dieser dieses dir doch dort du durch ein eine einem einen einer eines einig einige einigem einigen einiger einiges einmal er es etwas euch euer eure eurem euren eurer eures für gegen gewesen hab habe haben hat hatte hatten hier hin hinter ich ihm ihn ihnen ihr ihre ihrem ihren ihrer ihres im in indem ins ist jede jedem jeden jeder jedes jene jenem jenen jener jenes jetzt kann kein keine keinem keinen keiner keines können könnte machen man manche manchem manchen mancher manches mein meine meinem meinen meiner meines mich mir mit muss musste nach nicht nichts noch nun nur ob oder ohne sehr sein seine seinem seinen seiner seines selbst sich sie sind so solche solchem solchen solcher solches soll sollte sondern sonst um und uns unse unsem unsen unser unses unter viel vom von vor war waren warst was weg weil weiter welche welchem welchen welcher welches wenn werde werden wie wieder will wir wird wirst wo wollen wollte während würde würden zu zum zur zwar zwischen über'.split(' '));
lunr.Pipeline.registerFunction(lunr.de.stopWordFilter, 'stopWordFilter-de');
};
}))
@@ -0,0 +1,450 @@
/*!
* Lunr languages, `Dutch` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
console.warn("[Lunr Languages] Please use the \"nl\" instead of the \"du\". The \"nl\" code is the standard code for Dutch language, and \"du\" will be removed in the next major versions.");
/* register specific locale function */
lunr.du = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.du.trimmer,
lunr.du.stopWordFilter,
lunr.du.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.du.stemmer)
}
};
/* lunr trimmer function */
lunr.du.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.du.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.du.wordCharacters);
lunr.Pipeline.registerFunction(lunr.du.trimmer, 'trimmer-du');
/* lunr stemmer function */
lunr.du.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function DutchStemmer() {
var a_0 = [new Among("", -1, 6), new Among("\u00E1", 0, 1),
new Among("\u00E4", 0, 1), new Among("\u00E9", 0, 2),
new Among("\u00EB", 0, 2), new Among("\u00ED", 0, 3),
new Among("\u00EF", 0, 3), new Among("\u00F3", 0, 4),
new Among("\u00F6", 0, 4), new Among("\u00FA", 0, 5),
new Among("\u00FC", 0, 5)
],
a_1 = [new Among("", -1, 3),
new Among("I", 0, 2), new Among("Y", 0, 1)
],
a_2 = [
new Among("dd", -1, -1), new Among("kk", -1, -1),
new Among("tt", -1, -1)
],
a_3 = [new Among("ene", -1, 2),
new Among("se", -1, 3), new Among("en", -1, 2),
new Among("heden", 2, 1), new Among("s", -1, 3)
],
a_4 = [
new Among("end", -1, 1), new Among("ig", -1, 2),
new Among("ing", -1, 1), new Among("lijk", -1, 3),
new Among("baar", -1, 4), new Among("bar", -1, 5)
],
a_5 = [
new Among("aa", -1, -1), new Among("ee", -1, -1),
new Among("oo", -1, -1), new Among("uu", -1, -1)
],
g_v = [17, 65,
16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
],
g_v_I = [1, 0, 0,
17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
],
g_v_j = [
17, 67, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
],
I_p2, I_p1, B_e_found, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_prelude() {
var among_var, v_1 = sbp.cursor,
v_2, v_3;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_0, 11);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("a");
continue;
case 2:
sbp.slice_from("e");
continue;
case 3:
sbp.slice_from("i");
continue;
case 4:
sbp.slice_from("o");
continue;
case 5:
sbp.slice_from("u");
continue;
case 6:
if (sbp.cursor >= sbp.limit)
break;
sbp.cursor++;
continue;
}
}
break;
}
sbp.cursor = v_1;
sbp.bra = v_1;
if (sbp.eq_s(1, "y")) {
sbp.ket = sbp.cursor;
sbp.slice_from("Y");
} else
sbp.cursor = v_1;
while (true) {
v_2 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 232)) {
v_3 = sbp.cursor;
sbp.bra = v_3;
if (sbp.eq_s(1, "i")) {
sbp.ket = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 232)) {
sbp.slice_from("I");
sbp.cursor = v_2;
}
} else {
sbp.cursor = v_3;
if (sbp.eq_s(1, "y")) {
sbp.ket = sbp.cursor;
sbp.slice_from("Y");
sbp.cursor = v_2;
} else if (habr1(v_2))
break;
}
} else if (habr1(v_2))
break;
}
}
function habr1(v_1) {
sbp.cursor = v_1;
if (v_1 >= sbp.limit)
return true;
sbp.cursor++;
return false;
}
function r_mark_regions() {
I_p1 = sbp.limit;
I_p2 = I_p1;
if (!habr2()) {
I_p1 = sbp.cursor;
if (I_p1 < 3)
I_p1 = 3;
if (!habr2())
I_p2 = sbp.cursor;
}
}
function habr2() {
while (!sbp.in_grouping(g_v, 97, 232)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 232)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
function r_postlude() {
var among_var;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_1, 3);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("y");
break;
case 2:
sbp.slice_from("i");
break;
case 3:
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
break;
}
}
}
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_undouble() {
var v_1 = sbp.limit - sbp.cursor;
if (sbp.find_among_b(a_2, 3)) {
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
}
}
function r_e_ending() {
var v_1;
B_e_found = false;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "e")) {
sbp.bra = sbp.cursor;
if (r_R1()) {
v_1 = sbp.limit - sbp.cursor;
if (sbp.out_grouping_b(g_v, 97, 232)) {
sbp.cursor = sbp.limit - v_1;
sbp.slice_del();
B_e_found = true;
r_undouble();
}
}
}
}
function r_en_ending() {
var v_1;
if (r_R1()) {
v_1 = sbp.limit - sbp.cursor;
if (sbp.out_grouping_b(g_v, 97, 232)) {
sbp.cursor = sbp.limit - v_1;
if (!sbp.eq_s_b(3, "gem")) {
sbp.cursor = sbp.limit - v_1;
sbp.slice_del();
r_undouble();
}
}
}
}
function r_standard_suffix() {
var among_var, v_1 = sbp.limit - sbp.cursor,
v_2, v_3, v_4, v_5, v_6;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 5);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_R1())
sbp.slice_from("heid");
break;
case 2:
r_en_ending();
break;
case 3:
if (r_R1() && sbp.out_grouping_b(g_v_j, 97, 232))
sbp.slice_del();
break;
}
}
sbp.cursor = sbp.limit - v_1;
r_e_ending();
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(4, "heid")) {
sbp.bra = sbp.cursor;
if (r_R2()) {
v_2 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "c")) {
sbp.cursor = sbp.limit - v_2;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "en")) {
sbp.bra = sbp.cursor;
r_en_ending();
}
}
}
}
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 6);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_R2()) {
sbp.slice_del();
v_3 = sbp.limit - sbp.cursor;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "ig")) {
sbp.bra = sbp.cursor;
if (r_R2()) {
v_4 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "e")) {
sbp.cursor = sbp.limit - v_4;
sbp.slice_del();
break;
}
}
}
sbp.cursor = sbp.limit - v_3;
r_undouble();
}
break;
case 2:
if (r_R2()) {
v_5 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "e")) {
sbp.cursor = sbp.limit - v_5;
sbp.slice_del();
}
}
break;
case 3:
if (r_R2()) {
sbp.slice_del();
r_e_ending();
}
break;
case 4:
if (r_R2())
sbp.slice_del();
break;
case 5:
if (r_R2() && B_e_found)
sbp.slice_del();
break;
}
}
sbp.cursor = sbp.limit - v_1;
if (sbp.out_grouping_b(g_v_I, 73, 232)) {
v_6 = sbp.limit - sbp.cursor;
if (sbp.find_among_b(a_5, 4) && sbp.out_grouping_b(g_v, 97, 232)) {
sbp.cursor = sbp.limit - v_6;
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_prelude();
sbp.cursor = v_1;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_standard_suffix();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.du.stemmer, 'stemmer-du');
lunr.du.stopWordFilter = lunr.generateStopWordFilter(' aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou'.split(' '));
lunr.Pipeline.registerFunction(lunr.du.stopWordFilter, 'stopWordFilter-du');
};
}))
@@ -0,0 +1,599 @@
/*!
* Lunr languages, `Spanish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.es = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.es.trimmer,
lunr.es.stopWordFilter,
lunr.es.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.es.stemmer)
}
};
/* lunr trimmer function */
lunr.es.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.es.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.es.wordCharacters);
lunr.Pipeline.registerFunction(lunr.es.trimmer, 'trimmer-es');
/* lunr stemmer function */
lunr.es.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function SpanishStemmer() {
var a_0 = [new Among("", -1, 6), new Among("\u00E1", 0, 1),
new Among("\u00E9", 0, 2), new Among("\u00ED", 0, 3),
new Among("\u00F3", 0, 4), new Among("\u00FA", 0, 5)
],
a_1 = [
new Among("la", -1, -1), new Among("sela", 0, -1),
new Among("le", -1, -1), new Among("me", -1, -1),
new Among("se", -1, -1), new Among("lo", -1, -1),
new Among("selo", 5, -1), new Among("las", -1, -1),
new Among("selas", 7, -1), new Among("les", -1, -1),
new Among("los", -1, -1), new Among("selos", 10, -1),
new Among("nos", -1, -1)
],
a_2 = [new Among("ando", -1, 6),
new Among("iendo", -1, 6), new Among("yendo", -1, 7),
new Among("\u00E1ndo", -1, 2), new Among("i\u00E9ndo", -1, 1),
new Among("ar", -1, 6), new Among("er", -1, 6),
new Among("ir", -1, 6), new Among("\u00E1r", -1, 3),
new Among("\u00E9r", -1, 4), new Among("\u00EDr", -1, 5)
],
a_3 = [
new Among("ic", -1, -1), new Among("ad", -1, -1),
new Among("os", -1, -1), new Among("iv", -1, 1)
],
a_4 = [
new Among("able", -1, 1), new Among("ible", -1, 1),
new Among("ante", -1, 1)
],
a_5 = [new Among("ic", -1, 1),
new Among("abil", -1, 1), new Among("iv", -1, 1)
],
a_6 = [
new Among("ica", -1, 1), new Among("ancia", -1, 2),
new Among("encia", -1, 5), new Among("adora", -1, 2),
new Among("osa", -1, 1), new Among("ista", -1, 1),
new Among("iva", -1, 9), new Among("anza", -1, 1),
new Among("log\u00EDa", -1, 3), new Among("idad", -1, 8),
new Among("able", -1, 1), new Among("ible", -1, 1),
new Among("ante", -1, 2), new Among("mente", -1, 7),
new Among("amente", 13, 6), new Among("aci\u00F3n", -1, 2),
new Among("uci\u00F3n", -1, 4), new Among("ico", -1, 1),
new Among("ismo", -1, 1), new Among("oso", -1, 1),
new Among("amiento", -1, 1), new Among("imiento", -1, 1),
new Among("ivo", -1, 9), new Among("ador", -1, 2),
new Among("icas", -1, 1), new Among("ancias", -1, 2),
new Among("encias", -1, 5), new Among("adoras", -1, 2),
new Among("osas", -1, 1), new Among("istas", -1, 1),
new Among("ivas", -1, 9), new Among("anzas", -1, 1),
new Among("log\u00EDas", -1, 3), new Among("idades", -1, 8),
new Among("ables", -1, 1), new Among("ibles", -1, 1),
new Among("aciones", -1, 2), new Among("uciones", -1, 4),
new Among("adores", -1, 2), new Among("antes", -1, 2),
new Among("icos", -1, 1), new Among("ismos", -1, 1),
new Among("osos", -1, 1), new Among("amientos", -1, 1),
new Among("imientos", -1, 1), new Among("ivos", -1, 9)
],
a_7 = [
new Among("ya", -1, 1), new Among("ye", -1, 1),
new Among("yan", -1, 1), new Among("yen", -1, 1),
new Among("yeron", -1, 1), new Among("yendo", -1, 1),
new Among("yo", -1, 1), new Among("yas", -1, 1),
new Among("yes", -1, 1), new Among("yais", -1, 1),
new Among("yamos", -1, 1), new Among("y\u00F3", -1, 1)
],
a_8 = [
new Among("aba", -1, 2), new Among("ada", -1, 2),
new Among("ida", -1, 2), new Among("ara", -1, 2),
new Among("iera", -1, 2), new Among("\u00EDa", -1, 2),
new Among("ar\u00EDa", 5, 2), new Among("er\u00EDa", 5, 2),
new Among("ir\u00EDa", 5, 2), new Among("ad", -1, 2),
new Among("ed", -1, 2), new Among("id", -1, 2),
new Among("ase", -1, 2), new Among("iese", -1, 2),
new Among("aste", -1, 2), new Among("iste", -1, 2),
new Among("an", -1, 2), new Among("aban", 16, 2),
new Among("aran", 16, 2), new Among("ieran", 16, 2),
new Among("\u00EDan", 16, 2), new Among("ar\u00EDan", 20, 2),
new Among("er\u00EDan", 20, 2), new Among("ir\u00EDan", 20, 2),
new Among("en", -1, 1), new Among("asen", 24, 2),
new Among("iesen", 24, 2), new Among("aron", -1, 2),
new Among("ieron", -1, 2), new Among("ar\u00E1n", -1, 2),
new Among("er\u00E1n", -1, 2), new Among("ir\u00E1n", -1, 2),
new Among("ado", -1, 2), new Among("ido", -1, 2),
new Among("ando", -1, 2), new Among("iendo", -1, 2),
new Among("ar", -1, 2), new Among("er", -1, 2),
new Among("ir", -1, 2), new Among("as", -1, 2),
new Among("abas", 39, 2), new Among("adas", 39, 2),
new Among("idas", 39, 2), new Among("aras", 39, 2),
new Among("ieras", 39, 2), new Among("\u00EDas", 39, 2),
new Among("ar\u00EDas", 45, 2), new Among("er\u00EDas", 45, 2),
new Among("ir\u00EDas", 45, 2), new Among("es", -1, 1),
new Among("ases", 49, 2), new Among("ieses", 49, 2),
new Among("abais", -1, 2), new Among("arais", -1, 2),
new Among("ierais", -1, 2), new Among("\u00EDais", -1, 2),
new Among("ar\u00EDais", 55, 2), new Among("er\u00EDais", 55, 2),
new Among("ir\u00EDais", 55, 2), new Among("aseis", -1, 2),
new Among("ieseis", -1, 2), new Among("asteis", -1, 2),
new Among("isteis", -1, 2), new Among("\u00E1is", -1, 2),
new Among("\u00E9is", -1, 1), new Among("ar\u00E9is", 64, 2),
new Among("er\u00E9is", 64, 2), new Among("ir\u00E9is", 64, 2),
new Among("ados", -1, 2), new Among("idos", -1, 2),
new Among("amos", -1, 2), new Among("\u00E1bamos", 70, 2),
new Among("\u00E1ramos", 70, 2), new Among("i\u00E9ramos", 70, 2),
new Among("\u00EDamos", 70, 2), new Among("ar\u00EDamos", 74, 2),
new Among("er\u00EDamos", 74, 2), new Among("ir\u00EDamos", 74, 2),
new Among("emos", -1, 1), new Among("aremos", 78, 2),
new Among("eremos", 78, 2), new Among("iremos", 78, 2),
new Among("\u00E1semos", 78, 2), new Among("i\u00E9semos", 78, 2),
new Among("imos", -1, 2), new Among("ar\u00E1s", -1, 2),
new Among("er\u00E1s", -1, 2), new Among("ir\u00E1s", -1, 2),
new Among("\u00EDs", -1, 2), new Among("ar\u00E1", -1, 2),
new Among("er\u00E1", -1, 2), new Among("ir\u00E1", -1, 2),
new Among("ar\u00E9", -1, 2), new Among("er\u00E9", -1, 2),
new Among("ir\u00E9", -1, 2), new Among("i\u00F3", -1, 2)
],
a_9 = [
new Among("a", -1, 1), new Among("e", -1, 2),
new Among("o", -1, 1), new Among("os", -1, 1),
new Among("\u00E1", -1, 1), new Among("\u00E9", -1, 2),
new Among("\u00ED", -1, 1), new Among("\u00F3", -1, 1)
],
g_v = [17,
65, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 17, 4, 10
],
I_p2, I_p1, I_pV, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function habr1() {
if (sbp.out_grouping(g_v, 97, 252)) {
while (!sbp.in_grouping(g_v, 97, 252)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
return true;
}
function habr2() {
if (sbp.in_grouping(g_v, 97, 252)) {
var v_1 = sbp.cursor;
if (habr1()) {
sbp.cursor = v_1;
if (!sbp.in_grouping(g_v, 97, 252))
return true;
while (!sbp.out_grouping(g_v, 97, 252)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
}
return false;
}
return true;
}
function habr3() {
var v_1 = sbp.cursor,
v_2;
if (habr2()) {
sbp.cursor = v_1;
if (!sbp.out_grouping(g_v, 97, 252))
return;
v_2 = sbp.cursor;
if (habr1()) {
sbp.cursor = v_2;
if (!sbp.in_grouping(g_v, 97, 252) || sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
}
I_pV = sbp.cursor;
}
function habr4() {
while (!sbp.in_grouping(g_v, 97, 252)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 252)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
return true;
}
function r_mark_regions() {
var v_1 = sbp.cursor;
I_pV = sbp.limit;
I_p1 = I_pV;
I_p2 = I_pV;
habr3();
sbp.cursor = v_1;
if (habr4()) {
I_p1 = sbp.cursor;
if (habr4())
I_p2 = sbp.cursor;
}
}
function r_postlude() {
var among_var;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_0, 6);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("a");
continue;
case 2:
sbp.slice_from("e");
continue;
case 3:
sbp.slice_from("i");
continue;
case 4:
sbp.slice_from("o");
continue;
case 5:
sbp.slice_from("u");
continue;
case 6:
if (sbp.cursor >= sbp.limit)
break;
sbp.cursor++;
continue;
}
}
break;
}
}
function r_RV() {
return I_pV <= sbp.cursor;
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_attached_pronoun() {
var among_var;
sbp.ket = sbp.cursor;
if (sbp.find_among_b(a_1, 13)) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among_b(a_2, 11);
if (among_var && r_RV())
switch (among_var) {
case 1:
sbp.bra = sbp.cursor;
sbp.slice_from("iendo");
break;
case 2:
sbp.bra = sbp.cursor;
sbp.slice_from("ando");
break;
case 3:
sbp.bra = sbp.cursor;
sbp.slice_from("ar");
break;
case 4:
sbp.bra = sbp.cursor;
sbp.slice_from("er");
break;
case 5:
sbp.bra = sbp.cursor;
sbp.slice_from("ir");
break;
case 6:
sbp.slice_del();
break;
case 7:
if (sbp.eq_s_b(1, "u"))
sbp.slice_del();
break;
}
}
}
function habr5(a, n) {
if (!r_R2())
return true;
sbp.slice_del();
sbp.ket = sbp.cursor;
var among_var = sbp.find_among_b(a, n);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1 && r_R2())
sbp.slice_del();
}
return false;
}
function habr6(c1) {
if (!r_R2())
return true;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, c1)) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
return false;
}
function r_standard_suffix() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_6, 46);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (!r_R2())
return false;
sbp.slice_del();
break;
case 2:
if (habr6("ic"))
return false;
break;
case 3:
if (!r_R2())
return false;
sbp.slice_from("log");
break;
case 4:
if (!r_R2())
return false;
sbp.slice_from("u");
break;
case 5:
if (!r_R2())
return false;
sbp.slice_from("ente");
break;
case 6:
if (!r_R1())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 4);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R2()) {
sbp.slice_del();
if (among_var == 1) {
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "at")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
}
}
}
break;
case 7:
if (habr5(a_4, 3))
return false;
break;
case 8:
if (habr5(a_5, 3))
return false;
break;
case 9:
if (habr6("at"))
return false;
break;
}
return true;
}
return false;
}
function r_y_verb_suffix() {
var among_var, v_1;
if (sbp.cursor >= I_pV) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_7, 12);
sbp.limit_backward = v_1;
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1) {
if (!sbp.eq_s_b(1, "u"))
return false;
sbp.slice_del();
}
return true;
}
}
return false;
}
function r_verb_suffix() {
var among_var, v_1, v_2, v_3;
if (sbp.cursor >= I_pV) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_8, 96);
sbp.limit_backward = v_1;
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
v_2 = sbp.limit - sbp.cursor;
if (sbp.eq_s_b(1, "u")) {
v_3 = sbp.limit - sbp.cursor;
if (sbp.eq_s_b(1, "g"))
sbp.cursor = sbp.limit - v_3;
else
sbp.cursor = sbp.limit - v_2;
} else
sbp.cursor = sbp.limit - v_2;
sbp.bra = sbp.cursor;
case 2:
sbp.slice_del();
break;
}
}
}
}
function r_residual_suffix() {
var among_var, v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_9, 8);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_RV())
sbp.slice_del();
break;
case 2:
if (r_RV()) {
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "u")) {
sbp.bra = sbp.cursor;
v_1 = sbp.limit - sbp.cursor;
if (sbp.eq_s_b(1, "g")) {
sbp.cursor = sbp.limit - v_1;
if (r_RV())
sbp.slice_del();
}
}
}
break;
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_attached_pronoun();
sbp.cursor = sbp.limit;
if (!r_standard_suffix()) {
sbp.cursor = sbp.limit;
if (!r_y_verb_suffix()) {
sbp.cursor = sbp.limit;
r_verb_suffix();
}
}
sbp.cursor = sbp.limit;
r_residual_suffix();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.es.stemmer, 'stemmer-es');
lunr.es.stopWordFilter = lunr.generateStopWordFilter('a al algo algunas algunos ante antes como con contra cual cuando de del desde donde durante e el ella ellas ellos en entre era erais eran eras eres es esa esas ese eso esos esta estaba estabais estaban estabas estad estada estadas estado estados estamos estando estar estaremos estará estarán estarás estaré estaréis estaría estaríais estaríamos estarían estarías estas este estemos esto estos estoy estuve estuviera estuvierais estuvieran estuvieras estuvieron estuviese estuvieseis estuviesen estuvieses estuvimos estuviste estuvisteis estuviéramos estuviésemos estuvo está estábamos estáis están estás esté estéis estén estés fue fuera fuerais fueran fueras fueron fuese fueseis fuesen fueses fui fuimos fuiste fuisteis fuéramos fuésemos ha habida habidas habido habidos habiendo habremos habrá habrán habrás habré habréis habría habríais habríamos habrían habrías habéis había habíais habíamos habían habías han has hasta hay haya hayamos hayan hayas hayáis he hemos hube hubiera hubierais hubieran hubieras hubieron hubiese hubieseis hubiesen hubieses hubimos hubiste hubisteis hubiéramos hubiésemos hubo la las le les lo los me mi mis mucho muchos muy más mí mía mías mío míos nada ni no nos nosotras nosotros nuestra nuestras nuestro nuestros o os otra otras otro otros para pero poco por porque que quien quienes qué se sea seamos sean seas seremos será serán serás seré seréis sería seríais seríamos serían serías seáis sido siendo sin sobre sois somos son soy su sus suya suyas suyo suyos sí también tanto te tendremos tendrá tendrán tendrás tendré tendréis tendría tendríais tendríamos tendrían tendrías tened tenemos tenga tengamos tengan tengas tengo tengáis tenida tenidas tenido tenidos teniendo tenéis tenía teníais teníamos tenían tenías ti tiene tienen tienes todo todos tu tus tuve tuviera tuvierais tuvieran tuvieras tuvieron tuviese tuvieseis tuviesen tuvieses tuvimos tuviste tuvisteis tuviéramos tuviésemos tuvo tuya tuyas tuyo tuyos tú un una uno unos vosotras vosotros vuestra vuestras vuestro vuestros y ya yo él éramos'.split(' '));
lunr.Pipeline.registerFunction(lunr.es.stopWordFilter, 'stopWordFilter-es');
};
}))
@@ -0,0 +1,541 @@
/*!
* Lunr languages, `Finnish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.fi = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.fi.trimmer,
lunr.fi.stopWordFilter,
lunr.fi.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.fi.stemmer)
}
};
/* lunr trimmer function */
lunr.fi.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.fi.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.fi.wordCharacters);
lunr.Pipeline.registerFunction(lunr.fi.trimmer, 'trimmer-fi');
/* lunr stemmer function */
lunr.fi.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function FinnishStemmer() {
var a_0 = [new Among("pa", -1, 1), new Among("sti", -1, 2),
new Among("kaan", -1, 1), new Among("han", -1, 1),
new Among("kin", -1, 1), new Among("h\u00E4n", -1, 1),
new Among("k\u00E4\u00E4n", -1, 1), new Among("ko", -1, 1),
new Among("p\u00E4", -1, 1), new Among("k\u00F6", -1, 1)
],
a_1 = [
new Among("lla", -1, -1), new Among("na", -1, -1),
new Among("ssa", -1, -1), new Among("ta", -1, -1),
new Among("lta", 3, -1), new Among("sta", 3, -1)
],
a_2 = [
new Among("ll\u00E4", -1, -1), new Among("n\u00E4", -1, -1),
new Among("ss\u00E4", -1, -1), new Among("t\u00E4", -1, -1),
new Among("lt\u00E4", 3, -1), new Among("st\u00E4", 3, -1)
],
a_3 = [
new Among("lle", -1, -1), new Among("ine", -1, -1)
],
a_4 = [
new Among("nsa", -1, 3), new Among("mme", -1, 3),
new Among("nne", -1, 3), new Among("ni", -1, 2),
new Among("si", -1, 1), new Among("an", -1, 4),
new Among("en", -1, 6), new Among("\u00E4n", -1, 5),
new Among("ns\u00E4", -1, 3)
],
a_5 = [new Among("aa", -1, -1),
new Among("ee", -1, -1), new Among("ii", -1, -1),
new Among("oo", -1, -1), new Among("uu", -1, -1),
new Among("\u00E4\u00E4", -1, -1),
new Among("\u00F6\u00F6", -1, -1)
],
a_6 = [new Among("a", -1, 8),
new Among("lla", 0, -1), new Among("na", 0, -1),
new Among("ssa", 0, -1), new Among("ta", 0, -1),
new Among("lta", 4, -1), new Among("sta", 4, -1),
new Among("tta", 4, 9), new Among("lle", -1, -1),
new Among("ine", -1, -1), new Among("ksi", -1, -1),
new Among("n", -1, 7), new Among("han", 11, 1),
new Among("den", 11, -1, r_VI), new Among("seen", 11, -1, r_LONG),
new Among("hen", 11, 2), new Among("tten", 11, -1, r_VI),
new Among("hin", 11, 3), new Among("siin", 11, -1, r_VI),
new Among("hon", 11, 4), new Among("h\u00E4n", 11, 5),
new Among("h\u00F6n", 11, 6), new Among("\u00E4", -1, 8),
new Among("ll\u00E4", 22, -1), new Among("n\u00E4", 22, -1),
new Among("ss\u00E4", 22, -1), new Among("t\u00E4", 22, -1),
new Among("lt\u00E4", 26, -1), new Among("st\u00E4", 26, -1),
new Among("tt\u00E4", 26, 9)
],
a_7 = [new Among("eja", -1, -1),
new Among("mma", -1, 1), new Among("imma", 1, -1),
new Among("mpa", -1, 1), new Among("impa", 3, -1),
new Among("mmi", -1, 1), new Among("immi", 5, -1),
new Among("mpi", -1, 1), new Among("impi", 7, -1),
new Among("ej\u00E4", -1, -1), new Among("mm\u00E4", -1, 1),
new Among("imm\u00E4", 10, -1), new Among("mp\u00E4", -1, 1),
new Among("imp\u00E4", 12, -1)
],
a_8 = [new Among("i", -1, -1),
new Among("j", -1, -1)
],
a_9 = [new Among("mma", -1, 1),
new Among("imma", 0, -1)
],
g_AEI = [17, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 8
],
g_V1 = [17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 8, 0, 32
],
g_V2 = [17, 65, 16, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 8, 0, 32
],
g_particle_end = [17, 97, 24, 1, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 32
],
B_ending_removed, S_x, I_p2, I_p1, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_mark_regions() {
I_p1 = sbp.limit;
I_p2 = I_p1;
if (!habr1()) {
I_p1 = sbp.cursor;
if (!habr1())
I_p2 = sbp.cursor;
}
}
function habr1() {
var v_1;
while (true) {
v_1 = sbp.cursor;
if (sbp.in_grouping(g_V1, 97, 246))
break;
sbp.cursor = v_1;
if (v_1 >= sbp.limit)
return true;
sbp.cursor++;
}
sbp.cursor = v_1;
while (!sbp.out_grouping(g_V1, 97, 246)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_particle_etc() {
var among_var, v_1;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_0, 10);
if (among_var) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_1;
switch (among_var) {
case 1:
if (!sbp.in_grouping_b(g_particle_end, 97, 246))
return;
break;
case 2:
if (!r_R2())
return;
break;
}
sbp.slice_del();
} else
sbp.limit_backward = v_1;
}
}
function r_possessive() {
var among_var, v_1, v_2;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 9);
if (among_var) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_1;
switch (among_var) {
case 1:
v_2 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "k")) {
sbp.cursor = sbp.limit - v_2;
sbp.slice_del();
}
break;
case 2:
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(3, "kse")) {
sbp.bra = sbp.cursor;
sbp.slice_from("ksi");
}
break;
case 3:
sbp.slice_del();
break;
case 4:
if (sbp.find_among_b(a_1, 6))
sbp.slice_del();
break;
case 5:
if (sbp.find_among_b(a_2, 6))
sbp.slice_del();
break;
case 6:
if (sbp.find_among_b(a_3, 2))
sbp.slice_del();
break;
}
} else
sbp.limit_backward = v_1;
}
}
function r_LONG() {
return sbp.find_among_b(a_5, 7);
}
function r_VI() {
return sbp.eq_s_b(1, "i") && sbp.in_grouping_b(g_V2, 97, 246);
}
function r_case_ending() {
var among_var, v_1, v_2;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_6, 30);
if (among_var) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_1;
switch (among_var) {
case 1:
if (!sbp.eq_s_b(1, "a"))
return;
break;
case 2:
case 9:
if (!sbp.eq_s_b(1, "e"))
return;
break;
case 3:
if (!sbp.eq_s_b(1, "i"))
return;
break;
case 4:
if (!sbp.eq_s_b(1, "o"))
return;
break;
case 5:
if (!sbp.eq_s_b(1, "\u00E4"))
return;
break;
case 6:
if (!sbp.eq_s_b(1, "\u00F6"))
return;
break;
case 7:
v_2 = sbp.limit - sbp.cursor;
if (!r_LONG()) {
sbp.cursor = sbp.limit - v_2;
if (!sbp.eq_s_b(2, "ie")) {
sbp.cursor = sbp.limit - v_2;
break;
}
}
sbp.cursor = sbp.limit - v_2;
if (sbp.cursor <= sbp.limit_backward) {
sbp.cursor = sbp.limit - v_2;
break;
}
sbp.cursor--;
sbp.bra = sbp.cursor;
break;
case 8:
if (!sbp.in_grouping_b(g_V1, 97, 246) ||
!sbp.out_grouping_b(g_V1, 97, 246))
return;
break;
}
sbp.slice_del();
B_ending_removed = true;
} else
sbp.limit_backward = v_1;
}
}
function r_other_endings() {
var among_var, v_1, v_2;
if (sbp.cursor >= I_p2) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p2;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_7, 14);
if (among_var) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_1;
if (among_var == 1) {
v_2 = sbp.limit - sbp.cursor;
if (sbp.eq_s_b(2, "po"))
return;
sbp.cursor = sbp.limit - v_2;
}
sbp.slice_del();
} else
sbp.limit_backward = v_1;
}
}
function r_i_plural() {
var v_1;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
if (sbp.find_among_b(a_8, 2)) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_1;
sbp.slice_del();
} else
sbp.limit_backward = v_1;
}
}
function r_t_plural() {
var among_var, v_1, v_2, v_3, v_4, v_5;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "t")) {
sbp.bra = sbp.cursor;
v_2 = sbp.limit - sbp.cursor;
if (sbp.in_grouping_b(g_V1, 97, 246)) {
sbp.cursor = sbp.limit - v_2;
sbp.slice_del();
sbp.limit_backward = v_1;
v_3 = sbp.limit - sbp.cursor;
if (sbp.cursor >= I_p2) {
sbp.cursor = I_p2;
v_4 = sbp.limit_backward;
sbp.limit_backward = sbp.cursor;
sbp.cursor = sbp.limit - v_3;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_9, 2);
if (among_var) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_4;
if (among_var == 1) {
v_5 = sbp.limit - sbp.cursor;
if (sbp.eq_s_b(2, "po"))
return;
sbp.cursor = sbp.limit - v_5;
}
sbp.slice_del();
return;
}
}
}
}
sbp.limit_backward = v_1;
}
}
function r_tidy() {
var v_1, v_2, v_3, v_4;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
v_2 = sbp.limit - sbp.cursor;
if (r_LONG()) {
sbp.cursor = sbp.limit - v_2;
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
}
sbp.cursor = sbp.limit - v_2;
sbp.ket = sbp.cursor;
if (sbp.in_grouping_b(g_AEI, 97, 228)) {
sbp.bra = sbp.cursor;
if (sbp.out_grouping_b(g_V1, 97, 246))
sbp.slice_del();
}
sbp.cursor = sbp.limit - v_2;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "j")) {
sbp.bra = sbp.cursor;
v_3 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "o")) {
sbp.cursor = sbp.limit - v_3;
if (sbp.eq_s_b(1, "u"))
sbp.slice_del();
} else
sbp.slice_del();
}
sbp.cursor = sbp.limit - v_2;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "o")) {
sbp.bra = sbp.cursor;
if (sbp.eq_s_b(1, "j"))
sbp.slice_del();
}
sbp.cursor = sbp.limit - v_2;
sbp.limit_backward = v_1;
while (true) {
v_4 = sbp.limit - sbp.cursor;
if (sbp.out_grouping_b(g_V1, 97, 246)) {
sbp.cursor = sbp.limit - v_4;
break;
}
sbp.cursor = sbp.limit - v_4;
if (sbp.cursor <= sbp.limit_backward)
return;
sbp.cursor--;
}
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
S_x = sbp.slice_to();
if (sbp.eq_v_b(S_x))
sbp.slice_del();
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_mark_regions();
B_ending_removed = false;
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_particle_etc();
sbp.cursor = sbp.limit;
r_possessive();
sbp.cursor = sbp.limit;
r_case_ending();
sbp.cursor = sbp.limit;
r_other_endings();
sbp.cursor = sbp.limit;
if (B_ending_removed) {
r_i_plural();
sbp.cursor = sbp.limit;
} else {
sbp.cursor = sbp.limit;
r_t_plural();
sbp.cursor = sbp.limit;
}
r_tidy();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.fi.stemmer, 'stemmer-fi');
lunr.fi.stopWordFilter = lunr.generateStopWordFilter('ei eivät emme en et ette että he heidän heidät heihin heille heillä heiltä heissä heistä heitä hän häneen hänelle hänellä häneltä hänen hänessä hänestä hänet häntä itse ja johon joiden joihin joiksi joilla joille joilta joina joissa joista joita joka joksi jolla jolle jolta jona jonka jos jossa josta jota jotka kanssa keiden keihin keiksi keille keillä keiltä keinä keissä keistä keitä keneen keneksi kenelle kenellä keneltä kenen kenenä kenessä kenestä kenet ketkä ketkä ketä koska kuin kuka kun me meidän meidät meihin meille meillä meiltä meissä meistä meitä mihin miksi mikä mille millä miltä minkä minkä minua minulla minulle minulta minun minussa minusta minut minuun minä minä missä mistä mitkä mitä mukaan mutta ne niiden niihin niiksi niille niillä niiltä niin niin niinä niissä niistä niitä noiden noihin noiksi noilla noille noilta noin noina noissa noista noita nuo nyt näiden näihin näiksi näille näillä näiltä näinä näissä näistä näitä nämä ole olemme olen olet olette oli olimme olin olisi olisimme olisin olisit olisitte olisivat olit olitte olivat olla olleet ollut on ovat poikki se sekä sen siihen siinä siitä siksi sille sillä sillä siltä sinua sinulla sinulle sinulta sinun sinussa sinusta sinut sinuun sinä sinä sitä tai te teidän teidät teihin teille teillä teiltä teissä teistä teitä tuo tuohon tuoksi tuolla tuolle tuolta tuon tuona tuossa tuosta tuota tähän täksi tälle tällä tältä tämä tämän tänä tässä tästä tätä vaan vai vaikka yli'.split(' '));
lunr.Pipeline.registerFunction(lunr.fi.stopWordFilter, 'stopWordFilter-fi');
};
}))
@@ -0,0 +1,703 @@
/*!
* Lunr languages, `French` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.fr = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.fr.trimmer,
lunr.fr.stopWordFilter,
lunr.fr.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.fr.stemmer)
}
};
/* lunr trimmer function */
lunr.fr.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.fr.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.fr.wordCharacters);
lunr.Pipeline.registerFunction(lunr.fr.trimmer, 'trimmer-fr');
/* lunr stemmer function */
lunr.fr.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function FrenchStemmer() {
var a_0 = [new Among("col", -1, -1), new Among("par", -1, -1),
new Among("tap", -1, -1)
],
a_1 = [new Among("", -1, 4),
new Among("I", 0, 1), new Among("U", 0, 2), new Among("Y", 0, 3)
],
a_2 = [
new Among("iqU", -1, 3), new Among("abl", -1, 3),
new Among("I\u00E8r", -1, 4), new Among("i\u00E8r", -1, 4),
new Among("eus", -1, 2), new Among("iv", -1, 1)
],
a_3 = [
new Among("ic", -1, 2), new Among("abil", -1, 1),
new Among("iv", -1, 3)
],
a_4 = [new Among("iqUe", -1, 1),
new Among("atrice", -1, 2), new Among("ance", -1, 1),
new Among("ence", -1, 5), new Among("logie", -1, 3),
new Among("able", -1, 1), new Among("isme", -1, 1),
new Among("euse", -1, 11), new Among("iste", -1, 1),
new Among("ive", -1, 8), new Among("if", -1, 8),
new Among("usion", -1, 4), new Among("ation", -1, 2),
new Among("ution", -1, 4), new Among("ateur", -1, 2),
new Among("iqUes", -1, 1), new Among("atrices", -1, 2),
new Among("ances", -1, 1), new Among("ences", -1, 5),
new Among("logies", -1, 3), new Among("ables", -1, 1),
new Among("ismes", -1, 1), new Among("euses", -1, 11),
new Among("istes", -1, 1), new Among("ives", -1, 8),
new Among("ifs", -1, 8), new Among("usions", -1, 4),
new Among("ations", -1, 2), new Among("utions", -1, 4),
new Among("ateurs", -1, 2), new Among("ments", -1, 15),
new Among("ements", 30, 6), new Among("issements", 31, 12),
new Among("it\u00E9s", -1, 7), new Among("ment", -1, 15),
new Among("ement", 34, 6), new Among("issement", 35, 12),
new Among("amment", 34, 13), new Among("emment", 34, 14),
new Among("aux", -1, 10), new Among("eaux", 39, 9),
new Among("eux", -1, 1), new Among("it\u00E9", -1, 7)
],
a_5 = [
new Among("ira", -1, 1), new Among("ie", -1, 1),
new Among("isse", -1, 1), new Among("issante", -1, 1),
new Among("i", -1, 1), new Among("irai", 4, 1),
new Among("ir", -1, 1), new Among("iras", -1, 1),
new Among("ies", -1, 1), new Among("\u00EEmes", -1, 1),
new Among("isses", -1, 1), new Among("issantes", -1, 1),
new Among("\u00EEtes", -1, 1), new Among("is", -1, 1),
new Among("irais", 13, 1), new Among("issais", 13, 1),
new Among("irions", -1, 1), new Among("issions", -1, 1),
new Among("irons", -1, 1), new Among("issons", -1, 1),
new Among("issants", -1, 1), new Among("it", -1, 1),
new Among("irait", 21, 1), new Among("issait", 21, 1),
new Among("issant", -1, 1), new Among("iraIent", -1, 1),
new Among("issaIent", -1, 1), new Among("irent", -1, 1),
new Among("issent", -1, 1), new Among("iront", -1, 1),
new Among("\u00EEt", -1, 1), new Among("iriez", -1, 1),
new Among("issiez", -1, 1), new Among("irez", -1, 1),
new Among("issez", -1, 1)
],
a_6 = [new Among("a", -1, 3),
new Among("era", 0, 2), new Among("asse", -1, 3),
new Among("ante", -1, 3), new Among("\u00E9e", -1, 2),
new Among("ai", -1, 3), new Among("erai", 5, 2),
new Among("er", -1, 2), new Among("as", -1, 3),
new Among("eras", 8, 2), new Among("\u00E2mes", -1, 3),
new Among("asses", -1, 3), new Among("antes", -1, 3),
new Among("\u00E2tes", -1, 3), new Among("\u00E9es", -1, 2),
new Among("ais", -1, 3), new Among("erais", 15, 2),
new Among("ions", -1, 1), new Among("erions", 17, 2),
new Among("assions", 17, 3), new Among("erons", -1, 2),
new Among("ants", -1, 3), new Among("\u00E9s", -1, 2),
new Among("ait", -1, 3), new Among("erait", 23, 2),
new Among("ant", -1, 3), new Among("aIent", -1, 3),
new Among("eraIent", 26, 2), new Among("\u00E8rent", -1, 2),
new Among("assent", -1, 3), new Among("eront", -1, 2),
new Among("\u00E2t", -1, 3), new Among("ez", -1, 2),
new Among("iez", 32, 2), new Among("eriez", 33, 2),
new Among("assiez", 33, 3), new Among("erez", 32, 2),
new Among("\u00E9", -1, 2)
],
a_7 = [new Among("e", -1, 3),
new Among("I\u00E8re", 0, 2), new Among("i\u00E8re", 0, 2),
new Among("ion", -1, 1), new Among("Ier", -1, 2),
new Among("ier", -1, 2), new Among("\u00EB", -1, 4)
],
a_8 = [
new Among("ell", -1, -1), new Among("eill", -1, -1),
new Among("enn", -1, -1), new Among("onn", -1, -1),
new Among("ett", -1, -1)
],
g_v = [17, 65, 16, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 128, 130, 103, 8, 5
],
g_keep_with_s = [1, 65, 20, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
],
I_p2, I_p1, I_pV, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function habr1(c1, c2, v_1) {
if (sbp.eq_s(1, c1)) {
sbp.ket = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 251)) {
sbp.slice_from(c2);
sbp.cursor = v_1;
return true;
}
}
return false;
}
function habr2(c1, c2, v_1) {
if (sbp.eq_s(1, c1)) {
sbp.ket = sbp.cursor;
sbp.slice_from(c2);
sbp.cursor = v_1;
return true;
}
return false;
}
function r_prelude() {
var v_1, v_2;
while (true) {
v_1 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 251)) {
sbp.bra = sbp.cursor;
v_2 = sbp.cursor;
if (habr1("u", "U", v_1))
continue;
sbp.cursor = v_2;
if (habr1("i", "I", v_1))
continue;
sbp.cursor = v_2;
if (habr2("y", "Y", v_1))
continue;
}
sbp.cursor = v_1;
sbp.bra = v_1;
if (!habr1("y", "Y", v_1)) {
sbp.cursor = v_1;
if (sbp.eq_s(1, "q")) {
sbp.bra = sbp.cursor;
if (habr2("u", "U", v_1))
continue;
}
sbp.cursor = v_1;
if (v_1 >= sbp.limit)
return;
sbp.cursor++;
}
}
}
function habr3() {
while (!sbp.in_grouping(g_v, 97, 251)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 251)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
function r_mark_regions() {
var v_1 = sbp.cursor;
I_pV = sbp.limit;
I_p1 = I_pV;
I_p2 = I_pV;
if (sbp.in_grouping(g_v, 97, 251) && sbp.in_grouping(g_v, 97, 251) &&
sbp.cursor < sbp.limit)
sbp.cursor++;
else {
sbp.cursor = v_1;
if (!sbp.find_among(a_0, 3)) {
sbp.cursor = v_1;
do {
if (sbp.cursor >= sbp.limit) {
sbp.cursor = I_pV;
break;
}
sbp.cursor++;
} while (!sbp.in_grouping(g_v, 97, 251));
}
}
I_pV = sbp.cursor;
sbp.cursor = v_1;
if (!habr3()) {
I_p1 = sbp.cursor;
if (!habr3())
I_p2 = sbp.cursor;
}
}
function r_postlude() {
var among_var, v_1;
while (true) {
v_1 = sbp.cursor;
sbp.bra = v_1;
among_var = sbp.find_among(a_1, 4);
if (!among_var)
break;
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("i");
break;
case 2:
sbp.slice_from("u");
break;
case 3:
sbp.slice_from("y");
break;
case 4:
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
break;
}
}
}
function r_RV() {
return I_pV <= sbp.cursor;
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_standard_suffix() {
var among_var, v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 43);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (!r_R2())
return false;
sbp.slice_del();
break;
case 2:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "ic")) {
sbp.bra = sbp.cursor;
if (!r_R2())
sbp.slice_from("iqU");
else
sbp.slice_del();
}
break;
case 3:
if (!r_R2())
return false;
sbp.slice_from("log");
break;
case 4:
if (!r_R2())
return false;
sbp.slice_from("u");
break;
case 5:
if (!r_R2())
return false;
sbp.slice_from("ent");
break;
case 6:
if (!r_RV())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_2, 6);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_R2()) {
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "at")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
}
break;
case 2:
if (r_R2())
sbp.slice_del();
else if (r_R1())
sbp.slice_from("eux");
break;
case 3:
if (r_R2())
sbp.slice_del();
break;
case 4:
if (r_RV())
sbp.slice_from("i");
break;
}
}
break;
case 7:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 3);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_R2())
sbp.slice_del();
else
sbp.slice_from("abl");
break;
case 2:
if (r_R2())
sbp.slice_del();
else
sbp.slice_from("iqU");
break;
case 3:
if (r_R2())
sbp.slice_del();
break;
}
}
break;
case 8:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "at")) {
sbp.bra = sbp.cursor;
if (r_R2()) {
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "ic")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
else
sbp.slice_from("iqU");
break;
}
}
}
break;
case 9:
sbp.slice_from("eau");
break;
case 10:
if (!r_R1())
return false;
sbp.slice_from("al");
break;
case 11:
if (r_R2())
sbp.slice_del();
else if (!r_R1())
return false;
else
sbp.slice_from("eux");
break;
case 12:
if (!r_R1() || !sbp.out_grouping_b(g_v, 97, 251))
return false;
sbp.slice_del();
break;
case 13:
if (r_RV())
sbp.slice_from("ant");
return false;
case 14:
if (r_RV())
sbp.slice_from("ent");
return false;
case 15:
v_1 = sbp.limit - sbp.cursor;
if (sbp.in_grouping_b(g_v, 97, 251) && r_RV()) {
sbp.cursor = sbp.limit - v_1;
sbp.slice_del();
}
return false;
}
return true;
}
return false;
}
function r_i_verb_suffix() {
var among_var, v_1;
if (sbp.cursor < I_pV)
return false;
v_1 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_5, 35);
if (!among_var) {
sbp.limit_backward = v_1;
return false;
}
sbp.bra = sbp.cursor;
if (among_var == 1) {
if (!sbp.out_grouping_b(g_v, 97, 251)) {
sbp.limit_backward = v_1;
return false;
}
sbp.slice_del();
}
sbp.limit_backward = v_1;
return true;
}
function r_verb_suffix() {
var among_var, v_2, v_3;
if (sbp.cursor < I_pV)
return false;
v_2 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_6, 38);
if (!among_var) {
sbp.limit_backward = v_2;
return false;
}
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (!r_R2()) {
sbp.limit_backward = v_2;
return false;
}
sbp.slice_del();
break;
case 2:
sbp.slice_del();
break;
case 3:
sbp.slice_del();
v_3 = sbp.limit - sbp.cursor;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "e")) {
sbp.bra = sbp.cursor;
sbp.slice_del();
} else
sbp.cursor = sbp.limit - v_3;
break;
}
sbp.limit_backward = v_2;
return true;
}
function r_residual_suffix() {
var among_var, v_1 = sbp.limit - sbp.cursor,
v_2, v_4, v_5;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "s")) {
sbp.bra = sbp.cursor;
v_2 = sbp.limit - sbp.cursor;
if (sbp.out_grouping_b(g_keep_with_s, 97, 232)) {
sbp.cursor = sbp.limit - v_2;
sbp.slice_del();
} else
sbp.cursor = sbp.limit - v_1;
} else
sbp.cursor = sbp.limit - v_1;
if (sbp.cursor >= I_pV) {
v_4 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_7, 7);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_R2()) {
v_5 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "s")) {
sbp.cursor = sbp.limit - v_5;
if (!sbp.eq_s_b(1, "t"))
break;
}
sbp.slice_del();
}
break;
case 2:
sbp.slice_from("i");
break;
case 3:
sbp.slice_del();
break;
case 4:
if (sbp.eq_s_b(2, "gu"))
sbp.slice_del();
break;
}
}
sbp.limit_backward = v_4;
}
}
function r_un_double() {
var v_1 = sbp.limit - sbp.cursor;
if (sbp.find_among_b(a_8, 5)) {
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
}
}
function r_un_accent() {
var v_1, v_2 = 1;
while (sbp.out_grouping_b(g_v, 97, 251))
v_2--;
if (v_2 <= 0) {
sbp.ket = sbp.cursor;
v_1 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "\u00E9")) {
sbp.cursor = sbp.limit - v_1;
if (!sbp.eq_s_b(1, "\u00E8"))
return;
}
sbp.bra = sbp.cursor;
sbp.slice_from("e");
}
}
function habr5() {
if (!r_standard_suffix()) {
sbp.cursor = sbp.limit;
if (!r_i_verb_suffix()) {
sbp.cursor = sbp.limit;
if (!r_verb_suffix()) {
sbp.cursor = sbp.limit;
r_residual_suffix();
return;
}
}
}
sbp.cursor = sbp.limit;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "Y")) {
sbp.bra = sbp.cursor;
sbp.slice_from("i");
} else {
sbp.cursor = sbp.limit;
if (sbp.eq_s_b(1, "\u00E7")) {
sbp.bra = sbp.cursor;
sbp.slice_from("c");
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_prelude();
sbp.cursor = v_1;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
habr5();
sbp.cursor = sbp.limit;
r_un_double();
sbp.cursor = sbp.limit;
r_un_accent();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.fr.stemmer, 'stemmer-fr');
lunr.fr.stopWordFilter = lunr.generateStopWordFilter('ai aie aient aies ait as au aura aurai auraient aurais aurait auras aurez auriez aurions aurons auront aux avaient avais avait avec avez aviez avions avons ayant ayez ayons c ce ceci celà ces cet cette d dans de des du elle en es est et eu eue eues eurent eus eusse eussent eusses eussiez eussions eut eux eûmes eût eûtes furent fus fusse fussent fusses fussiez fussions fut fûmes fût fûtes ici il ils j je l la le les leur leurs lui m ma mais me mes moi mon même n ne nos notre nous on ont ou par pas pour qu que quel quelle quelles quels qui s sa sans se sera serai seraient serais serait seras serez seriez serions serons seront ses soi soient sois soit sommes son sont soyez soyons suis sur t ta te tes toi ton tu un une vos votre vous y à étaient étais était étant étiez étions été étée étées étés êtes'.split(' '));
lunr.Pipeline.registerFunction(lunr.fr.stopWordFilter, 'stopWordFilter-fr');
};
}))
@@ -0,0 +1,123 @@
/*!
* Lunr languages, `Hindi` language
* https://github.com/MiKr13/lunr-languages
*
* Copyright 2020, Mihir Kumar
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.hi = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.hi.trimmer,
lunr.hi.stopWordFilter,
lunr.hi.stemmer
);
// change the tokenizer for japanese one
// if (isLunr2) { // for lunr version 2.0.0
// this.tokenizer = lunr.hi.tokenizer;
// } else {
// if (lunr.tokenizer) { // for lunr version 0.6.0
// lunr.tokenizer = lunr.hi.tokenizer;
// }
// if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
// this.tokenizerFn = lunr.hi.tokenizer;
// }
// }
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.hi.stemmer)
}
};
/* lunr trimmer function */
lunr.hi.wordCharacters = "\u0900-\u0903\u0904-\u090f\u0910-\u091f\u0920-\u092f\u0930-\u093f\u0940-\u094f\u0950-\u095f\u0960-\u096f\u0970-\u097fa-zA-Za-zA-Z0-90-9";
// lunr.hi.wordCharacters = "ऀँंःऄअआइईउऊऋऌऍऎएऐऑऒओऔकखगघङचछजझञटठडढणतथदधनऩपफबभमयरऱलळऴवशषसहऺऻ़ऽािीुूृॄॅॆेैॉॊोौ्ॎॏॐ॒॑॓॔ॕॖॗक़ख़ग़ज़ड़ढ़फ़य़ॠॡॢॣ।॥०१२३४५६७८९॰ॱॲॳॴॵॶॷॸॹॺॻॼॽॾॿa-zA-Za-zA-Z0-90-9";
lunr.hi.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.hi.wordCharacters);
lunr.Pipeline.registerFunction(lunr.hi.trimmer, 'trimmer-hi');
/* lunr stop word filter */
lunr.hi.stopWordFilter = lunr.generateStopWordFilter(
'अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने'.split(' '));
/* lunr stemmer function */
lunr.hi.stemmer = (function() {
return function(word) {
// for lunr version 2
if (typeof word.update === "function") {
return word.update(function(word) {
return word;
})
} else { // for lunr version <= 1
return word;
}
}
})();
var segmenter = lunr.wordcut;
segmenter.init();
lunr.hi.tokenizer = function(obj) {
if (!arguments.length || obj == null || obj == undefined) return []
if (Array.isArray(obj)) return obj.map(function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase()
});
var str = obj.toString().toLowerCase().replace(/^\s+/, '');
return segmenter.cut(str).split('|');
}
lunr.Pipeline.registerFunction(lunr.hi.stemmer, 'stemmer-hi');
lunr.Pipeline.registerFunction(lunr.hi.stopWordFilter, 'stopWordFilter-hi');
};
}))
@@ -0,0 +1,565 @@
/*!
* Lunr languages, `Hungarian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.hu = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.hu.trimmer,
lunr.hu.stopWordFilter,
lunr.hu.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.hu.stemmer)
}
};
/* lunr trimmer function */
lunr.hu.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.hu.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.hu.wordCharacters);
lunr.Pipeline.registerFunction(lunr.hu.trimmer, 'trimmer-hu');
/* lunr stemmer function */
lunr.hu.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function HungarianStemmer() {
var a_0 = [new Among("cs", -1, -1), new Among("dzs", -1, -1),
new Among("gy", -1, -1), new Among("ly", -1, -1),
new Among("ny", -1, -1), new Among("sz", -1, -1),
new Among("ty", -1, -1), new Among("zs", -1, -1)
],
a_1 = [
new Among("\u00E1", -1, 1), new Among("\u00E9", -1, 2)
],
a_2 = [
new Among("bb", -1, -1), new Among("cc", -1, -1),
new Among("dd", -1, -1), new Among("ff", -1, -1),
new Among("gg", -1, -1), new Among("jj", -1, -1),
new Among("kk", -1, -1), new Among("ll", -1, -1),
new Among("mm", -1, -1), new Among("nn", -1, -1),
new Among("pp", -1, -1), new Among("rr", -1, -1),
new Among("ccs", -1, -1), new Among("ss", -1, -1),
new Among("zzs", -1, -1), new Among("tt", -1, -1),
new Among("vv", -1, -1), new Among("ggy", -1, -1),
new Among("lly", -1, -1), new Among("nny", -1, -1),
new Among("tty", -1, -1), new Among("ssz", -1, -1),
new Among("zz", -1, -1)
],
a_3 = [new Among("al", -1, 1),
new Among("el", -1, 2)
],
a_4 = [new Among("ba", -1, -1),
new Among("ra", -1, -1), new Among("be", -1, -1),
new Among("re", -1, -1), new Among("ig", -1, -1),
new Among("nak", -1, -1), new Among("nek", -1, -1),
new Among("val", -1, -1), new Among("vel", -1, -1),
new Among("ul", -1, -1), new Among("n\u00E1l", -1, -1),
new Among("n\u00E9l", -1, -1), new Among("b\u00F3l", -1, -1),
new Among("r\u00F3l", -1, -1), new Among("t\u00F3l", -1, -1),
new Among("b\u00F5l", -1, -1), new Among("r\u00F5l", -1, -1),
new Among("t\u00F5l", -1, -1), new Among("\u00FCl", -1, -1),
new Among("n", -1, -1), new Among("an", 19, -1),
new Among("ban", 20, -1), new Among("en", 19, -1),
new Among("ben", 22, -1), new Among("k\u00E9ppen", 22, -1),
new Among("on", 19, -1), new Among("\u00F6n", 19, -1),
new Among("k\u00E9pp", -1, -1), new Among("kor", -1, -1),
new Among("t", -1, -1), new Among("at", 29, -1),
new Among("et", 29, -1), new Among("k\u00E9nt", 29, -1),
new Among("ank\u00E9nt", 32, -1), new Among("enk\u00E9nt", 32, -1),
new Among("onk\u00E9nt", 32, -1), new Among("ot", 29, -1),
new Among("\u00E9rt", 29, -1), new Among("\u00F6t", 29, -1),
new Among("hez", -1, -1), new Among("hoz", -1, -1),
new Among("h\u00F6z", -1, -1), new Among("v\u00E1", -1, -1),
new Among("v\u00E9", -1, -1)
],
a_5 = [new Among("\u00E1n", -1, 2),
new Among("\u00E9n", -1, 1), new Among("\u00E1nk\u00E9nt", -1, 3)
],
a_6 = [
new Among("stul", -1, 2), new Among("astul", 0, 1),
new Among("\u00E1stul", 0, 3), new Among("st\u00FCl", -1, 2),
new Among("est\u00FCl", 3, 1), new Among("\u00E9st\u00FCl", 3, 4)
],
a_7 = [
new Among("\u00E1", -1, 1), new Among("\u00E9", -1, 2)
],
a_8 = [
new Among("k", -1, 7), new Among("ak", 0, 4),
new Among("ek", 0, 6), new Among("ok", 0, 5),
new Among("\u00E1k", 0, 1), new Among("\u00E9k", 0, 2),
new Among("\u00F6k", 0, 3)
],
a_9 = [new Among("\u00E9i", -1, 7),
new Among("\u00E1\u00E9i", 0, 6), new Among("\u00E9\u00E9i", 0, 5),
new Among("\u00E9", -1, 9), new Among("k\u00E9", 3, 4),
new Among("ak\u00E9", 4, 1), new Among("ek\u00E9", 4, 1),
new Among("ok\u00E9", 4, 1), new Among("\u00E1k\u00E9", 4, 3),
new Among("\u00E9k\u00E9", 4, 2), new Among("\u00F6k\u00E9", 4, 1),
new Among("\u00E9\u00E9", 3, 8)
],
a_10 = [new Among("a", -1, 18),
new Among("ja", 0, 17), new Among("d", -1, 16),
new Among("ad", 2, 13), new Among("ed", 2, 13),
new Among("od", 2, 13), new Among("\u00E1d", 2, 14),
new Among("\u00E9d", 2, 15), new Among("\u00F6d", 2, 13),
new Among("e", -1, 18), new Among("je", 9, 17),
new Among("nk", -1, 4), new Among("unk", 11, 1),
new Among("\u00E1nk", 11, 2), new Among("\u00E9nk", 11, 3),
new Among("\u00FCnk", 11, 1), new Among("uk", -1, 8),
new Among("juk", 16, 7), new Among("\u00E1juk", 17, 5),
new Among("\u00FCk", -1, 8), new Among("j\u00FCk", 19, 7),
new Among("\u00E9j\u00FCk", 20, 6), new Among("m", -1, 12),
new Among("am", 22, 9), new Among("em", 22, 9),
new Among("om", 22, 9), new Among("\u00E1m", 22, 10),
new Among("\u00E9m", 22, 11), new Among("o", -1, 18),
new Among("\u00E1", -1, 19), new Among("\u00E9", -1, 20)
],
a_11 = [
new Among("id", -1, 10), new Among("aid", 0, 9),
new Among("jaid", 1, 6), new Among("eid", 0, 9),
new Among("jeid", 3, 6), new Among("\u00E1id", 0, 7),
new Among("\u00E9id", 0, 8), new Among("i", -1, 15),
new Among("ai", 7, 14), new Among("jai", 8, 11),
new Among("ei", 7, 14), new Among("jei", 10, 11),
new Among("\u00E1i", 7, 12), new Among("\u00E9i", 7, 13),
new Among("itek", -1, 24), new Among("eitek", 14, 21),
new Among("jeitek", 15, 20), new Among("\u00E9itek", 14, 23),
new Among("ik", -1, 29), new Among("aik", 18, 26),
new Among("jaik", 19, 25), new Among("eik", 18, 26),
new Among("jeik", 21, 25), new Among("\u00E1ik", 18, 27),
new Among("\u00E9ik", 18, 28), new Among("ink", -1, 20),
new Among("aink", 25, 17), new Among("jaink", 26, 16),
new Among("eink", 25, 17), new Among("jeink", 28, 16),
new Among("\u00E1ink", 25, 18), new Among("\u00E9ink", 25, 19),
new Among("aitok", -1, 21), new Among("jaitok", 32, 20),
new Among("\u00E1itok", -1, 22), new Among("im", -1, 5),
new Among("aim", 35, 4), new Among("jaim", 36, 1),
new Among("eim", 35, 4), new Among("jeim", 38, 1),
new Among("\u00E1im", 35, 2), new Among("\u00E9im", 35, 3)
],
g_v = [
17, 65, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 17, 52, 14
],
I_p1, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_mark_regions() {
var v_1 = sbp.cursor,
v_2;
I_p1 = sbp.limit;
if (sbp.in_grouping(g_v, 97, 252)) {
while (true) {
v_2 = sbp.cursor;
if (sbp.out_grouping(g_v, 97, 252)) {
sbp.cursor = v_2;
if (!sbp.find_among(a_0, 8)) {
sbp.cursor = v_2;
if (v_2 < sbp.limit)
sbp.cursor++;
}
I_p1 = sbp.cursor;
return;
}
sbp.cursor = v_2;
if (v_2 >= sbp.limit) {
I_p1 = v_2;
return;
}
sbp.cursor++;
}
}
sbp.cursor = v_1;
if (sbp.out_grouping(g_v, 97, 252)) {
while (!sbp.in_grouping(g_v, 97, 252)) {
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
I_p1 = sbp.cursor;
}
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_v_ending() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_1, 2);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
sbp.slice_from("a");
break;
case 2:
sbp.slice_from("e");
break;
}
}
}
}
function r_double() {
var v_1 = sbp.limit - sbp.cursor;
if (!sbp.find_among_b(a_2, 23))
return false;
sbp.cursor = sbp.limit - v_1;
return true;
}
function r_undouble() {
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.ket = sbp.cursor;
var c = sbp.cursor - 1;
if (sbp.limit_backward <= c && c <= sbp.limit) {
sbp.cursor = c;
sbp.bra = c;
sbp.slice_del();
}
}
}
function r_instrum() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 2);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
if (among_var == 1 || among_var == 2)
if (!r_double())
return;
sbp.slice_del();
r_undouble();
}
}
}
function r_case() {
sbp.ket = sbp.cursor;
if (sbp.find_among_b(a_4, 44)) {
sbp.bra = sbp.cursor;
if (r_R1()) {
sbp.slice_del();
r_v_ending();
}
}
}
function r_case_special() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_5, 3);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
sbp.slice_from("e");
break;
case 2:
case 3:
sbp.slice_from("a");
break;
}
}
}
}
function r_case_other() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_6, 6);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
case 2:
sbp.slice_del();
break;
case 3:
sbp.slice_from("a");
break;
case 4:
sbp.slice_from("e");
break;
}
}
}
}
function r_factive() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_7, 2);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
if (among_var == 1 || among_var == 2)
if (!r_double())
return;
sbp.slice_del();
r_undouble()
}
}
}
function r_plural() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_8, 7);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
sbp.slice_from("a");
break;
case 2:
sbp.slice_from("e");
break;
case 3:
case 4:
case 5:
case 6:
case 7:
sbp.slice_del();
break;
}
}
}
}
function r_owned() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_9, 12);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
case 4:
case 7:
case 9:
sbp.slice_del();
break;
case 2:
case 5:
case 8:
sbp.slice_from("e");
break;
case 3:
case 6:
sbp.slice_from("a");
break;
}
}
}
}
function r_sing_owner() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_10, 31);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
case 4:
case 7:
case 8:
case 9:
case 12:
case 13:
case 16:
case 17:
case 18:
sbp.slice_del();
break;
case 2:
case 5:
case 10:
case 14:
case 19:
sbp.slice_from("a");
break;
case 3:
case 6:
case 11:
case 15:
case 20:
sbp.slice_from("e");
break;
}
}
}
}
function r_plur_owner() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_11, 42);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
case 4:
case 5:
case 6:
case 9:
case 10:
case 11:
case 14:
case 15:
case 16:
case 17:
case 20:
case 21:
case 24:
case 25:
case 26:
case 29:
sbp.slice_del();
break;
case 2:
case 7:
case 12:
case 18:
case 22:
case 27:
sbp.slice_from("a");
break;
case 3:
case 8:
case 13:
case 19:
case 23:
case 28:
sbp.slice_from("e");
break;
}
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_instrum();
sbp.cursor = sbp.limit;
r_case();
sbp.cursor = sbp.limit;
r_case_special();
sbp.cursor = sbp.limit;
r_case_other();
sbp.cursor = sbp.limit;
r_factive();
sbp.cursor = sbp.limit;
r_owned();
sbp.cursor = sbp.limit;
r_sing_owner();
sbp.cursor = sbp.limit;
r_plur_owner();
sbp.cursor = sbp.limit;
r_plural();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.hu.stemmer, 'stemmer-hu');
lunr.hu.stopWordFilter = lunr.generateStopWordFilter('a abban ahhoz ahogy ahol aki akik akkor alatt amely amelyek amelyekben amelyeket amelyet amelynek ami amikor amit amolyan amíg annak arra arról az azok azon azonban azt aztán azután azzal azért be belül benne bár cikk cikkek cikkeket csak de e ebben eddig egy egyes egyetlen egyik egyre egyéb egész ehhez ekkor el ellen elsõ elég elõ elõször elõtt emilyen ennek erre ez ezek ezen ezt ezzel ezért fel felé hanem hiszen hogy hogyan igen ill ill. illetve ilyen ilyenkor ismét ison itt jobban jó jól kell kellett keressünk keresztül ki kívül között közül legalább legyen lehet lehetett lenne lenni lesz lett maga magát majd majd meg mellett mely melyek mert mi mikor milyen minden mindenki mindent mindig mint mintha mit mivel miért most már más másik még míg nagy nagyobb nagyon ne nekem neki nem nincs néha néhány nélkül olyan ott pedig persze rá s saját sem semmi sok sokat sokkal szemben szerint szinte számára talán tehát teljes tovább továbbá több ugyanis utolsó után utána vagy vagyis vagyok valaki valami valamint való van vannak vele vissza viszont volna volt voltak voltam voltunk által általában át én éppen és így õ õk õket össze úgy új újabb újra'.split(' '));
lunr.Pipeline.registerFunction(lunr.hu.stopWordFilter, 'stopWordFilter-hu');
};
}))
@@ -0,0 +1,98 @@
/*!
* Lunr languages, `Armenian` language
* https://github.com/turbobit/lunr-languages
*
* Copyright 2021, Manikandan Venkatasubban
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.hy = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.hy.trimmer,
lunr.hy.stopWordFilter
);
};
/* lunr trimmer function */
// http://www.unicode.org/charts/
lunr.hy.wordCharacters = "[" +
"A-Za-z" +
"\u0530-\u058F" + // armenian alphabet
"\uFB00-\uFB4F" + // armenian ligatures
"]";
lunr.hy.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.hy.wordCharacters);
lunr.Pipeline.registerFunction(lunr.hy.trimmer, 'trimmer-hy');
/* lunr stop word filter */
// https://www.ranks.nl/stopwords/armenian
lunr.hy.stopWordFilter = lunr.generateStopWordFilter('դու և եք էիր էիք հետո նաև նրանք որը վրա է որ պիտի են այս մեջ ն իր ու ի այդ որոնք այն կամ էր մի ես համար այլ իսկ էին ենք հետ ին թ էինք մենք նրա նա դուք եմ էի ըստ որպես ում'.split(' '));
lunr.Pipeline.registerFunction(lunr.hy.stopWordFilter, 'stopWordFilter-hy');
/* lunr stemmer function */
lunr.hy.stemmer = (function() {
return function(word) {
// for lunr version 2
if (typeof word.update === "function") {
return word.update(function(word) {
return word;
})
} else { // for lunr version <= 1
return word;
}
}
})();
lunr.Pipeline.registerFunction(lunr.hy.stemmer, 'stemmer-hy');
};
}))
@@ -0,0 +1,617 @@
/*!
* Lunr languages, `Italian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.it = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.it.trimmer,
lunr.it.stopWordFilter,
lunr.it.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.it.stemmer)
}
};
/* lunr trimmer function */
lunr.it.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.it.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.it.wordCharacters);
lunr.Pipeline.registerFunction(lunr.it.trimmer, 'trimmer-it');
/* lunr stemmer function */
lunr.it.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function ItalianStemmer() {
var a_0 = [new Among("", -1, 7), new Among("qu", 0, 6),
new Among("\u00E1", 0, 1), new Among("\u00E9", 0, 2),
new Among("\u00ED", 0, 3), new Among("\u00F3", 0, 4),
new Among("\u00FA", 0, 5)
],
a_1 = [new Among("", -1, 3),
new Among("I", 0, 1), new Among("U", 0, 2)
],
a_2 = [
new Among("la", -1, -1), new Among("cela", 0, -1),
new Among("gliela", 0, -1), new Among("mela", 0, -1),
new Among("tela", 0, -1), new Among("vela", 0, -1),
new Among("le", -1, -1), new Among("cele", 6, -1),
new Among("gliele", 6, -1), new Among("mele", 6, -1),
new Among("tele", 6, -1), new Among("vele", 6, -1),
new Among("ne", -1, -1), new Among("cene", 12, -1),
new Among("gliene", 12, -1), new Among("mene", 12, -1),
new Among("sene", 12, -1), new Among("tene", 12, -1),
new Among("vene", 12, -1), new Among("ci", -1, -1),
new Among("li", -1, -1), new Among("celi", 20, -1),
new Among("glieli", 20, -1), new Among("meli", 20, -1),
new Among("teli", 20, -1), new Among("veli", 20, -1),
new Among("gli", 20, -1), new Among("mi", -1, -1),
new Among("si", -1, -1), new Among("ti", -1, -1),
new Among("vi", -1, -1), new Among("lo", -1, -1),
new Among("celo", 31, -1), new Among("glielo", 31, -1),
new Among("melo", 31, -1), new Among("telo", 31, -1),
new Among("velo", 31, -1)
],
a_3 = [new Among("ando", -1, 1),
new Among("endo", -1, 1), new Among("ar", -1, 2),
new Among("er", -1, 2), new Among("ir", -1, 2)
],
a_4 = [
new Among("ic", -1, -1), new Among("abil", -1, -1),
new Among("os", -1, -1), new Among("iv", -1, 1)
],
a_5 = [
new Among("ic", -1, 1), new Among("abil", -1, 1),
new Among("iv", -1, 1)
],
a_6 = [new Among("ica", -1, 1),
new Among("logia", -1, 3), new Among("osa", -1, 1),
new Among("ista", -1, 1), new Among("iva", -1, 9),
new Among("anza", -1, 1), new Among("enza", -1, 5),
new Among("ice", -1, 1), new Among("atrice", 7, 1),
new Among("iche", -1, 1), new Among("logie", -1, 3),
new Among("abile", -1, 1), new Among("ibile", -1, 1),
new Among("usione", -1, 4), new Among("azione", -1, 2),
new Among("uzione", -1, 4), new Among("atore", -1, 2),
new Among("ose", -1, 1), new Among("ante", -1, 1),
new Among("mente", -1, 1), new Among("amente", 19, 7),
new Among("iste", -1, 1), new Among("ive", -1, 9),
new Among("anze", -1, 1), new Among("enze", -1, 5),
new Among("ici", -1, 1), new Among("atrici", 25, 1),
new Among("ichi", -1, 1), new Among("abili", -1, 1),
new Among("ibili", -1, 1), new Among("ismi", -1, 1),
new Among("usioni", -1, 4), new Among("azioni", -1, 2),
new Among("uzioni", -1, 4), new Among("atori", -1, 2),
new Among("osi", -1, 1), new Among("anti", -1, 1),
new Among("amenti", -1, 6), new Among("imenti", -1, 6),
new Among("isti", -1, 1), new Among("ivi", -1, 9),
new Among("ico", -1, 1), new Among("ismo", -1, 1),
new Among("oso", -1, 1), new Among("amento", -1, 6),
new Among("imento", -1, 6), new Among("ivo", -1, 9),
new Among("it\u00E0", -1, 8), new Among("ist\u00E0", -1, 1),
new Among("ist\u00E8", -1, 1), new Among("ist\u00EC", -1, 1)
],
a_7 = [
new Among("isca", -1, 1), new Among("enda", -1, 1),
new Among("ata", -1, 1), new Among("ita", -1, 1),
new Among("uta", -1, 1), new Among("ava", -1, 1),
new Among("eva", -1, 1), new Among("iva", -1, 1),
new Among("erebbe", -1, 1), new Among("irebbe", -1, 1),
new Among("isce", -1, 1), new Among("ende", -1, 1),
new Among("are", -1, 1), new Among("ere", -1, 1),
new Among("ire", -1, 1), new Among("asse", -1, 1),
new Among("ate", -1, 1), new Among("avate", 16, 1),
new Among("evate", 16, 1), new Among("ivate", 16, 1),
new Among("ete", -1, 1), new Among("erete", 20, 1),
new Among("irete", 20, 1), new Among("ite", -1, 1),
new Among("ereste", -1, 1), new Among("ireste", -1, 1),
new Among("ute", -1, 1), new Among("erai", -1, 1),
new Among("irai", -1, 1), new Among("isci", -1, 1),
new Among("endi", -1, 1), new Among("erei", -1, 1),
new Among("irei", -1, 1), new Among("assi", -1, 1),
new Among("ati", -1, 1), new Among("iti", -1, 1),
new Among("eresti", -1, 1), new Among("iresti", -1, 1),
new Among("uti", -1, 1), new Among("avi", -1, 1),
new Among("evi", -1, 1), new Among("ivi", -1, 1),
new Among("isco", -1, 1), new Among("ando", -1, 1),
new Among("endo", -1, 1), new Among("Yamo", -1, 1),
new Among("iamo", -1, 1), new Among("avamo", -1, 1),
new Among("evamo", -1, 1), new Among("ivamo", -1, 1),
new Among("eremo", -1, 1), new Among("iremo", -1, 1),
new Among("assimo", -1, 1), new Among("ammo", -1, 1),
new Among("emmo", -1, 1), new Among("eremmo", 54, 1),
new Among("iremmo", 54, 1), new Among("immo", -1, 1),
new Among("ano", -1, 1), new Among("iscano", 58, 1),
new Among("avano", 58, 1), new Among("evano", 58, 1),
new Among("ivano", 58, 1), new Among("eranno", -1, 1),
new Among("iranno", -1, 1), new Among("ono", -1, 1),
new Among("iscono", 65, 1), new Among("arono", 65, 1),
new Among("erono", 65, 1), new Among("irono", 65, 1),
new Among("erebbero", -1, 1), new Among("irebbero", -1, 1),
new Among("assero", -1, 1), new Among("essero", -1, 1),
new Among("issero", -1, 1), new Among("ato", -1, 1),
new Among("ito", -1, 1), new Among("uto", -1, 1),
new Among("avo", -1, 1), new Among("evo", -1, 1),
new Among("ivo", -1, 1), new Among("ar", -1, 1),
new Among("ir", -1, 1), new Among("er\u00E0", -1, 1),
new Among("ir\u00E0", -1, 1), new Among("er\u00F2", -1, 1),
new Among("ir\u00F2", -1, 1)
],
g_v = [17, 65, 16, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 128, 128, 8, 2, 1
],
g_AEIO = [17, 65, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 128, 8, 2
],
g_CG = [17],
I_p2, I_p1, I_pV, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function habr1(c1, c2, v_1) {
if (sbp.eq_s(1, c1)) {
sbp.ket = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 249)) {
sbp.slice_from(c2);
sbp.cursor = v_1;
return true;
}
}
return false;
}
function r_prelude() {
var among_var, v_1 = sbp.cursor,
v_2, v_3, v_4;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_0, 7);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("\u00E0");
continue;
case 2:
sbp.slice_from("\u00E8");
continue;
case 3:
sbp.slice_from("\u00EC");
continue;
case 4:
sbp.slice_from("\u00F2");
continue;
case 5:
sbp.slice_from("\u00F9");
continue;
case 6:
sbp.slice_from("qU");
continue;
case 7:
if (sbp.cursor >= sbp.limit)
break;
sbp.cursor++;
continue;
}
}
break;
}
sbp.cursor = v_1;
while (true) {
v_2 = sbp.cursor;
while (true) {
v_3 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 249)) {
sbp.bra = sbp.cursor;
v_4 = sbp.cursor;
if (habr1("u", "U", v_3))
break;
sbp.cursor = v_4;
if (habr1("i", "I", v_3))
break;
}
sbp.cursor = v_3;
if (sbp.cursor >= sbp.limit) {
sbp.cursor = v_2;
return;
}
sbp.cursor++;
}
}
}
function habr2(v_1) {
sbp.cursor = v_1;
if (!sbp.in_grouping(g_v, 97, 249))
return false;
while (!sbp.out_grouping(g_v, 97, 249)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
return true;
}
function habr3() {
if (sbp.in_grouping(g_v, 97, 249)) {
var v_1 = sbp.cursor;
if (sbp.out_grouping(g_v, 97, 249)) {
while (!sbp.in_grouping(g_v, 97, 249)) {
if (sbp.cursor >= sbp.limit)
return habr2(v_1);
sbp.cursor++;
}
return true;
}
return habr2(v_1);
}
return false;
}
function habr4() {
var v_1 = sbp.cursor,
v_2;
if (!habr3()) {
sbp.cursor = v_1;
if (!sbp.out_grouping(g_v, 97, 249))
return;
v_2 = sbp.cursor;
if (sbp.out_grouping(g_v, 97, 249)) {
while (!sbp.in_grouping(g_v, 97, 249)) {
if (sbp.cursor >= sbp.limit) {
sbp.cursor = v_2;
if (sbp.in_grouping(g_v, 97, 249) &&
sbp.cursor < sbp.limit)
sbp.cursor++;
return;
}
sbp.cursor++;
}
I_pV = sbp.cursor;
return;
}
sbp.cursor = v_2;
if (!sbp.in_grouping(g_v, 97, 249) || sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
I_pV = sbp.cursor;
}
function habr5() {
while (!sbp.in_grouping(g_v, 97, 249)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 249)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
return true;
}
function r_mark_regions() {
var v_1 = sbp.cursor;
I_pV = sbp.limit;
I_p1 = I_pV;
I_p2 = I_pV;
habr4();
sbp.cursor = v_1;
if (habr5()) {
I_p1 = sbp.cursor;
if (habr5())
I_p2 = sbp.cursor;
}
}
function r_postlude() {
var among_var;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_1, 3);
if (!among_var)
break;
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("i");
break;
case 2:
sbp.slice_from("u");
break;
case 3:
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
break;
}
}
}
function r_RV() {
return I_pV <= sbp.cursor;
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_attached_pronoun() {
var among_var;
sbp.ket = sbp.cursor;
if (sbp.find_among_b(a_2, 37)) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among_b(a_3, 5);
if (among_var && r_RV()) {
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
sbp.slice_from("e");
break;
}
}
}
}
function r_standard_suffix() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_6, 51);
if (!among_var)
return false;
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (!r_R2())
return false;
sbp.slice_del();
break;
case 2:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "ic")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
break;
case 3:
if (!r_R2())
return false;
sbp.slice_from("log");
break;
case 4:
if (!r_R2())
return false;
sbp.slice_from("u");
break;
case 5:
if (!r_R2())
return false;
sbp.slice_from("ente");
break;
case 6:
if (!r_RV())
return false;
sbp.slice_del();
break;
case 7:
if (!r_R1())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 4);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R2()) {
sbp.slice_del();
if (among_var == 1) {
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "at")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
}
}
}
break;
case 8:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_5, 3);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1)
if (r_R2())
sbp.slice_del();
}
break;
case 9:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "at")) {
sbp.bra = sbp.cursor;
if (r_R2()) {
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "ic")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
}
}
break;
}
return true;
}
function r_verb_suffix() {
var among_var, v_1;
if (sbp.cursor >= I_pV) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_7, 87);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1)
sbp.slice_del();
}
sbp.limit_backward = v_1;
}
}
function habr6() {
var v_1 = sbp.limit - sbp.cursor;
sbp.ket = sbp.cursor;
if (sbp.in_grouping_b(g_AEIO, 97, 242)) {
sbp.bra = sbp.cursor;
if (r_RV()) {
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "i")) {
sbp.bra = sbp.cursor;
if (r_RV()) {
sbp.slice_del();
return;
}
}
}
}
sbp.cursor = sbp.limit - v_1;
}
function r_vowel_suffix() {
habr6();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "h")) {
sbp.bra = sbp.cursor;
if (sbp.in_grouping_b(g_CG, 99, 103))
if (r_RV())
sbp.slice_del();
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_prelude();
sbp.cursor = v_1;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_attached_pronoun();
sbp.cursor = sbp.limit;
if (!r_standard_suffix()) {
sbp.cursor = sbp.limit;
r_verb_suffix();
}
sbp.cursor = sbp.limit;
r_vowel_suffix();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.it.stemmer, 'stemmer-it');
lunr.it.stopWordFilter = lunr.generateStopWordFilter('a abbia abbiamo abbiano abbiate ad agl agli ai al all alla alle allo anche avemmo avendo avesse avessero avessi avessimo aveste avesti avete aveva avevamo avevano avevate avevi avevo avrai avranno avrebbe avrebbero avrei avremmo avremo avreste avresti avrete avrà avrò avuta avute avuti avuto c che chi ci coi col come con contro cui da dagl dagli dai dal dall dalla dalle dallo degl degli dei del dell della delle dello di dov dove e ebbe ebbero ebbi ed era erano eravamo eravate eri ero essendo faccia facciamo facciano facciate faccio facemmo facendo facesse facessero facessi facessimo faceste facesti faceva facevamo facevano facevate facevi facevo fai fanno farai faranno farebbe farebbero farei faremmo faremo fareste faresti farete farà farò fece fecero feci fosse fossero fossi fossimo foste fosti fu fui fummo furono gli ha hai hanno ho i il in io l la le lei li lo loro lui ma mi mia mie miei mio ne negl negli nei nel nell nella nelle nello noi non nostra nostre nostri nostro o per perché più quale quanta quante quanti quanto quella quelle quelli quello questa queste questi questo sarai saranno sarebbe sarebbero sarei saremmo saremo sareste saresti sarete sarà sarò se sei si sia siamo siano siate siete sono sta stai stando stanno starai staranno starebbe starebbero starei staremmo staremo stareste staresti starete starà starò stava stavamo stavano stavate stavi stavo stemmo stesse stessero stessi stessimo steste stesti stette stettero stetti stia stiamo stiano stiate sto su sua sue sugl sugli sui sul sull sulla sulle sullo suo suoi ti tra tu tua tue tuo tuoi tutti tutto un una uno vi voi vostra vostre vostri vostro è'.split(' '));
lunr.Pipeline.registerFunction(lunr.it.stopWordFilter, 'stopWordFilter-it');
};
}))
@@ -0,0 +1,188 @@
/*!
* Lunr languages, `Japanese` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Chad Liu
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/*
Japanese tokenization is trickier, since it does not
take into account spaces.
Since the tokenization function is represented different
internally for each of the Lunr versions, this had to be done
in order to try to try to pick the best way of doing this based
on the Lunr version
*/
var isLunr2 = lunr.version[0] == "2";
/* register specific locale function */
lunr.ja = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.ja.trimmer,
lunr.ja.stopWordFilter,
lunr.ja.stemmer
);
// change the tokenizer for japanese one
if (isLunr2) { // for lunr version 2.0.0
this.tokenizer = lunr.ja.tokenizer;
} else {
if (lunr.tokenizer) { // for lunr version 0.6.0
lunr.tokenizer = lunr.ja.tokenizer;
}
if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
this.tokenizerFn = lunr.ja.tokenizer;
}
}
};
var segmenter = new lunr.TinySegmenter(); // インスタンス生成
lunr.ja.tokenizer = function(obj) {
var i;
var str;
var len;
var segs;
var tokens;
var char;
var sliceLength;
var sliceStart;
var sliceEnd;
var segStart;
if (!arguments.length || obj == null || obj == undefined)
return [];
if (Array.isArray(obj)) {
return obj.map(
function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase();
}
);
}
str = obj.toString().toLowerCase().replace(/^\s+/, '');
for (i = str.length - 1; i >= 0; i--) {
if (/\S/.test(str.charAt(i))) {
str = str.substring(0, i + 1);
break;
}
}
tokens = [];
len = str.length;
for (sliceEnd = 0, sliceStart = 0; sliceEnd <= len; sliceEnd++) {
char = str.charAt(sliceEnd);
sliceLength = sliceEnd - sliceStart;
if ((char.match(/\s/) || sliceEnd == len)) {
if (sliceLength > 0) {
segs = segmenter.segment(str.slice(sliceStart, sliceEnd)).filter(
function(token) {
return !!token;
}
);
segStart = sliceStart;
for (i = 0; i < segs.length; i++) {
if (isLunr2) {
tokens.push(
new lunr.Token(
segs[i], {
position: [segStart, segs[i].length],
index: tokens.length
}
)
);
} else {
tokens.push(segs[i]);
}
segStart += segs[i].length;
}
}
sliceStart = sliceEnd + 1;
}
}
return tokens;
}
/* lunr stemmer function */
lunr.ja.stemmer = (function() {
/* TODO japanese stemmer */
return function(word) {
return word;
}
})();
lunr.Pipeline.registerFunction(lunr.ja.stemmer, 'stemmer-ja');
/* lunr trimmer function */
lunr.ja.wordCharacters = "一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9";
lunr.ja.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.ja.wordCharacters);
lunr.Pipeline.registerFunction(lunr.ja.trimmer, 'trimmer-ja');
/* lunr stop word filter. see http://www.ranks.nl/stopwords/japanese */
lunr.ja.stopWordFilter = lunr.generateStopWordFilter(
'これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし'.split(' '));
lunr.Pipeline.registerFunction(lunr.ja.stopWordFilter, 'stopWordFilter-ja');
// alias ja => jp for backward-compatibility.
// jp is the country code, while ja is the language code
// a new lunr.ja.js has been created, but in order to
// keep the backward compatibility, we'll leave the lunr.jp.js
// here for a while, and just make it use the new lunr.ja.js
lunr.jp = lunr.ja;
lunr.Pipeline.registerFunction(lunr.jp.stemmer, 'stemmer-jp');
lunr.Pipeline.registerFunction(lunr.jp.trimmer, 'trimmer-jp');
lunr.Pipeline.registerFunction(lunr.jp.stopWordFilter, 'stopWordFilter-jp');
};
}))
@@ -0,0 +1,5 @@
// jp is the country code, while ja is the language code
// a new lunr.ja.js has been created, but in order to
// keep the backward compatibility, we'll leave the lunr.jp.js
// here for a while, and just make it use the new lunr.ja.js
module.exports = require('./lunr.ja');
@@ -0,0 +1,110 @@
/*!
* Lunr languages, `Kannada` language
* https://github.com/MiKr13/lunr-languages
*
* Copyright 2023, India
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.kn = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.kn.trimmer,
lunr.kn.stopWordFilter,
lunr.kn.stemmer
);
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.kn.stemmer)
}
};
/* lunr trimmer function */
lunr.kn.wordCharacters = "\u0C80-\u0C84\u0C85-\u0C94\u0C95-\u0CB9\u0CBE-\u0CCC\u0CBC-\u0CBD\u0CD5-\u0CD6\u0CDD-\u0CDE\u0CE0-\u0CE1\u0CE2-\u0CE3\u0CE4\u0CE5\u0CE6-\u0CEF\u0CF1-\u0CF3";
lunr.kn.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.kn.wordCharacters);
lunr.Pipeline.registerFunction(lunr.kn.trimmer, 'trimmer-kn');
/* lunr stop word filter */
lunr.kn.stopWordFilter = lunr.generateStopWordFilter(
'ಮತ್ತು ಈ ಒಂದು ರಲ್ಲಿ ಹಾಗೂ ಎಂದು ಅಥವಾ ಇದು ರ ಅವರು ಎಂಬ ಮೇಲೆ ಅವರ ತನ್ನ ಆದರೆ ತಮ್ಮ ನಂತರ ಮೂಲಕ ಹೆಚ್ಚು ನ ಆ ಕೆಲವು ಅನೇಕ ಎರಡು ಹಾಗು ಪ್ರಮುಖ ಇದನ್ನು ಇದರ ಸುಮಾರು ಅದರ ಅದು ಮೊದಲ ಬಗ್ಗೆ ನಲ್ಲಿ ರಂದು ಇತರ ಅತ್ಯಂತ ಹೆಚ್ಚಿನ ಸಹ ಸಾಮಾನ್ಯವಾಗಿ ನೇ ಹಲವಾರು ಹೊಸ ದಿ ಕಡಿಮೆ ಯಾವುದೇ ಹೊಂದಿದೆ ದೊಡ್ಡ ಅನ್ನು ಇವರು ಪ್ರಕಾರ ಇದೆ ಮಾತ್ರ ಕೂಡ ಇಲ್ಲಿ ಎಲ್ಲಾ ವಿವಿಧ ಅದನ್ನು ಹಲವು ರಿಂದ ಕೇವಲ ದ ದಕ್ಷಿಣ ಗೆ ಅವನ ಅತಿ ನೆಯ ಬಹಳ ಕೆಲಸ ಎಲ್ಲ ಪ್ರತಿ ಇತ್ಯಾದಿ ಇವು ಬೇರೆ ಹೀಗೆ ನಡುವೆ ಇದಕ್ಕೆ ಎಸ್ ಇವರ ಮೊದಲು ಶ್ರೀ ಮಾಡುವ ಇದರಲ್ಲಿ ರೀತಿಯ ಮಾಡಿದ ಕಾಲ ಅಲ್ಲಿ ಮಾಡಲು ಅದೇ ಈಗ ಅವು ಗಳು ಎ ಎಂಬುದು ಅವನು ಅಂದರೆ ಅವರಿಗೆ ಇರುವ ವಿಶೇಷ ಮುಂದೆ ಅವುಗಳ ಮುಂತಾದ ಮೂಲ ಬಿ ಮೀ ಒಂದೇ ಇನ್ನೂ ಹೆಚ್ಚಾಗಿ ಮಾಡಿ ಅವರನ್ನು ಇದೇ ಯ ರೀತಿಯಲ್ಲಿ ಜೊತೆ ಅದರಲ್ಲಿ ಮಾಡಿದರು ನಡೆದ ಆಗ ಮತ್ತೆ ಪೂರ್ವ ಆತ ಬಂದ ಯಾವ ಒಟ್ಟು ಇತರೆ ಹಿಂದೆ ಪ್ರಮಾಣದ ಗಳನ್ನು ಕುರಿತು ಯು ಆದ್ದರಿಂದ ಅಲ್ಲದೆ ನಗರದ ಮೇಲಿನ ಏಕೆಂದರೆ ರಷ್ಟು ಎಂಬುದನ್ನು ಬಾರಿ ಎಂದರೆ ಹಿಂದಿನ ಆದರೂ ಆದ ಸಂಬಂಧಿಸಿದ ಮತ್ತೊಂದು ಸಿ ಆತನ '.split(' '));
/* lunr stemmer function */
lunr.kn.stemmer = (function() {
return function(word) {
// for lunr version 2
if (typeof word.update === "function") {
return word.update(function(word) {
return word;
})
} else { // for lunr version <= 1
return word;
}
}
})();
var segmenter = lunr.wordcut;
segmenter.init();
lunr.kn.tokenizer = function(obj) {
if (!arguments.length || obj == null || obj == undefined) return []
if (Array.isArray(obj)) return obj.map(function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase()
});
var str = obj.toString().toLowerCase().replace(/^\s+/, '');
return segmenter.cut(str).split('|');
}
lunr.Pipeline.registerFunction(lunr.kn.stemmer, 'stemmer-kn');
lunr.Pipeline.registerFunction(lunr.kn.stopWordFilter, 'stopWordFilter-kn');
};
}))
@@ -0,0 +1,114 @@
/*!
* Lunr languages, `Korean` language
* https://github.com/turbobit/lunr-languages
*
* Copyright 2021, Manikandan Venkatasubban
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.ko = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.ko.trimmer,
lunr.ko.stopWordFilter
);
// change the tokenizer for japanese one
// if (isLunr2) { // for lunr version 2.0.0
// this.tokenizer = lunr.ko.tokenizer;
// } else {
// if (lunr.tokenizer) { // for lunr version 0.6.0
// lunr.tokenizer = lunr.ko.tokenizer;
// }
// if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
// this.tokenizerFn = lunr.ko.tokenizer;
// }
// }
/*
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.ko.stemmer)
}
*/
};
/* lunr trimmer function */
lunr.ko.wordCharacters = "[" +
"A-Za-z" +
"\uac00-\ud7a3" +
"]";
lunr.ko.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.ko.wordCharacters);
lunr.Pipeline.registerFunction(lunr.ko.trimmer, 'trimmer-ko');
/* lunr stop word filter */
//https://www.ranks.nl/stopwords/korean
lunr.ko.stopWordFilter = lunr.generateStopWordFilter('아 휴 아이구 아이쿠 아이고 어 나 우리 저희 따라 의해 을 를 에 의 가 으로 로 에게 뿐이다 의거하여 근거하여 입각하여 기준으로 예하면 예를 들면 예를 들자면 저 소인 소생 저희 지말고 하지마 하지마라 다른 물론 또한 그리고 비길수 없다 해서는 안된다 뿐만 아니라 만이 아니다 만은 아니다 막론하고 관계없이 그치지 않다 그러나 그런데 하지만 든간에 논하지 않다 따지지 않다 설사 비록 더라도 아니면 만 못하다 하는 편이 낫다 불문하고 향하여 향해서 향하다 쪽으로 틈타 이용하여 타다 오르다 제외하고 이 외에 이 밖에 하여야 비로소 한다면 몰라도 외에도 이곳 여기 부터 기점으로 따라서 할 생각이다 하려고하다 이리하여 그리하여 그렇게 함으로써 하지만 일때 할때 앞에서 중에서 보는데서 으로써 로써 까지 해야한다 일것이다 반드시 할줄알다 할수있다 할수있어 임에 틀림없다 한다면 등 등등 제 겨우 단지 다만 할뿐 딩동 댕그 대해서 대하여 대하면 훨씬 얼마나 얼마만큼 얼마큼 남짓 여 얼마간 약간 다소 좀 조금 다수 몇 얼마 지만 하물며 또한 그러나 그렇지만 하지만 이외에도 대해 말하자면 뿐이다 다음에 반대로 반대로 말하자면 이와 반대로 바꾸어서 말하면 바꾸어서 한다면 만약 그렇지않으면 까악 툭 딱 삐걱거리다 보드득 비걱거리다 꽈당 응당 해야한다 에 가서 각 각각 여러분 각종 각자 제각기 하도록하다 와 과 그러므로 그래서 고로 한 까닭에 하기 때문에 거니와 이지만 대하여 관하여 관한 과연 실로 아니나다를가 생각한대로 진짜로 한적이있다 하곤하였다 하 하하 허허 아하 거바 와 오 왜 어째서 무엇때문에 어찌 하겠는가 무슨 어디 어느곳 더군다나 하물며 더욱이는 어느때 언제 야 이봐 어이 여보시오 흐흐 흥 휴 헉헉 헐떡헐떡 영차 여차 어기여차 끙끙 아야 앗 아야 콸콸 졸졸 좍좍 뚝뚝 주룩주룩 솨 우르르 그래도 또 그리고 바꾸어말하면 바꾸어말하자면 혹은 혹시 답다 및 그에 따르는 때가 되어 즉 지든지 설령 가령 하더라도 할지라도 일지라도 지든지 몇 거의 하마터면 인젠 이젠 된바에야 된이상 만큼 어찌됏든 그위에 게다가 점에서 보아 비추어 보아 고려하면 하게될것이다 일것이다 비교적 좀 보다더 비하면 시키다 하게하다 할만하다 의해서 연이서 이어서 잇따라 뒤따라 뒤이어 결국 의지하여 기대여 통하여 자마자 더욱더 불구하고 얼마든지 마음대로 주저하지 않고 곧 즉시 바로 당장 하자마자 밖에 안된다 하면된다 그래 그렇지 요컨대 다시 말하자면 바꿔 말하면 즉 구체적으로 말하자면 시작하여 시초에 이상 허 헉 허걱 바와같이 해도좋다 해도된다 게다가 더구나 하물며 와르르 팍 퍽 펄렁 동안 이래 하고있었다 이었다 에서 로부터 까지 예하면 했어요 해요 함께 같이 더불어 마저 마저도 양자 모두 습니다 가까스로 하려고하다 즈음하여 다른 다른 방면으로 해봐요 습니까 했어요 말할것도 없고 무릎쓰고 개의치않고 하는것만 못하다 하는것이 낫다 매 매번 들 모 어느것 어느 로써 갖고말하자면 어디 어느쪽 어느것 어느해 어느 년도 라 해도 언젠가 어떤것 어느것 저기 저쪽 저것 그때 그럼 그러면 요만한걸 그래 그때 저것만큼 그저 이르기까지 할 줄 안다 할 힘이 있다 너 너희 당신 어찌 설마 차라리 할지언정 할지라도 할망정 할지언정 구토하다 게우다 토하다 메쓰겁다 옆사람 퉤 쳇 의거하여 근거하여 의해 따라 힘입어 그 다음 버금 두번째로 기타 첫번째로 나머지는 그중에서 견지에서 형식으로 쓰여 입장에서 위해서 단지 의해되다 하도록시키다 뿐만아니라 반대로 전후 전자 앞의것 잠시 잠깐 하면서 그렇지만 다음에 그러한즉 그런즉 남들 아무거나 어찌하든지 같다 비슷하다 예컨대 이럴정도로 어떻게 만약 만일 위에서 서술한바와같이 인 듯하다 하지 않는다면 만약에 무엇 무슨 어느 어떤 아래윗 조차 한데 그럼에도 불구하고 여전히 심지어 까지도 조차도 하지 않도록 않기 위하여 때 시각 무렵 시간 동안 어때 어떠한 하여금 네 예 우선 누구 누가 알겠는가 아무도 줄은모른다 줄은 몰랏다 하는 김에 겸사겸사 하는바 그런 까닭에 한 이유는 그러니 그러니까 때문에 그 너희 그들 너희들 타인 것 것들 너 위하여 공동으로 동시에 하기 위하여 Line truncated
lunr.Pipeline.registerFunction(lunr.ko.stopWordFilter, 'stopWordFilter-ko');
/* lunr stemmer function */
lunr.ko.stemmer = (function() {
return function(word) {
// for lunr version 2
if (typeof word.update === "function") {
return word.update(function(word) {
return word;
})
} else { // for lunr version <= 1
return word;
}
}
})();
lunr.Pipeline.registerFunction(lunr.ko.stemmer, 'stemmer-ko');
};
}))
@@ -0,0 +1,79 @@
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function () {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* Set up the pipeline for indexing content in multiple languages. The
corresponding lunr.{lang} files must be loaded before calling this
function; English ('en') is built in.
Returns: a lunr plugin for use in your indexer.
Known drawback: every word will be stemmed with stemmers for every
language. This could mean that sometimes words that have the same
stemming root will not be stemmed as such.
*/
lunr.multiLanguage = function(/* lang1, lang2, ... */) {
var languages = Array.prototype.slice.call(arguments);
var nameSuffix = languages.join('-');
var wordCharacters = "";
var pipeline = [];
var searchPipeline = [];
for (var i = 0; i < languages.length; ++i) {
if (languages[i] == 'en') {
wordCharacters += '\\w';
pipeline.unshift(lunr.stopWordFilter);
pipeline.push(lunr.stemmer);
searchPipeline.push(lunr.stemmer);
} else {
wordCharacters += lunr[languages[i]].wordCharacters;
if (lunr[languages[i]].stopWordFilter) {
pipeline.unshift(lunr[languages[i]].stopWordFilter);
}
if (lunr[languages[i]].stemmer) {
pipeline.push(lunr[languages[i]].stemmer);
searchPipeline.push(lunr[languages[i]].stemmer);
}
}
};
var multiTrimmer = lunr.trimmerSupport.generateTrimmer(wordCharacters);
lunr.Pipeline.registerFunction(multiTrimmer, 'lunr-multi-trimmer-' + nameSuffix);
pipeline.unshift(multiTrimmer);
return function() {
this.pipeline.reset();
this.pipeline.add.apply(this.pipeline, pipeline);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add.apply(this.searchPipeline, searchPipeline);
}
};
}
}
}));
@@ -0,0 +1,448 @@
/*!
* Lunr languages, `Dutch` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.nl = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.nl.trimmer,
lunr.nl.stopWordFilter,
lunr.nl.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.nl.stemmer)
}
};
/* lunr trimmer function */
lunr.nl.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.nl.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.nl.wordCharacters);
lunr.Pipeline.registerFunction(lunr.nl.trimmer, 'trimmer-nl');
/* lunr stemmer function */
lunr.nl.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function DutchStemmer() {
var a_0 = [new Among("", -1, 6), new Among("\u00E1", 0, 1),
new Among("\u00E4", 0, 1), new Among("\u00E9", 0, 2),
new Among("\u00EB", 0, 2), new Among("\u00ED", 0, 3),
new Among("\u00EF", 0, 3), new Among("\u00F3", 0, 4),
new Among("\u00F6", 0, 4), new Among("\u00FA", 0, 5),
new Among("\u00FC", 0, 5)
],
a_1 = [new Among("", -1, 3),
new Among("I", 0, 2), new Among("Y", 0, 1)
],
a_2 = [
new Among("dd", -1, -1), new Among("kk", -1, -1),
new Among("tt", -1, -1)
],
a_3 = [new Among("ene", -1, 2),
new Among("se", -1, 3), new Among("en", -1, 2),
new Among("heden", 2, 1), new Among("s", -1, 3)
],
a_4 = [
new Among("end", -1, 1), new Among("ig", -1, 2),
new Among("ing", -1, 1), new Among("lijk", -1, 3),
new Among("baar", -1, 4), new Among("bar", -1, 5)
],
a_5 = [
new Among("aa", -1, -1), new Among("ee", -1, -1),
new Among("oo", -1, -1), new Among("uu", -1, -1)
],
g_v = [17, 65,
16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
],
g_v_I = [1, 0, 0,
17, 65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
],
g_v_j = [
17, 67, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128
],
I_p2, I_p1, B_e_found, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_prelude() {
var among_var, v_1 = sbp.cursor,
v_2, v_3;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_0, 11);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("a");
continue;
case 2:
sbp.slice_from("e");
continue;
case 3:
sbp.slice_from("i");
continue;
case 4:
sbp.slice_from("o");
continue;
case 5:
sbp.slice_from("u");
continue;
case 6:
if (sbp.cursor >= sbp.limit)
break;
sbp.cursor++;
continue;
}
}
break;
}
sbp.cursor = v_1;
sbp.bra = v_1;
if (sbp.eq_s(1, "y")) {
sbp.ket = sbp.cursor;
sbp.slice_from("Y");
} else
sbp.cursor = v_1;
while (true) {
v_2 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 232)) {
v_3 = sbp.cursor;
sbp.bra = v_3;
if (sbp.eq_s(1, "i")) {
sbp.ket = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 232)) {
sbp.slice_from("I");
sbp.cursor = v_2;
}
} else {
sbp.cursor = v_3;
if (sbp.eq_s(1, "y")) {
sbp.ket = sbp.cursor;
sbp.slice_from("Y");
sbp.cursor = v_2;
} else if (habr1(v_2))
break;
}
} else if (habr1(v_2))
break;
}
}
function habr1(v_1) {
sbp.cursor = v_1;
if (v_1 >= sbp.limit)
return true;
sbp.cursor++;
return false;
}
function r_mark_regions() {
I_p1 = sbp.limit;
I_p2 = I_p1;
if (!habr2()) {
I_p1 = sbp.cursor;
if (I_p1 < 3)
I_p1 = 3;
if (!habr2())
I_p2 = sbp.cursor;
}
}
function habr2() {
while (!sbp.in_grouping(g_v, 97, 232)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 232)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
function r_postlude() {
var among_var;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_1, 3);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("y");
break;
case 2:
sbp.slice_from("i");
break;
case 3:
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
break;
}
}
}
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_undouble() {
var v_1 = sbp.limit - sbp.cursor;
if (sbp.find_among_b(a_2, 3)) {
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
}
}
function r_e_ending() {
var v_1;
B_e_found = false;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "e")) {
sbp.bra = sbp.cursor;
if (r_R1()) {
v_1 = sbp.limit - sbp.cursor;
if (sbp.out_grouping_b(g_v, 97, 232)) {
sbp.cursor = sbp.limit - v_1;
sbp.slice_del();
B_e_found = true;
r_undouble();
}
}
}
}
function r_en_ending() {
var v_1;
if (r_R1()) {
v_1 = sbp.limit - sbp.cursor;
if (sbp.out_grouping_b(g_v, 97, 232)) {
sbp.cursor = sbp.limit - v_1;
if (!sbp.eq_s_b(3, "gem")) {
sbp.cursor = sbp.limit - v_1;
sbp.slice_del();
r_undouble();
}
}
}
}
function r_standard_suffix() {
var among_var, v_1 = sbp.limit - sbp.cursor,
v_2, v_3, v_4, v_5, v_6;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 5);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_R1())
sbp.slice_from("heid");
break;
case 2:
r_en_ending();
break;
case 3:
if (r_R1() && sbp.out_grouping_b(g_v_j, 97, 232))
sbp.slice_del();
break;
}
}
sbp.cursor = sbp.limit - v_1;
r_e_ending();
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(4, "heid")) {
sbp.bra = sbp.cursor;
if (r_R2()) {
v_2 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "c")) {
sbp.cursor = sbp.limit - v_2;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "en")) {
sbp.bra = sbp.cursor;
r_en_ending();
}
}
}
}
sbp.cursor = sbp.limit - v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 6);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_R2()) {
sbp.slice_del();
v_3 = sbp.limit - sbp.cursor;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "ig")) {
sbp.bra = sbp.cursor;
if (r_R2()) {
v_4 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "e")) {
sbp.cursor = sbp.limit - v_4;
sbp.slice_del();
break;
}
}
}
sbp.cursor = sbp.limit - v_3;
r_undouble();
}
break;
case 2:
if (r_R2()) {
v_5 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "e")) {
sbp.cursor = sbp.limit - v_5;
sbp.slice_del();
}
}
break;
case 3:
if (r_R2()) {
sbp.slice_del();
r_e_ending();
}
break;
case 4:
if (r_R2())
sbp.slice_del();
break;
case 5:
if (r_R2() && B_e_found)
sbp.slice_del();
break;
}
}
sbp.cursor = sbp.limit - v_1;
if (sbp.out_grouping_b(g_v_I, 73, 232)) {
v_6 = sbp.limit - sbp.cursor;
if (sbp.find_among_b(a_5, 4) && sbp.out_grouping_b(g_v, 97, 232)) {
sbp.cursor = sbp.limit - v_6;
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_prelude();
sbp.cursor = v_1;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_standard_suffix();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.nl.stemmer, 'stemmer-nl');
lunr.nl.stopWordFilter = lunr.generateStopWordFilter(' aan al alles als altijd andere ben bij daar dan dat de der deze die dit doch doen door dus een eens en er ge geen geweest haar had heb hebben heeft hem het hier hij hoe hun iemand iets ik in is ja je kan kon kunnen maar me meer men met mij mijn moet na naar niet niets nog nu of om omdat onder ons ook op over reeds te tegen toch toen tot u uit uw van veel voor want waren was wat werd wezen wie wil worden wordt zal ze zelf zich zij zijn zo zonder zou'.split(' '));
lunr.Pipeline.registerFunction(lunr.nl.stopWordFilter, 'stopWordFilter-nl');
};
}))
@@ -0,0 +1,258 @@
/*!
* Lunr languages, `Norwegian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.no = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.no.trimmer,
lunr.no.stopWordFilter,
lunr.no.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.no.stemmer)
}
};
/* lunr trimmer function */
lunr.no.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.no.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.no.wordCharacters);
lunr.Pipeline.registerFunction(lunr.no.trimmer, 'trimmer-no');
/* lunr stemmer function */
lunr.no.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function NorwegianStemmer() {
var a_0 = [new Among("a", -1, 1), new Among("e", -1, 1),
new Among("ede", 1, 1), new Among("ande", 1, 1),
new Among("ende", 1, 1), new Among("ane", 1, 1),
new Among("ene", 1, 1), new Among("hetene", 6, 1),
new Among("erte", 1, 3), new Among("en", -1, 1),
new Among("heten", 9, 1), new Among("ar", -1, 1),
new Among("er", -1, 1), new Among("heter", 12, 1),
new Among("s", -1, 2), new Among("as", 14, 1),
new Among("es", 14, 1), new Among("edes", 16, 1),
new Among("endes", 16, 1), new Among("enes", 16, 1),
new Among("hetenes", 19, 1), new Among("ens", 14, 1),
new Among("hetens", 21, 1), new Among("ers", 14, 1),
new Among("ets", 14, 1), new Among("et", -1, 1),
new Among("het", 25, 1), new Among("ert", -1, 3),
new Among("ast", -1, 1)
],
a_1 = [new Among("dt", -1, -1),
new Among("vt", -1, -1)
],
a_2 = [new Among("leg", -1, 1),
new Among("eleg", 0, 1), new Among("ig", -1, 1),
new Among("eig", 2, 1), new Among("lig", 2, 1),
new Among("elig", 4, 1), new Among("els", -1, 1),
new Among("lov", -1, 1), new Among("elov", 7, 1),
new Among("slov", 7, 1), new Among("hetslov", 9, 1)
],
g_v = [17,
65, 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 128
],
g_s_ending = [
119, 125, 149, 1
],
I_x, I_p1, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_mark_regions() {
var v_1, c = sbp.cursor + 3;
I_p1 = sbp.limit;
if (0 <= c || c <= sbp.limit) {
I_x = c;
while (true) {
v_1 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 248)) {
sbp.cursor = v_1;
break;
}
if (v_1 >= sbp.limit)
return;
sbp.cursor = v_1 + 1;
}
while (!sbp.out_grouping(g_v, 97, 248)) {
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
I_p1 = sbp.cursor;
if (I_p1 < I_x)
I_p1 = I_x;
}
}
function r_main_suffix() {
var among_var, v_1, v_2;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_0, 29);
sbp.limit_backward = v_1;
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
v_2 = sbp.limit - sbp.cursor;
if (sbp.in_grouping_b(g_s_ending, 98, 122))
sbp.slice_del();
else {
sbp.cursor = sbp.limit - v_2;
if (sbp.eq_s_b(1, "k") &&
sbp.out_grouping_b(g_v, 97, 248))
sbp.slice_del();
}
break;
case 3:
sbp.slice_from("er");
break;
}
}
}
}
function r_consonant_pair() {
var v_1 = sbp.limit - sbp.cursor,
v_2;
if (sbp.cursor >= I_p1) {
v_2 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
if (sbp.find_among_b(a_1, 2)) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_2;
sbp.cursor = sbp.limit - v_1;
if (sbp.cursor > sbp.limit_backward) {
sbp.cursor--;
sbp.bra = sbp.cursor;
sbp.slice_del();
}
} else
sbp.limit_backward = v_2;
}
}
function r_other_suffix() {
var among_var, v_1;
if (sbp.cursor >= I_p1) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_2, 11);
if (among_var) {
sbp.bra = sbp.cursor;
sbp.limit_backward = v_1;
if (among_var == 1)
sbp.slice_del();
} else
sbp.limit_backward = v_1;
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_main_suffix();
sbp.cursor = sbp.limit;
r_consonant_pair();
sbp.cursor = sbp.limit;
r_other_suffix();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.no.stemmer, 'stemmer-no');
lunr.no.stopWordFilter = lunr.generateStopWordFilter('alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å'.split(' '));
lunr.Pipeline.registerFunction(lunr.no.stopWordFilter, 'stopWordFilter-no');
};
}))
@@ -0,0 +1,570 @@
/*!
* Lunr languages, `Portuguese` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.pt = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.pt.trimmer,
lunr.pt.stopWordFilter,
lunr.pt.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.pt.stemmer)
}
};
/* lunr trimmer function */
lunr.pt.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.pt.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.pt.wordCharacters);
lunr.Pipeline.registerFunction(lunr.pt.trimmer, 'trimmer-pt');
/* lunr stemmer function */
lunr.pt.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function PortugueseStemmer() {
var a_0 = [new Among("", -1, 3), new Among("\u00E3", 0, 1),
new Among("\u00F5", 0, 2)
],
a_1 = [new Among("", -1, 3),
new Among("a~", 0, 1), new Among("o~", 0, 2)
],
a_2 = [
new Among("ic", -1, -1), new Among("ad", -1, -1),
new Among("os", -1, -1), new Among("iv", -1, 1)
],
a_3 = [
new Among("ante", -1, 1), new Among("avel", -1, 1),
new Among("\u00EDvel", -1, 1)
],
a_4 = [new Among("ic", -1, 1),
new Among("abil", -1, 1), new Among("iv", -1, 1)
],
a_5 = [
new Among("ica", -1, 1), new Among("\u00E2ncia", -1, 1),
new Among("\u00EAncia", -1, 4), new Among("ira", -1, 9),
new Among("adora", -1, 1), new Among("osa", -1, 1),
new Among("ista", -1, 1), new Among("iva", -1, 8),
new Among("eza", -1, 1), new Among("log\u00EDa", -1, 2),
new Among("idade", -1, 7), new Among("ante", -1, 1),
new Among("mente", -1, 6), new Among("amente", 12, 5),
new Among("\u00E1vel", -1, 1), new Among("\u00EDvel", -1, 1),
new Among("uci\u00F3n", -1, 3), new Among("ico", -1, 1),
new Among("ismo", -1, 1), new Among("oso", -1, 1),
new Among("amento", -1, 1), new Among("imento", -1, 1),
new Among("ivo", -1, 8), new Among("a\u00E7a~o", -1, 1),
new Among("ador", -1, 1), new Among("icas", -1, 1),
new Among("\u00EAncias", -1, 4), new Among("iras", -1, 9),
new Among("adoras", -1, 1), new Among("osas", -1, 1),
new Among("istas", -1, 1), new Among("ivas", -1, 8),
new Among("ezas", -1, 1), new Among("log\u00EDas", -1, 2),
new Among("idades", -1, 7), new Among("uciones", -1, 3),
new Among("adores", -1, 1), new Among("antes", -1, 1),
new Among("a\u00E7o~es", -1, 1), new Among("icos", -1, 1),
new Among("ismos", -1, 1), new Among("osos", -1, 1),
new Among("amentos", -1, 1), new Among("imentos", -1, 1),
new Among("ivos", -1, 8)
],
a_6 = [new Among("ada", -1, 1),
new Among("ida", -1, 1), new Among("ia", -1, 1),
new Among("aria", 2, 1), new Among("eria", 2, 1),
new Among("iria", 2, 1), new Among("ara", -1, 1),
new Among("era", -1, 1), new Among("ira", -1, 1),
new Among("ava", -1, 1), new Among("asse", -1, 1),
new Among("esse", -1, 1), new Among("isse", -1, 1),
new Among("aste", -1, 1), new Among("este", -1, 1),
new Among("iste", -1, 1), new Among("ei", -1, 1),
new Among("arei", 16, 1), new Among("erei", 16, 1),
new Among("irei", 16, 1), new Among("am", -1, 1),
new Among("iam", 20, 1), new Among("ariam", 21, 1),
new Among("eriam", 21, 1), new Among("iriam", 21, 1),
new Among("aram", 20, 1), new Among("eram", 20, 1),
new Among("iram", 20, 1), new Among("avam", 20, 1),
new Among("em", -1, 1), new Among("arem", 29, 1),
new Among("erem", 29, 1), new Among("irem", 29, 1),
new Among("assem", 29, 1), new Among("essem", 29, 1),
new Among("issem", 29, 1), new Among("ado", -1, 1),
new Among("ido", -1, 1), new Among("ando", -1, 1),
new Among("endo", -1, 1), new Among("indo", -1, 1),
new Among("ara~o", -1, 1), new Among("era~o", -1, 1),
new Among("ira~o", -1, 1), new Among("ar", -1, 1),
new Among("er", -1, 1), new Among("ir", -1, 1),
new Among("as", -1, 1), new Among("adas", 47, 1),
new Among("idas", 47, 1), new Among("ias", 47, 1),
new Among("arias", 50, 1), new Among("erias", 50, 1),
new Among("irias", 50, 1), new Among("aras", 47, 1),
new Among("eras", 47, 1), new Among("iras", 47, 1),
new Among("avas", 47, 1), new Among("es", -1, 1),
new Among("ardes", 58, 1), new Among("erdes", 58, 1),
new Among("irdes", 58, 1), new Among("ares", 58, 1),
new Among("eres", 58, 1), new Among("ires", 58, 1),
new Among("asses", 58, 1), new Among("esses", 58, 1),
new Among("isses", 58, 1), new Among("astes", 58, 1),
new Among("estes", 58, 1), new Among("istes", 58, 1),
new Among("is", -1, 1), new Among("ais", 71, 1),
new Among("eis", 71, 1), new Among("areis", 73, 1),
new Among("ereis", 73, 1), new Among("ireis", 73, 1),
new Among("\u00E1reis", 73, 1), new Among("\u00E9reis", 73, 1),
new Among("\u00EDreis", 73, 1), new Among("\u00E1sseis", 73, 1),
new Among("\u00E9sseis", 73, 1), new Among("\u00EDsseis", 73, 1),
new Among("\u00E1veis", 73, 1), new Among("\u00EDeis", 73, 1),
new Among("ar\u00EDeis", 84, 1), new Among("er\u00EDeis", 84, 1),
new Among("ir\u00EDeis", 84, 1), new Among("ados", -1, 1),
new Among("idos", -1, 1), new Among("amos", -1, 1),
new Among("\u00E1ramos", 90, 1), new Among("\u00E9ramos", 90, 1),
new Among("\u00EDramos", 90, 1), new Among("\u00E1vamos", 90, 1),
new Among("\u00EDamos", 90, 1), new Among("ar\u00EDamos", 95, 1),
new Among("er\u00EDamos", 95, 1), new Among("ir\u00EDamos", 95, 1),
new Among("emos", -1, 1), new Among("aremos", 99, 1),
new Among("eremos", 99, 1), new Among("iremos", 99, 1),
new Among("\u00E1ssemos", 99, 1), new Among("\u00EAssemos", 99, 1),
new Among("\u00EDssemos", 99, 1), new Among("imos", -1, 1),
new Among("armos", -1, 1), new Among("ermos", -1, 1),
new Among("irmos", -1, 1), new Among("\u00E1mos", -1, 1),
new Among("ar\u00E1s", -1, 1), new Among("er\u00E1s", -1, 1),
new Among("ir\u00E1s", -1, 1), new Among("eu", -1, 1),
new Among("iu", -1, 1), new Among("ou", -1, 1),
new Among("ar\u00E1", -1, 1), new Among("er\u00E1", -1, 1),
new Among("ir\u00E1", -1, 1)
],
a_7 = [new Among("a", -1, 1),
new Among("i", -1, 1), new Among("o", -1, 1),
new Among("os", -1, 1), new Among("\u00E1", -1, 1),
new Among("\u00ED", -1, 1), new Among("\u00F3", -1, 1)
],
a_8 = [
new Among("e", -1, 1), new Among("\u00E7", -1, 2),
new Among("\u00E9", -1, 1), new Among("\u00EA", -1, 1)
],
g_v = [17,
65, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 19, 12, 2
],
I_p2, I_p1, I_pV, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_prelude() {
var among_var;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_0, 3);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("a~");
continue;
case 2:
sbp.slice_from("o~");
continue;
case 3:
if (sbp.cursor >= sbp.limit)
break;
sbp.cursor++;
continue;
}
}
break;
}
}
function habr2() {
if (sbp.out_grouping(g_v, 97, 250)) {
while (!sbp.in_grouping(g_v, 97, 250)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
return true;
}
function habr3() {
if (sbp.in_grouping(g_v, 97, 250)) {
while (!sbp.out_grouping(g_v, 97, 250)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
}
I_pV = sbp.cursor;
return true;
}
function habr4() {
var v_1 = sbp.cursor,
v_2, v_3;
if (sbp.in_grouping(g_v, 97, 250)) {
v_2 = sbp.cursor;
if (habr2()) {
sbp.cursor = v_2;
if (habr3())
return;
} else
I_pV = sbp.cursor;
}
sbp.cursor = v_1;
if (sbp.out_grouping(g_v, 97, 250)) {
v_3 = sbp.cursor;
if (habr2()) {
sbp.cursor = v_3;
if (!sbp.in_grouping(g_v, 97, 250) || sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
I_pV = sbp.cursor;
}
}
function habr5() {
while (!sbp.in_grouping(g_v, 97, 250)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 250)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
return true;
}
function r_mark_regions() {
var v_1 = sbp.cursor;
I_pV = sbp.limit;
I_p1 = I_pV;
I_p2 = I_pV;
habr4();
sbp.cursor = v_1;
if (habr5()) {
I_p1 = sbp.cursor;
if (habr5())
I_p2 = sbp.cursor;
}
}
function r_postlude() {
var among_var;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_1, 3);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("\u00E3");
continue;
case 2:
sbp.slice_from("\u00F5");
continue;
case 3:
if (sbp.cursor >= sbp.limit)
break;
sbp.cursor++;
continue;
}
}
break;
}
}
function r_RV() {
return I_pV <= sbp.cursor;
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_standard_suffix() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_5, 45);
if (!among_var)
return false;
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (!r_R2())
return false;
sbp.slice_del();
break;
case 2:
if (!r_R2())
return false;
sbp.slice_from("log");
break;
case 3:
if (!r_R2())
return false;
sbp.slice_from("u");
break;
case 4:
if (!r_R2())
return false;
sbp.slice_from("ente");
break;
case 5:
if (!r_R1())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_2, 4);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R2()) {
sbp.slice_del();
if (among_var == 1) {
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "at")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
}
}
}
break;
case 6:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 3);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1)
if (r_R2())
sbp.slice_del();
}
break;
case 7:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 3);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1)
if (r_R2())
sbp.slice_del();
}
break;
case 8:
if (!r_R2())
return false;
sbp.slice_del();
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(2, "at")) {
sbp.bra = sbp.cursor;
if (r_R2())
sbp.slice_del();
}
break;
case 9:
if (!r_RV() || !sbp.eq_s_b(1, "e"))
return false;
sbp.slice_from("ir");
break;
}
return true;
}
function r_verb_suffix() {
var among_var, v_1;
if (sbp.cursor >= I_pV) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_6, 120);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1)
sbp.slice_del();
sbp.limit_backward = v_1;
return true;
}
sbp.limit_backward = v_1;
}
return false;
}
function r_residual_suffix() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_7, 7);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1)
if (r_RV())
sbp.slice_del();
}
}
function habr6(c1, c2) {
if (sbp.eq_s_b(1, c1)) {
sbp.bra = sbp.cursor;
var v_1 = sbp.limit - sbp.cursor;
if (sbp.eq_s_b(1, c2)) {
sbp.cursor = sbp.limit - v_1;
if (r_RV())
sbp.slice_del();
return false;
}
}
return true;
}
function r_residual_form() {
var among_var, v_1, v_2, v_3;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_8, 4);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
if (r_RV()) {
sbp.slice_del();
sbp.ket = sbp.cursor;
v_1 = sbp.limit - sbp.cursor;
if (habr6("u", "g"))
habr6("i", "c")
}
break;
case 2:
sbp.slice_from("c");
break;
}
}
}
function habr1() {
if (!r_standard_suffix()) {
sbp.cursor = sbp.limit;
if (!r_verb_suffix()) {
sbp.cursor = sbp.limit;
r_residual_suffix();
return;
}
}
sbp.cursor = sbp.limit;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "i")) {
sbp.bra = sbp.cursor;
if (sbp.eq_s_b(1, "c")) {
sbp.cursor = sbp.limit;
if (r_RV())
sbp.slice_del();
}
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_prelude();
sbp.cursor = v_1;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
habr1();
sbp.cursor = sbp.limit;
r_residual_form();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.pt.stemmer, 'stemmer-pt');
lunr.pt.stopWordFilter = lunr.generateStopWordFilter('a ao aos aquela aquelas aquele aqueles aquilo as até com como da das de dela delas dele deles depois do dos e ela elas ele eles em entre era eram essa essas esse esses esta estamos estas estava estavam este esteja estejam estejamos estes esteve estive estivemos estiver estivera estiveram estiverem estivermos estivesse estivessem estivéramos estivéssemos estou está estávamos estão eu foi fomos for fora foram forem formos fosse fossem fui fôramos fôssemos haja hajam hajamos havemos hei houve houvemos houver houvera houveram houverei houverem houveremos houveria houveriam houvermos houverá houverão houveríamos houvesse houvessem houvéramos houvéssemos há hão isso isto já lhe lhes mais mas me mesmo meu meus minha minhas muito na nas nem no nos nossa nossas nosso nossos num numa não nós o os ou para pela pelas pelo pelos por qual quando que quem se seja sejam sejamos sem serei seremos seria seriam será serão seríamos seu seus somos sou sua suas são só também te tem temos tenha tenham tenhamos tenho terei teremos teria teriam terá terão teríamos teu teus teve tinha tinham tive tivemos tiver tivera tiveram tiverem tivermos tivesse tivessem tivéramos tivéssemos tu tua tuas tém tínhamos um uma você vocês vos à às éramos'.split(' '));
lunr.Pipeline.registerFunction(lunr.pt.stopWordFilter, 'stopWordFilter-pt');
};
}))
@@ -0,0 +1,558 @@
/*!
* Lunr languages, `Romanian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.ro = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.ro.trimmer,
lunr.ro.stopWordFilter,
lunr.ro.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.ro.stemmer)
}
};
/* lunr trimmer function */
lunr.ro.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.ro.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.ro.wordCharacters);
lunr.Pipeline.registerFunction(lunr.ro.trimmer, 'trimmer-ro');
/* lunr stemmer function */
lunr.ro.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function RomanianStemmer() {
var a_0 = [new Among("", -1, 3), new Among("I", 0, 1), new Among("U", 0, 2)],
a_1 = [
new Among("ea", -1, 3), new Among("a\u0163ia", -1, 7),
new Among("aua", -1, 2), new Among("iua", -1, 4),
new Among("a\u0163ie", -1, 7), new Among("ele", -1, 3),
new Among("ile", -1, 5), new Among("iile", 6, 4),
new Among("iei", -1, 4), new Among("atei", -1, 6),
new Among("ii", -1, 4), new Among("ului", -1, 1),
new Among("ul", -1, 1), new Among("elor", -1, 3),
new Among("ilor", -1, 4), new Among("iilor", 14, 4)
],
a_2 = [
new Among("icala", -1, 4), new Among("iciva", -1, 4),
new Among("ativa", -1, 5), new Among("itiva", -1, 6),
new Among("icale", -1, 4), new Among("a\u0163iune", -1, 5),
new Among("i\u0163iune", -1, 6), new Among("atoare", -1, 5),
new Among("itoare", -1, 6), new Among("\u0103toare", -1, 5),
new Among("icitate", -1, 4), new Among("abilitate", -1, 1),
new Among("ibilitate", -1, 2), new Among("ivitate", -1, 3),
new Among("icive", -1, 4), new Among("ative", -1, 5),
new Among("itive", -1, 6), new Among("icali", -1, 4),
new Among("atori", -1, 5), new Among("icatori", 18, 4),
new Among("itori", -1, 6), new Among("\u0103tori", -1, 5),
new Among("icitati", -1, 4), new Among("abilitati", -1, 1),
new Among("ivitati", -1, 3), new Among("icivi", -1, 4),
new Among("ativi", -1, 5), new Among("itivi", -1, 6),
new Among("icit\u0103i", -1, 4), new Among("abilit\u0103i", -1, 1),
new Among("ivit\u0103i", -1, 3),
new Among("icit\u0103\u0163i", -1, 4),
new Among("abilit\u0103\u0163i", -1, 1),
new Among("ivit\u0103\u0163i", -1, 3), new Among("ical", -1, 4),
new Among("ator", -1, 5), new Among("icator", 35, 4),
new Among("itor", -1, 6), new Among("\u0103tor", -1, 5),
new Among("iciv", -1, 4), new Among("ativ", -1, 5),
new Among("itiv", -1, 6), new Among("ical\u0103", -1, 4),
new Among("iciv\u0103", -1, 4), new Among("ativ\u0103", -1, 5),
new Among("itiv\u0103", -1, 6)
],
a_3 = [new Among("ica", -1, 1),
new Among("abila", -1, 1), new Among("ibila", -1, 1),
new Among("oasa", -1, 1), new Among("ata", -1, 1),
new Among("ita", -1, 1), new Among("anta", -1, 1),
new Among("ista", -1, 3), new Among("uta", -1, 1),
new Among("iva", -1, 1), new Among("ic", -1, 1),
new Among("ice", -1, 1), new Among("abile", -1, 1),
new Among("ibile", -1, 1), new Among("isme", -1, 3),
new Among("iune", -1, 2), new Among("oase", -1, 1),
new Among("ate", -1, 1), new Among("itate", 17, 1),
new Among("ite", -1, 1), new Among("ante", -1, 1),
new Among("iste", -1, 3), new Among("ute", -1, 1),
new Among("ive", -1, 1), new Among("ici", -1, 1),
new Among("abili", -1, 1), new Among("ibili", -1, 1),
new Among("iuni", -1, 2), new Among("atori", -1, 1),
new Among("osi", -1, 1), new Among("ati", -1, 1),
new Among("itati", 30, 1), new Among("iti", -1, 1),
new Among("anti", -1, 1), new Among("isti", -1, 3),
new Among("uti", -1, 1), new Among("i\u015Fti", -1, 3),
new Among("ivi", -1, 1), new Among("it\u0103i", -1, 1),
new Among("o\u015Fi", -1, 1), new Among("it\u0103\u0163i", -1, 1),
new Among("abil", -1, 1), new Among("ibil", -1, 1),
new Among("ism", -1, 3), new Among("ator", -1, 1),
new Among("os", -1, 1), new Among("at", -1, 1),
new Among("it", -1, 1), new Among("ant", -1, 1),
new Among("ist", -1, 3), new Among("ut", -1, 1),
new Among("iv", -1, 1), new Among("ic\u0103", -1, 1),
new Among("abil\u0103", -1, 1), new Among("ibil\u0103", -1, 1),
new Among("oas\u0103", -1, 1), new Among("at\u0103", -1, 1),
new Among("it\u0103", -1, 1), new Among("ant\u0103", -1, 1),
new Among("ist\u0103", -1, 3), new Among("ut\u0103", -1, 1),
new Among("iv\u0103", -1, 1)
],
a_4 = [new Among("ea", -1, 1),
new Among("ia", -1, 1), new Among("esc", -1, 1),
new Among("\u0103sc", -1, 1), new Among("ind", -1, 1),
new Among("\u00E2nd", -1, 1), new Among("are", -1, 1),
new Among("ere", -1, 1), new Among("ire", -1, 1),
new Among("\u00E2re", -1, 1), new Among("se", -1, 2),
new Among("ase", 10, 1), new Among("sese", 10, 2),
new Among("ise", 10, 1), new Among("use", 10, 1),
new Among("\u00E2se", 10, 1), new Among("e\u015Fte", -1, 1),
new Among("\u0103\u015Fte", -1, 1), new Among("eze", -1, 1),
new Among("ai", -1, 1), new Among("eai", 19, 1),
new Among("iai", 19, 1), new Among("sei", -1, 2),
new Among("e\u015Fti", -1, 1), new Among("\u0103\u015Fti", -1, 1),
new Among("ui", -1, 1), new Among("ezi", -1, 1),
new Among("\u00E2i", -1, 1), new Among("a\u015Fi", -1, 1),
new Among("se\u015Fi", -1, 2), new Among("ase\u015Fi", 29, 1),
new Among("sese\u015Fi", 29, 2), new Among("ise\u015Fi", 29, 1),
new Among("use\u015Fi", 29, 1),
new Among("\u00E2se\u015Fi", 29, 1), new Among("i\u015Fi", -1, 1),
new Among("u\u015Fi", -1, 1), new Among("\u00E2\u015Fi", -1, 1),
new Among("a\u0163i", -1, 2), new Among("ea\u0163i", 38, 1),
new Among("ia\u0163i", 38, 1), new Among("e\u0163i", -1, 2),
new Among("i\u0163i", -1, 2), new Among("\u00E2\u0163i", -1, 2),
new Among("ar\u0103\u0163i", -1, 1),
new Among("ser\u0103\u0163i", -1, 2),
new Among("aser\u0103\u0163i", 45, 1),
new Among("seser\u0103\u0163i", 45, 2),
new Among("iser\u0103\u0163i", 45, 1),
new Among("user\u0103\u0163i", 45, 1),
new Among("\u00E2ser\u0103\u0163i", 45, 1),
new Among("ir\u0103\u0163i", -1, 1),
new Among("ur\u0103\u0163i", -1, 1),
new Among("\u00E2r\u0103\u0163i", -1, 1), new Among("am", -1, 1),
new Among("eam", 54, 1), new Among("iam", 54, 1),
new Among("em", -1, 2), new Among("asem", 57, 1),
new Among("sesem", 57, 2), new Among("isem", 57, 1),
new Among("usem", 57, 1), new Among("\u00E2sem", 57, 1),
new Among("im", -1, 2), new Among("\u00E2m", -1, 2),
new Among("\u0103m", -1, 2), new Among("ar\u0103m", 65, 1),
new Among("ser\u0103m", 65, 2), new Among("aser\u0103m", 67, 1),
new Among("seser\u0103m", 67, 2), new Among("iser\u0103m", 67, 1),
new Among("user\u0103m", 67, 1),
new Among("\u00E2ser\u0103m", 67, 1),
new Among("ir\u0103m", 65, 1), new Among("ur\u0103m", 65, 1),
new Among("\u00E2r\u0103m", 65, 1), new Among("au", -1, 1),
new Among("eau", 76, 1), new Among("iau", 76, 1),
new Among("indu", -1, 1), new Among("\u00E2ndu", -1, 1),
new Among("ez", -1, 1), new Among("easc\u0103", -1, 1),
new Among("ar\u0103", -1, 1), new Among("ser\u0103", -1, 2),
new Among("aser\u0103", 84, 1), new Among("seser\u0103", 84, 2),
new Among("iser\u0103", 84, 1), new Among("user\u0103", 84, 1),
new Among("\u00E2ser\u0103", 84, 1), new Among("ir\u0103", -1, 1),
new Among("ur\u0103", -1, 1), new Among("\u00E2r\u0103", -1, 1),
new Among("eaz\u0103", -1, 1)
],
a_5 = [new Among("a", -1, 1),
new Among("e", -1, 1), new Among("ie", 1, 1),
new Among("i", -1, 1), new Among("\u0103", -1, 1)
],
g_v = [17, 65,
16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 32, 0, 0, 4
],
B_standard_suffix_removed, I_p2, I_p1, I_pV, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function habr1(c1, c2) {
if (sbp.eq_s(1, c1)) {
sbp.ket = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 259))
sbp.slice_from(c2);
}
}
function r_prelude() {
var v_1, v_2;
while (true) {
v_1 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 259)) {
v_2 = sbp.cursor;
sbp.bra = v_2;
habr1("u", "U");
sbp.cursor = v_2;
habr1("i", "I");
}
sbp.cursor = v_1;
if (sbp.cursor >= sbp.limit) {
break;
}
sbp.cursor++;
}
}
function habr2() {
if (sbp.out_grouping(g_v, 97, 259)) {
while (!sbp.in_grouping(g_v, 97, 259)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
return false;
}
return true;
}
function habr3() {
if (sbp.in_grouping(g_v, 97, 259)) {
while (!sbp.out_grouping(g_v, 97, 259)) {
if (sbp.cursor >= sbp.limit)
return true;
sbp.cursor++;
}
}
return false;
}
function habr4() {
var v_1 = sbp.cursor,
v_2, v_3;
if (sbp.in_grouping(g_v, 97, 259)) {
v_2 = sbp.cursor;
if (habr2()) {
sbp.cursor = v_2;
if (!habr3()) {
I_pV = sbp.cursor;
return;
}
} else {
I_pV = sbp.cursor;
return;
}
}
sbp.cursor = v_1;
if (sbp.out_grouping(g_v, 97, 259)) {
v_3 = sbp.cursor;
if (habr2()) {
sbp.cursor = v_3;
if (sbp.in_grouping(g_v, 97, 259) && sbp.cursor < sbp.limit)
sbp.cursor++;
}
I_pV = sbp.cursor;
}
}
function habr5() {
while (!sbp.in_grouping(g_v, 97, 259)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 259)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
return true;
}
function r_mark_regions() {
var v_1 = sbp.cursor;
I_pV = sbp.limit;
I_p1 = I_pV;
I_p2 = I_pV;
habr4();
sbp.cursor = v_1;
if (habr5()) {
I_p1 = sbp.cursor;
if (habr5())
I_p2 = sbp.cursor;
}
}
function r_postlude() {
var among_var;
while (true) {
sbp.bra = sbp.cursor;
among_var = sbp.find_among(a_0, 3);
if (among_var) {
sbp.ket = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_from("i");
continue;
case 2:
sbp.slice_from("u");
continue;
case 3:
if (sbp.cursor >= sbp.limit)
break;
sbp.cursor++;
continue;
}
}
break;
}
}
function r_RV() {
return I_pV <= sbp.cursor;
}
function r_R1() {
return I_p1 <= sbp.cursor;
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function r_step_0() {
var among_var, v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_1, 16);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
sbp.slice_from("a");
break;
case 3:
sbp.slice_from("e");
break;
case 4:
sbp.slice_from("i");
break;
case 5:
v_1 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(2, "ab")) {
sbp.cursor = sbp.limit - v_1;
sbp.slice_from("i");
}
break;
case 6:
sbp.slice_from("at");
break;
case 7:
sbp.slice_from("a\u0163i");
break;
}
}
}
}
function r_combo_suffix() {
var among_var, v_1 = sbp.limit - sbp.cursor;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_2, 46);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R1()) {
switch (among_var) {
case 1:
sbp.slice_from("abil");
break;
case 2:
sbp.slice_from("ibil");
break;
case 3:
sbp.slice_from("iv");
break;
case 4:
sbp.slice_from("ic");
break;
case 5:
sbp.slice_from("at");
break;
case 6:
sbp.slice_from("it");
break;
}
B_standard_suffix_removed = true;
sbp.cursor = sbp.limit - v_1;
return true;
}
}
return false;
}
function r_standard_suffix() {
var among_var, v_1;
B_standard_suffix_removed = false;
while (true) {
v_1 = sbp.limit - sbp.cursor;
if (!r_combo_suffix()) {
sbp.cursor = sbp.limit - v_1;
break;
}
}
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_3, 62);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R2()) {
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
if (sbp.eq_s_b(1, "\u0163")) {
sbp.bra = sbp.cursor;
sbp.slice_from("t");
}
break;
case 3:
sbp.slice_from("ist");
break;
}
B_standard_suffix_removed = true;
}
}
}
function r_verb_suffix() {
var among_var, v_1, v_2;
if (sbp.cursor >= I_pV) {
v_1 = sbp.limit_backward;
sbp.limit_backward = I_pV;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_4, 94);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
v_2 = sbp.limit - sbp.cursor;
if (!sbp.out_grouping_b(g_v, 97, 259)) {
sbp.cursor = sbp.limit - v_2;
if (!sbp.eq_s_b(1, "u"))
break;
}
case 2:
sbp.slice_del();
break;
}
}
sbp.limit_backward = v_1;
}
}
function r_vowel_suffix() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_5, 5);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_RV() && among_var == 1)
sbp.slice_del();
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_prelude();
sbp.cursor = v_1;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_step_0();
sbp.cursor = sbp.limit;
r_standard_suffix();
sbp.cursor = sbp.limit;
if (!B_standard_suffix_removed) {
sbp.cursor = sbp.limit;
r_verb_suffix();
sbp.cursor = sbp.limit;
}
r_vowel_suffix();
sbp.cursor = sbp.limit_backward;
r_postlude();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.ro.stemmer, 'stemmer-ro');
lunr.ro.stopWordFilter = lunr.generateStopWordFilter('acea aceasta această aceea acei aceia acel acela acele acelea acest acesta aceste acestea aceşti aceştia acolo acord acum ai aia aibă aici al ale alea altceva altcineva am ar are asemenea asta astea astăzi asupra au avea avem aveţi azi aş aşadar aţi bine bucur bună ca care caut ce cel ceva chiar cinci cine cineva contra cu cum cumva curând curînd când cât câte câtva câţi cînd cît cîte cîtva cîţi că căci cărei căror cărui către da dacă dar datorită dată dau de deci deja deoarece departe deşi din dinaintea dintr- dintre doi doilea două drept după dă ea ei el ele eram este eu eşti face fata fi fie fiecare fii fim fiu fiţi frumos fără graţie halbă iar ieri la le li lor lui lângă lîngă mai mea mei mele mereu meu mi mie mine mult multă mulţi mulţumesc mâine mîine mă ne nevoie nici nicăieri nimeni nimeri nimic nişte noastre noastră noi noroc nostru nouă noştri nu opt ori oricare orice oricine oricum oricând oricât oricînd oricît oriunde patra patru patrulea pe pentru peste pic poate pot prea prima primul prin puţin puţina puţină până pînă rog sa sale sau se spate spre sub sunt suntem sunteţi sută sînt sîntem sînteţi să săi său ta tale te timp tine toate toată tot totuşi toţi trei treia treilea tu tăi tău un una unde undeva unei uneia unele uneori unii unor unora unu unui unuia unul vi voastre voastră voi vostru vouă voştri vreme vreo vreun vă zece zero zi zice îi îl îmi împotriva în înainte înaintea încotro încât încît între întrucât întrucît îţi ăla ălea ăsta ăstea ăştia şapte şase şi ştiu ţi ţie'.split(' '));
lunr.Pipeline.registerFunction(lunr.ro.stopWordFilter, 'stopWordFilter-ro');
};
}))
@@ -0,0 +1,391 @@
/*!
* Lunr languages, `Russian` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.ru = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.ru.trimmer,
lunr.ru.stopWordFilter,
lunr.ru.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.ru.stemmer)
}
};
/* lunr trimmer function */
lunr.ru.wordCharacters = "\u0400-\u0484\u0487-\u052F\u1D2B\u1D78\u2DE0-\u2DFF\uA640-\uA69F\uFE2E\uFE2F";
lunr.ru.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.ru.wordCharacters);
lunr.Pipeline.registerFunction(lunr.ru.trimmer, 'trimmer-ru');
/* lunr stemmer function */
lunr.ru.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function RussianStemmer() {
var a_0 = [new Among("\u0432", -1, 1), new Among("\u0438\u0432", 0, 2),
new Among("\u044B\u0432", 0, 2),
new Among("\u0432\u0448\u0438", -1, 1),
new Among("\u0438\u0432\u0448\u0438", 3, 2),
new Among("\u044B\u0432\u0448\u0438", 3, 2),
new Among("\u0432\u0448\u0438\u0441\u044C", -1, 1),
new Among("\u0438\u0432\u0448\u0438\u0441\u044C", 6, 2),
new Among("\u044B\u0432\u0448\u0438\u0441\u044C", 6, 2)
],
a_1 = [
new Among("\u0435\u0435", -1, 1), new Among("\u0438\u0435", -1, 1),
new Among("\u043E\u0435", -1, 1), new Among("\u044B\u0435", -1, 1),
new Among("\u0438\u043C\u0438", -1, 1),
new Among("\u044B\u043C\u0438", -1, 1),
new Among("\u0435\u0439", -1, 1), new Among("\u0438\u0439", -1, 1),
new Among("\u043E\u0439", -1, 1), new Among("\u044B\u0439", -1, 1),
new Among("\u0435\u043C", -1, 1), new Among("\u0438\u043C", -1, 1),
new Among("\u043E\u043C", -1, 1), new Among("\u044B\u043C", -1, 1),
new Among("\u0435\u0433\u043E", -1, 1),
new Among("\u043E\u0433\u043E", -1, 1),
new Among("\u0435\u043C\u0443", -1, 1),
new Among("\u043E\u043C\u0443", -1, 1),
new Among("\u0438\u0445", -1, 1), new Among("\u044B\u0445", -1, 1),
new Among("\u0435\u044E", -1, 1), new Among("\u043E\u044E", -1, 1),
new Among("\u0443\u044E", -1, 1), new Among("\u044E\u044E", -1, 1),
new Among("\u0430\u044F", -1, 1), new Among("\u044F\u044F", -1, 1)
],
a_2 = [
new Among("\u0435\u043C", -1, 1), new Among("\u043D\u043D", -1, 1),
new Among("\u0432\u0448", -1, 1),
new Among("\u0438\u0432\u0448", 2, 2),
new Among("\u044B\u0432\u0448", 2, 2), new Among("\u0449", -1, 1),
new Among("\u044E\u0449", 5, 1),
new Among("\u0443\u044E\u0449", 6, 2)
],
a_3 = [
new Among("\u0441\u044C", -1, 1), new Among("\u0441\u044F", -1, 1)
],
a_4 = [
new Among("\u043B\u0430", -1, 1),
new Among("\u0438\u043B\u0430", 0, 2),
new Among("\u044B\u043B\u0430", 0, 2),
new Among("\u043D\u0430", -1, 1),
new Among("\u0435\u043D\u0430", 3, 2),
new Among("\u0435\u0442\u0435", -1, 1),
new Among("\u0438\u0442\u0435", -1, 2),
new Among("\u0439\u0442\u0435", -1, 1),
new Among("\u0435\u0439\u0442\u0435", 7, 2),
new Among("\u0443\u0439\u0442\u0435", 7, 2),
new Among("\u043B\u0438", -1, 1),
new Among("\u0438\u043B\u0438", 10, 2),
new Among("\u044B\u043B\u0438", 10, 2), new Among("\u0439", -1, 1),
new Among("\u0435\u0439", 13, 2), new Among("\u0443\u0439", 13, 2),
new Among("\u043B", -1, 1), new Among("\u0438\u043B", 16, 2),
new Among("\u044B\u043B", 16, 2), new Among("\u0435\u043C", -1, 1),
new Among("\u0438\u043C", -1, 2), new Among("\u044B\u043C", -1, 2),
new Among("\u043D", -1, 1), new Among("\u0435\u043D", 22, 2),
new Among("\u043B\u043E", -1, 1),
new Among("\u0438\u043B\u043E", 24, 2),
new Among("\u044B\u043B\u043E", 24, 2),
new Among("\u043D\u043E", -1, 1),
new Among("\u0435\u043D\u043E", 27, 2),
new Among("\u043D\u043D\u043E", 27, 1),
new Among("\u0435\u0442", -1, 1),
new Among("\u0443\u0435\u0442", 30, 2),
new Among("\u0438\u0442", -1, 2), new Among("\u044B\u0442", -1, 2),
new Among("\u044E\u0442", -1, 1),
new Among("\u0443\u044E\u0442", 34, 2),
new Among("\u044F\u0442", -1, 2), new Among("\u043D\u044B", -1, 1),
new Among("\u0435\u043D\u044B", 37, 2),
new Among("\u0442\u044C", -1, 1),
new Among("\u0438\u0442\u044C", 39, 2),
new Among("\u044B\u0442\u044C", 39, 2),
new Among("\u0435\u0448\u044C", -1, 1),
new Among("\u0438\u0448\u044C", -1, 2), new Among("\u044E", -1, 2),
new Among("\u0443\u044E", 44, 2)
],
a_5 = [
new Among("\u0430", -1, 1), new Among("\u0435\u0432", -1, 1),
new Among("\u043E\u0432", -1, 1), new Among("\u0435", -1, 1),
new Among("\u0438\u0435", 3, 1), new Among("\u044C\u0435", 3, 1),
new Among("\u0438", -1, 1), new Among("\u0435\u0438", 6, 1),
new Among("\u0438\u0438", 6, 1),
new Among("\u0430\u043C\u0438", 6, 1),
new Among("\u044F\u043C\u0438", 6, 1),
new Among("\u0438\u044F\u043C\u0438", 10, 1),
new Among("\u0439", -1, 1), new Among("\u0435\u0439", 12, 1),
new Among("\u0438\u0435\u0439", 13, 1),
new Among("\u0438\u0439", 12, 1), new Among("\u043E\u0439", 12, 1),
new Among("\u0430\u043C", -1, 1), new Among("\u0435\u043C", -1, 1),
new Among("\u0438\u0435\u043C", 18, 1),
new Among("\u043E\u043C", -1, 1), new Among("\u044F\u043C", -1, 1),
new Among("\u0438\u044F\u043C", 21, 1), new Among("\u043E", -1, 1),
new Among("\u0443", -1, 1), new Among("\u0430\u0445", -1, 1),
new Among("\u044F\u0445", -1, 1),
new Among("\u0438\u044F\u0445", 26, 1), new Among("\u044B", -1, 1),
new Among("\u044C", -1, 1), new Among("\u044E", -1, 1),
new Among("\u0438\u044E", 30, 1), new Among("\u044C\u044E", 30, 1),
new Among("\u044F", -1, 1), new Among("\u0438\u044F", 33, 1),
new Among("\u044C\u044F", 33, 1)
],
a_6 = [
new Among("\u043E\u0441\u0442", -1, 1),
new Among("\u043E\u0441\u0442\u044C", -1, 1)
],
a_7 = [
new Among("\u0435\u0439\u0448\u0435", -1, 1),
new Among("\u043D", -1, 2), new Among("\u0435\u0439\u0448", -1, 1),
new Among("\u044C", -1, 3)
],
g_v = [33, 65, 8, 232],
I_p2, I_pV, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function habr3() {
while (!sbp.in_grouping(g_v, 1072, 1103)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
return true;
}
function habr4() {
while (!sbp.out_grouping(g_v, 1072, 1103)) {
if (sbp.cursor >= sbp.limit)
return false;
sbp.cursor++;
}
return true;
}
function r_mark_regions() {
I_pV = sbp.limit;
I_p2 = I_pV;
if (habr3()) {
I_pV = sbp.cursor;
if (habr4())
if (habr3())
if (habr4())
I_p2 = sbp.cursor;
}
}
function r_R2() {
return I_p2 <= sbp.cursor;
}
function habr2(a, n) {
var among_var, v_1;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a, n);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
v_1 = sbp.limit - sbp.cursor;
if (!sbp.eq_s_b(1, "\u0430")) {
sbp.cursor = sbp.limit - v_1;
if (!sbp.eq_s_b(1, "\u044F"))
return false;
}
case 2:
sbp.slice_del();
break;
}
return true;
}
return false;
}
function r_perfective_gerund() {
return habr2(a_0, 9);
}
function habr1(a, n) {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a, n);
if (among_var) {
sbp.bra = sbp.cursor;
if (among_var == 1)
sbp.slice_del();
return true;
}
return false;
}
function r_adjective() {
return habr1(a_1, 26);
}
function r_adjectival() {
var among_var;
if (r_adjective()) {
habr2(a_2, 8);
return true;
}
return false;
}
function r_reflexive() {
return habr1(a_3, 2);
}
function r_verb() {
return habr2(a_4, 46);
}
function r_noun() {
habr1(a_5, 36);
}
function r_derivational() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_6, 2);
if (among_var) {
sbp.bra = sbp.cursor;
if (r_R2() && among_var == 1)
sbp.slice_del();
}
}
function r_tidy_up() {
var among_var;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_7, 4);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_del();
sbp.ket = sbp.cursor;
if (!sbp.eq_s_b(1, "\u043D"))
break;
sbp.bra = sbp.cursor;
case 2:
if (!sbp.eq_s_b(1, "\u043D"))
break;
case 3:
sbp.slice_del();
break;
}
}
}
this.stem = function() {
r_mark_regions();
sbp.cursor = sbp.limit;
if (sbp.cursor < I_pV)
return false;
sbp.limit_backward = I_pV;
if (!r_perfective_gerund()) {
sbp.cursor = sbp.limit;
if (!r_reflexive())
sbp.cursor = sbp.limit;
if (!r_adjectival()) {
sbp.cursor = sbp.limit;
if (!r_verb()) {
sbp.cursor = sbp.limit;
r_noun();
}
}
}
sbp.cursor = sbp.limit;
sbp.ket = sbp.cursor;
if (sbp.eq_s_b(1, "\u0438")) {
sbp.bra = sbp.cursor;
sbp.slice_del();
} else
sbp.cursor = sbp.limit;
r_derivational();
sbp.cursor = sbp.limit;
r_tidy_up();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.ru.stemmer, 'stemmer-ru');
lunr.ru.stopWordFilter = lunr.generateStopWordFilter('алло без близко более больше будем будет будете будешь будто буду будут будь бы бывает бывь был была были было быть в важная важное важные важный вам вами вас ваш ваша ваше ваши вверх вдали вдруг ведь везде весь вниз внизу во вокруг вон восемнадцатый восемнадцать восемь восьмой вот впрочем времени время все всегда всего всем всеми всему всех всею всю всюду вся всё второй вы г где говорил говорит год года году да давно даже далеко дальше даром два двадцатый двадцать две двенадцатый двенадцать двух девятнадцатый девятнадцать девятый девять действительно дел день десятый десять для до довольно долго должно другая другие других друго другое другой е его ее ей ему если есть еще ещё ею её ж же жизнь за занят занята занято заняты затем зато зачем здесь значит и из или им именно иметь ими имя иногда их к каждая каждое каждые каждый кажется как какая какой кем когда кого ком кому конечно которая которого которой которые который которых кроме кругом кто куда лет ли лишь лучше люди м мало между меля менее меньше меня миллионов мимо мира мне много многочисленная многочисленное многочисленные многочисленный мной мною мог могут мож может можно можхо мои мой мор мочь моя моё мы на наверху над надо назад наиболее наконец нам нами нас начала наш наша наше наши не него недавно недалеко нее ней нельзя нем немного нему непрерывно нередко несколько нет нею неё ни нибудь ниже низко никогда никуда ними них ничего но ну нужно нх о об оба обычно один одиннадцатый одиннадцать однажды однако одного одной около он она они оно опять особенно от отовсюду отсюда очень первый перед по под пожалуйста позже пока пор пора после посреди потом потому почему почти прекрасно при про просто против процентов пятнадцатый пятнадцать пятый пять раз разве рано раньше рядом с сам сама сами самим самими самих само самого самой самом самому саму свое своего своей свои своих свою сеаой себе себя сегодня седьмой сейчас семнадцатый семнадцать семь сих сказал сказала сказать сколько слишком сначала снова со собой собою совсем спасибо стал суть т та так такая также такие такое такой там твой твоя твоё те тебе тебя тем теми теперь тех то тобой тобою тогда того тоже только том тому тот тою третий три тринадцатый тринадцать ту туда тут ты тысяч у уж уже уметь хорошо хотеть хоть хотя хочешь часто чаще чего человек чем чему через четвертый четыре четырнадцатый четырнадцать что чтоб чтобы чуть шестнадцатый шестнадцать шестой шесть эта эти этим этими этих это этого этой этом этому этот эту я а'.split(' '));
lunr.Pipeline.registerFunction(lunr.ru.stopWordFilter, 'stopWordFilter-ru');
};
}))
@@ -0,0 +1,110 @@
/*!
* Lunr languages, `Sanskrit` language
* https://github.com/MiKr13/lunr-languages
*
* Copyright 2023, India
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.sa = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.sa.trimmer,
lunr.sa.stopWordFilter,
lunr.sa.stemmer
);
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.sa.stemmer)
}
};
/* lunr trimmer function */
lunr.sa.wordCharacters = "\u0900-\u0903\u0904-\u090f\u0910-\u091f\u0920-\u092f\u0930-\u093f\u0940-\u094f\u0950-\u095f\u0960-\u096f\u0970-\u097f\uA8E0-\uA8F1\uA8F2-\uA8F7\uA8F8-\uA8FB\uA8FC-\uA8FD\uA8FE-\uA8FF\u11B00-\u11B09";
lunr.sa.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.sa.wordCharacters);
lunr.Pipeline.registerFunction(lunr.sa.trimmer, 'trimmer-sa');
/* lunr stop word filter */
lunr.sa.stopWordFilter = lunr.generateStopWordFilter(
'तथा अयम्‌ एकम्‌ इत्यस्मिन्‌ तथा तत्‌ वा अयम्‌ इत्यस्य ते आहूत उपरि तेषाम्‌ किन्तु तेषाम्‌ तदा इत्यनेन अधिकः इत्यस्य तत्‌ केचन बहवः द्वि तथा महत्वपूर्णः अयम्‌ अस्य विषये अयं अस्ति तत्‌ प्रथमः विषये इत्युपरि इत्युपरि इतर अधिकतमः अधिकः अपि सामान्यतया ठ इतरेतर नूतनम्‌ द न्यूनम्‌ कश्चित्‌ वा विशालः द सः अस्ति तदनुसारम् तत्र अस्ति केवलम्‌ अपि अत्र सर्वे विविधाः तत्‌ बहवः यतः इदानीम्‌ द दक्षिण इत्यस्मै तस्य उपरि नथ अतीव कार्यम्‌ सर्वे एकैकम्‌ इत्यादि। एते सन्ति उत इत्थम्‌ मध्ये एतदर्थं . स कस्य प्रथमः श्री. करोति अस्मिन् प्रकारः निर्मिता कालः तत्र कर्तुं समान अधुना ते सन्ति स एकः अस्ति सः अर्थात् तेषां कृते . स्थितम् विशेषः अग्रिम तेषाम्‌ समान स्रोतः ख म समान इदानीमपि अधिकतया करोतु ते समान इत्यस्य वीथी सह यस्मिन् कृतवान्‌ धृतः तदा पुनः पूर्वं सः आगतः किम्‌ कुल इतर पुरा मात्रा स विषये उ अतएव अपि नगरस्य उपरि यतः प्रतिशतं कतरः कालः साधनानि भूत तथापि जात सम्बन्धि अन्यत्‌ ग अतः अस्माकं स्वकीयाः अस्माकं इदानीं अन्तः इत्यादयः भवन्तः इत्यादयः एते एताः तस्य अस्य इदम् एते तेषां तेषां तेषां तान् तेषां तेषां तेषां समानः सः एकः च तादृशाः बहवः अन्ये च वदन्ति यत् कियत् कस्मै कस्मै यस्मै यस्मै यस्मै यस्मै न अतिनीचः किन्तु प्रथमं सम्पूर्णतया ततः चिरकालानन्तरं पुस्तकं सम्पूर्णतया अन्तः किन्तु अत्र वा इह इव श्रद्धाय अवशिष्यते परन्तु अन्ये वर्गाः सन्ति ते सन्ति शक्नुवन्ति सर्वे मिलित्वा सर्वे एकत्र"'.split(' '));
/* lunr stemmer function */
lunr.sa.stemmer = (function() {
return function(word) {
// for lunr version 2
if (typeof word.update === "function") {
return word.update(function(word) {
return word;
})
} else { // for lunr version <= 1
return word;
}
}
})();
var segmenter = lunr.wordcut;
segmenter.init();
lunr.sa.tokenizer = function(obj) {
if (!arguments.length || obj == null || obj == undefined) return []
if (Array.isArray(obj)) return obj.map(function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase()
});
var str = obj.toString().toLowerCase().replace(/^\s+/, '');
return segmenter.cut(str).split('|');
}
lunr.Pipeline.registerFunction(lunr.sa.stemmer, 'stemmer-sa');
lunr.Pipeline.registerFunction(lunr.sa.stopWordFilter, 'stopWordFilter-sa');
};
}))
@@ -0,0 +1,304 @@
/*!
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function () {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* provides utilities for the included stemmers */
lunr.stemmerSupport = {
Among: function(s, substring_i, result, method) {
this.toCharArray = function(s) {
var sLength = s.length, charArr = new Array(sLength);
for (var i = 0; i < sLength; i++)
charArr[i] = s.charCodeAt(i);
return charArr;
};
if ((!s && s != "") || (!substring_i && (substring_i != 0)) || !result)
throw ("Bad Among initialisation: s:" + s + ", substring_i: "
+ substring_i + ", result: " + result);
this.s_size = s.length;
this.s = this.toCharArray(s);
this.substring_i = substring_i;
this.result = result;
this.method = method;
},
SnowballProgram: function() {
var current;
return {
bra : 0,
ket : 0,
limit : 0,
cursor : 0,
limit_backward : 0,
setCurrent : function(word) {
current = word;
this.cursor = 0;
this.limit = word.length;
this.limit_backward = 0;
this.bra = this.cursor;
this.ket = this.limit;
},
getCurrent : function() {
var result = current;
current = null;
return result;
},
in_grouping : function(s, min, max) {
if (this.cursor < this.limit) {
var ch = current.charCodeAt(this.cursor);
if (ch <= max && ch >= min) {
ch -= min;
if (s[ch >> 3] & (0X1 << (ch & 0X7))) {
this.cursor++;
return true;
}
}
}
return false;
},
in_grouping_b : function(s, min, max) {
if (this.cursor > this.limit_backward) {
var ch = current.charCodeAt(this.cursor - 1);
if (ch <= max && ch >= min) {
ch -= min;
if (s[ch >> 3] & (0X1 << (ch & 0X7))) {
this.cursor--;
return true;
}
}
}
return false;
},
out_grouping : function(s, min, max) {
if (this.cursor < this.limit) {
var ch = current.charCodeAt(this.cursor);
if (ch > max || ch < min) {
this.cursor++;
return true;
}
ch -= min;
if (!(s[ch >> 3] & (0X1 << (ch & 0X7)))) {
this.cursor++;
return true;
}
}
return false;
},
out_grouping_b : function(s, min, max) {
if (this.cursor > this.limit_backward) {
var ch = current.charCodeAt(this.cursor - 1);
if (ch > max || ch < min) {
this.cursor--;
return true;
}
ch -= min;
if (!(s[ch >> 3] & (0X1 << (ch & 0X7)))) {
this.cursor--;
return true;
}
}
return false;
},
eq_s : function(s_size, s) {
if (this.limit - this.cursor < s_size)
return false;
for (var i = 0; i < s_size; i++)
if (current.charCodeAt(this.cursor + i) != s.charCodeAt(i))
return false;
this.cursor += s_size;
return true;
},
eq_s_b : function(s_size, s) {
if (this.cursor - this.limit_backward < s_size)
return false;
for (var i = 0; i < s_size; i++)
if (current.charCodeAt(this.cursor - s_size + i) != s
.charCodeAt(i))
return false;
this.cursor -= s_size;
return true;
},
find_among : function(v, v_size) {
var i = 0, j = v_size, c = this.cursor, l = this.limit, common_i = 0, common_j = 0, first_key_inspected = false;
while (true) {
var k = i + ((j - i) >> 1), diff = 0, common = common_i < common_j
? common_i
: common_j, w = v[k];
for (var i2 = common; i2 < w.s_size; i2++) {
if (c + common == l) {
diff = -1;
break;
}
diff = current.charCodeAt(c + common) - w.s[i2];
if (diff)
break;
common++;
}
if (diff < 0) {
j = k;
common_j = common;
} else {
i = k;
common_i = common;
}
if (j - i <= 1) {
if (i > 0 || j == i || first_key_inspected)
break;
first_key_inspected = true;
}
}
while (true) {
var w = v[i];
if (common_i >= w.s_size) {
this.cursor = c + w.s_size;
if (!w.method)
return w.result;
var res = w.method();
this.cursor = c + w.s_size;
if (res)
return w.result;
}
i = w.substring_i;
if (i < 0)
return 0;
}
},
find_among_b : function(v, v_size) {
var i = 0, j = v_size, c = this.cursor, lb = this.limit_backward, common_i = 0, common_j = 0, first_key_inspected = false;
while (true) {
var k = i + ((j - i) >> 1), diff = 0, common = common_i < common_j
? common_i
: common_j, w = v[k];
for (var i2 = w.s_size - 1 - common; i2 >= 0; i2--) {
if (c - common == lb) {
diff = -1;
break;
}
diff = current.charCodeAt(c - 1 - common) - w.s[i2];
if (diff)
break;
common++;
}
if (diff < 0) {
j = k;
common_j = common;
} else {
i = k;
common_i = common;
}
if (j - i <= 1) {
if (i > 0 || j == i || first_key_inspected)
break;
first_key_inspected = true;
}
}
while (true) {
var w = v[i];
if (common_i >= w.s_size) {
this.cursor = c - w.s_size;
if (!w.method)
return w.result;
var res = w.method();
this.cursor = c - w.s_size;
if (res)
return w.result;
}
i = w.substring_i;
if (i < 0)
return 0;
}
},
replace_s : function(c_bra, c_ket, s) {
var adjustment = s.length - (c_ket - c_bra), left = current
.substring(0, c_bra), right = current.substring(c_ket);
current = left + s + right;
this.limit += adjustment;
if (this.cursor >= c_ket)
this.cursor += adjustment;
else if (this.cursor > c_bra)
this.cursor = c_bra;
return adjustment;
},
slice_check : function() {
if (this.bra < 0 || this.bra > this.ket || this.ket > this.limit
|| this.limit > current.length)
throw ("faulty slice operation");
},
slice_from : function(s) {
this.slice_check();
this.replace_s(this.bra, this.ket, s);
},
slice_del : function() {
this.slice_from("");
},
insert : function(c_bra, c_ket, s) {
var adjustment = this.replace_s(c_bra, c_ket, s);
if (c_bra <= this.bra)
this.bra += adjustment;
if (c_bra <= this.ket)
this.ket += adjustment;
},
slice_to : function() {
this.slice_check();
return current.substring(this.bra, this.ket);
},
eq_v_b : function(s) {
return this.eq_s_b(s.length, s);
}
};
}
};
lunr.trimmerSupport = {
generateTrimmer: function(wordCharacters) {
var startRegex = new RegExp("^[^" + wordCharacters + "]+")
var endRegex = new RegExp("[^" + wordCharacters + "]+$")
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function (s) {
return s
.replace(startRegex, '')
.replace(endRegex, '');
})
} else { // for lunr version 1
return token
.replace(startRegex, '')
.replace(endRegex, '');
}
};
}
}
}
}));
@@ -0,0 +1,256 @@
/*!
* Lunr languages, `Swedish` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2014, Mihai Valentin
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.sv = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.sv.trimmer,
lunr.sv.stopWordFilter,
lunr.sv.stemmer
);
// for lunr version 2
// this is necessary so that every searched word is also stemmed before
// in lunr <= 1 this is not needed, as it is done using the normal pipeline
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.sv.stemmer)
}
};
/* lunr trimmer function */
lunr.sv.wordCharacters = "A-Za-z\xAA\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02B8\u02E0-\u02E4\u1D00-\u1D25\u1D2C-\u1D5C\u1D62-\u1D65\u1D6B-\u1D77\u1D79-\u1DBE\u1E00-\u1EFF\u2071\u207F\u2090-\u209C\u212A\u212B\u2132\u214E\u2160-\u2188\u2C60-\u2C7F\uA722-\uA787\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA7FF\uAB30-\uAB5A\uAB5C-\uAB64\uFB00-\uFB06\uFF21-\uFF3A\uFF41-\uFF5A";
lunr.sv.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.sv.wordCharacters);
lunr.Pipeline.registerFunction(lunr.sv.trimmer, 'trimmer-sv');
/* lunr stemmer function */
lunr.sv.stemmer = (function() {
/* create the wrapped stemmer object */
var Among = lunr.stemmerSupport.Among,
SnowballProgram = lunr.stemmerSupport.SnowballProgram,
st = new function SwedishStemmer() {
var a_0 = [new Among("a", -1, 1), new Among("arna", 0, 1),
new Among("erna", 0, 1), new Among("heterna", 2, 1),
new Among("orna", 0, 1), new Among("ad", -1, 1),
new Among("e", -1, 1), new Among("ade", 6, 1),
new Among("ande", 6, 1), new Among("arne", 6, 1),
new Among("are", 6, 1), new Among("aste", 6, 1),
new Among("en", -1, 1), new Among("anden", 12, 1),
new Among("aren", 12, 1), new Among("heten", 12, 1),
new Among("ern", -1, 1), new Among("ar", -1, 1),
new Among("er", -1, 1), new Among("heter", 18, 1),
new Among("or", -1, 1), new Among("s", -1, 2),
new Among("as", 21, 1), new Among("arnas", 22, 1),
new Among("ernas", 22, 1), new Among("ornas", 22, 1),
new Among("es", 21, 1), new Among("ades", 26, 1),
new Among("andes", 26, 1), new Among("ens", 21, 1),
new Among("arens", 29, 1), new Among("hetens", 29, 1),
new Among("erns", 21, 1), new Among("at", -1, 1),
new Among("andet", -1, 1), new Among("het", -1, 1),
new Among("ast", -1, 1)
],
a_1 = [new Among("dd", -1, -1),
new Among("gd", -1, -1), new Among("nn", -1, -1),
new Among("dt", -1, -1), new Among("gt", -1, -1),
new Among("kt", -1, -1), new Among("tt", -1, -1)
],
a_2 = [
new Among("ig", -1, 1), new Among("lig", 0, 1),
new Among("els", -1, 1), new Among("fullt", -1, 3),
new Among("l\u00F6st", -1, 2)
],
g_v = [17, 65, 16, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 24, 0, 32
],
g_s_ending = [119, 127, 149],
I_x, I_p1, sbp = new SnowballProgram();
this.setCurrent = function(word) {
sbp.setCurrent(word);
};
this.getCurrent = function() {
return sbp.getCurrent();
};
function r_mark_regions() {
var v_1, c = sbp.cursor + 3;
I_p1 = sbp.limit;
if (0 <= c || c <= sbp.limit) {
I_x = c;
while (true) {
v_1 = sbp.cursor;
if (sbp.in_grouping(g_v, 97, 246)) {
sbp.cursor = v_1;
break;
}
sbp.cursor = v_1;
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
while (!sbp.out_grouping(g_v, 97, 246)) {
if (sbp.cursor >= sbp.limit)
return;
sbp.cursor++;
}
I_p1 = sbp.cursor;
if (I_p1 < I_x)
I_p1 = I_x;
}
}
function r_main_suffix() {
var among_var, v_2 = sbp.limit_backward;
if (sbp.cursor >= I_p1) {
sbp.limit_backward = I_p1;
sbp.cursor = sbp.limit;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_0, 37);
sbp.limit_backward = v_2;
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
if (sbp.in_grouping_b(g_s_ending, 98, 121))
sbp.slice_del();
break;
}
}
}
}
function r_consonant_pair() {
var v_1 = sbp.limit_backward;
if (sbp.cursor >= I_p1) {
sbp.limit_backward = I_p1;
sbp.cursor = sbp.limit;
if (sbp.find_among_b(a_1, 7)) {
sbp.cursor = sbp.limit;
sbp.ket = sbp.cursor;
if (sbp.cursor > sbp.limit_backward) {
sbp.bra = --sbp.cursor;
sbp.slice_del();
}
}
sbp.limit_backward = v_1;
}
}
function r_other_suffix() {
var among_var, v_2;
if (sbp.cursor >= I_p1) {
v_2 = sbp.limit_backward;
sbp.limit_backward = I_p1;
sbp.cursor = sbp.limit;
sbp.ket = sbp.cursor;
among_var = sbp.find_among_b(a_2, 5);
if (among_var) {
sbp.bra = sbp.cursor;
switch (among_var) {
case 1:
sbp.slice_del();
break;
case 2:
sbp.slice_from("l\u00F6s");
break;
case 3:
sbp.slice_from("full");
break;
}
}
sbp.limit_backward = v_2;
}
}
this.stem = function() {
var v_1 = sbp.cursor;
r_mark_regions();
sbp.limit_backward = v_1;
sbp.cursor = sbp.limit;
r_main_suffix();
sbp.cursor = sbp.limit;
r_consonant_pair();
sbp.cursor = sbp.limit;
r_other_suffix();
return true;
}
};
/* and return a function that stems a word for the current locale */
return function(token) {
// for lunr version 2
if (typeof token.update === "function") {
return token.update(function(word) {
st.setCurrent(word);
st.stem();
return st.getCurrent();
})
} else { // for lunr version <= 1
st.setCurrent(token);
st.stem();
return st.getCurrent();
}
}
})();
lunr.Pipeline.registerFunction(lunr.sv.stemmer, 'stemmer-sv');
lunr.sv.stopWordFilter = lunr.generateStopWordFilter('alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över'.split(' '));
lunr.Pipeline.registerFunction(lunr.sv.stopWordFilter, 'stopWordFilter-sv');
};
}))
@@ -0,0 +1,123 @@
/*!
* Lunr languages, `Tamil` language
* https://github.com/tvmani/lunr-languages
*
* Copyright 2021, Manikandan Venkatasubban
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.ta = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.ta.trimmer,
lunr.ta.stopWordFilter,
lunr.ta.stemmer
);
// change the tokenizer for japanese one
// if (isLunr2) { // for lunr version 2.0.0
// this.tokenizer = lunr.ta.tokenizer;
// } else {
// if (lunr.tokenizer) { // for lunr version 0.6.0
// lunr.tokenizer = lunr.ta.tokenizer;
// }
// if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
// this.tokenizerFn = lunr.ta.tokenizer;
// }
// }
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.ta.stemmer)
}
};
/* lunr trimmer function */
lunr.ta.wordCharacters = "\u0b80-\u0b89\u0b8a-\u0b8f\u0b90-\u0b99\u0b9a-\u0b9f\u0ba0-\u0ba9\u0baa-\u0baf\u0bb0-\u0bb9\u0bba-\u0bbf\u0bc0-\u0bc9\u0bca-\u0bcf\u0bd0-\u0bd9\u0bda-\u0bdf\u0be0-\u0be9\u0bea-\u0bef\u0bf0-\u0bf9\u0bfa-\u0bffa-zA-Za-zA-Z0-90-9";
lunr.ta.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.ta.wordCharacters);
lunr.Pipeline.registerFunction(lunr.ta.trimmer, 'trimmer-ta');
/* lunr stop word filter */
lunr.ta.stopWordFilter = lunr.generateStopWordFilter(
'அங்கு அங்கே அது அதை அந்த அவர் அவர்கள் அவள் அவன் அவை ஆக ஆகவே ஆகையால் ஆதலால் ஆதலினால் ஆனாலும் ஆனால் இங்கு இங்கே இது இதை இந்த இப்படி இவர் இவர்கள் இவள் இவன் இவை இவ்வளவு உனக்கு உனது உன் உன்னால் எங்கு எங்கே எது எதை எந்த எப்படி எவர் எவர்கள் எவள் எவன் எவை எவ்வளவு எனக்கு எனது எனவே என் என்ன என்னால் ஏது ஏன் தனது தன்னால் தானே தான் நாங்கள் நாம் நான் நீ நீங்கள்'.split(' '));
/* lunr stemmer function */
lunr.ta.stemmer = (function() {
return function(word) {
// for lunr version 2
if (typeof word.update === "function") {
return word.update(function(word) {
return word;
})
} else { // for lunr version <= 1
return word;
}
}
})();
var segmenter = lunr.wordcut;
segmenter.init();
lunr.ta.tokenizer = function(obj) {
if (!arguments.length || obj == null || obj == undefined) return []
if (Array.isArray(obj)) return obj.map(function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase()
});
var str = obj.toString().toLowerCase().replace(/^\s+/, '');
return segmenter.cut(str).split('|');
}
lunr.Pipeline.registerFunction(lunr.ta.stemmer, 'stemmer-ta');
lunr.Pipeline.registerFunction(lunr.ta.stopWordFilter, 'stopWordFilter-ta');
};
}))
@@ -0,0 +1,122 @@
/*!
* Lunr languages, `Hindi` language
* https://github.com/MiKr13/lunr-languages
*
* Copyright 2023, India
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.te = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.te.trimmer,
lunr.te.stopWordFilter,
lunr.te.stemmer
);
// change the tokenizer for japanese one
// if (isLunr2) { // for lunr version 2.0.0
// this.tokenizer = lunr.hi.tokenizer;
// } else {
// if (lunr.tokenizer) { // for lunr version 0.6.0
// lunr.tokenizer = lunr.hi.tokenizer;
// }
// if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
// this.tokenizerFn = lunr.hi.tokenizer;
// }
// }
if (this.searchPipeline) {
this.searchPipeline.reset();
this.searchPipeline.add(lunr.te.stemmer)
}
};
/* lunr trimmer function */
lunr.te.wordCharacters = "\u0C00-\u0C04\u0C05-\u0C14\u0C15-\u0C39\u0C3E-\u0C4C\u0C55-\u0C56\u0C58-\u0C5A\u0C60-\u0C61\u0C62-\u0C63\u0C66-\u0C6F\u0C78-\u0C7F\u0C3C\u0C3D\u0C4D\u0C5D\u0C77\u0C64\u0C65";
lunr.te.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.te.wordCharacters);
lunr.Pipeline.registerFunction(lunr.te.trimmer, 'trimmer-te');
/* lunr stop word filter */
lunr.te.stopWordFilter = lunr.generateStopWordFilter(
'అందరూ అందుబాటులో అడగండి అడగడం అడ్డంగా అనుగుణంగా అనుమతించు అనుమతిస్తుంది అయితే ఇప్పటికే ఉన్నారు ఎక్కడైనా ఎప్పుడు ఎవరైనా ఎవరో ఏ ఏదైనా ఏమైనప్పటికి ఒక ఒకరు కనిపిస్తాయి కాదు కూడా గా గురించి చుట్టూ చేయగలిగింది తగిన తర్వాత దాదాపు దూరంగా నిజంగా పై ప్రకారం ప్రక్కన మధ్య మరియు మరొక మళ్ళీ మాత్రమే మెచ్చుకో వద్ద వెంట వేరుగా వ్యతిరేకంగా సంబంధం'.split(' '));
/* lunr stemmer function */
lunr.te.stemmer = (function() {
return function(word) {
// for lunr version 2
if (typeof word.update === "function") {
return word.update(function(word) {
return word;
})
} else { // for lunr version <= 1
return word;
}
}
})();
var segmenter = lunr.wordcut;
segmenter.init();
lunr.te.tokenizer = function(obj) {
if (!arguments.length || obj == null || obj == undefined) return []
if (Array.isArray(obj)) return obj.map(function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase()
});
var str = obj.toString().toLowerCase().replace(/^\s+/, '');
return segmenter.cut(str).split('|');
}
lunr.Pipeline.registerFunction(lunr.te.stemmer, 'stemmer-te');
lunr.Pipeline.registerFunction(lunr.te.stopWordFilter, 'stopWordFilter-te');
};
}))
@@ -0,0 +1,99 @@
/*!
* Lunr languages, `Thai` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2017, Keerati Thiwanruk
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/*
Thai tokenization is the same to Japanense, which does not take into account spaces.
So, it uses the same logic to assign tokenization function due to different Lunr versions.
*/
var isLunr2 = lunr.version[0] == "2";
/* register specific locale function */
lunr.th = function() {
this.pipeline.reset();
this.pipeline.add(
/*lunr.th.stopWordFilter,*/
lunr.th.trimmer
);
if (isLunr2) { // for lunr version 2.0.0
this.tokenizer = lunr.th.tokenizer;
} else {
if (lunr.tokenizer) { // for lunr version 0.6.0
lunr.tokenizer = lunr.th.tokenizer;
}
if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
this.tokenizerFn = lunr.th.tokenizer;
}
}
};
/* lunr trimmer function */
lunr.th.wordCharacters = "[\u0e00-\u0e7f]";
lunr.th.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.th.wordCharacters);
lunr.Pipeline.registerFunction(lunr.th.trimmer, 'trimmer-th');
var segmenter = lunr.wordcut;
segmenter.init();
lunr.th.tokenizer = function(obj) {
//console.log(obj);
if (!arguments.length || obj == null || obj == undefined) return []
if (Array.isArray(obj)) return obj.map(function(t) {
return isLunr2 ? new lunr.Token(t) : t
})
var str = obj.toString().replace(/^\s+/, '');
return segmenter.cut(str).split('|');
}
};
}))
@@ -0,0 +1,84 @@
/*!
* Lunr languages, `Vietnamese` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2017, Keerati Thiwanruk
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball JavaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function() {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/* register specific locale function */
lunr.vi = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.vi.stopWordFilter,
lunr.vi.trimmer
);
};
/* lunr trimmer function */
lunr.vi.wordCharacters = "[" +
"A-Za-z" +
"\u0300\u0350" + // dấu huyền
"\u0301\u0351" + // dấu sắc
"\u0309" + // dấu hỏi
"\u0323" + // dấu nặng
"\u0303\u0343" + // dấu ngã
"\u00C2\u00E2" + // Â
"\u00CA\u00EA" + // Ê
"\u00D4\u00F4" + // Ô
"\u0102-\u0103" + // Ă
"\u0110-\u0111" + // Đ
"\u01A0-\u01A1" + // Ơ
"\u01AF-\u01B0" + // Ư
"]";
lunr.vi.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.vi.wordCharacters);
lunr.Pipeline.registerFunction(lunr.vi.trimmer, 'trimmer-vi');
lunr.vi.stopWordFilter = lunr.generateStopWordFilter('là cái nhưng mà'.split(' '));
};
}))
@@ -0,0 +1,145 @@
/*!
* Lunr languages, `Chinese` language
* https://github.com/MihaiValentin/lunr-languages
*
* Copyright 2019, Felix Lian (repairearth)
* http://www.mozilla.org/MPL/
*/
/*!
* based on
* Snowball zhvaScript Library v0.3
* http://code.google.com/p/urim/
* http://snowball.tartarus.org/
*
* Copyright 2010, Oleg Mazko
* http://www.mozilla.org/MPL/
*/
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;
(function(root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory(require('@node-rs/jieba'))
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function(nodejieba) {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr, nodejiebaDictJson) {
/* throw error if lunr is not yet included */
if ('undefined' === typeof lunr) {
throw new Error('Lunr is not present. Please include / require Lunr before this script.');
}
/* throw error if lunr stemmer support is not yet included */
if ('undefined' === typeof lunr.stemmerSupport) {
throw new Error('Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.');
}
/*
Chinese tokenization is trickier, since it does not
take into account spaces.
Since the tokenization function is represented different
internally for each of the Lunr versions, this had to be done
in order to try to try to pick the best way of doing this based
on the Lunr version
*/
var isLunr2 = lunr.version[0] == "2";
/* register specific locale function */
lunr.zh = function() {
this.pipeline.reset();
this.pipeline.add(
lunr.zh.trimmer,
lunr.zh.stopWordFilter,
lunr.zh.stemmer
);
// change the tokenizer for Chinese one
if (isLunr2) { // for lunr version 2.0.0
this.tokenizer = lunr.zh.tokenizer;
} else {
if (lunr.tokenizer) { // for lunr version 0.6.0
lunr.tokenizer = lunr.zh.tokenizer;
}
if (this.tokenizerFn) { // for lunr version 0.7.0 -> 1.0.0
this.tokenizerFn = lunr.zh.tokenizer;
}
}
};
lunr.zh.tokenizer = function(obj) {
if (!arguments.length || obj == null || obj == undefined) return []
if (Array.isArray(obj)) return obj.map(function(t) {
return isLunr2 ? new lunr.Token(t.toLowerCase()) : t.toLowerCase()
})
nodejiebaDictJson && nodejieba.load(nodejiebaDictJson)
var str = obj.toString().trim().toLowerCase();
var tokens = [];
nodejieba.cut(str, true).forEach(function(seg) {
tokens = tokens.concat(seg.split(' '))
})
tokens = tokens.filter(function(token) {
return !!token;
});
var fromIndex = 0
return tokens.map(function(token, index) {
if (isLunr2) {
var start = str.indexOf(token, fromIndex)
var tokenMetadata = {}
tokenMetadata["position"] = [start, token.length]
tokenMetadata["index"] = index
fromIndex = start
return new lunr.Token(token, tokenMetadata);
} else {
return token
}
});
}
/* lunr trimmer function */
lunr.zh.wordCharacters = "\\w\u4e00-\u9fa5";
lunr.zh.trimmer = lunr.trimmerSupport.generateTrimmer(lunr.zh.wordCharacters);
lunr.Pipeline.registerFunction(lunr.zh.trimmer, 'trimmer-zh');
/* lunr stemmer function */
lunr.zh.stemmer = (function() {
/* TODO Chinese stemmer */
return function(word) {
return word;
}
})();
lunr.Pipeline.registerFunction(lunr.zh.stemmer, 'stemmer-zh');
/* lunr stop word filter. see https://www.ranks.nl/stopwords/chinese-stopwords */
lunr.zh.stopWordFilter = lunr.generateStopWordFilter(
'的 一 不 在 人 有 是 为 為 以 于 於 上 他 而 后 後 之 来 來 及 了 因 下 可 到 由 这 這 与 與 也 此 但 并 並 个 個 其 已 无 無 小 我 们 們 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 當 从 從 得 打 凡 儿 兒 尔 爾 该 該 各 给 給 跟 和 何 还 還 即 几 幾 既 看 据 據 距 靠 啦 另 么 麽 每 嘛 拿 哪 您 凭 憑 且 却 卻 让 讓 仍 啥 如 若 使 谁 誰 虽 雖 随 隨 同 所 她 哇 嗡 往 些 向 沿 哟 喲 用 咱 则 則 怎 曾 至 致 着 著 诸 諸 自'.split(' '));
lunr.Pipeline.registerFunction(lunr.zh.stopWordFilter, 'stopWordFilter-zh');
};
}))
@@ -0,0 +1,206 @@
/**
* export the module via AMD, CommonJS or as a browser global
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
*/
;(function (root, factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(factory)
} else if (typeof exports === 'object') {
/**
* Node. Does not work with strict CommonJS, but
* only CommonJS-like environments that support module.exports,
* like Node.
*/
module.exports = factory()
} else {
// Browser globals (root is window)
factory()(root.lunr);
}
}(this, function () {
/**
* Just return a value to define the module export.
* This example returns an object, but the module
* can return a function as the exported value.
*/
return function(lunr) {
// TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript
// (c) 2008 Taku Kudo <taku@chasen.org>
// TinySegmenter is freely distributable under the terms of a new BSD licence.
// For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt
function TinySegmenter() {
var patterns = {
"[一二三四五六七八九十百千万億兆]":"M",
"[一-龠々〆ヵヶ]":"H",
"[ぁ-ん]":"I",
"[ァ-ヴーア-ン゙ー]":"K",
"[a-zA-Za-zA-Z]":"A",
"[0-90-9]":"N"
}
this.chartype_ = [];
for (var i in patterns) {
var regexp = new RegExp(i);
this.chartype_.push([regexp, patterns[i]]);
}
this.BIAS__ = -332
this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378};
this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920};
this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266};
this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352};
this.BP2__ = {"BO":60,"OO":-1762};
this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965};
this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146};
this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699};
this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973};
this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682};
this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669};
this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990};
this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832};
this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649};
this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393};
this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841};
this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68};
this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591};
this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685};
this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156};
this.TW1__ = {"につい":-4681,"東京都":2026};
this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216};
this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287};
this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865};
this.UC1__ = {"A":484,"K":93,"M":645,"O":-505};
this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646};
this.UC3__ = {"A":-1370,"I":2311};
this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646};
this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831};
this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387};
this.UP1__ = {"O":-214};
this.UP2__ = {"B":69,"O":935};
this.UP3__ = {"B":189};
this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422};
this.UQ2__ = {"BH":216,"BI":113,"OK":1759};
this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212};
this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135};
this.UW2__ = {",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568};
this.UW3__ = {",":4889,"1":-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278};
this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637};
this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343};
this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496};
return this;
}
TinySegmenter.prototype.ctype_ = function(str) {
for (var i in this.chartype_) {
if (str.match(this.chartype_[i][0])) {
return this.chartype_[i][1];
}
}
return "O";
}
TinySegmenter.prototype.ts_ = function(v) {
if (v) { return v; }
return 0;
}
TinySegmenter.prototype.segment = function(input) {
if (input == null || input == undefined || input == "") {
return [];
}
var result = [];
var seg = ["B3","B2","B1"];
var ctype = ["O","O","O"];
var o = input.split("");
for (i = 0; i < o.length; ++i) {
seg.push(o[i]);
ctype.push(this.ctype_(o[i]))
}
seg.push("E1");
seg.push("E2");
seg.push("E3");
ctype.push("O");
ctype.push("O");
ctype.push("O");
var word = seg[3];
var p1 = "U";
var p2 = "U";
var p3 = "U";
for (var i = 4; i < seg.length - 3; ++i) {
var score = this.BIAS__;
var w1 = seg[i-3];
var w2 = seg[i-2];
var w3 = seg[i-1];
var w4 = seg[i];
var w5 = seg[i+1];
var w6 = seg[i+2];
var c1 = ctype[i-3];
var c2 = ctype[i-2];
var c3 = ctype[i-1];
var c4 = ctype[i];
var c5 = ctype[i+1];
var c6 = ctype[i+2];
score += this.ts_(this.UP1__[p1]);
score += this.ts_(this.UP2__[p2]);
score += this.ts_(this.UP3__[p3]);
score += this.ts_(this.BP1__[p1 + p2]);
score += this.ts_(this.BP2__[p2 + p3]);
score += this.ts_(this.UW1__[w1]);
score += this.ts_(this.UW2__[w2]);
score += this.ts_(this.UW3__[w3]);
score += this.ts_(this.UW4__[w4]);
score += this.ts_(this.UW5__[w5]);
score += this.ts_(this.UW6__[w6]);
score += this.ts_(this.BW1__[w2 + w3]);
score += this.ts_(this.BW2__[w3 + w4]);
score += this.ts_(this.BW3__[w4 + w5]);
score += this.ts_(this.TW1__[w1 + w2 + w3]);
score += this.ts_(this.TW2__[w2 + w3 + w4]);
score += this.ts_(this.TW3__[w3 + w4 + w5]);
score += this.ts_(this.TW4__[w4 + w5 + w6]);
score += this.ts_(this.UC1__[c1]);
score += this.ts_(this.UC2__[c2]);
score += this.ts_(this.UC3__[c3]);
score += this.ts_(this.UC4__[c4]);
score += this.ts_(this.UC5__[c5]);
score += this.ts_(this.UC6__[c6]);
score += this.ts_(this.BC1__[c2 + c3]);
score += this.ts_(this.BC2__[c3 + c4]);
score += this.ts_(this.BC3__[c4 + c5]);
score += this.ts_(this.TC1__[c1 + c2 + c3]);
score += this.ts_(this.TC2__[c2 + c3 + c4]);
score += this.ts_(this.TC3__[c3 + c4 + c5]);
score += this.ts_(this.TC4__[c4 + c5 + c6]);
// score += this.ts_(this.TC5__[c4 + c5 + c6]);
score += this.ts_(this.UQ1__[p1 + c1]);
score += this.ts_(this.UQ2__[p2 + c2]);
score += this.ts_(this.UQ3__[p3 + c3]);
score += this.ts_(this.BQ1__[p2 + c2 + c3]);
score += this.ts_(this.BQ2__[p2 + c3 + c4]);
score += this.ts_(this.BQ3__[p3 + c2 + c3]);
score += this.ts_(this.BQ4__[p3 + c3 + c4]);
score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]);
score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]);
score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]);
score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]);
var p = "O";
if (score > 0) {
result.push(word);
word = "";
p = "B";
}
p1 = p2;
p2 = p3;
p3 = p;
word += seg[i];
}
result.push(word);
return result;
}
lunr.TinySegmenter = TinySegmenter;
};
}));
@@ -0,0 +1,56 @@
var lunr = require('./templates/search/lunr'),
stdin = process.stdin,
stdout = process.stdout,
buffer = [];
stdin.resume();
stdin.setEncoding('utf8');
stdin.on('data', function (data) {
buffer.push(data);
});
stdin.on('end', function () {
var data = JSON.parse(buffer.join('')),
lang = ['en'];
if (data.config) {
if (data.config.lang && data.config.lang.length) {
lang = data.config.lang;
if (lang.length > 1 || lang[0] !== "en") {
require('./lunr-language/lunr.stemmer.support')(lunr);
if (lang.length > 1) {
require('./lunr-language/lunr.multi')(lunr);
}
if (lang.includes("ja") || lang.includes("jp")) {
require('./lunr-language/tinyseg')(lunr);
}
for (var i=0; i < lang.length; i++) {
if (lang[i] != 'en') {
require('./lunr-language/lunr.' + lang[i])(lunr);
}
}
}
}
if (data.config.separator && data.config.separator.length) {
lunr.tokenizer.separator = new RegExp(data.config.separator);
}
}
var idx = lunr(function () {
if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) {
this.use(lunr[lang[0]]);
} else if (lang.length > 1) {
this.use(lunr.multiLanguage.apply(null, lang));
}
this.field('title');
this.field('text');
this.ref('location');
data.docs.forEach(function (doc) {
this.add(doc);
}, this);
});
stdout.write(JSON.stringify(idx));
});
@@ -0,0 +1,225 @@
from __future__ import annotations
import json
import logging
import os
import re
import subprocess
from html.parser import HTMLParser
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from mkdocs.structure.pages import Page
from mkdocs.structure.toc import AnchorLink, TableOfContents
try:
from lunr import lunr # type: ignore
haslunrpy = True
except ImportError:
haslunrpy = False
log = logging.getLogger(__name__)
class SearchIndex:
"""
Search index is a collection of pages and sections (heading
tags and their following content are sections).
"""
def __init__(self, **config) -> None:
self._entries: list[dict] = []
self.config = config
def _find_toc_by_id(self, toc, id_: str | None) -> AnchorLink | None:
"""
Given a table of contents and HTML ID, iterate through
and return the matched item in the TOC.
"""
for toc_item in toc:
if toc_item.id == id_:
return toc_item
toc_item_r = self._find_toc_by_id(toc_item.children, id_)
if toc_item_r is not None:
return toc_item_r
return None
def _add_entry(self, title: str | None, text: str, loc: str) -> None:
"""A simple wrapper to add an entry, dropping bad characters."""
text = text.replace('\u00a0', ' ')
text = re.sub(r'[ \t\n\r\f\v]+', ' ', text.strip())
self._entries.append({'title': title, 'text': text, 'location': loc})
def add_entry_from_context(self, page: Page) -> None:
"""
Create a set of entries in the index for a page. One for
the page itself and then one for each of its' heading
tags.
"""
# Create the content parser and feed in the HTML for the
# full page. This handles all the parsing and prepares
# us to iterate through it.
parser = ContentParser()
assert page.content is not None
parser.feed(page.content)
parser.close()
# Get the absolute URL for the page, this is then
# prepended to the urls of the sections
url = page.url
# Create an entry for the full page.
text = parser.stripped_html.rstrip('\n') if self.config['indexing'] == 'full' else ''
self._add_entry(title=page.title, text=text, loc=url)
if self.config['indexing'] in ['full', 'sections']:
for section in parser.data:
self.create_entry_for_section(section, page.toc, url)
def create_entry_for_section(
self, section: ContentSection, toc: TableOfContents, abs_url: str
) -> None:
"""
Given a section on the page, the table of contents and
the absolute url for the page create an entry in the
index.
"""
toc_item = self._find_toc_by_id(toc, section.id)
text = ' '.join(section.text) if self.config['indexing'] == 'full' else ''
if toc_item is not None:
self._add_entry(title=toc_item.title, text=text, loc=abs_url + toc_item.url)
def generate_search_index(self) -> str:
"""Python to json conversion."""
page_dicts = {'docs': self._entries, 'config': self.config}
data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':'), default=str)
if self.config['prebuild_index'] in (True, 'node'):
try:
script_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)), 'prebuild-index.js'
)
p = subprocess.Popen(
['node', script_path],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding='utf-8',
)
idx, err = p.communicate(data)
if not err:
page_dicts['index'] = json.loads(idx)
data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':'))
log.debug('Pre-built search index created successfully.')
else:
log.warning(f'Failed to pre-build search index. Error: {err}')
except (OSError, ValueError) as e:
log.warning(f'Failed to pre-build search index. Error: {e}')
elif self.config['prebuild_index'] == 'python':
if haslunrpy:
lunr_idx = lunr(
ref='location',
fields=('title', 'text'),
documents=self._entries,
languages=self.config['lang'],
)
page_dicts['index'] = lunr_idx.serialize()
data = json.dumps(page_dicts, sort_keys=True, separators=(',', ':'))
else:
log.warning(
"Failed to pre-build search index. The 'python' method was specified; "
"however, the 'lunr.py' library does not appear to be installed. Try "
"installing it with 'pip install lunr'. If you are using any language "
"other than English you will also need to install 'lunr[languages]'."
)
return data
class ContentSection:
"""
Used by the ContentParser class to capture the information we
need when it is parsing the HTML.
"""
def __init__(
self,
text: list[str] | None = None,
id_: str | None = None,
title: str | None = None,
) -> None:
self.text = text or []
self.id = id_
self.title = title
def __eq__(self, other):
return self.text == other.text and self.id == other.id and self.title == other.title
_HEADER_TAGS = tuple(f"h{x}" for x in range(1, 7))
class ContentParser(HTMLParser):
"""
Given a block of HTML, group the content under the preceding
heading tags which can then be used for creating an index
for that section.
"""
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.data: list[ContentSection] = []
self.section: ContentSection | None = None
self.is_header_tag = False
self._stripped_html: list[str] = []
def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None:
"""Called at the start of every HTML tag."""
# We only care about the opening tag for headings.
if tag not in _HEADER_TAGS:
return
# We are dealing with a new header, create a new section
# for it and assign the ID if it has one.
self.is_header_tag = True
self.section = ContentSection()
self.data.append(self.section)
for attr in attrs:
if attr[0] == "id":
self.section.id = attr[1]
def handle_endtag(self, tag: str) -> None:
"""Called at the end of every HTML tag."""
# We only care about the opening tag for headings.
if tag not in _HEADER_TAGS:
return
self.is_header_tag = False
def handle_data(self, data: str) -> None:
"""Called for the text contents of each tag."""
self._stripped_html.append(data)
if self.section is None:
# This means we have some content at the start of the
# HTML before we reach a heading tag. We don't actually
# care about that content as it will be added to the
# overall page entry in the search. So just skip it.
return
# If this is a header, then the data is the title.
# Otherwise it is content of something under that header
# section.
if self.is_header_tag:
self.section.title = data
else:
self.section.text.append(data.rstrip('\n'))
@property
def stripped_html(self) -> str:
return '\n'.join(self._stripped_html)
@@ -0,0 +1,109 @@
function getSearchTermFromLocation() {
var sPageURL = window.location.search.substring(1);
var sURLVariables = sPageURL.split('&');
for (var i = 0; i < sURLVariables.length; i++) {
var sParameterName = sURLVariables[i].split('=');
if (sParameterName[0] == 'q') {
return decodeURIComponent(sParameterName[1].replace(/\+/g, '%20'));
}
}
}
function joinUrl (base, path) {
if (path.substring(0, 1) === "/") {
// path starts with `/`. Thus it is absolute.
return path;
}
if (base.substring(base.length-1) === "/") {
// base ends with `/`
return base + path;
}
return base + "/" + path;
}
function escapeHtml (value) {
return value.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
}
function formatResult (location, title, summary) {
return '<article><h3><a href="' + joinUrl(base_url, location) + '">'+ escapeHtml(title) + '</a></h3><p>' + escapeHtml(summary) +'</p></article>';
}
function displayResults (results) {
var search_results = document.getElementById("mkdocs-search-results");
while (search_results.firstChild) {
search_results.removeChild(search_results.firstChild);
}
if (results.length > 0){
for (var i=0; i < results.length; i++){
var result = results[i];
var html = formatResult(result.location, result.title, result.summary);
search_results.insertAdjacentHTML('beforeend', html);
}
} else {
var noResultsText = search_results.getAttribute('data-no-results-text');
if (!noResultsText) {
noResultsText = "No results found";
}
search_results.insertAdjacentHTML('beforeend', '<p>' + noResultsText + '</p>');
}
}
function doSearch () {
var query = document.getElementById('mkdocs-search-query').value;
if (query.length > min_search_length) {
if (!window.Worker) {
displayResults(search(query));
} else {
searchWorker.postMessage({query: query});
}
} else {
// Clear results for short queries
displayResults([]);
}
}
function initSearch () {
var search_input = document.getElementById('mkdocs-search-query');
if (search_input) {
search_input.addEventListener("keyup", doSearch);
}
var term = getSearchTermFromLocation();
if (term) {
search_input.value = term;
doSearch();
}
}
function onWorkerMessage (e) {
if (e.data.allowSearch) {
initSearch();
} else if (e.data.results) {
var results = e.data.results;
displayResults(results);
} else if (e.data.config) {
min_search_length = e.data.config.min_search_length-1;
}
}
if (!window.Worker) {
console.log('Web Worker API not supported');
// load index in main thread
$.getScript(joinUrl(base_url, "search/worker.js")).done(function () {
console.log('Loaded worker');
init();
window.postMessage = function (msg) {
onWorkerMessage({data: msg});
};
}).fail(function (jqxhr, settings, exception) {
console.error('Could not load worker.js');
});
} else {
// Wrap search in a web worker
var searchWorker = new Worker(joinUrl(base_url, "search/worker.js"));
searchWorker.postMessage({init: true});
searchWorker.onmessage = onWorkerMessage;
}
@@ -0,0 +1,133 @@
var base_path = 'function' === typeof importScripts ? '.' : '/search/';
var allowSearch = false;
var index;
var documents = {};
var lang = ['en'];
var data;
function getScript(script, callback) {
console.log('Loading script: ' + script);
$.getScript(base_path + script).done(function () {
callback();
}).fail(function (jqxhr, settings, exception) {
console.log('Error: ' + exception);
});
}
function getScriptsInOrder(scripts, callback) {
if (scripts.length === 0) {
callback();
return;
}
getScript(scripts[0], function() {
getScriptsInOrder(scripts.slice(1), callback);
});
}
function loadScripts(urls, callback) {
if( 'function' === typeof importScripts ) {
importScripts.apply(null, urls);
callback();
} else {
getScriptsInOrder(urls, callback);
}
}
function onJSONLoaded () {
data = JSON.parse(this.responseText);
var scriptsToLoad = ['lunr.js'];
if (data.config && data.config.lang && data.config.lang.length) {
lang = data.config.lang;
}
if (lang.length > 1 || lang[0] !== "en") {
scriptsToLoad.push('lunr.stemmer.support.js');
if (lang.length > 1) {
scriptsToLoad.push('lunr.multi.js');
}
if (lang.includes("ja") || lang.includes("jp")) {
scriptsToLoad.push('tinyseg.js');
}
for (var i=0; i < lang.length; i++) {
if (lang[i] != 'en') {
scriptsToLoad.push(['lunr', lang[i], 'js'].join('.'));
}
}
}
loadScripts(scriptsToLoad, onScriptsLoaded);
}
function onScriptsLoaded () {
console.log('All search scripts loaded, building Lunr index...');
if (data.config && data.config.separator && data.config.separator.length) {
lunr.tokenizer.separator = new RegExp(data.config.separator);
}
if (data.index) {
index = lunr.Index.load(data.index);
data.docs.forEach(function (doc) {
documents[doc.location] = doc;
});
console.log('Lunr pre-built index loaded, search ready');
} else {
index = lunr(function () {
if (lang.length === 1 && lang[0] !== "en" && lunr[lang[0]]) {
this.use(lunr[lang[0]]);
} else if (lang.length > 1) {
this.use(lunr.multiLanguage.apply(null, lang)); // spread operator not supported in all browsers: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator#Browser_compatibility
}
this.field('title');
this.field('text');
this.ref('location');
for (var i=0; i < data.docs.length; i++) {
var doc = data.docs[i];
this.add(doc);
documents[doc.location] = doc;
}
});
console.log('Lunr index built, search ready');
}
allowSearch = true;
postMessage({config: data.config});
postMessage({allowSearch: allowSearch});
}
function init () {
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", onJSONLoaded);
var index_path = base_path + '/search_index.json';
if( 'function' === typeof importScripts ){
index_path = 'search_index.json';
}
oReq.open("GET", index_path);
oReq.send();
}
function search (query) {
if (!allowSearch) {
console.error('Assets for search still loading');
return;
}
var resultDocuments = [];
var results = index.search(query);
for (var i=0; i < results.length; i++){
var result = results[i];
doc = documents[result.ref];
doc.summary = doc.text.substring(0, 200);
resultDocuments.push(doc);
}
return resultDocuments;
}
if( 'function' === typeof importScripts ) {
onmessage = function (e) {
if (e.data.init) {
init();
} else if (e.data.query) {
postMessage({ results: search(e.data.query) });
} else {
console.error("Worker - Unrecognized message: " + e);
}
};
}
@@ -0,0 +1,41 @@
from __future__ import annotations
from click import ClickException, echo
class MkDocsException(ClickException):
"""
The base class which all MkDocs exceptions inherit from. This should
not be raised directly. One of the subclasses should be raised instead.
"""
class Abort(MkDocsException, SystemExit):
"""Abort the build."""
code = 1
def show(self, *args, **kwargs) -> None:
echo('\n' + self.format_message())
class ConfigurationError(MkDocsException):
"""
This error is raised by configuration validation when a validation error
is encountered. This error should be raised by any configuration options
defined in a plugin's [config_scheme][].
"""
class BuildError(MkDocsException):
"""
This error may be raised by MkDocs during the build process. Plugins should
not raise this error.
"""
class PluginError(BuildError):
"""
A subclass of [`mkdocs.exceptions.BuildError`][] which can be raised by plugin
events.
"""
@@ -0,0 +1,381 @@
from __future__ import annotations
import functools
import io
import ipaddress
import logging
import mimetypes
import os
import os.path
import pathlib
import posixpath
import re
import socket
import socketserver
import string
import sys
import threading
import time
import traceback
import urllib.parse
import webbrowser
import wsgiref.simple_server
import wsgiref.util
from typing import Any, BinaryIO, Callable, Iterable
import watchdog.events
import watchdog.observers.polling
_SCRIPT_TEMPLATE_STR = """
var livereload = function(epoch, requestId) {
var req, timeout;
var poll = function() {
req = new XMLHttpRequest();
req.onloadend = function() {
if (parseFloat(this.responseText) > epoch) {
location.reload();
} else {
timeout = setTimeout(poll, this.status === 200 ? 0 : 3000);
}
};
req.open("GET", "/livereload/" + epoch + "/" + requestId);
req.send();
}
var stop = function() {
if (req) {
req.abort();
}
if (timeout) {
clearTimeout(timeout);
}
req = timeout = undefined;
};
window.addEventListener("load", function() {
if (document.visibilityState === "visible") {
poll();
}
});
window.addEventListener("visibilitychange", function() {
if (document.visibilityState === "visible") {
poll();
} else {
stop();
}
});
window.addEventListener("beforeunload", stop);
console.log('Enabled live reload');
}
livereload(${epoch}, ${request_id});
"""
_SCRIPT_TEMPLATE = string.Template(_SCRIPT_TEMPLATE_STR)
class _LoggerAdapter(logging.LoggerAdapter):
def process(self, msg: str, kwargs: dict) -> tuple[str, dict]: # type: ignore[override]
return time.strftime("[%H:%M:%S] ") + msg, kwargs
log = _LoggerAdapter(logging.getLogger(__name__), {})
def _normalize_mount_path(mount_path: str) -> str:
"""Ensure the mount path starts and ends with a slash."""
return ("/" + mount_path.lstrip("/")).rstrip("/") + "/"
def _serve_url(host: str, port: int, path: str) -> str:
return f"http://{host}:{port}{_normalize_mount_path(path)}"
class LiveReloadServer(socketserver.ThreadingMixIn, wsgiref.simple_server.WSGIServer):
daemon_threads = True
poll_response_timeout = 60
def __init__(
self,
builder: Callable[[], None],
host: str,
port: int,
root: str,
mount_path: str = "/",
polling_interval: float = 0.5,
shutdown_delay: float = 0.25,
) -> None:
self.builder = builder
try:
if isinstance(ipaddress.ip_address(host), ipaddress.IPv6Address):
self.address_family = socket.AF_INET6
except Exception:
pass
self.root = os.path.abspath(root)
self.mount_path = _normalize_mount_path(mount_path)
self.url = _serve_url(host, port, mount_path)
self.build_delay = 0.1
self.shutdown_delay = shutdown_delay
# To allow custom error pages.
self.error_handler: Callable[[int], bytes | None] = lambda code: None
super().__init__((host, port), _Handler, bind_and_activate=False)
self.set_app(self.serve_request)
self._wanted_epoch = _timestamp() # The version of the site that started building.
self._visible_epoch = self._wanted_epoch # Latest fully built version of the site.
self._epoch_cond = threading.Condition() # Must be held when accessing _visible_epoch.
self._want_rebuild: bool = False
self._rebuild_cond = threading.Condition() # Must be held when accessing _want_rebuild.
self._shutdown = False
self.serve_thread = threading.Thread(target=lambda: self.serve_forever(shutdown_delay))
self.observer = watchdog.observers.polling.PollingObserver(timeout=polling_interval)
self._watched_paths: dict[str, int] = {}
self._watch_refs: dict[str, Any] = {}
def watch(self, path: str, func: None = None, *, recursive: bool = True) -> None:
"""Add the 'path' to watched paths, call the function and reload when any file changes under it."""
path = os.path.abspath(path)
if not (func is None or func is self.builder): # type: ignore[unreachable]
raise TypeError("Plugins can no longer pass a 'func' parameter to watch().")
if path in self._watched_paths:
self._watched_paths[path] += 1
return
self._watched_paths[path] = 1
def callback(event):
if event.is_directory:
return
log.debug(str(event))
with self._rebuild_cond:
self._want_rebuild = True
self._rebuild_cond.notify_all()
handler = watchdog.events.FileSystemEventHandler()
handler.on_any_event = callback # type: ignore[method-assign]
log.debug(f"Watching '{path}'")
self._watch_refs[path] = self.observer.schedule(handler, path, recursive=recursive)
def unwatch(self, path: str) -> None:
"""Stop watching file changes for path. Raises if there was no corresponding `watch` call."""
path = os.path.abspath(path)
self._watched_paths[path] -= 1
if self._watched_paths[path] <= 0:
self._watched_paths.pop(path)
self.observer.unschedule(self._watch_refs.pop(path))
def serve(self, *, open_in_browser=False):
self.server_bind()
self.server_activate()
if self._watched_paths:
self.observer.start()
paths_str = ", ".join(f"'{_try_relativize_path(path)}'" for path in self._watched_paths)
log.info(f"Watching paths for changes: {paths_str}")
if open_in_browser:
log.info(f"Serving on {self.url} and opening it in a browser")
else:
log.info(f"Serving on {self.url}")
self.serve_thread.start()
if open_in_browser:
webbrowser.open(self.url)
self._build_loop()
def _build_loop(self):
while True:
with self._rebuild_cond:
while not self._rebuild_cond.wait_for(
lambda: self._want_rebuild or self._shutdown, timeout=self.shutdown_delay
):
# We could have used just one wait instead of a loop + timeout, but we need
# occasional breaks, otherwise on Windows we can't receive KeyboardInterrupt.
pass
if self._shutdown:
break
log.info("Detected file changes")
while self._rebuild_cond.wait(timeout=self.build_delay):
log.debug("Waiting for file changes to stop happening")
self._wanted_epoch = _timestamp()
self._want_rebuild = False
try:
self.builder()
except Exception as e:
if isinstance(e, SystemExit):
print(e, file=sys.stderr) # noqa: T201
else:
traceback.print_exc()
log.error(
"An error happened during the rebuild. The server will appear stuck until build errors are resolved."
)
continue
with self._epoch_cond:
log.info("Reloading browsers")
self._visible_epoch = self._wanted_epoch
self._epoch_cond.notify_all()
def shutdown(self, wait=False) -> None:
self.observer.stop()
with self._rebuild_cond:
self._shutdown = True
self._rebuild_cond.notify_all()
if self.serve_thread.is_alive():
super().shutdown()
self.server_close()
if wait:
self.serve_thread.join()
self.observer.join()
def serve_request(self, environ, start_response) -> Iterable[bytes]:
try:
result = self._serve_request(environ, start_response)
except Exception:
code = 500
msg = "500 Internal Server Error"
log.exception(msg)
else:
if result is not None:
return result
code = 404
msg = "404 Not Found"
error_content = None
try:
error_content = self.error_handler(code)
except Exception:
log.exception("Failed to render an error message!")
if error_content is None:
error_content = msg.encode()
start_response(msg, [("Content-Type", "text/html")])
return [error_content]
def _serve_request(self, environ, start_response) -> Iterable[bytes] | None:
# https://bugs.python.org/issue16679
# https://github.com/bottlepy/bottle/blob/f9b1849db4/bottle.py#L984
path = environ["PATH_INFO"].encode("latin-1").decode("utf-8", "ignore")
if path.startswith("/livereload/"):
if m := re.fullmatch(r"/livereload/([0-9]+)/[0-9]+", path):
epoch = int(m[1])
start_response("200 OK", [("Content-Type", "text/plain")])
def condition():
return self._visible_epoch > epoch
with self._epoch_cond:
if not condition():
# Stall the browser, respond as soon as there's something new.
# If there's not, respond anyway after a minute.
self._log_poll_request(environ.get("HTTP_REFERER"), request_id=path)
self._epoch_cond.wait_for(condition, timeout=self.poll_response_timeout)
return [b"%d" % self._visible_epoch]
if (path + "/").startswith(self.mount_path):
rel_file_path = path[len(self.mount_path) :]
if path.endswith("/"):
rel_file_path += "index.html"
# Prevent directory traversal - normalize the path.
rel_file_path = posixpath.normpath("/" + rel_file_path).lstrip("/")
file_path = os.path.join(self.root, rel_file_path)
elif path == "/":
start_response("302 Found", [("Location", urllib.parse.quote(self.mount_path))])
return []
else:
return None # Not found
# Wait until the ongoing rebuild (if any) finishes, so we're not serving a half-built site.
with self._epoch_cond:
self._epoch_cond.wait_for(lambda: self._visible_epoch == self._wanted_epoch)
epoch = self._visible_epoch
try:
file: BinaryIO = open(file_path, "rb")
except OSError:
if not path.endswith("/") and os.path.isfile(os.path.join(file_path, "index.html")):
start_response("302 Found", [("Location", urllib.parse.quote(path) + "/")])
return []
return None # Not found
if self._watched_paths and file_path.endswith(".html"):
with file:
content = file.read()
content = self._inject_js_into_html(content, epoch)
file = io.BytesIO(content)
content_length = len(content)
else:
content_length = os.path.getsize(file_path)
content_type = self._guess_type(file_path)
start_response(
"200 OK", [("Content-Type", content_type), ("Content-Length", str(content_length))]
)
return wsgiref.util.FileWrapper(file)
def _inject_js_into_html(self, content, epoch):
try:
body_end = content.rindex(b"</body>")
except ValueError:
body_end = len(content)
# The page will reload if the livereload poller returns a newer epoch than what it knows.
# The other timestamp becomes just a unique identifier for the initiating page.
script = _SCRIPT_TEMPLATE.substitute(epoch=epoch, request_id=_timestamp())
return b"%b<script>%b</script>%b" % (
content[:body_end],
script.encode(),
content[body_end:],
)
@classmethod
@functools.lru_cache # "Cache" to not repeat the same message for the same browser tab.
def _log_poll_request(cls, url, request_id):
log.info(f"Browser connected: {url}")
@classmethod
def _guess_type(cls, path):
# MkDocs only ensures a few common types (as seen in livereload_tests.py::test_mime_types).
# Other uncommon types will not be accepted.
if path.endswith((".js", ".JS", ".mjs")):
return "application/javascript"
if path.endswith(".gz"):
return "application/gzip"
guess, _ = mimetypes.guess_type(path)
if guess:
return guess
return "application/octet-stream"
class _Handler(wsgiref.simple_server.WSGIRequestHandler):
def log_request(self, code="-", size="-"):
level = logging.DEBUG if str(code) == "200" else logging.WARNING
log.log(level, f'"{self.requestline}" code {code}')
def log_message(self, format, *args):
log.debug(format, *args)
def _timestamp() -> int:
return round(time.monotonic() * 1000)
def _try_relativize_path(path: str) -> str:
"""Make the path relative to current directory if it's under that directory."""
p = pathlib.Path(path)
try:
p = p.relative_to(os.getcwd())
except ValueError:
pass
return str(p)
@@ -0,0 +1,92 @@
from __future__ import annotations
import logging
import os
from typing import TYPE_CHECKING, Sequence
from jinja2.ext import Extension, InternationalizationExtension
from mkdocs.config.base import ValidationError
if TYPE_CHECKING:
import jinja2
try:
from babel.core import Locale, UnknownLocaleError
from babel.support import NullTranslations, Translations
has_babel = True
except ImportError: # pragma: no cover
from mkdocs.utils.babel_stub import Locale, UnknownLocaleError # type: ignore
has_babel = False
log = logging.getLogger(__name__)
base_path = os.path.dirname(os.path.abspath(__file__))
class NoBabelExtension(InternationalizationExtension): # pragma: no cover
def __init__(self, environment):
Extension.__init__(self, environment)
environment.extend(
install_null_translations=self._install_null,
newstyle_gettext=False,
)
def parse_locale(locale: str) -> Locale:
try:
return Locale.parse(locale, sep='_')
except (ValueError, UnknownLocaleError, TypeError) as e:
raise ValidationError(f'Invalid value for locale: {e}')
def install_translations(
env: jinja2.Environment, locale: Locale, theme_dirs: Sequence[str]
) -> None:
if has_babel:
env.add_extension('jinja2.ext.i18n')
translations = _get_merged_translations(theme_dirs, 'locales', locale)
if translations is not None:
env.install_gettext_translations(translations) # type: ignore[attr-defined]
else:
env.install_null_translations() # type: ignore[attr-defined]
if locale.language != 'en':
log.warning(
f"No translations could be found for the locale '{locale}'. "
'Defaulting to English.'
)
else: # pragma: no cover
# no babel installed, add dummy support for trans/endtrans blocks
env.add_extension(NoBabelExtension)
env.install_null_translations() # type: ignore[attr-defined]
def _get_merged_translations(
theme_dirs: Sequence[str], locales_dir: str, locale: Locale
) -> Translations | None:
merged_translations: Translations | None = None
log.debug(f"Looking for translations for locale '{locale}'")
if locale.territory:
locale_str = f"{locale.language}_{locale.territory}"
else:
locale_str = locale.language
for theme_dir in reversed(theme_dirs):
dirname = os.path.join(theme_dir, locales_dir)
translations = Translations.load(dirname, [locale_str])
if type(translations) is NullTranslations:
log.debug(f"No translations found here: '{dirname}'")
continue
if TYPE_CHECKING:
assert isinstance(translations, Translations)
log.debug(f"Translations found here: '{dirname}'")
if merged_translations is None:
merged_translations = translations
else:
merged_translations.merge(translations)
return merged_translations
@@ -0,0 +1,697 @@
"""Implements the plugin API for MkDocs."""
from __future__ import annotations
import logging
import sys
from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, MutableMapping, TypeVar, overload
if sys.version_info >= (3, 10):
from importlib.metadata import EntryPoint, entry_points
else:
from importlib_metadata import EntryPoint, entry_points
if TYPE_CHECKING:
import jinja2.environment
from mkdocs import utils
from mkdocs.config.base import Config, ConfigErrors, ConfigWarnings, LegacyConfig, PlainConfigSchema
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.livereload import LiveReloadServer
from mkdocs.structure.files import Files
from mkdocs.structure.nav import Navigation
from mkdocs.structure.pages import Page
from mkdocs.utils.templates import TemplateContext
if TYPE_CHECKING:
from typing_extensions import Concatenate, ParamSpec
else:
ParamSpec = TypeVar
P = ParamSpec('P')
T = TypeVar('T')
log = logging.getLogger('mkdocs.plugins')
def get_plugins() -> dict[str, EntryPoint]:
"""Return a dict of all installed Plugins as {name: EntryPoint}."""
plugins = entry_points(group='mkdocs.plugins')
# Allow third-party plugins to override core plugins
pluginmap = {}
for plugin in plugins:
if plugin.name in pluginmap and plugin.value.startswith("mkdocs.contrib."):
continue
pluginmap[plugin.name] = plugin
return pluginmap
SomeConfig = TypeVar('SomeConfig', bound=Config)
class BasePlugin(Generic[SomeConfig]):
"""
Plugin base class.
All plugins should subclass this class.
"""
config_class: type[SomeConfig] = LegacyConfig # type: ignore[assignment]
config_scheme: PlainConfigSchema = ()
config: SomeConfig = {} # type: ignore[assignment]
supports_multiple_instances: bool = False
"""Set to true in subclasses to declare support for adding the same plugin multiple times."""
def __class_getitem__(cls, config_class: type[Config]):
"""Eliminates the need to write `config_class = FooConfig` when subclassing BasePlugin[FooConfig]."""
name = f'{cls.__name__}[{config_class.__name__}]'
return type(name, (cls,), dict(config_class=config_class))
def __init_subclass__(cls):
if not issubclass(cls.config_class, Config):
raise TypeError(
f"config_class {cls.config_class} must be a subclass of `mkdocs.config.base.Config`"
)
if cls.config_class is not LegacyConfig:
cls.config_scheme = cls.config_class._schema # For compatibility.
def load_config(
self, options: dict[str, Any], config_file_path: str | None = None
) -> tuple[ConfigErrors, ConfigWarnings]:
"""Load config from a dict of options. Returns a tuple of (errors, warnings)."""
if self.config_class is LegacyConfig:
self.config = LegacyConfig(self.config_scheme, config_file_path=config_file_path) # type: ignore
else:
self.config = self.config_class(config_file_path=config_file_path)
self.config.load_dict(options)
return self.config.validate()
# One-time events
def on_startup(self, *, command: Literal['build', 'gh-deploy', 'serve'], dirty: bool) -> None:
"""
The `startup` event runs once at the very beginning of an `mkdocs` invocation.
New in MkDocs 1.4.
The presence of an `on_startup` method (even if empty) migrates the plugin to the new
system where the plugin object is kept across builds within one `mkdocs serve`.
Note that for initializing variables, the `__init__` method is still preferred.
For initializing per-build variables (and whenever in doubt), use the `on_config` event.
Args:
command: the command that MkDocs was invoked with, e.g. "serve" for `mkdocs serve`.
dirty: whether `--dirty` flag was passed.
"""
def on_shutdown(self) -> None:
"""
The `shutdown` event runs once at the very end of an `mkdocs` invocation, before exiting.
This event is relevant only for support of `mkdocs serve`, otherwise within a
single build it's undistinguishable from `on_post_build`.
New in MkDocs 1.4.
The presence of an `on_shutdown` method (even if empty) migrates the plugin to the new
system where the plugin object is kept across builds within one `mkdocs serve`.
Note the `on_post_build` method is still preferred for cleanups, when possible, as it has
a much higher chance of actually triggering. `on_shutdown` is "best effort" because it
relies on detecting a graceful shutdown of MkDocs.
"""
def on_serve(
self, server: LiveReloadServer, /, *, config: MkDocsConfig, builder: Callable
) -> LiveReloadServer | None:
"""
The `serve` event is only called when the `serve` command is used during
development. It runs only once, after the first build finishes.
It is passed the `Server` instance which can be modified before
it is activated. For example, additional files or directories could be added
to the list of "watched" files for auto-reloading.
Args:
server: `livereload.Server` instance
config: global configuration object
builder: a callable which gets passed to each call to `server.watch`
Returns:
`livereload.Server` instance
"""
return server
# Global events
def on_config(self, config: MkDocsConfig) -> MkDocsConfig | None:
"""
The `config` event is the first event called on build and is run immediately
after the user configuration is loaded and validated. Any alterations to the
config should be made here.
Args:
config: global configuration object
Returns:
global configuration object
"""
return config
def on_pre_build(self, *, config: MkDocsConfig) -> None:
"""
The `pre_build` event does not alter any variables. Use this event to call
pre-build scripts.
Args:
config: global configuration object
"""
def on_files(self, files: Files, /, *, config: MkDocsConfig) -> Files | None:
"""
The `files` event is called after the files collection is populated from the
`docs_dir`. Use this event to add, remove, or alter files in the
collection. Note that Page objects have not yet been associated with the
file objects in the collection. Use [Page Events](plugins.md#page-events) to manipulate page
specific data.
Args:
files: global files collection
config: global configuration object
Returns:
global files collection
"""
return files
def on_nav(
self, nav: Navigation, /, *, config: MkDocsConfig, files: Files
) -> Navigation | None:
"""
The `nav` event is called after the site navigation is created and can
be used to alter the site navigation.
Args:
nav: global navigation object
config: global configuration object
files: global files collection
Returns:
global navigation object
"""
return nav
def on_env(
self, env: jinja2.Environment, /, *, config: MkDocsConfig, files: Files
) -> jinja2.Environment | None:
"""
The `env` event is called after the Jinja template environment is created
and can be used to alter the
[Jinja environment](https://jinja.palletsprojects.com/en/latest/api/#jinja2.Environment).
Args:
env: global Jinja environment
config: global configuration object
files: global files collection
Returns:
global Jinja Environment
"""
return env
def on_post_build(self, *, config: MkDocsConfig) -> None:
"""
The `post_build` event does not alter any variables. Use this event to call
post-build scripts.
Args:
config: global configuration object
"""
def on_build_error(self, *, error: Exception) -> None:
"""
The `build_error` event is called after an exception of any kind
is caught by MkDocs during the build process.
Use this event to clean things up before MkDocs terminates. Note that any other
events which were scheduled to run after the error will have been skipped. See
[Handling Errors](plugins.md#handling-errors) for more details.
Args:
error: exception raised
"""
# Template events
def on_pre_template(
self, template: jinja2.Template, /, *, template_name: str, config: MkDocsConfig
) -> jinja2.Template | None:
"""
The `pre_template` event is called immediately after the subject template is
loaded and can be used to alter the template.
Args:
template: a Jinja2 [Template](https://jinja.palletsprojects.com/en/latest/api/#jinja2.Template) object
template_name: string filename of template
config: global configuration object
Returns:
a Jinja2 [Template](https://jinja.palletsprojects.com/en/latest/api/#jinja2.Template) object
"""
return template
def on_template_context(
self, context: TemplateContext, /, *, template_name: str, config: MkDocsConfig
) -> TemplateContext | None:
"""
The `template_context` event is called immediately after the context is created
for the subject template and can be used to alter the context for that specific
template only.
Args:
context: dict of template context variables
template_name: string filename of template
config: global configuration object
Returns:
dict of template context variables
"""
return context
def on_post_template(
self, output_content: str, /, *, template_name: str, config: MkDocsConfig
) -> str | None:
"""
The `post_template` event is called after the template is rendered, but before
it is written to disc and can be used to alter the output of the template.
If an empty string is returned, the template is skipped and nothing is is
written to disc.
Args:
output_content: output of rendered template as string
template_name: string filename of template
config: global configuration object
Returns:
output of rendered template as string
"""
return output_content
# Page events
def on_pre_page(self, page: Page, /, *, config: MkDocsConfig, files: Files) -> Page | None:
"""
The `pre_page` event is called before any actions are taken on the subject
page and can be used to alter the `Page` instance.
Args:
page: `mkdocs.structure.pages.Page` instance
config: global configuration object
files: global files collection
Returns:
`mkdocs.structure.pages.Page` instance
"""
return page
def on_page_read_source(self, /, *, page: Page, config: MkDocsConfig) -> str | None:
"""
> DEPRECATED: Instead of this event, prefer one of these alternatives:
>
> * Since MkDocs 1.6, instead set `content_bytes`/`content_string` of a `File` inside [`on_files`][].
> * Usually (although it's not an exact alternative), `on_page_markdown` can serve the same purpose.
The `on_page_read_source` event can replace the default mechanism to read
the contents of a page's source from the filesystem.
Args:
page: `mkdocs.structure.pages.Page` instance
config: global configuration object
Returns:
The raw source for a page as unicode string. If `None` is returned, the
default loading from a file will be performed.
"""
return None
def on_page_markdown(
self, markdown: str, /, *, page: Page, config: MkDocsConfig, files: Files
) -> str | None:
"""
The `page_markdown` event is called after the page's markdown is loaded
from file and can be used to alter the Markdown source text. The meta-
data has been stripped off and is available as `page.meta` at this point.
Args:
markdown: Markdown source text of page as string
page: `mkdocs.structure.pages.Page` instance
config: global configuration object
files: global files collection
Returns:
Markdown source text of page as string
"""
return markdown
def on_page_content(
self, html: str, /, *, page: Page, config: MkDocsConfig, files: Files
) -> str | None:
"""
The `page_content` event is called after the Markdown text is rendered to
HTML (but before being passed to a template) and can be used to alter the
HTML body of the page.
Args:
html: HTML rendered from Markdown source as string
page: `mkdocs.structure.pages.Page` instance
config: global configuration object
files: global files collection
Returns:
HTML rendered from Markdown source as string
"""
return html
def on_page_context(
self, context: TemplateContext, /, *, page: Page, config: MkDocsConfig, nav: Navigation
) -> TemplateContext | None:
"""
The `page_context` event is called after the context for a page is created
and can be used to alter the context for that specific page only.
Args:
context: dict of template context variables
page: `mkdocs.structure.pages.Page` instance
config: global configuration object
nav: global navigation object
Returns:
dict of template context variables
"""
return context
def on_post_page(self, output: str, /, *, page: Page, config: MkDocsConfig) -> str | None:
"""
The `post_page` event is called after the template is rendered, but
before it is written to disc and can be used to alter the output of the
page. If an empty string is returned, the page is skipped and nothing is
written to disc.
Args:
output: output of rendered template as string
page: `mkdocs.structure.pages.Page` instance
config: global configuration object
Returns:
output of rendered template as string
"""
return output
EVENTS = tuple(k[3:] for k in BasePlugin.__dict__ if k.startswith("on_"))
# The above definitions were just for docs and type checking, we don't actually want them.
for k in EVENTS:
delattr(BasePlugin, 'on_' + k)
def event_priority(priority: float) -> Callable[[T], T]:
"""
A decorator to set an event priority for an event handler method.
Recommended priority values:
`100` "first", `50` "early", `0` "default", `-50` "late", `-100` "last".
As different plugins discover more precise relations to each other, the values should be further tweaked.
Usage example:
```python
@plugins.event_priority(-100) # Wishing to run this after all other plugins' `on_files` events.
def on_files(self, files, config, **kwargs):
...
```
New in MkDocs 1.4.
Recommended shim for backwards compatibility:
```python
try:
from mkdocs.plugins import event_priority
except ImportError:
event_priority = lambda priority: lambda f: f # No-op fallback
```
"""
def decorator(event_method):
event_method.mkdocs_priority = priority
return event_method
return decorator
class CombinedEvent(Generic[P, T]):
"""
A descriptor that allows defining multiple event handlers and declaring them under one event's name.
Usage example:
```python
@plugins.event_priority(100)
def _on_page_markdown_1(self, markdown: str, **kwargs):
...
@plugins.event_priority(-50)
def _on_page_markdown_2(self, markdown: str, **kwargs):
...
on_page_markdown = plugins.CombinedEvent(_on_page_markdown_1, _on_page_markdown_2)
```
NOTE: The names of the sub-methods **can't** start with `on_`;
instead they can start with `_on_` like in the the above example, or anything else.
"""
def __init__(self, *methods: Callable[Concatenate[Any, P], T]):
self.methods = methods
# This is only for mypy, so CombinedEvent can be a valid override of the methods in BasePlugin
def __call__(self, instance: BasePlugin, *args: P.args, **kwargs: P.kwargs) -> T:
raise TypeError(f"{type(self).__name__!r} object is not callable")
def __get__(self, instance, owner=None):
return CombinedEvent(*(f.__get__(instance, owner) for f in self.methods))
class PluginCollection(dict, MutableMapping[str, BasePlugin]):
"""
A collection of plugins.
In addition to being a dict of Plugin instances, each event method is registered
upon being added. All registered methods for a given event can then be run in order
by calling `run_event`.
"""
_current_plugin: str | None
def __init__(self, *args, **kwargs) -> None:
super().__init__(*args, **kwargs)
self.events: dict[str, list[Callable]] = {k: [] for k in EVENTS}
self._event_origins: dict[Callable, str] = {}
def _register_event(
self, event_name: str, method: CombinedEvent | Callable, plugin_name: str | None = None
) -> None:
"""Register a method for an event."""
if isinstance(method, CombinedEvent):
for sub in method.methods:
self._register_event(event_name, sub, plugin_name=plugin_name)
else:
events = self.events[event_name]
if event_name == 'page_read_source' and len(events) == 1:
plugin1 = self._event_origins.get(next(iter(events)), '<unknown>')
plugin2 = plugin_name or '<unknown>'
log.warning(
"Multiple 'on_page_read_source' handlers can't work "
f"(both plugins '{plugin1}' and '{plugin2}' registered one)."
)
utils.insort(events, method, key=lambda m: -getattr(m, 'mkdocs_priority', 0))
if plugin_name:
try:
self._event_origins[method] = plugin_name
except TypeError: # If the method is somehow not hashable.
pass
def __getitem__(self, key: str) -> BasePlugin:
return super().__getitem__(key)
def __setitem__(self, key: str, value: BasePlugin) -> None:
super().__setitem__(key, value)
# Register all of the event methods defined for this Plugin.
for event_name in (x for x in dir(value) if x.startswith('on_')):
method = getattr(value, event_name, None)
if callable(method):
self._register_event(event_name[3:], method, plugin_name=key)
@overload
def run_event(self, name: str, **kwargs) -> Any:
...
@overload
def run_event(self, name: str, item: T, **kwargs) -> T:
...
def run_event(self, name: str, item=None, **kwargs):
"""
Run all registered methods of an event.
`item` is the object to be modified or replaced and returned by the event method.
If it isn't given the event method creates a new object to be returned.
All other keywords are variables for context, but would not generally
be modified by the event method.
"""
pass_item = item is not None
for method in self.events[name]:
self._current_plugin = self._event_origins.get(method, '<unknown>')
if log.getEffectiveLevel() <= logging.DEBUG:
log.debug(f"Running `{name}` event from plugin '{self._current_plugin}'")
if pass_item:
result = method(item, **kwargs)
else:
result = method(**kwargs)
# keep item if method returned `None`
if result is not None:
item = result
self._current_plugin = None
return item
def on_startup(self, *, command: Literal['build', 'gh-deploy', 'serve'], dirty: bool) -> None:
return self.run_event('startup', command=command, dirty=dirty)
def on_shutdown(self) -> None:
return self.run_event('shutdown')
def on_serve(
self, server: LiveReloadServer, *, config: MkDocsConfig, builder: Callable
) -> LiveReloadServer:
return self.run_event('serve', server, config=config, builder=builder)
def on_config(self, config: MkDocsConfig) -> MkDocsConfig:
return self.run_event('config', config)
def on_pre_build(self, *, config: MkDocsConfig) -> None:
return self.run_event('pre_build', config=config)
def on_files(self, files: Files, *, config: MkDocsConfig) -> Files:
return self.run_event('files', files, config=config)
def on_nav(self, nav: Navigation, *, config: MkDocsConfig, files: Files) -> Navigation:
return self.run_event('nav', nav, config=config, files=files)
def on_env(self, env: jinja2.Environment, *, config: MkDocsConfig, files: Files):
return self.run_event('env', env, config=config, files=files)
def on_post_build(self, *, config: MkDocsConfig) -> None:
return self.run_event('post_build', config=config)
def on_build_error(self, *, error: Exception) -> None:
return self.run_event('build_error', error=error)
def on_pre_template(
self, template: jinja2.Template, *, template_name: str, config: MkDocsConfig
) -> jinja2.Template:
return self.run_event('pre_template', template, template_name=template_name, config=config)
def on_template_context(
self, context: TemplateContext, *, template_name: str, config: MkDocsConfig
) -> TemplateContext:
return self.run_event(
'template_context', context, template_name=template_name, config=config
)
def on_post_template(
self, output_content: str, *, template_name: str, config: MkDocsConfig
) -> str:
return self.run_event(
'post_template', output_content, template_name=template_name, config=config
)
def on_pre_page(self, page: Page, *, config: MkDocsConfig, files: Files) -> Page:
return self.run_event('pre_page', page, config=config, files=files)
def on_page_read_source(self, *, page: Page, config: MkDocsConfig) -> str | None:
return self.run_event('page_read_source', page=page, config=config)
def on_page_markdown(
self, markdown: str, *, page: Page, config: MkDocsConfig, files: Files
) -> str:
return self.run_event('page_markdown', markdown, page=page, config=config, files=files)
def on_page_content(self, html: str, *, page: Page, config: MkDocsConfig, files: Files) -> str:
return self.run_event('page_content', html, page=page, config=config, files=files)
def on_page_context(
self, context: TemplateContext, *, page: Page, config: MkDocsConfig, nav: Navigation
) -> TemplateContext:
return self.run_event('page_context', context, page=page, config=config, nav=nav)
def on_post_page(self, output: str, *, page: Page, config: MkDocsConfig) -> str:
return self.run_event('post_page', output, page=page, config=config)
class PrefixedLogger(logging.LoggerAdapter):
"""A logger adapter to prefix log messages."""
def __init__(self, prefix: str, logger: logging.Logger) -> None:
"""
Initialize the logger adapter.
Arguments:
prefix: The string to insert in front of every message.
logger: The logger instance.
"""
super().__init__(logger, {})
self.prefix = prefix
def process(self, msg: str, kwargs: MutableMapping[str, Any]) -> tuple[str, Any]:
"""
Process the message.
Arguments:
msg: The message:
kwargs: Remaining arguments.
Returns:
The processed message.
"""
return f"{self.prefix}: {msg}", kwargs
def get_plugin_logger(name: str) -> PrefixedLogger:
"""
Return a logger for plugins.
Arguments:
name: The name to use with `logging.getLogger`.
Returns:
A logger configured to work well in MkDocs,
prefixing each message with the plugin package name.
Example:
```python
from mkdocs.plugins import get_plugin_logger
log = get_plugin_logger(__name__)
log.info("My plugin message")
```
"""
logger = logging.getLogger(f"mkdocs.plugins.{name}")
return PrefixedLogger(name.split(".", 1)[0], logger)
Whitespace-only changes.
@@ -0,0 +1,36 @@
from __future__ import annotations
import abc
from typing import TYPE_CHECKING, Iterable
if TYPE_CHECKING:
from mkdocs.structure.nav import Section
class StructureItem(metaclass=abc.ABCMeta):
"""An item in MkDocs structure - see concrete subclasses Section, Page or Link."""
@abc.abstractmethod
def __init__(self):
...
parent: Section | None = None
"""The immediate parent of the item in the site navigation. `None` if it's at the top level."""
@property
def is_top_level(self) -> bool:
return self.parent is None
title: str | None
is_section: bool = False
is_page: bool = False
is_link: bool = False
@property
def ancestors(self) -> Iterable[StructureItem]:
if self.parent is None:
return []
return [self.parent, *self.parent.ancestors]
def _indent_print(self, depth: int = 0) -> str:
return (' ' * depth) + repr(self)
@@ -0,0 +1,626 @@
from __future__ import annotations
import enum
import fnmatch
import logging
import os
import posixpath
import shutil
import warnings
from functools import cached_property
from pathlib import PurePath, PurePosixPath
from typing import TYPE_CHECKING, Callable, Iterable, Iterator, Mapping, Sequence, overload
from urllib.parse import quote as urlquote
import pathspec
import pathspec.gitignore
import pathspec.util
from mkdocs import utils
if TYPE_CHECKING:
import jinja2.environment
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.pages import Page
log = logging.getLogger(__name__)
class InclusionLevel(enum.Enum):
EXCLUDED = -3
"""The file is excluded and will not be processed."""
DRAFT = -2
"""The file is excluded from the final site, but will still be populated during `mkdocs serve`."""
NOT_IN_NAV = -1
"""The file is part of the site, but doesn't produce nav warnings."""
UNDEFINED = 0
"""Still needs to be computed based on the config. If the config doesn't kick in, acts the same as `included`."""
INCLUDED = 1
"""The file is part of the site. Documentation pages that are omitted from the nav will produce warnings."""
def all(self):
return True
def is_included(self):
return self.value > self.DRAFT.value
def is_excluded(self):
return self.value <= self.DRAFT.value
def is_in_serve(self):
return self.value >= self.DRAFT.value
def is_in_nav(self):
return self.value > self.NOT_IN_NAV.value
def is_not_in_nav(self):
return self.value <= self.NOT_IN_NAV.value
class Files:
"""A collection of [File][mkdocs.structure.files.File] objects."""
def __init__(self, files: Iterable[File]) -> None:
self._src_uris = {f.src_uri: f for f in files}
def __iter__(self) -> Iterator[File]:
"""Iterate over the files within."""
return iter(self._src_uris.values())
def __len__(self) -> int:
"""The number of files within."""
return len(self._src_uris)
def __contains__(self, path: str) -> bool:
"""Soft-deprecated, prefer `get_file_from_path(path) is not None`."""
return PurePath(path).as_posix() in self._src_uris
@property
def src_paths(self) -> dict[str, File]:
"""Soft-deprecated, prefer `src_uris`."""
return {file.src_path: file for file in self}
@property
def src_uris(self) -> Mapping[str, File]:
"""
A mapping containing every file, with the keys being their
[`src_uri`][mkdocs.structure.files.File.src_uri].
"""
return self._src_uris
def get_file_from_path(self, path: str) -> File | None:
"""Return a File instance with File.src_uri equal to path."""
return self._src_uris.get(PurePath(path).as_posix())
def append(self, file: File) -> None:
"""Add file to the Files collection."""
if file.src_uri in self._src_uris:
warnings.warn(
"To replace an existing file, call `remove` before `append`.", DeprecationWarning
)
del self._src_uris[file.src_uri]
self._src_uris[file.src_uri] = file
def remove(self, file: File) -> None:
"""Remove file from Files collection."""
try:
del self._src_uris[file.src_uri]
except KeyError:
raise ValueError(f'{file.src_uri!r} not in collection')
def copy_static_files(
self,
dirty: bool = False,
*,
inclusion: Callable[[InclusionLevel], bool] = InclusionLevel.is_included,
) -> None:
"""Copy static files from source to destination."""
for file in self:
if not file.is_documentation_page() and inclusion(file.inclusion):
file.copy_file(dirty)
def documentation_pages(
self, *, inclusion: Callable[[InclusionLevel], bool] = InclusionLevel.is_included
) -> Sequence[File]:
"""Return iterable of all Markdown page file objects."""
return [file for file in self if file.is_documentation_page() and inclusion(file.inclusion)]
def static_pages(self) -> Sequence[File]:
"""Return iterable of all static page file objects."""
return [file for file in self if file.is_static_page()]
def media_files(self) -> Sequence[File]:
"""Return iterable of all file objects which are not documentation or static pages."""
return [file for file in self if file.is_media_file()]
def javascript_files(self) -> Sequence[File]:
"""Return iterable of all javascript file objects."""
return [file for file in self if file.is_javascript()]
def css_files(self) -> Sequence[File]:
"""Return iterable of all CSS file objects."""
return [file for file in self if file.is_css()]
def add_files_from_theme(self, env: jinja2.Environment, config: MkDocsConfig) -> None:
"""Retrieve static files from Jinja environment and add to collection."""
def filter(name):
# '.*' filters dot files/dirs at root level whereas '*/.*' filters nested levels
patterns = ['.*', '*/.*', '*.py', '*.pyc', '*.html', '*readme*', 'mkdocs_theme.yml']
# Exclude translation files
patterns.append("locales/*")
patterns.extend(f'*{x}' for x in utils.markdown_extensions)
patterns.extend(config.theme.static_templates)
for pattern in patterns:
if fnmatch.fnmatch(name.lower(), pattern):
return False
return True
for path in env.list_templates(filter_func=filter):
# Theme files do not override docs_dir files
if self.get_file_from_path(path) is None:
for dir in config.theme.dirs:
# Find the first theme dir which contains path
if os.path.isfile(os.path.join(dir, path)):
self.append(File(path, dir, config.site_dir, config.use_directory_urls))
break
@property
def _files(self) -> Iterable[File]:
warnings.warn("Do not access Files._files.", DeprecationWarning)
return self
@_files.setter
def _files(self, value: Iterable[File]):
warnings.warn("Do not access Files._files.", DeprecationWarning)
self._src_uris = {f.src_uri: f for f in value}
class File:
"""
A MkDocs File object.
It represents how the contents of one file should be populated in the destination site.
A file always has its `abs_dest_path` (obtained by joining `dest_dir` and `dest_path`),
where the `dest_dir` is understood to be the *site* directory.
`content_bytes`/`content_string` (new in MkDocs 1.6) can always be used to obtain the file's
content. But it may be backed by one of the two sources:
* A physical source file at `abs_src_path` (by default obtained by joining `src_dir` and
`src_uri`). `src_dir` is understood to be the *docs* directory.
Then `content_bytes`/`content_string` will read the file at `abs_src_path`.
`src_dir` *should* be populated for real files and should be `None` for generated files.
* Since MkDocs 1.6 a file may alternatively be stored in memory - `content_string`/`content_bytes`.
Then `src_dir` and `abs_src_path` will remain `None`. `content_bytes`/`content_string` need
to be written to, or populated through the `content` argument in the constructor.
But `src_uri` is still populated for such files as well! The virtual file pretends as if it
originated from that path in the `docs` directory, and other values are derived.
For static files the file is just copied to the destination, and `dest_uri` equals `src_uri`.
For Markdown files (determined by the file extension in `src_uri`) the destination content
will be the rendered content, and `dest_uri` will have the `.html` extension and some
additional transformations to the path, based on `use_directory_urls`.
"""
src_uri: str
"""The pure path (always '/'-separated) of the source file relative to the source directory."""
use_directory_urls: bool
"""Whether directory URLs ('foo/') should be used or not ('foo.html').
If `False`, a Markdown file is mapped to an HTML file of the same name (the file extension is
changed to `.html`). If True, a Markdown file is mapped to an HTML index file (`index.html`)
nested in a directory using the "name" of the file in `path`. Non-Markdown files retain their
original path.
"""
src_dir: str | None
"""The OS path of the top-level directory that the source file originates from.
Assumed to be the *docs_dir*; not populated for generated files."""
dest_dir: str
"""The OS path of the destination directory (top-level site_dir) that the file should be copied to."""
inclusion: InclusionLevel = InclusionLevel.UNDEFINED
"""Whether the file will be excluded from the built site."""
generated_by: str | None = None
"""If not None, indicates that a plugin generated this file on the fly.
The value is the plugin's entrypoint name and can be used to find the plugin by key in the PluginCollection."""
_content: str | bytes | None = None
"""If set, the file's content will be read from here.
This logic is handled by `content_bytes`/`content_string`, which should be used instead of
accessing this attribute."""
@property
def src_path(self) -> str:
"""Same as `src_uri` (and synchronized with it) but will use backslashes on Windows. Discouraged."""
return os.path.normpath(self.src_uri)
@src_path.setter
def src_path(self, value: str):
self.src_uri = PurePath(value).as_posix()
@property
def dest_path(self) -> str:
"""Same as `dest_uri` (and synchronized with it) but will use backslashes on Windows. Discouraged."""
return os.path.normpath(self.dest_uri)
@dest_path.setter
def dest_path(self, value: str):
self.dest_uri = PurePath(value).as_posix()
page: Page | None = None
@overload
@classmethod
def generated(
cls,
config: MkDocsConfig,
src_uri: str,
*,
content: str | bytes,
inclusion: InclusionLevel = InclusionLevel.UNDEFINED,
) -> File:
"""
Create a virtual file backed by in-memory content.
It will pretend to be a file in the docs dir at `src_uri`.
"""
@overload
@classmethod
def generated(
cls,
config: MkDocsConfig,
src_uri: str,
*,
abs_src_path: str,
inclusion: InclusionLevel = InclusionLevel.UNDEFINED,
) -> File:
"""
Create a virtual file backed by a physical temporary file at `abs_src_path`.
It will pretend to be a file in the docs dir at `src_uri`.
"""
@classmethod
def generated(
cls,
config: MkDocsConfig,
src_uri: str,
*,
content: str | bytes | None = None,
abs_src_path: str | None = None,
inclusion: InclusionLevel = InclusionLevel.UNDEFINED,
) -> File:
"""
Create a virtual file, backed either by in-memory `content` or by a file at `abs_src_path`.
It will pretend to be a file in the docs dir at `src_uri`.
"""
if (content is None) == (abs_src_path is None):
raise TypeError("File must have exactly one of 'content' or 'abs_src_path'")
f = cls(
src_uri,
src_dir=None,
dest_dir=config.site_dir,
use_directory_urls=config.use_directory_urls,
inclusion=inclusion,
)
f.generated_by = config.plugins._current_plugin or '<unknown>'
f.abs_src_path = abs_src_path
f._content = content
return f
def __init__(
self,
path: str,
src_dir: str | None,
dest_dir: str,
use_directory_urls: bool,
*,
dest_uri: str | None = None,
inclusion: InclusionLevel = InclusionLevel.UNDEFINED,
) -> None:
self.src_path = path
self.src_dir = src_dir
self.dest_dir = dest_dir
self.use_directory_urls = use_directory_urls
if dest_uri is not None:
self.dest_uri = dest_uri
self.inclusion = inclusion
def __repr__(self):
return (
f"{type(self).__name__}({self.src_uri!r}, src_dir={self.src_dir!r}, "
f"dest_dir={self.dest_dir!r}, use_directory_urls={self.use_directory_urls!r}, "
f"dest_uri={self.dest_uri!r}, inclusion={self.inclusion})"
)
@utils.weak_property
def edit_uri(self) -> str | None:
"""
A path relative to the source repository to use for the "edit" button.
Defaults to `src_uri` and can be overwritten.
For generated files this should be set to `None`.
"""
return self.src_uri if self.generated_by is None else None
def _get_stem(self) -> str:
"""Soft-deprecated, do not use."""
filename = posixpath.basename(self.src_uri)
stem, ext = posixpath.splitext(filename)
return 'index' if stem == 'README' else stem
name = cached_property(_get_stem)
"""Return the name of the file without its extension."""
def _get_dest_path(self, use_directory_urls: bool | None = None) -> str:
"""Soft-deprecated, do not use."""
if self.is_documentation_page():
parent, filename = posixpath.split(self.src_uri)
if use_directory_urls is None:
use_directory_urls = self.use_directory_urls
if not use_directory_urls or self.name == 'index':
# index.md or README.md => index.html
# foo.md => foo.html
return posixpath.join(parent, self.name + '.html')
else:
# foo.md => foo/index.html
return posixpath.join(parent, self.name, 'index.html')
return self.src_uri
dest_uri = cached_property(_get_dest_path)
"""The pure path (always '/'-separated) of the destination file relative to the destination directory."""
def _get_url(self, use_directory_urls: bool | None = None) -> str:
"""Soft-deprecated, do not use."""
url = self.dest_uri
dirname, filename = posixpath.split(url)
if use_directory_urls is None:
use_directory_urls = self.use_directory_urls
if use_directory_urls and filename == 'index.html':
url = (dirname or '.') + '/'
return urlquote(url)
url = cached_property(_get_url)
"""The URI of the destination file relative to the destination directory as a string."""
@cached_property
def abs_src_path(self) -> str | None:
"""
The absolute concrete path of the source file. Will use backslashes on Windows.
Note: do not use this path to read the file, prefer `content_bytes`/`content_string`.
"""
if self.src_dir is None:
return None
return os.path.normpath(os.path.join(self.src_dir, self.src_uri))
@cached_property
def abs_dest_path(self) -> str:
"""The absolute concrete path of the destination file. Will use backslashes on Windows."""
return os.path.normpath(os.path.join(self.dest_dir, self.dest_uri))
def url_relative_to(self, other: File | str) -> str:
"""Return url for file relative to other file."""
return utils.get_relative_url(self.url, other.url if isinstance(other, File) else other)
@property
def content_bytes(self) -> bytes:
"""
Get the content of this file as a bytestring.
May raise if backed by a real file (`abs_src_path`) if it cannot be read.
If used as a setter, it defines the content of the file, and `abs_src_path` becomes unset.
"""
content = self._content
if content is None:
assert self.abs_src_path is not None
with open(self.abs_src_path, 'rb') as f:
return f.read()
if not isinstance(content, bytes):
content = content.encode()
return content
@content_bytes.setter
def content_bytes(self, value: bytes):
assert isinstance(value, bytes)
self._content = value
self.abs_src_path = None
@property
def content_string(self) -> str:
"""
Get the content of this file as a string. Assumes UTF-8 encoding, may raise.
May also raise if backed by a real file (`abs_src_path`) if it cannot be read.
If used as a setter, it defines the content of the file, and `abs_src_path` becomes unset.
"""
content = self._content
if content is None:
assert self.abs_src_path is not None
with open(self.abs_src_path, encoding='utf-8-sig', errors='strict') as f:
return f.read()
if not isinstance(content, str):
content = content.decode('utf-8-sig', errors='strict')
return content
@content_string.setter
def content_string(self, value: str):
assert isinstance(value, str)
self._content = value
self.abs_src_path = None
def copy_file(self, dirty: bool = False) -> None:
"""Copy source file to destination, ensuring parent directories exist."""
if dirty and not self.is_modified():
log.debug(f"Skip copying unmodified file: '{self.src_uri}'")
return
log.debug(f"Copying media file: '{self.src_uri}'")
output_path = self.abs_dest_path
os.makedirs(os.path.dirname(output_path), exist_ok=True)
content = self._content
if content is None:
assert self.abs_src_path is not None
try:
utils.copy_file(self.abs_src_path, output_path)
except shutil.SameFileError:
pass # Let plugins write directly into site_dir.
elif isinstance(content, str):
with open(output_path, 'w', encoding='utf-8') as output_file:
output_file.write(content)
else:
with open(output_path, 'wb') as output_file:
output_file.write(content)
def is_modified(self) -> bool:
if self._content is not None:
return True
assert self.abs_src_path is not None
if os.path.isfile(self.abs_dest_path):
return os.path.getmtime(self.abs_dest_path) < os.path.getmtime(self.abs_src_path)
return True
def is_documentation_page(self) -> bool:
"""Return True if file is a Markdown page."""
return utils.is_markdown_file(self.src_uri)
def is_static_page(self) -> bool:
"""Return True if file is a static page (HTML, XML, JSON)."""
return self.src_uri.endswith(('.html', '.htm', '.xml', '.json'))
def is_media_file(self) -> bool:
"""Return True if file is not a documentation or static page."""
return not (self.is_documentation_page() or self.is_static_page())
def is_javascript(self) -> bool:
"""Return True if file is a JavaScript file."""
return self.src_uri.endswith(('.js', '.javascript', '.mjs'))
def is_css(self) -> bool:
"""Return True if file is a CSS file."""
return self.src_uri.endswith('.css')
_default_exclude = pathspec.gitignore.GitIgnoreSpec.from_lines(['.*', '/templates/'])
def set_exclusions(files: Iterable[File], config: MkDocsConfig) -> None:
"""Re-calculate which files are excluded, based on the patterns in the config."""
exclude: pathspec.gitignore.GitIgnoreSpec | None = config.get('exclude_docs')
exclude = _default_exclude + exclude if exclude else _default_exclude
drafts: pathspec.gitignore.GitIgnoreSpec | None = config.get('draft_docs')
nav_exclude: pathspec.gitignore.GitIgnoreSpec | None = config.get('not_in_nav')
for file in files:
if file.inclusion == InclusionLevel.UNDEFINED:
if exclude.match_file(file.src_uri):
file.inclusion = InclusionLevel.EXCLUDED
elif drafts and drafts.match_file(file.src_uri):
file.inclusion = InclusionLevel.DRAFT
elif nav_exclude and nav_exclude.match_file(file.src_uri):
file.inclusion = InclusionLevel.NOT_IN_NAV
else:
file.inclusion = InclusionLevel.INCLUDED
def get_files(config: MkDocsConfig) -> Files:
"""Walk the `docs_dir` and return a Files collection."""
files: list[File] = []
conflicting_files: list[tuple[File, File]] = []
for source_dir, dirnames, filenames in os.walk(config['docs_dir'], followlinks=True):
relative_dir = os.path.relpath(source_dir, config['docs_dir'])
dirnames.sort()
filenames.sort(key=_file_sort_key)
files_by_dest: dict[str, File] = {}
for filename in filenames:
file = File(
os.path.join(relative_dir, filename),
config['docs_dir'],
config['site_dir'],
config['use_directory_urls'],
)
# Skip README.md if an index file also exists in dir (part 1)
prev_file = files_by_dest.setdefault(file.dest_uri, file)
if prev_file is not file:
conflicting_files.append((prev_file, file))
files.append(file)
prev_file = file
set_exclusions(files, config)
# Skip README.md if an index file also exists in dir (part 2)
for a, b in conflicting_files:
if b.inclusion.is_included():
if a.inclusion.is_included():
log.warning(
f"Excluding '{a.src_uri}' from the site because it conflicts with '{b.src_uri}'."
)
try:
files.remove(a)
except ValueError:
pass # Catching this to avoid errors if attempting to remove the same file twice.
else:
try:
files.remove(b)
except ValueError:
pass
return Files(files)
def file_sort_key(f: File, /):
"""
Replicates the sort order how `get_files` produces it - index first, directories last.
To sort a list of `File`, pass as the `key` argument to `sort`.
"""
parts = PurePosixPath(f.src_uri).parts
if not parts:
return ()
return (parts[:-1], f.name != "index", parts[-1])
def _file_sort_key(f: str):
"""Always sort `index` or `README` as first filename in list. This works only on basenames of files."""
return (os.path.splitext(f)[0] not in ('index', 'README'), f)
def _sort_files(filenames: Iterable[str]) -> list[str]:
"""Soft-deprecated, do not use."""
return sorted(filenames, key=_file_sort_key)
def _filter_paths(basename: str, path: str, is_dir: bool, exclude: Iterable[str]) -> bool:
warnings.warn(
"_filter_paths is not used since MkDocs 1.5 and will be removed soon.", DeprecationWarning
)
for item in exclude:
# Items ending in '/' apply only to directories.
if item.endswith('/') and not is_dir:
continue
# Items starting with '/' apply to the whole path.
# In any other cases just the basename is used.
match = path if item.startswith('/') else basename
if fnmatch.fnmatch(match, item.strip('/')):
return True
return False
@@ -0,0 +1,251 @@
from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Iterator, TypeVar
from urllib.parse import urlsplit
from mkdocs.exceptions import BuildError
from mkdocs.structure import StructureItem
from mkdocs.structure.files import file_sort_key
from mkdocs.structure.pages import Page, _AbsoluteLinksValidationValue
from mkdocs.utils import nest_paths
if TYPE_CHECKING:
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import Files
log = logging.getLogger(__name__)
class Navigation:
def __init__(self, items: list, pages: list[Page]) -> None:
self.items = items # Nested List with full navigation of Sections, Pages, and Links.
self.pages = pages # Flat List of subset of Pages in nav, in order.
self.homepage = None
for page in pages:
if page.is_homepage:
self.homepage = page
break
homepage: Page | None
"""The [page][mkdocs.structure.pages.Page] object for the homepage of the site."""
pages: list[Page]
"""A flat list of all [page][mkdocs.structure.pages.Page] objects contained in the navigation."""
def __str__(self) -> str:
return '\n'.join(item._indent_print() for item in self)
def __iter__(self) -> Iterator:
return iter(self.items)
def __len__(self) -> int:
return len(self.items)
class Section(StructureItem):
def __init__(self, title: str, children: list[StructureItem]) -> None:
self.title = title
self.children = children
self.active = False
def __repr__(self):
name = self.__class__.__name__
return f"{name}(title={self.title!r})"
title: str
"""The title of the section."""
children: list[StructureItem]
"""An iterable of all child navigation objects. Children may include nested sections, pages and links."""
@property
def active(self) -> bool:
"""
When `True`, indicates that a child page of this section is the current page and
can be used to highlight the section as the currently viewed section. Defaults
to `False`.
"""
return self.__active
@active.setter
def active(self, value: bool):
"""Set active status of section and ancestors."""
self.__active = bool(value)
if self.parent is not None:
self.parent.active = bool(value)
is_section: bool = True
"""Indicates that the navigation object is a "section" object. Always `True` for section objects."""
is_page: bool = False
"""Indicates that the navigation object is a "page" object. Always `False` for section objects."""
is_link: bool = False
"""Indicates that the navigation object is a "link" object. Always `False` for section objects."""
def _indent_print(self, depth: int = 0) -> str:
ret = [super()._indent_print(depth)]
for item in self.children:
ret.append(item._indent_print(depth + 1))
return '\n'.join(ret)
class Link(StructureItem):
def __init__(self, title: str, url: str):
self.title = title
self.url = url
def __repr__(self):
name = self.__class__.__name__
title = f"{self.title!r}" if self.title is not None else '[blank]'
return f"{name}(title={title}, url={self.url!r})"
title: str
"""The title of the link. This would generally be used as the label of the link."""
url: str
"""The URL that the link points to. The URL should always be an absolute URLs and
should not need to have `base_url` prepended."""
children: None = None
"""Links do not contain children and the attribute is always `None`."""
active: bool = False
"""External links cannot be "active" and the attribute is always `False`."""
is_section: bool = False
"""Indicates that the navigation object is a "section" object. Always `False` for link objects."""
is_page: bool = False
"""Indicates that the navigation object is a "page" object. Always `False` for link objects."""
is_link: bool = True
"""Indicates that the navigation object is a "link" object. Always `True` for link objects."""
def get_navigation(files: Files, config: MkDocsConfig) -> Navigation:
"""Build site navigation from config and files."""
documentation_pages = files.documentation_pages()
nav_config = config['nav']
if nav_config is None:
documentation_pages = sorted(documentation_pages, key=file_sort_key)
nav_config = nest_paths(f.src_uri for f in documentation_pages if f.inclusion.is_in_nav())
items = _data_to_navigation(nav_config, files, config)
if not isinstance(items, list):
items = [items]
# Get only the pages from the navigation, ignoring any sections and links.
pages = _get_by_type(items, Page)
# Include next, previous and parent links.
_add_previous_and_next_links(pages)
_add_parent_links(items)
missing_from_config = []
for file in documentation_pages:
if file.page is None:
# Any documentation files not found in the nav should still have an associated page, so we
# create them here. The Page object will automatically be assigned to `file.page` during
# its creation (and this is the only way in which these page objects are accessible).
Page(None, file, config)
if file.inclusion.is_in_nav():
missing_from_config.append(file.src_path)
if missing_from_config:
log.log(
config.validation.nav.omitted_files,
'The following pages exist in the docs directory, but are not '
'included in the "nav" configuration:\n - ' + '\n - '.join(missing_from_config),
)
links = _get_by_type(items, Link)
for link in links:
scheme, netloc, path, query, fragment = urlsplit(link.url)
if scheme or netloc:
log.debug(f"An external link to '{link.url}' is included in the 'nav' configuration.")
elif (
link.url.startswith('/')
and config.validation.nav.absolute_links
is not _AbsoluteLinksValidationValue.RELATIVE_TO_DOCS
):
log.log(
config.validation.nav.absolute_links,
f"An absolute path to '{link.url}' is included in the 'nav' "
"configuration, which presumably points to an external resource.",
)
else:
log.log(
config.validation.nav.not_found,
f"A reference to '{link.url}' is included in the 'nav' "
"configuration, which is not found in the documentation files.",
)
return Navigation(items, pages)
def _data_to_navigation(data, files: Files, config: MkDocsConfig):
if isinstance(data, dict):
return [
_data_to_navigation((key, value), files, config)
if isinstance(value, str)
else Section(title=key, children=_data_to_navigation(value, files, config))
for key, value in data.items()
]
elif isinstance(data, list):
return [
_data_to_navigation(item, files, config)[0]
if isinstance(item, dict) and len(item) == 1
else _data_to_navigation(item, files, config)
for item in data
]
title, path = data if isinstance(data, tuple) else (None, data)
lookup_path = path
if (
lookup_path.startswith('/')
and config.validation.nav.absolute_links is _AbsoluteLinksValidationValue.RELATIVE_TO_DOCS
):
lookup_path = lookup_path.lstrip('/')
if file := files.get_file_from_path(lookup_path):
if file.inclusion.is_excluded():
log.log(
min(logging.INFO, config.validation.nav.not_found),
f"A reference to '{file.src_path}' is included in the 'nav' "
"configuration, but this file is excluded from the built site.",
)
page = file.page
if page is not None:
if not isinstance(page, Page):
raise BuildError("A plugin has set File.page to a type other than Page.")
return page
return Page(title, file, config)
return Link(title, path)
T = TypeVar('T')
def _get_by_type(nav, t: type[T]) -> list[T]:
ret = []
for item in nav:
if isinstance(item, t):
ret.append(item)
if item.children:
ret.extend(_get_by_type(item.children, t))
return ret
def _add_parent_links(nav) -> None:
for item in nav:
if item.is_section:
for child in item.children:
child.parent = item
_add_parent_links(item.children)
def _add_previous_and_next_links(pages: list[Page]) -> None:
bookended = [None, *pages, None]
zipped = zip(bookended[:-2], pages, bookended[2:])
for page0, page1, page2 in zipped:
page1.previous_page, page1.next_page = page0, page2
@@ -0,0 +1,569 @@
from __future__ import annotations
import enum
import logging
import posixpath
import warnings
from typing import TYPE_CHECKING, Any, Callable, Iterator, MutableMapping, Sequence
from urllib.parse import unquote as urlunquote
from urllib.parse import urljoin, urlsplit, urlunsplit
import markdown
import markdown.extensions.toc
import markdown.htmlparser # type: ignore
import markdown.postprocessors
import markdown.treeprocessors
from markdown.util import AMP_SUBSTITUTE
from mkdocs import utils
from mkdocs.structure import StructureItem
from mkdocs.structure.toc import get_toc
from mkdocs.utils import _removesuffix, get_build_date, get_markdown_title, meta, weak_property
from mkdocs.utils.rendering import get_heading_text
if TYPE_CHECKING:
from xml.etree import ElementTree as etree
from mkdocs.config.defaults import MkDocsConfig
from mkdocs.structure.files import File, Files
from mkdocs.structure.toc import TableOfContents
log = logging.getLogger(__name__)
class Page(StructureItem):
def __init__(self, title: str | None, file: File, config: MkDocsConfig) -> None:
file.page = self
self.file = file
if title is not None:
self.title = title
# Navigation attributes
self.children = None
self.previous_page = None
self.next_page = None
self.active = False
self.update_date: str = get_build_date()
self._set_canonical_url(config.get('site_url', None))
self._set_edit_url(
config.get('repo_url', None), config.get('edit_uri'), config.get('edit_uri_template')
)
# Placeholders to be filled in later in the build process.
self.markdown = None
self._title_from_render: str | None = None
self.content = None
self.toc = [] # type: ignore
self.meta = {}
def __eq__(self, other) -> bool:
return (
isinstance(other, self.__class__)
and self.title == other.title
and self.file == other.file
)
def __repr__(self):
name = self.__class__.__name__
title = f"{self.title!r}" if self.title is not None else '[blank]'
url = self.abs_url or self.file.url
return f"{name}(title={title}, url={url!r})"
markdown: str | None
"""The original Markdown content from the file."""
content: str | None
"""The rendered Markdown as HTML, this is the contents of the documentation.
Populated after `.render()`."""
toc: TableOfContents
"""An iterable object representing the Table of contents for a page. Each item in
the `toc` is an [`AnchorLink`][mkdocs.structure.toc.AnchorLink]."""
meta: MutableMapping[str, Any]
"""A mapping of the metadata included at the top of the markdown page."""
@property
def url(self) -> str:
"""The URL of the page relative to the MkDocs `site_dir`."""
url = self.file.url
if url in ('.', './'):
return ''
return url
file: File
"""The documentation [`File`][mkdocs.structure.files.File] that the page is being rendered from."""
abs_url: str | None
"""The absolute URL of the page from the server root as determined by the value
assigned to the [site_url][] configuration setting. The value includes any
subdirectory included in the `site_url`, but not the domain. [base_url][] should
not be used with this variable."""
canonical_url: str | None
"""The full, canonical URL to the current page as determined by the value assigned
to the [site_url][] configuration setting. The value includes the domain and any
subdirectory included in the `site_url`. [base_url][] should not be used with this
variable."""
@property
def active(self) -> bool:
"""When `True`, indicates that this page is the currently viewed page. Defaults to `False`."""
return self.__active
@active.setter
def active(self, value: bool):
"""Set active status of page and ancestors."""
self.__active = bool(value)
if self.parent is not None:
self.parent.active = bool(value)
@property
def is_index(self) -> bool:
return self.file.name == 'index'
edit_url: str | None
"""The full URL to the source page in the source repository. Typically used to
provide a link to edit the source page. [base_url][] should not be used with this
variable."""
@property
def is_homepage(self) -> bool:
"""Evaluates to `True` for the homepage of the site and `False` for all other pages."""
return self.is_top_level and self.is_index and self.file.url in ('.', './', 'index.html')
previous_page: Page | None
"""The [page][mkdocs.structure.pages.Page] object for the previous page or `None`.
The value will be `None` if the current page is the first item in the site navigation
or if the current page is not included in the navigation at all."""
next_page: Page | None
"""The [page][mkdocs.structure.pages.Page] object for the next page or `None`.
The value will be `None` if the current page is the last item in the site navigation
or if the current page is not included in the navigation at all."""
children: None = None
"""Pages do not contain children and the attribute is always `None`."""
is_section: bool = False
"""Indicates that the navigation object is a "section" object. Always `False` for page objects."""
is_page: bool = True
"""Indicates that the navigation object is a "page" object. Always `True` for page objects."""
is_link: bool = False
"""Indicates that the navigation object is a "link" object. Always `False` for page objects."""
def _set_canonical_url(self, base: str | None) -> None:
if base:
if not base.endswith('/'):
base += '/'
self.canonical_url = canonical_url = urljoin(base, self.url)
self.abs_url = urlsplit(canonical_url).path
else:
self.canonical_url = None
self.abs_url = None
def _set_edit_url(
self,
repo_url: str | None,
edit_uri: str | None = None,
edit_uri_template: str | None = None,
) -> None:
if not edit_uri_template and not edit_uri:
self.edit_url = None
return
src_uri = self.file.edit_uri
if src_uri is None:
self.edit_url = None
return
if edit_uri_template:
noext = posixpath.splitext(src_uri)[0]
file_edit_uri = edit_uri_template.format(path=src_uri, path_noext=noext)
else:
assert edit_uri is not None and edit_uri.endswith('/')
file_edit_uri = edit_uri + src_uri
if repo_url:
# Ensure urljoin behavior is correct
if not file_edit_uri.startswith(('?', '#')) and not repo_url.endswith('/'):
repo_url += '/'
else:
try:
parsed_url = urlsplit(file_edit_uri)
if not parsed_url.scheme or not parsed_url.netloc:
log.warning(
f"edit_uri: {file_edit_uri!r} is not a valid URL, it should include the http:// (scheme)"
)
except ValueError as e:
log.warning(f"edit_uri: {file_edit_uri!r} is not a valid URL: {e}")
self.edit_url = urljoin(repo_url or '', file_edit_uri)
def read_source(self, config: MkDocsConfig) -> None:
source = config.plugins.on_page_read_source(page=self, config=config)
if source is None:
try:
source = self.file.content_string
except OSError:
log.error(f'File not found: {self.file.src_path}')
raise
except ValueError:
log.error(f'Encoding error reading file: {self.file.src_path}')
raise
self.markdown, self.meta = meta.get_data(source)
def _set_title(self) -> None:
warnings.warn(
"_set_title is no longer used in MkDocs and will be removed soon.", DeprecationWarning
)
@weak_property
def title(self) -> str | None: # type: ignore[override]
"""
Returns the title for the current page.
Before calling `read_source()`, this value is empty. It can also be updated by `render()`.
Checks these in order and uses the first that returns a valid title:
- value provided on init (passed in from config)
- value of metadata 'title'
- content of the first H1 in Markdown content
- convert filename to title
"""
if self.markdown is None:
return None
if 'title' in self.meta:
return self.meta['title']
if self._title_from_render:
return self._title_from_render
elif self.content is None: # Preserve legacy behavior only for edge cases in plugins.
title_from_md = get_markdown_title(self.markdown)
if title_from_md is not None:
return title_from_md
if self.is_homepage:
return 'Home'
title = self.file.name.replace('-', ' ').replace('_', ' ')
# Capitalize if the filename was all lowercase, otherwise leave it as-is.
if title.lower() == title:
title = title.capitalize()
return title
def render(self, config: MkDocsConfig, files: Files) -> None:
"""Convert the Markdown source file to HTML as per the config."""
if self.markdown is None:
raise RuntimeError("`markdown` field hasn't been set (via `read_source`)")
md = markdown.Markdown(
extensions=config['markdown_extensions'],
extension_configs=config['mdx_configs'] or {},
)
raw_html_ext = _RawHTMLPreprocessor()
raw_html_ext._register(md)
extract_anchors_ext = _ExtractAnchorsTreeprocessor(self.file, files, config)
extract_anchors_ext._register(md)
relative_path_ext = _RelativePathTreeprocessor(self.file, files, config)
relative_path_ext._register(md)
extract_title_ext = _ExtractTitleTreeprocessor()
extract_title_ext._register(md)
self.content = md.convert(self.markdown)
self.toc = get_toc(getattr(md, 'toc_tokens', []))
self._title_from_render = extract_title_ext.title
self.present_anchor_ids = (
extract_anchors_ext.present_anchor_ids | raw_html_ext.present_anchor_ids
)
if log.getEffectiveLevel() > logging.DEBUG:
self.links_to_anchors = relative_path_ext.links_to_anchors
present_anchor_ids: set[str] | None = None
"""Anchor IDs that this page contains (can be linked to in this page)."""
links_to_anchors: dict[File, dict[str, str]] | None = None
"""Links to anchors in other files that this page contains.
The structure is: `{file_that_is_linked_to: {'anchor': 'original_link/to/some_file.md#anchor'}}`.
Populated after `.render()`. Populated only if `validation: {anchors: info}` (or greater) is set.
"""
def validate_anchor_links(self, *, files: Files, log_level: int) -> None:
if not self.links_to_anchors:
return
for to_file, links in self.links_to_anchors.items():
for anchor, original_link in links.items():
page = to_file.page
if page is None:
continue
if page.present_anchor_ids is None: # Page was somehow not rendered.
continue
if anchor in page.present_anchor_ids:
continue
context = ""
if to_file == self.file:
problem = "there is no such anchor on this page"
if anchor.startswith('fnref:'):
context = " This seems to be a footnote that is never referenced."
else:
problem = f"the doc '{to_file.src_uri}' does not contain an anchor '#{anchor}'"
log.log(
log_level,
f"Doc file '{self.file.src_uri}' contains a link '{original_link}', but {problem}.{context}",
)
class _ExtractAnchorsTreeprocessor(markdown.treeprocessors.Treeprocessor):
def __init__(self, file: File, files: Files, config: MkDocsConfig) -> None:
self.present_anchor_ids: set[str] = set()
def run(self, root: etree.Element) -> None:
add = self.present_anchor_ids.add
for element in root.iter():
if anchor := element.get('id'):
add(anchor)
if element.tag == 'a':
if anchor := element.get('name'):
add(anchor)
def _register(self, md: markdown.Markdown) -> None:
md.treeprocessors.register(self, "mkdocs_extract_anchors", priority=5) # Same as 'toc'.
class _RelativePathTreeprocessor(markdown.treeprocessors.Treeprocessor):
def __init__(self, file: File, files: Files, config: MkDocsConfig) -> None:
self.file = file
self.files = files
self.config = config
self.links_to_anchors: dict[File, dict[str, str]] = {}
def run(self, root: etree.Element) -> etree.Element:
"""
Update urls on anchors and images to make them relative.
Iterates through the full document tree looking for specific
tags and then makes them relative based on the site navigation
"""
for element in root.iter():
if element.tag == 'a':
key = 'href'
elif element.tag == 'img':
key = 'src'
else:
continue
url = element.get(key)
assert url is not None
new_url = self.path_to_url(url)
element.set(key, new_url)
return root
@classmethod
def _target_uri(cls, src_path: str, dest_path: str) -> str:
return posixpath.normpath(
posixpath.join(posixpath.dirname(src_path), dest_path).lstrip('/')
)
@classmethod
def _possible_target_uris(
cls, file: File, path: str, use_directory_urls: bool, suggest_absolute: bool = False
) -> Iterator[str]:
"""First yields the resolved file uri for the link, then proceeds to yield guesses for possible mistakes."""
target_uri = cls._target_uri(file.src_uri, path)
yield target_uri
if posixpath.normpath(path) == '.':
# Explicitly link to current file.
yield file.src_uri
return
tried = {target_uri}
prefixes = [target_uri, cls._target_uri(file.url, path)]
if prefixes[0] == prefixes[1]:
prefixes.pop()
suffixes: list[Callable[[str], str]] = []
if use_directory_urls:
suffixes.append(lambda p: p)
if not posixpath.splitext(target_uri)[-1]:
suffixes.append(lambda p: posixpath.join(p, 'index.md'))
suffixes.append(lambda p: posixpath.join(p, 'README.md'))
if (
not target_uri.endswith('.')
and not path.endswith('.md')
and (use_directory_urls or not path.endswith('/'))
):
suffixes.append(lambda p: _removesuffix(p, '.html') + '.md')
for pref in prefixes:
for suf in suffixes:
guess = posixpath.normpath(suf(pref))
if guess not in tried and not guess.startswith('../'):
yield guess
tried.add(guess)
def path_to_url(self, url: str) -> str:
scheme, netloc, path, query, anchor = urlsplit(url)
absolute_link = None
warning_level, warning = 0, ''
# Ignore URLs unless they are a relative link to a source file.
if scheme or netloc: # External link.
return url
elif url.startswith(('/', '\\')): # Absolute link.
absolute_link = self.config.validation.links.absolute_links
if absolute_link is not _AbsoluteLinksValidationValue.RELATIVE_TO_DOCS:
warning_level = absolute_link
warning = f"Doc file '{self.file.src_uri}' contains an absolute link '{url}', it was left as is."
elif AMP_SUBSTITUTE in url: # AMP_SUBSTITUTE is used internally by Markdown only for email.
return url
elif not path: # Self-link containing only query or anchor.
if anchor:
# Register that the page links to itself with an anchor.
self.links_to_anchors.setdefault(self.file, {}).setdefault(anchor, url)
return url
path = urlunquote(path)
# Determine the filepath of the target.
possible_target_uris = self._possible_target_uris(
self.file, path, self.config.use_directory_urls
)
if warning:
# For absolute path (already has a warning), the primary lookup path should be preserved as a tip option.
target_uri = url
target_file = None
else:
# Validate that the target exists in files collection.
target_uri = next(possible_target_uris)
target_file = self.files.get_file_from_path(target_uri)
if target_file is None and not warning:
# Primary lookup path had no match, definitely produce a warning, just choose which one.
if not posixpath.splitext(path)[-1] and absolute_link is None:
# No '.' in the last part of a path indicates path does not point to a file.
warning_level = self.config.validation.links.unrecognized_links
warning = (
f"Doc file '{self.file.src_uri}' contains an unrecognized relative link '{url}', "
f"it was left as is."
)
else:
target = f" '{target_uri}'" if target_uri != url.lstrip('/') else ""
warning_level = self.config.validation.links.not_found
warning = (
f"Doc file '{self.file.src_uri}' contains a link '{url}', "
f"but the target{target} is not found among documentation files."
)
if warning:
if self.file.inclusion.is_excluded():
warning_level = min(logging.INFO, warning_level)
# There was no match, so try to guess what other file could've been intended.
if warning_level > logging.DEBUG:
suggest_url = ''
for path in possible_target_uris:
if self.files.get_file_from_path(path) is not None:
if anchor and path == self.file.src_uri:
path = ''
elif absolute_link is _AbsoluteLinksValidationValue.RELATIVE_TO_DOCS:
path = '/' + path
else:
path = utils.get_relative_url(path, self.file.src_uri)
suggest_url = urlunsplit(('', '', path, query, anchor))
break
else:
if '@' in url and '.' in url and '/' not in url:
suggest_url = f'mailto:{url}'
if suggest_url:
warning += f" Did you mean '{suggest_url}'?"
log.log(warning_level, warning)
return url
assert target_uri is not None
assert target_file is not None
if anchor:
# Register that this page links to the target file with an anchor.
self.links_to_anchors.setdefault(target_file, {}).setdefault(anchor, url)
if target_file.inclusion.is_excluded():
if self.file.inclusion.is_excluded():
warning_level = logging.DEBUG
else:
warning_level = min(logging.INFO, self.config.validation.links.not_found)
warning = (
f"Doc file '{self.file.src_uri}' contains a link to "
f"'{target_uri}' which is excluded from the built site."
)
log.log(warning_level, warning)
path = utils.get_relative_url(target_file.url, self.file.url)
return urlunsplit(('', '', path, query, anchor))
def _register(self, md: markdown.Markdown) -> None:
md.treeprocessors.register(self, "relpath", 0)
class _RawHTMLPreprocessor(markdown.preprocessors.Preprocessor):
def __init__(self) -> None:
super().__init__()
self.present_anchor_ids: set[str] = set()
def run(self, lines: list[str]) -> list[str]:
parser = _HTMLHandler()
parser.feed('\n'.join(lines))
parser.close()
self.present_anchor_ids = parser.present_anchor_ids
return lines
def _register(self, md: markdown.Markdown) -> None:
md.preprocessors.register(
self, "mkdocs_raw_html", priority=21 # Right before 'html_block'.
)
class _HTMLHandler(markdown.htmlparser.htmlparser.HTMLParser): # type: ignore[name-defined]
def __init__(self) -> None:
super().__init__()
self.present_anchor_ids: set[str] = set()
def handle_starttag(self, tag: str, attrs: Sequence[tuple[str, str]]) -> None:
for k, v in attrs:
if k == 'id' or (k == 'name' and tag == 'a'):
self.present_anchor_ids.add(v)
return super().handle_starttag(tag, attrs)
class _ExtractTitleTreeprocessor(markdown.treeprocessors.Treeprocessor):
title: str | None = None
md: markdown.Markdown
def run(self, root: etree.Element) -> etree.Element:
for el in root:
if el.tag == 'h1':
self.title = get_heading_text(el, self.md)
break
return root
def _register(self, md: markdown.Markdown) -> None:
self.md = md
md.treeprocessors.register(self, "mkdocs_extract_title", priority=1) # Close to the end.
class _AbsoluteLinksValidationValue(enum.IntEnum):
RELATIVE_TO_DOCS = -1
@@ -0,0 +1,80 @@
"""
Deals with generating the per-page table of contents.
For the sake of simplicity we use the Python-Markdown `toc` extension to
generate a list of dicts for each toc item, and then store it as AnchorLinks to
maintain compatibility with older versions of MkDocs.
"""
from __future__ import annotations
from typing import Iterable, Iterator, TypedDict
class _TocToken(TypedDict):
level: int
id: str
name: str
children: list[_TocToken]
def get_toc(toc_tokens: list[_TocToken]) -> TableOfContents:
toc = [_parse_toc_token(i) for i in toc_tokens]
# For the table of contents, always mark the first element as active
if len(toc):
toc[0].active = True # type: ignore[attr-defined]
return TableOfContents(toc)
class AnchorLink:
"""A single entry in the table of contents."""
def __init__(self, title: str, id: str, level: int) -> None:
self.title, self.id, self.level = title, id, level
self.children = []
title: str
"""The text of the item, as HTML."""
@property
def url(self) -> str:
"""The hash fragment of a URL pointing to the item."""
return '#' + self.id
level: int
"""The zero-based level of the item."""
children: list[AnchorLink]
"""An iterable of any child items."""
def __str__(self) -> str:
return self.indent_print()
def indent_print(self, depth: int = 0) -> str:
indent = ' ' * depth
ret = f'{indent}{self.title} - {self.url}\n'
for item in self.children:
ret += item.indent_print(depth + 1)
return ret
class TableOfContents(Iterable[AnchorLink]):
"""Represents the table of contents for a given page."""
def __init__(self, items: list[AnchorLink]) -> None:
self.items = items
def __iter__(self) -> Iterator[AnchorLink]:
return iter(self.items)
def __len__(self) -> int:
return len(self.items)
def __str__(self) -> str:
return ''.join(str(item) for item in self)
def _parse_toc_token(token: _TocToken) -> AnchorLink:
anchor = AnchorLink(token['name'], token['id'], token['level'])
for i in token['children']:
anchor.children.append(_parse_toc_token(i))
return anchor
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{%- for file in pages -%}
{% if not file.page.is_link and (file.page.abs_url or file.page.canonical_url) %}
<url>
<loc>{% if file.page.canonical_url %}{{ file.page.canonical_url|e }}{% else %}{{ file.page.abs_url|e }}{% endif %}</loc>
{% if file.page.update_date %}<lastmod>{{file.page.update_date}}</lastmod>{% endif %}
</url>
{%- endif -%}
{% endfor %}
</urlset>
@@ -0,0 +1,166 @@
from __future__ import annotations
import logging
import os
import warnings
from typing import Any, Collection, MutableMapping
import jinja2
import yaml
try:
from yaml import CSafeLoader as SafeLoader
except ImportError: # pragma: no cover
from yaml import SafeLoader # type: ignore
from mkdocs import localization, utils
from mkdocs.config.base import ValidationError
from mkdocs.utils import templates
log = logging.getLogger(__name__)
class Theme(MutableMapping[str, Any]):
"""
A Theme object.
Args:
name: The name of the theme as defined by its entrypoint.
custom_dir: User defined directory for custom templates.
static_templates: A list of templates to render as static pages.
All other keywords are passed as-is and made available as a key/value mapping.
"""
def __init__(
self,
name: str | None = None,
*,
custom_dir: str | None = None,
static_templates: Collection[str] = (),
locale: str | None = None,
**user_config,
) -> None:
self.name = name
self._custom_dir = custom_dir
_vars: dict[str, Any] = {'name': name, 'locale': 'en'}
self.__vars = _vars
# MkDocs provided static templates are always included
package_dir = os.path.abspath(os.path.dirname(__file__))
mkdocs_templates = os.path.join(package_dir, 'templates')
self.static_templates = set(os.listdir(mkdocs_templates))
# Build self.dirs from various sources in order of precedence
self.dirs = []
if custom_dir is not None:
self.dirs.append(custom_dir)
if name:
self._load_theme_config(name)
# Include templates provided directly by MkDocs (outside any theme)
self.dirs.append(mkdocs_templates)
# Handle remaining user configs. Override theme configs (if set)
self.static_templates.update(static_templates)
_vars.update(user_config)
# Validate locale and convert to Locale object
if locale is None:
locale = _vars['locale']
_vars['locale'] = localization.parse_locale(locale)
name: str | None
@property
def locale(self) -> localization.Locale:
return self['locale']
@property
def custom_dir(self) -> str | None:
return self._custom_dir
@property
def _vars(self) -> dict[str, Any]:
warnings.warn(
"Do not access Theme._vars, instead access the keys of Theme directly.",
DeprecationWarning,
)
return self.__vars
dirs: list[str]
static_templates: set[str]
def __repr__(self) -> str:
return "{}(name={!r}, dirs={!r}, static_templates={!r}, {})".format(
self.__class__.__name__,
self.name,
self.dirs,
self.static_templates,
', '.join(f'{k}={v!r}' for k, v in self.items()),
)
def __getitem__(self, key: str) -> Any:
return self.__vars[key]
def __setitem__(self, key: str, value):
self.__vars[key] = value
def __delitem__(self, key: str):
del self.__vars[key]
def __contains__(self, item: object) -> bool:
return item in self.__vars
def __len__(self):
return len(self.__vars)
def __iter__(self):
return iter(self.__vars)
def _load_theme_config(self, name: str) -> None:
"""Recursively load theme and any parent themes."""
theme_dir = utils.get_theme_dir(name)
utils.get_themes.cache_clear()
self.dirs.append(theme_dir)
try:
file_path = os.path.join(theme_dir, 'mkdocs_theme.yml')
with open(file_path, 'rb') as f:
theme_config = yaml.load(f, SafeLoader)
except OSError as e:
log.debug(e)
raise ValidationError(
f"The theme '{name}' does not appear to have a configuration file. "
f"Please upgrade to a current version of the theme."
)
if theme_config is None:
theme_config = {}
log.debug(f"Loaded theme configuration for '{name}' from '{file_path}': {theme_config}")
if parent_theme := theme_config.pop('extends', None):
themes = utils.get_theme_names()
if parent_theme not in themes:
raise ValidationError(
f"The theme '{name}' inherits from '{parent_theme}', which does not appear to be installed. "
f"The available installed themes are: {', '.join(themes)}"
)
self._load_theme_config(parent_theme)
self.static_templates.update(theme_config.pop('static_templates', []))
self.__vars.update(theme_config)
def get_env(self) -> jinja2.Environment:
"""Return a Jinja environment for the theme."""
loader = jinja2.FileSystemLoader(self.dirs)
# No autoreload because editing a template in the middle of a build is not useful.
env = jinja2.Environment(loader=loader, auto_reload=False)
env.filters['url'] = templates.url_filter
env.filters['script_tag'] = templates.script_tag_filter
localization.install_translations(env, self.locale, self.dirs)
return env
Whitespace-only changes.
@@ -0,0 +1,12 @@
{% extends "base.html" %}
{% block content %}
<div class="row-fluid">
<div id="main-content" class="span12">
<h1 id="404-page-not-found" style="text-align: center">404</h1>
<p style="text-align: center"><strong>{% trans %}Page not found{% endtrans %}</strong></p>
</div>
</div>
{% endblock %}
@@ -0,0 +1,251 @@
<!DOCTYPE html>
<html lang="{{ config.theme.locale|default('en') }}" data-bs-theme="{{ config.theme.color_mode }}">
<head>
{%- block site_meta %}
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
{% if page and page.is_homepage %}<meta name="description" content="{{ config.site_description }}">{% endif %}
{% if config.site_author %}<meta name="author" content="{{ config.site_author }}">{% endif %}
{% if page and page.canonical_url %}<link rel="canonical" href="{{ page.canonical_url }}">{% endif %}
{% if config.site_favicon %}<link rel="shortcut icon" href="{{ config.site_favicon|url }}">
{% else %}<link rel="shortcut icon" href="{{ 'img/favicon.ico'|url }}">{% endif %}
{%- endblock %}
{%- block htmltitle %}
<title>{% if page and page.title and not page.is_homepage %}{{ page.title }} - {% endif %}{{ config.site_name }}</title>
{%- endblock %}
{%- block styles %}
<link href="{{ 'css/bootstrap.min.css'|url }}" rel="stylesheet">
<link href="{{ 'css/fontawesome.min.css'|url }}" rel="stylesheet">
<link href="{{ 'css/brands.min.css'|url }}" rel="stylesheet">
<link href="{{ 'css/solid.min.css'|url }}" rel="stylesheet">
<link href="{{ 'css/v4-font-face.min.css'|url }}" rel="stylesheet">
<link href="{{ 'css/base.css'|url }}" rel="stylesheet">
{%- if config.theme.highlightjs %}
<link id="hljs-light" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/{{ config.theme.hljs_style }}.min.css" {% if config.theme.color_mode != "light" %}disabled{% endif %}>
<link id="hljs-dark" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/{{ config.theme.hljs_style_dark }}.min.css" {% if config.theme.color_mode != "dark" %}disabled{% endif %}>
{%- endif %}
{%- for path in config.extra_css %}
<link href="{{ path|url }}" rel="stylesheet">
{%- endfor %}
{%- endblock %}
{%- block libs %}
{%- if config.theme.highlightjs %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"></script>
{%- for lang in config.theme.hljs_languages %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/languages/{{lang}}.min.js"></script>
{%- endfor %}
<script>hljs.highlightAll();</script>
{%- endif %}
{%- endblock %}
{%- block analytics %}
{%- if config.theme.analytics.gtag %}
<script async src="https://www.googletagmanager.com/gtag/js?id={{ config.theme.analytics.gtag }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', {{ config.theme.analytics.gtag|tojson }});
</script>
{%- elif config.google_analytics %}
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', {{ config.google_analytics[0]|tojson }}, {{ config.google_analytics[1]|tojson }});
ga('send', 'pageview');
</script>
{%- endif %}
{%- endblock %}
{%- block extrahead %} {% endblock %}
</head>
<body{% if page and page.is_homepage %} class="homepage"{% endif %}>
<div class="navbar fixed-top navbar-expand-lg navbar-{% if config.theme.nav_style == "light" %}light{% else %}dark{% endif %} bg-{{ config.theme.nav_style }}">
<div class="container">
{%- block site_name %}
<a class="navbar-brand" href="{{ nav.homepage.url|url }}">{{ config.site_name }}</a>
{%- endblock %}
{%- if nav|length>1 or (page and (page.next_page or page.previous_page)) or config.repo_url %}
<!-- Expander button -->
<button type="button" class="navbar-toggler" data-bs-toggle="collapse" data-bs-target="#navbar-collapse" aria-controls="navbar-collapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
{%- endif %}
<!-- Expanded navigation -->
<div id="navbar-collapse" class="navbar-collapse collapse">
{%- block site_nav %}
{%- if nav|length>1 %}
<!-- Main navigation -->
<ul class="nav navbar-nav">
{%- for nav_item in nav %}
{%- if nav_item.children %}
<li class="nav-item dropdown">
<a href="#" class="nav-link dropdown-toggle{% if nav_item.active %} active" aria-current="page{% endif %}" role="button" data-bs-toggle="dropdown" aria-expanded="false">{{ nav_item.title }}</a>
<ul class="dropdown-menu">
{%- for nav_item in nav_item.children %}
{% include "nav-sub.html" %}
{%- endfor %}
</ul>
</li>
{%- else %}
<li class="nav-item">
<a href="{{ nav_item.url|url }}" class="nav-link{% if nav_item.active %} active" aria-current="page{% endif %}">{{ nav_item.title }}</a>
</li>
{%- endif %}
{%- endfor %}
</ul>
{%- endif %}
{%- endblock %}
<ul class="nav navbar-nav ms-md-auto">
{%- block search_button %}
{%- if 'search' in config.plugins %}
<li class="nav-item">
<a href="#" class="nav-link" data-bs-toggle="modal" data-bs-target="#mkdocs_search_modal">
<i class="fa fa-search"></i> {% trans %}Search{% endtrans %}
</a>
</li>
{%- endif %}
{%- endblock %}
{%- block next_prev %}
{%- if page and (page.next_page or page.previous_page) %}
<li class="nav-item">
<a rel="prev" {% if page.previous_page %}href="{{ page.previous_page.url|url }}" class="nav-link"{% else %}class="nav-link disabled"{% endif %}>
<i class="fa fa-arrow-left"></i> {% trans %}Previous{% endtrans %}
</a>
</li>
<li class="nav-item">
<a rel="next" {% if page.next_page %}href="{{ page.next_page.url|url }}" class="nav-link"{% else %}class="nav-link disabled"{% endif %}>
{% trans %}Next{% endtrans %} <i class="fa fa-arrow-right"></i>
</a>
</li>
{%- endif %}
{%- endblock %}
{%- block repo %}
{%- if page and page.edit_url %}
<li class="nav-item">
<a href="{{ page.edit_url }}" class="nav-link">
{%- if config.repo_name == 'GitHub' -%}
<i class="fa-brands fa-github"></i> {% trans repo_name=config.repo_name %}Edit on {{ repo_name }}{% endtrans %}
{%- elif config.repo_name == 'Bitbucket' -%}
<i class="fa-brands fa-bitbucket"></i> {% trans repo_name=config.repo_name %}Edit on {{ repo_name }}{% endtrans %}
{%- elif config.repo_name == 'GitLab' -%}
<i class="fa-brands fa-gitlab"></i> {% trans repo_name=config.repo_name %}Edit on {{ repo_name }}{% endtrans %}
{%- elif config.repo_name -%}
{% trans repo_name=config.repo_name%}Edit on {{ repo_name }}{% endtrans %}
{% else %}
{% trans repo_name=config.repo_name%}Edit{% endtrans %}
{%- endif -%}
</a>
</li>
{%- elif config.repo_url %}
<li class="nav-item">
<a href="{{ config.repo_url }}" class="nav-link">
{%- if config.repo_name == 'GitHub' -%}
<i class="fa-brands fa-github"></i> {{ config.repo_name }}
{%- elif config.repo_name == 'Bitbucket' -%}
<i class="fa-brands fa-bitbucket"></i> {{ config.repo_name }}
{%- elif config.repo_name == 'GitLab' -%}
<i class="fa-brands fa-gitlab"></i> {{ config.repo_name }}
{%- else -%}
{{ config.repo_name }}
{%- endif -%}
</a>
</li>
{%- endif %}
{%- endblock %}
{%- if config.theme.user_color_mode_toggle %}
<li class="nav-item dropdown">
<button id="theme-menu" aria-expanded="false" data-bs-toggle="dropdown" data-bs-display="static" aria-label="Toggle theme" class="nav-link dropdown-toggle">
<i class="fa-solid fa-circle-half-stroke fa-fw"></i>
<span class="d-lg-none ms-2">Toggle theme</span>
</button>
<ul class="dropdown-menu dropdown-menu-end">
<li>
<button class="dropdown-item d-flex align-items-center" data-bs-theme-value="light" aria-pressed="{% if config.theme.color_mode == 'light' %}true{% else %}false{% endif %}">
<i class="fa-solid fa-sun fa-fw"></i>
<span class="ms-2">Light</span>
<i class="fa-solid fa-check ms-auto{% if config.theme.color_mode != 'light' %} d-none{% endif %}"></i>
</button>
</li>
<li>
<button class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark" aria-pressed="{% if config.theme.color_mode == 'dark' %}true{% else %}false{% endif %}">
<i class="fa-solid fa-moon fa-fw"></i>
<span class="ms-2">Dark</span>
<i class="fa-solid fa-check ms-auto{% if config.theme.color_mode != 'dark' %} d-none{% endif %}"></i>
</button>
</li>
<li>
<button class="dropdown-item d-flex align-items-center" data-bs-theme-value="auto" aria-pressed="{% if config.theme.color_mode == 'auto' %}true{% else %}false{% endif %}">
<i class="fa-solid fa-circle-half-stroke fa-fw"></i>
<span class="ms-2">Auto</span>
<i class="fa-solid fa-check ms-auto{% if config.theme.color_mode != 'auto' %} d-none{% endif %}"></i>
</button>
</li>
</ul>
</li>
{%- endif %}
</ul>
</div>
</div>
</div>
{%- if config.theme.color_mode != "light" or config.theme.user_color_mode_toggle %}
<script src="{{ 'js/darkmode.js'|url }}"></script>
{%- endif %}
<div class="container">
<div class="row">
{%- block content %}
<div class="col-md-3">{% include "toc.html" %}</div>
<div class="col-md-9" role="main">{% include "content.html" %}</div>
{%- endblock %}
</div>
</div>
<footer class="col-md-12">
{%- block footer %}
<hr>
{%- if config.copyright %}
<p>{{ config.copyright }}</p>
{%- endif %}
<p>{% trans mkdocs_link='<a href="https://www.mkdocs.org/">MkDocs</a>' %}Documentation built with {{ mkdocs_link }}.{% endtrans %}</p>
{%- endblock %}
</footer>
{%- block scripts %}
<script src="{{ 'js/bootstrap.bundle.min.js'|url }}"></script>
<script>
var base_url = {{ base_url|tojson }},
shortcuts = {{ config.theme.shortcuts|tojson }};
</script>
<script src="{{ 'js/base.js'|url }}"></script>
{%- for script in config.extra_javascript %}
{{ script|script_tag }}
{%- endfor %}
{%- endblock %}
{% if 'search' in config.plugins %}{%- include "search-modal.html" %}{% endif %}
{%- include "keyboard-modal.html" %}
</body>
</html>
{% if page and page.is_homepage %}
<!--
MkDocs version : {{ mkdocs_version }}
Build Date UTC : {{ build_date_utc }}
-->
{% endif %}
@@ -0,0 +1,9 @@
{% if page.meta.source %}
<div class="source-links">
{% for filename in page.meta.source %}
<span class="label label-primary">{{ filename }}</span>
{% endfor %}
</div>
{% endif %}
{{ page.content }}
@@ -0,0 +1,366 @@
html {
/* The nav header is 3.5rem high, plus 20px for the margin-top of the
main container. */
scroll-padding-top: calc(3.5rem + 20px);
}
/* Replacement for `body { background-attachment: fixed; }`, which has
performance issues when scrolling on large displays. See #1394. */
body::before {
content: ' ';
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background-color: var(--bs-body-bg);
background: url(../img/grid.png) repeat-x;
will-change: transform;
z-index: -1;
}
body > .container {
margin-top: 20px;
min-height: 400px;
}
.navbar.fixed-top {
position: -webkit-sticky;
position: sticky;
}
.source-links {
float: right;
}
.col-md-9 img {
max-width: 100%;
display: inline-block;
padding: 4px;
line-height: 1.428571429;
background-color: var(--bs-secondary-bg-subtle);
border: 1px solid var(--bs-secondary-border-subtle);
border-radius: 4px;
margin: 20px auto 30px auto;
}
h1 {
color: inherit;
font-weight: 400;
font-size: 42px;
}
h2, h3, h4, h5, h6 {
color: inherit;
font-weight: 300;
}
hr {
border-top: 1px solid #aaa;
opacity: 1;
}
pre, .rst-content tt {
max-width: 100%;
background-color: var(--bs-body-bg);
border: solid 1px var(--bs-border-color);
color: var(--bs-body-color);
overflow-x: auto;
}
code.code-large, .rst-content tt.code-large {
font-size: 90%;
}
code {
padding: 2px 5px;
background-color: rgba(var(--bs-body-bg-rgb), 0.75);
border: solid 1px var(--bs-border-color);
color: var(--bs-body-color);
white-space: pre-wrap;
word-wrap: break-word;
}
pre code {
display: block;
border: none;
white-space: pre;
word-wrap: normal;
font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
font-size: 12px;
}
kbd {
padding: 2px 4px;
font-size: 90%;
color: var(--bs-secondary-text-emphasis);
background-color: var(--bs-secondary-bg-subtle);
border-radius: 3px;
-webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);
}
a code {
color: inherit;
}
a:hover code, a:focus code {
color: inherit;
}
footer {
margin-top: 30px;
margin-bottom: 10px;
text-align: center;
font-weight: 200;
}
.modal-dialog {
margin-top: 60px;
}
/*
* Side navigation
*
* Scrollspy and affixed enhanced navigation to highlight sections and secondary
* sections of docs content.
*/
.bs-sidebar.affix {
position: -webkit-sticky;
position: sticky;
/* The nav header is 3.5rem high, plus 20px for the margin-top of the
main container. */
top: calc(3.5rem + 20px);
}
.bs-sidebar.card {
padding: 0;
max-height: 90%;
overflow-y: auto;
}
/* Toggle (vertically flip) sidebar collapse icon */
.bs-sidebar .navbar-toggler span {
-moz-transform: scale(1, -1);
-webkit-transform: scale(1, -1);
-o-transform: scale(1, -1);
-ms-transform: scale(1, -1);
transform: scale(1, -1);
}
.bs-sidebar .navbar-toggler.collapsed span {
-moz-transform: scale(1, 1);
-webkit-transform: scale(1, 1);
-o-transform: scale(1, 1);
-ms-transform: scale(1, 1);
transform: scale(1, 1);
}
/* First level of nav */
.bs-sidebar > .navbar-collapse > .nav {
padding-top: 10px;
padding-bottom: 10px;
border-radius: 5px;
width: 100%;
}
/* All levels of nav */
.bs-sidebar .nav > li > a {
display: block;
padding: 5px 20px;
z-index: 1;
}
.bs-sidebar .nav > li > a:hover,
.bs-sidebar .nav > li > a:focus {
text-decoration: none;
border-right: 1px solid;
}
.bs-sidebar .nav > li > a.active,
.bs-sidebar .nav > li > a.active:hover,
.bs-sidebar .nav > li > a.active:focus {
font-weight: bold;
background-color: transparent;
border-right: 1px solid;
}
.bs-sidebar .nav .nav .nav {
margin-left: 1em;
}
.bs-sidebar .nav > li > a {
font-weight: bold;
}
.bs-sidebar .nav .nav > li > a {
font-weight: normal;
}
.headerlink {
font-family: FontAwesome;
font-size: 14px;
display: none;
padding-left: .5em;
text-decoration: none;
vertical-align: middle;
}
h1:hover .headerlink, h2:hover .headerlink, h3:hover .headerlink, h4:hover .headerlink, h5:hover .headerlink, h6:hover .headerlink {
display:inline-block;
}
blockquote {
padding-left: 10px;
border-left: 4px solid #e6e6e6;
}
.admonition, details {
padding: 15px;
margin-bottom: 20px;
border: 1px solid transparent;
border-radius: 4px;
text-align: left;
}
.admonition.note, details.note {
color: var(--bs-primary-text-emphasis);
background-color: var(--bs-primary-bg-subtle);
border-color: var(--bs-primary-border-subtle);
}
.admonition.note h1, .admonition.note h2, .admonition.note h3,
.admonition.note h4, .admonition.note h5, .admonition.note h6,
details.note h1, details.note h2, details.note h3,
details.note h4, details.note h5, details.note h6 {
color: var(--bs-primary-text-emphasis);
}
.admonition.info, details.info {
color: var(--bs-info-text-emphasis);
background-color: var(--bs-info-bg-subtle);
border-color: var(--bs-info-border-subtle);
}
.admonition.info h1, .admonition.info h2, .admonition.info h3,
.admonition.info h4, .admonition.info h5, .admonition.info h6,
details.info h1, details.info h2, details.info h3,
details.info h4, details.info h5, details.info h6 {
color: var(--bs-info-text-emphasis);
}
.admonition.warning, details.warning {
color: var(--bs-warning-text-emphasis);
background-color: var(--bs-warning-bg-subtle);
border-color: var(--bs-warning-border-subtle);
}
.admonition.warning h1, .admonition.warning h2, .admonition.warning h3,
.admonition.warning h4, .admonition.warning h5, .admonition.warning h6,
details.warning h1, details.warning h2, details.warning h3,
details.warning h4, details.warning h5, details.warning h6 {
color: var(--bs-warning-text-emphasis);
}
.admonition.danger, details.danger {
color: var(--bs-danger-text-emphasis);
background-color: var(--bs-danger-bg-subtle);
border-color: var(--bs-danger-border-subtle);
}
.admonition.danger h1, .admonition.danger h2, .admonition.danger h3,
.admonition.danger h4, .admonition.danger h5, .admonition.danger h6,
details.danger h1, details.danger h2, details.danger h3,
details.danger h4, details.danger h5, details.danger h6 {
color: var(--bs-danger-text-emphasis);
}
.admonition, details {
color: var(--bs-light-text-emphasis);
background-color: var(--bs-light-bg-subtle);
border-color: var(--bs-light-border-subtle);
}
.admonition h1, .admonition h2, .admonition h3,
.admonition h4, .admonition h5, .admonition h6,
details h1, details h2, details h3,
details h4, details h5, details h6 {
color: var(--bs-light-text-emphasis);
}
.admonition-title, summary {
font-weight: bold;
text-align: left;
}
.admonition>p:last-child, details>p:last-child {
margin-bottom: 0;
}
@media (max-width: 991.98px) {
.navbar-collapse.show {
overflow-y: auto;
max-height: calc(100vh - 3.5rem);
}
}
.dropdown-item.open {
color: var(--bs-dropdown-link-active-color);
background-color: var(--bs-dropdown-link-active-bg);
}
.dropdown-submenu > .dropdown-menu {
margin: 0 0 0 1.5rem;
padding: 0;
border-width: 0;
}
.dropdown-submenu > a::after {
display: block;
content: " ";
float: right;
width: 0;
height: 0;
border-color: transparent;
border-style: solid;
border-width: 5px 0 5px 5px;
border-left-color: var(--bs-dropdown-link-active-color);
margin-top: 5px;
margin-right: -10px;
}
.dropdown-submenu:hover > a::after {
border-left-color: var(--bs-dropdown-link-active-color);
}
@media (min-width: 992px) {
.dropdown-menu {
overflow-y: auto;
max-height: calc(100vh - 3.5rem);
}
.dropdown-submenu {
position: relative;
}
.dropdown-submenu > .dropdown-menu {
position: fixed !important;
margin-top: -9px;
margin-left: -2px;
border-width: 1px;
padding: 0.5rem 0;
}
.dropdown-submenu.pull-left {
float: none;
}
.dropdown-submenu.pull-left > .dropdown-menu {
left: -100%;
margin-left: 10px;
}
}
@media print {
/* Remove sidebar when print */
.col-md-3 { display: none; }
}
@@ -0,0 +1,12 @@
@charset "UTF-8";/*!
* Bootswatch v5.3.2 (https://bootswatch.com)
* Theme: cerulean
* Copyright 2012-2023 Thomas Park
* Licensed under MIT
* Based on Bootstrap
*//*!
* Bootstrap v5.3.2 (https://getbootstrap.com/)
* Copyright 2011-2023 The Bootstrap Authors
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/:root,[data-bs-theme=light]{--bs-blue:#033c73;--bs-indigo:#6610f2;--bs-purple:#6f42c1;--bs-pink:#e83e8c;--bs-red:#c71c22;--bs-orange:#fd7e14;--bs-yellow:#dd5600;--bs-green:#73a839;--bs-teal:#20c997;--bs-cyan:#2fa4e7;--bs-black:#000;--bs-white:#fff;--bs-gray:#868e96;--bs-gray-dark:#343a40;--bs-gray-100:#f8f9fa;--bs-gray-200:#e9ecef;--bs-gray-300:#dee2e6;--bs-gray-400:#ced4da;--bs-gray-500:#adb5bd;--bs-gray-600:#868e96;--bs-gray-700:#495057;--bs-gray-800:#343a40;--bs-gray-900:#212529;--bs-primary:#2fa4e7;--bs-secondary:#e9ecef;--bs-success:#73a839;--bs-info:#033c73;--bs-warning:#dd5600;--bs-danger:#c71c22;--bs-light:#f8f9fa;--bs-dark:#343a40;--bs-primary-rgb:47,164,231;--bs-secondary-rgb:233,236,239;--bs-success-rgb:115,168,57;--bs-info-rgb:3,60,115;--bs-warning-rgb:221,86,0;--bs-danger-rgb:199,28,34;--bs-light-rgb:248,249,250;--bs-dark-rgb:52,58,64;--bs-primary-text-emphasis:#13425c;--bs-secondary-text-emphasis:#5d5e60;--bs-success-text-emphasis:#2e4317;--bs-info-text-emphasis:#01182e;--bs-warning-text-emphasis:#582200;--bs-danger-text-emphasis:#500b0e;--bs-light-text-emphasis:#495057;--bs-dark-text-emphasis:#495057;--bs-primary-bg-subtle:#d5edfa;--bs-secondary-bg-subtle:#fbfbfc;--bs-success-bg-subtle:#e3eed7;--bs-info-bg-subtle:#cdd8e3;--bs-warning-bg-subtle:#f8ddcc;--bs-danger-bg-subtle:#f4d2d3;--bs-light-bg-subtle:#fcfcfd;--bs-dark-bg-subtle:#ced4da;--bs-primary-border-subtle:#acdbf5;--bs-secondary-border-subtle:#f6f7f9;--bs-success-border-subtle:#c7dcb0;--bs-info-border-subtle:#9ab1c7;--bs-warning-border-subtle:#f1bb99;--bs-danger-border-subtle:#e9a4a7;--bs-light-border-subtle:#e9ecef;--bs-dark-border-subtle:#adb5bd;--bs-white-rgb:255,255,255;--bs-black-rgb:0,0,0;--bs-font-sans-serif:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue","Noto Sans","Liberation Sans",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--bs-font-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--bs-gradient:linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));--bs-body-font-family:var(--bs-font-sans-serif);--bs-body-font-size:1rem;--bs-body-font-weight:400;--bs-body-line-height:1.5;--bs-body-color:#495057;--bs-body-color-rgb:73,80,87;--bs-body-bg:#fff;--bs-body-bg-rgb:255,255,255;--bs-emphasis-color:#000;--bs-emphasis-color-rgb:0,0,0;--bs-secondary-color:rgba(73, 80, 87, 0.75);--bs-secondary-color-rgb:73,80,87;--bs-secondary-bg:#e9ecef;--bs-secondary-bg-rgb:233,236,239;--bs-tertiary-color:rgba(73, 80, 87, 0.5);--bs-tertiary-color-rgb:73,80,87;--bs-tertiary-bg:#f8f9fa;--bs-tertiary-bg-rgb:248,249,250;--bs-heading-color:#2fa4e7;--bs-link-color:#2fa4e7;--bs-link-color-rgb:47,164,231;--bs-link-decoration:underline;--bs-link-hover-color:#2683b9;--bs-link-hover-color-rgb:38,131,185;--bs-code-color:#e83e8c;--bs-highlight-color:#495057;--bs-highlight-bg:#f8ddcc;--bs-border-width:1px;--bs-border-style:solid;--bs-border-color:#dee2e6;--bs-border-color-translucent:rgba(0, 0, 0, 0.175);--bs-border-radius:0.375rem;--bs-border-radius-sm:0.25rem;--bs-border-radius-lg:0.5rem;--bs-border-radius-xl:1rem;--bs-border-radius-xxl:2rem;--bs-border-radius-2xl:var(--bs-border-radius-xxl);--bs-border-radius-pill:50rem;--bs-box-shadow:0 0.5rem 1rem rgba(0, 0, 0, 0.15);--bs-box-shadow-sm:0 0.125rem 0.25rem rgba(0, 0, 0, 0.075);--bs-box-shadow-lg:0 1rem 3rem rgba(0, 0, 0, 0.175);--bs-box-shadow-inset:inset 0 1px 2px rgba(0, 0, 0, 0.075);--bs-focus-ring-width:0.25rem;--bs-focus-ring-opacity:0.25;--bs-focus-ring-color:rgba(47, 164, 231, 0.25);--bs-form-valid-color:#73a839;--bs-form-valid-border-color:#73a839;--bs-form-invalid-color:#c71c22;--bs-form-invalid-border-color:#c71c22}[data-bs-theme=dark]{color-scheme:dark;--bs-body-color:#dee2e6;--bs-body-color-rgb:222,226,230;--bs-body-bg:#212529;--bs-body-bg-rgb:33,37,41;--bs-emphasis-color:#fff;--bs-emphasis-color-rgb:255,255,255;--bs-secondary-color:rgba(222, 226, 230, 0.75);--bs-secondary-color-rgb:222,226,230;--bs-secondary-bg:#343a40;--bs-secondary-bg-rgb:52,58,64;--bs-tertiary-color:rgba(222, 226, 230, 0.5);--bs-tertiary-color-rgb:222,226,230;--bs-tertiary-bg:#2b3035;--bs-tertiary-bg-rgb:43,48,53;--bs-primary-text-emphasis:#82c8f1;--bs-secondary-text-emphasis:#f2f4f5;--bs-success-text-emphasis:#abcb88;--bs-info-text-emphasis:#688aab;--bs-warning-text-emphasis:#eb9a66;--bs-danger-text-emphasis:#dd777a;--bs-light-text-emphasis:#f8f9fa;--bs-dark-text-emphasis:#dee2e6;--bs-primary-bg-subtle:#09212e;--bs-secondary-bg-subtle:#2f2f30;--bs-success-bg-subtle:#17220b;--bs-info-bg-subtle:#010c17;--bs-warning-bg-subtle:#2c1100;--bs-danger-bg-subtle:#280607;--bs-light-bg-subtle:#343a40;--bs-dark-bg-subtle:#1a1d20;--bs-primary-border-subtle:#1c628b;--bs-secondary-border-subtle:#8c8e8f;--bs-success-border-subtle:#456522;--bs-info-border-subtle:#022445;--bs-warning-border-subtle:#853400;--bs-danger-border-subtle:#771114;--bs-light-border-subtle:#495057;--bs-dark-border-subtle:#343a40;--bs-heading-color:inheriLine truncated
/*# sourceMappingURL=bootstrap.min.css.map */
@@ -0,0 +1 @@
{"version":3,"sources":["dist/cerulean/bootstrap.css"],"names":[],"mappings":"iBACA;;;;;;AAOA;;;;AAKA,MACA,sBACE,UAAW,QACX,YAAa,QACb,YAAa,QACb,UAAW,QACX,SAAU,QACV,YAAa,QACb,YAAa,QACb,WAAY,QACZ,UAAW,QACX,UAAW,QACX,WAAY,KACZ,WAAY,KACZ,UAAW,QACX,eAAgB,QAChB,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,cAAe,QACf,aAAc,QACd,eAAgB,QAChB,aAAc,QACd,UAAW,QACX,aAAc,QACd,YAAa,QACb,WAAY,QACZ,UAAW,QACX,iBAAkB,EAAE,CAAE,GAAG,CAAE,IAC3B,mBAAoB,GAAG,CAAE,GAAG,CAAE,IAC9B,iBAAkB,GAAG,CAAE,GAAG,CAAE,GAC5B,cAAe,CAAC,CAAE,EAAE,CAAE,IACtB,iBAAkB,GAAG,CAAE,EAAE,CAAE,EAC3B,gBAAiB,GAAG,CAAE,EAAE,CAAE,GAC1B,eAAgB,GAAG,CAAE,GAAG,CAAE,IAC1B,cAAe,EAAE,CAAE,EAAE,CAAE,GACvB,2BAA4B,QAC5B,6BAA8B,QAC9B,2BAA4B,QAC5B,wBAAyB,QACzB,2BAA4B,QAC5B,0BAA2B,QAC3B,yBAA0B,QAC1B,wBAAyB,QACzB,uBAAwB,QACxB,yBAA0B,QAC1B,uBAAwB,QACxB,oBAAqB,QACrB,uBAAwB,QACxB,sBAAuB,QACvB,qBAAsB,QACtB,oBAAqB,QACrB,2BAA4B,QAC5B,6BAA8B,QAC9B,2BAA4B,QAC5B,wBAAyB,QACzB,2BAA4B,QAC5B,0BAA2B,QAC3B,yBAA0B,QAC1B,wBAAyB,QACzB,eAAgB,GAAG,CAAE,GAAG,CAAE,IAC1B,eAAgB,CAAC,CAAE,CAAC,CAAE,EACtB,qBAAsB,SAAS,CAAE,aAAa,CAAE,UAAU,CAAE,MAAM,CAAE,gBAAgB,CAAE,WAAW,CAAE,iBAAiB,CAAE,KAAK,CAAE,UAAU,CAAE,mBAAmB,CAAE,gBAAgB,CAAE,iBAAiB,CAAE,mBACnM,oBAAqB,cAAc,CAAE,KAAK,CAAE,MAAM,CAAE,QAAQ,CAAE,iBAAiB,CAAE,aAAa,CAAE,UAChG,cAAe,2EACf,sBAAuB,0BACvB,oBAAqB,KACrB,sBAAuB,IACvB,sBAAuB,IACvB,gBAAiB,QACjB,oBAAqB,EAAE,CAAE,EAAE,CAAE,GAC7B,aAAc,KACd,iBAAkB,GAAG,CAAE,GAAG,CAAE,IAC5B,oBAAqB,KACrB,wBAAyB,CAAC,CAAE,CAAC,CAAE,EAC/B,qBAAsB,uBACtB,yBAA0B,EAAE,CAAE,EAAE,CAAE,GAClC,kBAAmB,QACnB,sBAAuB,GAAG,CAAE,GAAG,CAAE,IACjC,oBAAqB,sBACrB,wBAAyB,EAAE,CAAE,EAAE,CAAE,GACjC,iBAAkB,QAClB,qBAAsB,GAAG,CAAE,GAAG,CAAE,IAChC,mBAAoB,QACpB,gBAAiB,QACjB,oBAAqB,EAAE,CAAE,GAAG,CAAE,IAC9B,qBAAsB,UACtB,sBAAuB,QACvB,0BAA2B,EAAE,CAAE,GAAG,CAAE,IACpC,gBAAiB,QACjB,qBAAsB,QACtB,kBAAmB,QACnB,kBAAmB,IACnB,kBAAmB,MACnB,kBAAmB,QACnB,8BAA+B,qBAC/B,mBAAoB,SACpB,sBAAuB,QACvB,sBAAuB,OACvB,sBAAuB,KACvB,uBAAwB,KACxB,uBAAwB,4BACxB,wBAAyB,MACzB,gBAAiB,EAAE,OAAO,KAAK,oBAC/B,mBAAoB,EAAE,SAAS,QAAQ,qBACvC,mBAAoB,EAAE,KAAK,KAAK,qBAChC,sBAAuB,MAAM,EAAE,IAAI,IAAI,qBACvC,sBAAuB,QACvB,wBAAyB,KACzB,sBAAuB,yBACvB,sBAAuB,QACvB,6BAA8B,QAC9B,wBAAyB,QACzB,+BAAgC,QAGlC,qBACE,aAAc,KACd,gBAAiB,QACjB,oBAAqB,GAAG,CAAE,GAAG,CAAE,IAC/B,aAAc,QACd,iBAAkB,EAAE,CAAE,EAAE,CAAE,GAC1B,oBAAqB,KACrB,wBAAyB,GAAG,CAAE,GAAG,CAAE,IACnC,qBAAsB,0BACtB,yBAA0B,GAAG,CAAE,GAAG,CAAE,IACpC,kBAAmB,QACnB,sBAAuB,EAAE,CAAE,EAAE,CAAE,GAC/B,oBAAqB,yBACrB,wBAAyB,GAAG,CAAE,GAAG,CAAE,IACnC,iBAAkB,QAClB,qBAAsB,EAAE,CAAE,EAAE,CAAE,GAC9B,2BAA4B,QAC5B,6BAA8B,QAC9B,2BAA4B,QAC5B,wBAAyB,QACzB,2BAA4B,QAC5B,0BAA2B,QAC3B,yBAA0B,QAC1B,wBAAyB,QACzB,uBAAwB,QACxB,yBAA0B,QAC1B,uBAAwB,QACxB,oBAAqB,QACrB,uBAAwB,QACxB,sBAAuB,QACvB,qBAAsB,QACtB,oBAAqB,QACrB,2BAA4B,QAC5B,6BAA8B,QAC9B,2BAA4B,QAC5B,wBAAyB,QACzB,2BAA4B,QAC5B,0BAA2B,QAC3B,yBAA0B,QAC1B,wBAAyB,QACzB,mBAAoB,QACpB,gBAAiB,QACjB,sBAAuB,QACvB,oBAAqB,GAAG,CAAE,GAAG,CAAE,IAC/B,0BAA2B,GAAG,CAAE,GAAG,CAAE,IACrC,gBAAiB,QACjB,qBAAsB,QACtB,kBAAmB,QACnB,kBAAmB,QACnB,8BAA+B,0BAC/B,sBAAuB,QACvB,6BAA8B,QAC9B,wBAAyB,QACzB,+BAAgC,QAGlC,EAEA,QADA,SAEE,WAAY,WAGd,8CACE,MACE,gBAAiB,QAIrB,KACE,OAAQ,EACR,YAAa,2BACb,UAAW,yBACX,YAAa,2BACb,YAAa,2BACb,MAAO,qBACP,WAAY,0BACZ,iBAAkB,kBAClB,yBAA0B,KAC1B,4BAA6B,YAG/B,GACE,OAAQ,KAAK,EACb,MAAO,QACP,OAAQ,EACR,WAAY,uBAAuB,MACnC,QAAS,IAGsC,IAAT,IAAT,IAAT,IAAT,IAAT,IAAyC,GAAT,GAAT,GAAT,GAAT,GAAT,GACE,WAAY,EACZ,cAAe,MACf,YAAa,IACb,YAAa,IACb,MAAO,wBAGL,IAAJ,GACE,UAAW,uBAEb,0BACM,IAAJ,GACE,UAAW,QAIX,IAAJ,GACE,UAAW,sBAEb,0BACM,IAAJ,GACE,UAAW,MAIX,IAAJ,GACE,UAAW,oBAEb,0BACM,IAAJ,GACE,UAAW,SAIX,IAAJ,GACE,UAAW,sBAEb,0BACM,IAAJ,GACE,UAAW,QAIX,IAAJ,GACE,UAAW,QAGT,IAAJ,GACE,UAAW,KAGb,EACE,WAAY,EACZ,cAAe,KAGjB,YACE,wBAAyB,UAAU,OACnC,gBAAiB,UAAU,OAC3B,OAAQ,KACR,iCAAkC,KAClC,yBAA0B,KAG5B,QACE,cAAe,KACf,WAAY,OACZ,YAAa,QAGf,GACA,GACE,aAAc,KAKhB,GAFA,GACA,GAEE,WAAY,EACZ,cAAe,KAGjB,MAEA,MACA,MAFA,MAGE,cAAe,EAGjB,GACE,YAAa,IAGf,GACE,cAAe,MACf,YAAa,EAGf,WACE,OAAQ,EAAE,EAAE,KAGd,EACA,OACE,YAAa,OAGR,OAAP,MACE,UAAW,OAGP,MAAN,KACE,QAAS,QACT,MAAO,0BACP,iBAAkB,uBAGpB,IACA,IACE,SAAU,SACV,UAAW,MACX,YAAa,EACb,eAAgB,SAGlB,IACE,OAAQ,OAGV,IACE,IAAK,MAGP,EACE,MAAO,wDACP,gBAAiB,UAEnB,QACE,oBAAqB,+BAGvB,2BAA4B,iCAC1B,MAAO,QACP,gBAAiB,KAInB,KACA,IAFA,IAGA,KACE,YAAa,yBACb,UAAW,IAGb,IACE,QAAS,MACT,WAAY,EACZ,cAAe,KACf,SAAU,KACV,UAAW,OAEb,SACE,UAAW,QACX,MAAO,QACP,WAAY,OAGd,KACE,UAAW,OACX,MAAO,qBACP,UAAW,WAEb,OACE,MAAO,QAGT,IACE,QAAS,SAAU,QACnB,UAAW,OACX,MAAO,kBACP,iBAAkB,qBAClB,cAAe,OAEjB,QACE,QAAS,EACT,UAAW,IAGb,OACE,OAAQ,EAAE,EAAE,KAGd,IACA,IACE,eAAgB,OAGlB,MACE,aAAc,OACd,gBAAiB,SAGnB,QACE,YAAa,MACb,eAAgB,MAChB,MAAO,0BACP,WAAY,KAGd,GACE,WAAY,QACZ,WAAY,qBAId,MAGA,GAFA,MAGA,GALA,MAGA,GAGE,aAAc,QACd,aAAc,MACd,aAAc,EAGhB,MACE,QAAS,aAGX,OACE,cAAe,EAGjB,iCACE,QAAS,EAIX,OADA,MAGA,SADA,OAEA,SACE,OAAQ,EACR,YAAa,QACb,UAAW,QACX,YAAa,QAGf,OACA,OACE,eAAgB,KAGlB,cACE,OAAQ,QAGV,OACE,UAAW,OAEb,gBACE,QAAS,EAGX,0IACE,QAAS,eAIX,cACA,aACA,cAHA,OAIE,mBAAoB,OAGtB,6BACA,4BACA,6BAHA,sBAIE,OAAQ,QAGV,mBACE,QAAS,EACT,aAAc,KAGhB,SACE,OAAQ,SAGV,SACE,UAAW,EACX,QAAS,EACT,OAAQ,EACR,Line truncated
@@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2023 Fonticons, Inc.
*/
:host,:root{--fa-style-family-brands:"Font Awesome 6 Brands";--fa-font-brands:normal 400 1em/1 "Font Awesome 6 Brands"}@font-face{font-family:"Font Awesome 6 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}.fa-brands,.fab{font-weight:400}.fa-monero:before{content:"\f3d0"}.fa-hooli:before{content:"\f427"}.fa-yelp:before{content:"\f1e9"}.fa-cc-visa:before{content:"\f1f0"}.fa-lastfm:before{content:"\f202"}.fa-shopware:before{content:"\f5b5"}.fa-creative-commons-nc:before{content:"\f4e8"}.fa-aws:before{content:"\f375"}.fa-redhat:before{content:"\f7bc"}.fa-yoast:before{content:"\f2b1"}.fa-cloudflare:before{content:"\e07d"}.fa-ups:before{content:"\f7e0"}.fa-pixiv:before{content:"\e640"}.fa-wpexplorer:before{content:"\f2de"}.fa-dyalog:before{content:"\f399"}.fa-bity:before{content:"\f37a"}.fa-stackpath:before{content:"\f842"}.fa-buysellads:before{content:"\f20d"}.fa-first-order:before{content:"\f2b0"}.fa-modx:before{content:"\f285"}.fa-guilded:before{content:"\e07e"}.fa-vnv:before{content:"\f40b"}.fa-js-square:before,.fa-square-js:before{content:"\f3b9"}.fa-microsoft:before{content:"\f3ca"}.fa-qq:before{content:"\f1d6"}.fa-orcid:before{content:"\f8d2"}.fa-java:before{content:"\f4e4"}.fa-invision:before{content:"\f7b0"}.fa-creative-commons-pd-alt:before{content:"\f4ed"}.fa-centercode:before{content:"\f380"}.fa-glide-g:before{content:"\f2a6"}.fa-drupal:before{content:"\f1a9"}.fa-hire-a-helper:before{content:"\f3b0"}.fa-creative-commons-by:before{content:"\f4e7"}.fa-unity:before{content:"\e049"}.fa-whmcs:before{content:"\f40d"}.fa-rocketchat:before{content:"\f3e8"}.fa-vk:before{content:"\f189"}.fa-untappd:before{content:"\f405"}.fa-mailchimp:before{content:"\f59e"}.fa-css3-alt:before{content:"\f38b"}.fa-reddit-square:before,.fa-square-reddit:before{content:"\f1a2"}.fa-vimeo-v:before{content:"\f27d"}.fa-contao:before{content:"\f26d"}.fa-square-font-awesome:before{content:"\e5ad"}.fa-deskpro:before{content:"\f38f"}.fa-brave:before{content:"\e63c"}.fa-sistrix:before{content:"\f3ee"}.fa-instagram-square:before,.fa-square-instagram:before{content:"\e055"}.fa-battle-net:before{content:"\f835"}.fa-the-red-yeti:before{content:"\f69d"}.fa-hacker-news-square:before,.fa-square-hacker-news:before{content:"\f3af"}.fa-edge:before{content:"\f282"}.fa-threads:before{content:"\e618"}.fa-napster:before{content:"\f3d2"}.fa-snapchat-square:before,.fa-square-snapchat:before{content:"\f2ad"}.fa-google-plus-g:before{content:"\f0d5"}.fa-artstation:before{content:"\f77a"}.fa-markdown:before{content:"\f60f"}.fa-sourcetree:before{content:"\f7d3"}.fa-google-plus:before{content:"\f2b3"}.fa-diaspora:before{content:"\f791"}.fa-foursquare:before{content:"\f180"}.fa-stack-overflow:before{content:"\f16c"}.fa-github-alt:before{content:"\f113"}.fa-phoenix-squadron:before{content:"\f511"}.fa-pagelines:before{content:"\f18c"}.fa-algolia:before{content:"\f36c"}.fa-red-river:before{content:"\f3e3"}.fa-creative-commons-sa:before{content:"\f4ef"}.fa-safari:before{content:"\f267"}.fa-google:before{content:"\f1a0"}.fa-font-awesome-alt:before,.fa-square-font-awesome-stroke:before{content:"\f35c"}.fa-atlassian:before{content:"\f77b"}.fa-linkedin-in:before{content:"\f0e1"}.fa-digital-ocean:before{content:"\f391"}.fa-nimblr:before{content:"\f5a8"}.fa-chromecast:before{content:"\f838"}.fa-evernote:before{content:"\f839"}.fa-hacker-news:before{content:"\f1d4"}.fa-creative-commons-sampling:before{content:"\f4f0"}.fa-adversal:before{content:"\f36a"}.fa-creative-commons:before{content:"\f25e"}.fa-watchman-monitoring:before{content:"\e087"}.fa-fonticons:before{content:"\f280"}.fa-weixin:before{content:"\f1d7"}.fa-shirtsinbulk:before{content:"\f214"}.fa-codepen:before{content:"\f1cb"}.fa-git-alt:before{content:"\f841"}.fa-lyft:before{content:"\f3c3"}.fa-rev:before{content:"\f5b2"}.fa-windows:before{content:"\f17a"}.fa-wizards-of-the-coast:before{content:"\f730"}.fa-square-viadeo:before,.fa-viadeo-square:before{content:"\f2aa"}.fa-meetup:before{content:"\f2e0"}.fa-centos:before{content:"\f789"}.fa-adn:before{content:"\f170"}.fa-cloudsmith:before{content:"\f384"}.fa-opensuse:before{content:"\e62b"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-dribbble-square:before,.fa-square-dribbble:before{content:"\f397"}.fa-codiepie:before{content:"\f284"}.fa-node:before{content:"\f419"}.fa-mix:before{content:"\f3cb"}.fa-steam:before{content:"\f1b6"}.fa-cc-apple-pay:before{content:"\f416"}.fa-scribd:before{content:"\f28a"}.fa-debian:before{content:"\e60b"}.fa-openid:before{content:"\f19b"}.fa-instalod:before{content:"\e081"}.fa-expeditedssl:before{content:"\f23e"}.fa-sellcast:before{content:"\f2da"}.fa-square-twitter:before,.fa-twitter-square:before{content:"\f081"}.fa-r-project:before{content:"\f4f7"}.fa-delicious:before{content:"\f1a5"}.fa-freebsd:before{content:"\f3a4"}.fa-vuejs:before{content:"\f41f"}.fa-accusoft:before{content:"\f369"}.fa-ioxhost:before{contLine truncated
@@ -0,0 +1,9 @@
/*!
* Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2023 Fonticons, Inc.
*/
.fa{font-family:var(--fa-style-family,"Font Awesome 6 Free");font-weight:var(--fa-style,900)}.fa,.fa-brands,.fa-classic,.fa-regular,.fa-sharp,.fa-solid,.fab,.far,.fas{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:var(--fa-display,inline-block);font-style:normal;font-variant:normal;line-height:1;text-rendering:auto}.fa-classic,.fa-regular,.fa-solid,.far,.fas{font-family:"Font Awesome 6 Free"}.fa-brands,.fab{font-family:"Font Awesome 6 Brands"}.fa-1x{font-size:1em}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-6x{font-size:6em}.fa-7x{font-size:7em}.fa-8x{font-size:8em}.fa-9x{font-size:9em}.fa-10x{font-size:10em}.fa-2xs{font-size:.625em;line-height:.1em;vertical-align:.225em}.fa-xs{font-size:.75em;line-height:.08333em;vertical-align:.125em}.fa-sm{font-size:.875em;line-height:.07143em;vertical-align:.05357em}.fa-lg{font-size:1.25em;line-height:.05em;vertical-align:-.075em}.fa-xl{font-size:1.5em;line-height:.04167em;vertical-align:-.125em}.fa-2xl{font-size:2em;line-height:.03125em;vertical-align:-.1875em}.fa-fw{text-align:center;width:1.25em}.fa-ul{list-style-type:none;margin-left:var(--fa-li-margin,2.5em);padding-left:0}.fa-ul>li{position:relative}.fa-li{left:calc(var(--fa-li-width, 2em)*-1);position:absolute;text-align:center;width:var(--fa-li-width,2em);line-height:inherit}.fa-border{border-radius:var(--fa-border-radius,.1em);border:var(--fa-border-width,.08em) var(--fa-border-style,solid) var(--fa-border-color,#eee);padding:var(--fa-border-padding,.2em .25em .15em)}.fa-pull-left{float:left;margin-right:var(--fa-pull-margin,.3em)}.fa-pull-right{float:right;margin-left:var(--fa-pull-margin,.3em)}.fa-beat{-webkit-animation-name:fa-beat;animation-name:fa-beat;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-bounce{-webkit-animation-name:fa-bounce;animation-name:fa-bounce;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.28,.84,.42,1))}.fa-fade{-webkit-animation-name:fa-fade;animation-name:fa-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-beat-fade,.fa-fade{-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s)}.fa-beat-fade{-webkit-animation-name:fa-beat-fade;animation-name:fa-beat-fade;-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1));animation-timing-function:var(--fa-animation-timing,cubic-bezier(.4,0,.6,1))}.fa-flip{-webkit-animation-name:fa-flip;animation-name:fa-flip;-webkit-animation-delay:var(--fa-animation-delay,0s);animation-delay:var(--fa-animation-delay,0s);-webkit-animation-direction:var(--fa-animation-direction,normal);animation-direction:var(--fa-animation-direction,normal);-webkit-animation-duration:var(--fa-animation-duration,1s);animation-duration:var(--fa-animation-duration,1s);-webkit-animation-iteration-count:var(--fa-animation-iteration-count,infinite);animation-iteration-count:var(--fa-animation-iteration-count,infinite);-webkit-animation-timing-function:var(--fa-animation-timing,ease-in-out);animation-timing-function:var(--fa-animation-timing,ease-in-out)}.fa-shake{-webkit-animation-name:fa-shake;animation-name:fa-shake;-webkit-animation-duration:var(--fa-animatLine truncated
.fa-0:before{content:"\30"}.fa-1:before{content:"\31"}.fa-2:before{content:"\32"}.fa-3:before{content:"\33"}.fa-4:before{content:"\34"}.fa-5:before{content:"\35"}.fa-6:before{content:"\36"}.fa-7:before{content:"\37"}.fa-8:before{content:"\38"}.fa-9:before{content:"\39"}.fa-fill-drip:before{content:"\f576"}.fa-arrows-to-circle:before{content:"\e4bd"}.fa-chevron-circle-right:before,.fa-circle-chevron-right:before{content:"\f138"}.fa-at:before{content:"\40"}.fa-trash-alt:before,.fa-trash-can:before{content:"\f2ed"}.fa-text-height:before{content:"\f034"}.fa-user-times:before,.fa-user-xmark:before{content:"\f235"}.fa-stethoscope:before{content:"\f0f1"}.fa-comment-alt:before,.fa-message:before{content:"\f27a"}.fa-info:before{content:"\f129"}.fa-compress-alt:before,.fa-down-left-and-up-right-to-center:before{content:"\f422"}.fa-explosion:before{content:"\e4e9"}.fa-file-alt:before,.fa-file-lines:before,.fa-file-text:before{content:"\f15c"}.fa-wave-square:before{content:"\f83e"}.fa-ring:before{content:"\f70b"}.fa-building-un:before{content:"\e4d9"}.fa-dice-three:before{content:"\f527"}.fa-calendar-alt:before,.fa-calendar-days:before{content:"\f073"}.fa-anchor-circle-check:before{content:"\e4aa"}.fa-building-circle-arrow-right:before{content:"\e4d1"}.fa-volleyball-ball:before,.fa-volleyball:before{content:"\f45f"}.fa-arrows-up-to-line:before{content:"\e4c2"}.fa-sort-desc:before,.fa-sort-down:before{content:"\f0dd"}.fa-circle-minus:before,.fa-minus-circle:before{content:"\f056"}.fa-door-open:before{content:"\f52b"}.fa-right-from-bracket:before,.fa-sign-out-alt:before{content:"\f2f5"}.fa-atom:before{content:"\f5d2"}.fa-soap:before{content:"\e06e"}.fa-heart-music-camera-bolt:before,.fa-icons:before{content:"\f86d"}.fa-microphone-alt-slash:before,.fa-microphone-lines-slash:before{content:"\f539"}.fa-bridge-circle-check:before{content:"\e4c9"}.fa-pump-medical:before{content:"\e06a"}.fa-fingerprint:before{content:"\f577"}.fa-hand-point-right:before{content:"\f0a4"}.fa-magnifying-glass-location:before,.fa-search-location:before{content:"\f689"}.fa-forward-step:before,.fa-step-forward:before{content:"\f051"}.fa-face-smile-beam:before,.fa-smile-beam:before{content:"\f5b8"}.fa-flag-checkered:before{content:"\f11e"}.fa-football-ball:before,.fa-football:before{content:"\f44e"}.fa-school-circle-exclamation:before{content:"\e56c"}.fa-crop:before{content:"\f125"}.fa-angle-double-down:before,.fa-angles-down:before{content:"\f103"}.fa-users-rectangle:before{content:"\e594"}.fa-people-roof:before{content:"\e537"}.fa-people-line:before{content:"\e534"}.fa-beer-mug-empty:before,.fa-beer:before{content:"\f0fc"}.fa-diagram-predecessor:before{content:"\e477"}.fa-arrow-up-long:before,.fa-long-arrow-up:before{content:"\f176"}.fa-burn:before,.fa-fire-flame-simple:before{content:"\f46a"}.fa-male:before,.fa-person:before{content:"\f183"}.fa-laptop:before{content:"\f109"}.fa-file-csv:before{content:"\f6dd"}.fa-menorah:before{content:"\f676"}.fa-truck-plane:before{content:"\e58f"}.fa-record-vinyl:before{content:"\f8d9"}.fa-face-grin-stars:before,.fa-grin-stars:before{content:"\f587"}.fa-bong:before{content:"\f55c"}.fa-pastafarianism:before,.fa-spaghetti-monster-flying:before{content:"\f67b"}.fa-arrow-down-up-across-line:before{content:"\e4af"}.fa-spoon:before,.fa-utensil-spoon:before{content:"\f2e5"}.fa-jar-wheat:before{content:"\e517"}.fa-envelopes-bulk:before,.fa-mail-bulk:before{content:"\f674"}.fa-file-circle-exclamation:before{content:"\e4eb"}.fa-circle-h:before,.fa-hospital-symbol:before{content:"\f47e"}.fa-pager:before{content:"\f815"}.fa-address-book:before,.fa-contact-book:before{content:"\f2b9"}.fa-strikethrough:before{content:"\f0cc"}.fa-k:before{content:"\4b"}.fa-landmark-flag:before{content:"\e51c"}.fa-pencil-alt:before,.fa-pencil:before{content:"\f303"}.fa-backward:before{content:"\f04a"}.fa-caret-right:before{content:"\f0da"}.fa-comments:before{content:"\f086"}.fa-file-clipboard:before,.fa-paste:before{content:"\f0ea"}.fa-code-pull-request:before{content:"\e13c"}.fa-clipboard-list:before{content:"\f46d"}.fa-truck-loading:before,.fa-truck-ramp-box:before{content:"\f4de"}.fa-user-check:before{content:"\f4fc"}.fa-vial-virus:before{content:"\e597"}.fa-sheet-plastic:before{content:"\e571"}.fa-blog:before{content:"\f781"}.fa-user-ninja:before{content:"\f504"}.fa-person-arrow-up-from-line:before{content:"\e539"}.fa-scroll-torah:before,.fa-torah:before{content:"\f6a0"}.fa-broom-ball:before,.fa-quidditch-broom-ball:before,.fa-quidditch:before{content:"\f458"}.fa-toggle-off:before{content:"\f204"}.fa-archive:before,.fa-box-archive:before{content:"\f187"}.fa-person-drowning:before{content:"\e545"}.fa-arrow-down-9-1:before,.fa-sort-numeric-desc:before,.fa-sort-numeric-down-alt:before{content:"\f886"}.fa-face-grin-tongue-squint:before,.fa-grin-tongue-squint:before{content:"\f58a"}.fa-spray-can:before{content:"\f5bd"}.fa-truck-monster:before{content:"\f63b"}.fa-w:before{content:"\57"}.fa-earth-africa:before,.fa-globe-africa:before{content:"\f57Line truncated
.fa-sr-only,.fa-sr-only-focusable:not(:focus),.sr-only,.sr-only-focusable:not(:focus){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}
@@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2023 Fonticons, Inc.
*/
:host,:root{--fa-style-family-classic:"Font Awesome 6 Free";--fa-font-solid:normal 900 1em/1 "Font Awesome 6 Free"}@font-face{font-family:"Font Awesome 6 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}.fa-solid,.fas{font-weight:900}
@@ -0,0 +1,6 @@
/*!
* Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
* Copyright 2023 Fonticons, Inc.
*/
@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.ttf) format("truetype")}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-regular-400.woff2) format("woff2"),url(../webfonts/fa-regular-400.ttf) format("truetype");unicode-range:u+f003,u+f006,u+f014,u+f016-f017,u+f01a-f01b,u+f01d,u+f022,u+f03e,u+f044,u+f046,u+f05c-f05d,u+f06e,u+f070,u+f087-f088,u+f08a,u+f094,u+f096-f097,u+f09d,u+f0a0,u+f0a2,u+f0a4-f0a7,u+f0c5,u+f0c7,u+f0e5-f0e6,u+f0eb,u+f0f6-f0f8,u+f10c,u+f114-f115,u+f118-f11a,u+f11c-f11d,u+f133,u+f147,u+f14e,u+f150-f152,u+f185-f186,u+f18e,u+f190-f192,u+f196,u+f1c1-f1c9,u+f1d9,u+f1db,u+f1e3,u+f1ea,u+f1f7,u+f1f9,u+f20a,u+f247-f248,u+f24a,u+f24d,u+f255-f25b,u+f25d,u+f271-f274,u+f278,u+f27b,u+f28c,u+f28e,u+f29c,u+f2b5,u+f2b7,u+f2ba,u+f2bc,u+f2be,u+f2c0-f2c1,u+f2c3,u+f2d0,u+f2d2,u+f2d4,u+f2dc}@font-face{font-family:"FontAwesome";font-display:block;src:url(../webfonts/fa-v4compatibility.woff2) format("woff2"),url(../webfonts/fa-v4compatibility.ttf) format("truetype");unicode-range:u+f041,u+f047,u+f065-f066,u+f07d-f07e,u+f080,u+f08b,u+f08e,u+f090,u+f09a,u+f0ac,u+f0ae,u+f0b2,u+f0d0,u+f0d6,u+f0e4,u+f0ec,u+f10a-f10b,u+f123,u+f13e,u+f148-f149,u+f14c,u+f156,u+f15e,u+f160-f161,u+f163,u+f175-f178,u+f195,u+f1f8,u+f219,u+f27a}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Loaded 100 of 18684 files, more files were not shown because too many files have changed in this diff. Show more