mirror of
https://github.com/msberends/AMR.git
synced 2026-11-16 00:10:57 +01:00
(v3.1.0.9003) Rewrite the manual index on the website for findability: sections ordered by task (cleaning data, interpreting results as SIR, analysing data), titles before function names, a filter field that also finds topics mentioning a term, and colours prepared for dark mode; also make the tidymodels extensions public in the manual and use consistent help page titles
This commit is contained in:
1 parent
52d9c4a9e7
commit
bd208429cd
22 files changed
+524
-128
No files matched your search
+2
-2
@@ -1,6 +1,6 @@
|
||||
Package: AMR
|
||||
Version: 3.1.0.9002
|
||||
Date: 2026-10-16
|
||||
Version: 3.1.0.9003
|
||||
Date: 2026-10-17
|
||||
Title: Antimicrobial Resistance Data Analysis
|
||||
Description: Functions to simplify and standardise antimicrobial resistance (AMR)
|
||||
data analysis and to work with microbial and antimicrobial properties by
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
# AMR 3.1.0.9002
|
||||
# AMR 3.1.0.9003
|
||||
|
||||
### Other
|
||||
* The manual index on the website was rewritten to improve findability, with sections ordered by task and a filter field
|
||||
|
||||
# AMR 3.1.0
|
||||
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Options for the AMR package
|
||||
#' Options for the AMR Package
|
||||
#'
|
||||
#' @description
|
||||
#' This is an overview of all the package-specific options you can set in the `AMR` package. Set them using the [options()] function, e.g.:
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Transform Input to an Antibiotic ID
|
||||
#' Transform Input to an Antimicrobial Drug ID
|
||||
#'
|
||||
#' Use this function to determine the antimicrobial drug code of one or more antimicrobials. The data set [antimicrobials] will be searched for abbreviations, official names and synonyms (brand names).
|
||||
#' @param x A [character] vector to determine to antibiotic ID.
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Get Properties of an Antibiotic
|
||||
#' Get Properties of an Antimicrobial Drug
|
||||
#'
|
||||
#' Use these functions to return a specific property of an antibiotic from the [antimicrobials] data set. All input values will be evaluated internally with [as.ab()].
|
||||
#' @param x Any (vector of) text that can be coerced to a valid antibiotic drug code with [as.ab()].
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Guess Antibiotic Column
|
||||
#' Guess Antimicrobial Column
|
||||
#'
|
||||
#' This tries to find a column name in a data set based on information from the [antimicrobials] data set. Also supports WHONET abbreviations.
|
||||
#' @param x A [data.frame].
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Italicise Taxonomic Families, Genera, Species, Subspecies
|
||||
#' Italicise Taxonomic Families, Genera, Species, and Subspecies
|
||||
#'
|
||||
#' According to the binomial nomenclature, the lowest four taxonomic levels (family, genus, species, subspecies) should be printed in italics. This function finds taxonomic names within strings and makes them italic.
|
||||
#' @param string A [character] (vector).
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Random MIC Values/Disk Zones/SIR Generation
|
||||
#' Generate Random MIC Values, Disk Zones, or SIR Results
|
||||
#'
|
||||
#' These functions can be used for generating random MIC values and disk diffusion diameters, for AMR data analysis practice. By providing a microorganism and antimicrobial drug, the generated results will reflect reality as much as possible.
|
||||
#' @param size Desired size of the returned vector. If used in a [data.frame] call or `dplyr` verb, will get the current (group) size if left blank.
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#' These steps integrate with `recipes::recipe()` and work like standard preprocessing steps. They are useful for preparing data for modelling, especially with classification models.
|
||||
#' @seealso [recipes::recipe()], [as.sir()], [as.mic()], [as.disk()]
|
||||
#' @name amr-tidymodels
|
||||
#' @keywords internal
|
||||
#' @export
|
||||
#' @examples
|
||||
#' if (require("tidymodels")) {
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
# how to conduct AMR data analysis: https://amr-for-r.org #
|
||||
# ==================================================================== #
|
||||
|
||||
#' Deprecated Functions, Arguments, or Datasets
|
||||
#' Deprecated Functions, Arguments, or Data Sets
|
||||
#'
|
||||
#' These objects are so-called '[Deprecated]'. **They will be removed in a future version of this package.** Using these will give a warning with the name of the alternative object it has been replaced by (if there is one).
|
||||
#' @keywords internal
|
||||
|
||||
+80
-97
@@ -38,6 +38,8 @@ template:
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js" integrity="sha384-7zkQWkzuo3B5mTepMUcHkMB5jZaolc2xDwL6VFqjFALcbeS9Ggm/Yr2r3Dy4lfFg" crossorigin="anonymous"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js" integrity="sha384-43gviWU0YVjaDtb/GhzOouOXtZMP/7XUzwPTstBeZFe/+rCMvRwr4yROQP43s0Xk" crossorigin="anonymous" onload="renderMathInElement(document.body);"></script>
|
||||
bootswatch: "flatly"
|
||||
# dark mode: the CSS in pkgdown/extra.css is prepared for it, but light mode is enforced for now
|
||||
light-switch: false
|
||||
bslib:
|
||||
base_font: {google: "Lato"}
|
||||
heading_font: {google: "Lato"}
|
||||
@@ -127,155 +129,136 @@ navbar:
|
||||
href: "https://github.com/msberends/AMR"
|
||||
|
||||
reference:
|
||||
- title: "Introduction to the package"
|
||||
- title: "Getting started"
|
||||
desc: >
|
||||
Please find the introduction to (and some general information about) our package here.
|
||||
An overview of the package, its options for users and teams, and its 28 supported languages.
|
||||
contents:
|
||||
- "`AMR`"
|
||||
|
||||
- title: "Preparing data: microorganisms"
|
||||
- "`AMR-options`"
|
||||
- "`translate`"
|
||||
- "`amr_course`"
|
||||
|
||||
- title: "Cleaning data"
|
||||
desc: >
|
||||
These functions are meant to get taxonomically valid properties of microorganisms from any input, but
|
||||
also properties derived from taxonomy, such as the Gram stain (`mo_gramstain()`) , or `mo_is_yeast()`.
|
||||
Use `mo_source()` to teach this package how to translate your own codes to valid microorganisms, and
|
||||
use `add_custom_microorganisms()` to add your own custom microorganisms to this package.
|
||||
Transform raw input of any kind into valid microorganisms with `as.mo()`, antimicrobials with `as.ab()`, and MIC values and disk diffusion zones with `as.mic()` and `as.disk()`, and retrieve their properties.
|
||||
- subtitle: "Microorganisms"
|
||||
contents:
|
||||
- "`as.mo`"
|
||||
- "`mo_property`"
|
||||
- "`add_custom_microorganisms`"
|
||||
- "`mo_source`"
|
||||
|
||||
- title: "Preparing data: antimicrobials"
|
||||
desc: >
|
||||
Use these functions to get valid properties of antimicrobials from any input or to clean your input.
|
||||
You can even retrieve drug names and doses from clinical text records, using `ab_from_text()`.
|
||||
- "`add_custom_microorganisms`"
|
||||
- "`mo_matching_score`"
|
||||
- subtitle: "Antimicrobials"
|
||||
contents:
|
||||
- "`as.ab`"
|
||||
- "`ab_property`"
|
||||
- "`ab_from_text`"
|
||||
- "`atc_online_property`"
|
||||
- "`add_custom_antimicrobials`"
|
||||
|
||||
- title: "Interpreting data: antimicrobial results"
|
||||
desc: >
|
||||
With `as.mic()` and `as.disk()` you can transform your raw input to valid MIC or disk diffusion values.
|
||||
Use `as.sir()` for cleaning raw data to let it only contain "R", "I" and "S", or to interpret MIC or disk diffusion values as SIR based on the lastest EUCAST and CLSI guidelines.
|
||||
Afterwards, you can extend antibiotic interpretations by applying interpretive rules, for example [from EUCAST](https://www.eucast.org/expert_rules_and_intrinsic_resistance/) with `interpretive_rules()`.
|
||||
- "`atc_online_property`"
|
||||
- subtitle: "Antivirals"
|
||||
contents:
|
||||
- "`as.av`"
|
||||
- "`av_property`"
|
||||
- "`av_from_text`"
|
||||
- subtitle: "Test results"
|
||||
contents:
|
||||
- "`as.sir`"
|
||||
- "`as.mic`"
|
||||
- "`as.disk`"
|
||||
|
||||
- title: "Interpreting results as SIR"
|
||||
desc: >
|
||||
Interpret MIC values and disk diffusion zones as SIR with `as.sir()`, according to EUCAST or CLSI, for every guideline year from 2011 to 2026, and apply interpretive rules. `as.sir()` also cleans existing SIR data.
|
||||
contents:
|
||||
- "`as.sir`"
|
||||
- "`interpretive_rules`"
|
||||
- "`custom_interpretive_rules`"
|
||||
|
||||
- title: "Analysing data"
|
||||
desc: >
|
||||
Use these function for the analysis part. You can use `susceptibility()` or `resistance()` on any antibiotic column.
|
||||
With `antibiogram()`, you can generate a traditional, combined, syndromic, or weighted-incidence syndromic combination
|
||||
antibiogram (WISCA). This function also comes with support for R Markdown and Quarto.
|
||||
Be sure to first select the isolates that are appropiate for analysis, by using `first_isolate()` or `is_new_episode()`.
|
||||
You can also filter your data on certain resistance in certain antibiotic classes (`carbapenems()`, `aminoglycosides()`),
|
||||
or determine multi-drug resistant microorganisms (MDRO, `mdro()`).
|
||||
Select first isolates with `first_isolate()`, generate traditional, combination, syndromic, and WISCA antibiograms with `antibiogram()` and `wisca()`, calculate resistance, and determine multidrug-resistant organisms.
|
||||
- subtitle: "Selecting isolates and antimicrobials"
|
||||
contents:
|
||||
- "`first_isolate`"
|
||||
- "`get_episode`"
|
||||
- "`key_antimicrobials`"
|
||||
- "`top_n_microorganisms`"
|
||||
- "`antimicrobial_selectors`"
|
||||
- "`guess_ab_col`"
|
||||
- "`availability`"
|
||||
- subtitle: "Generating antibiograms and WISCA"
|
||||
contents:
|
||||
- "`antibiogram`"
|
||||
- subtitle: "Calculating resistance and susceptibility"
|
||||
contents:
|
||||
- "`proportion`"
|
||||
- "`count`"
|
||||
- "`sir_combine`"
|
||||
- "`is_new_episode`"
|
||||
- "`first_isolate`"
|
||||
- "`key_antimicrobials`"
|
||||
- "`bug_drug_combinations`"
|
||||
- subtitle: "Determining multidrug resistance"
|
||||
contents:
|
||||
- "`mdro`"
|
||||
- "`custom_mdro_guideline`"
|
||||
- "`bug_drug_combinations`"
|
||||
- "`antimicrobial_selectors`"
|
||||
- "`top_n_microorganisms`"
|
||||
- "`mean_amr_distance`"
|
||||
- "`resistance_predict`"
|
||||
- "`guess_ab_col`"
|
||||
|
||||
- title: "Plotting data"
|
||||
|
||||
- title: "Visualising data"
|
||||
desc: >
|
||||
Use these functions for the plotting part. The `scale_*_mic()` functions extend the ggplot2 package to allow plotting of
|
||||
MIC values, even within a manually set range.
|
||||
If using `plot()` (base R) or `autoplot()` (ggplot2) on MIC values or disk diffusion values, the user can
|
||||
set the interpretation guideline to give the bars the right SIR colours.
|
||||
The `ggplot_sir()` function is a short wrapper for users not much accustomed to ggplot2 yet.
|
||||
The `ggplot_pca()` function is a specific function to plot so-called biplots for PCA (principal component analysis).
|
||||
Plot MIC values, disk zones, and SIR results in base R or `ggplot2`, with scales and colours tailored to AMR data.
|
||||
contents:
|
||||
- "`plot`"
|
||||
- "`ggplot_sir`"
|
||||
- "`ggplot_pca`"
|
||||
|
||||
- title: "AMR-specific options"
|
||||
desc: >
|
||||
The AMR package is customisable, by providing settings that can be set per user or per team. For
|
||||
example, the default interpretation guideline can be changed from EUCAST to CLSI, or a supported
|
||||
language can be set for the whole team (system-language independent) for antibiotic names in a
|
||||
foreign language.
|
||||
contents:
|
||||
- "`AMR-options`"
|
||||
|
||||
- title: "Other: antiviral drugs"
|
||||
desc: >
|
||||
This package also provides extensive support for antiviral agents, even though it is not the primary
|
||||
scope of this package. Working with data containing information about antiviral drugs was never easier.
|
||||
Use these functions to get valid properties of antiviral drugs from any input or to clean your input.
|
||||
You can even retrieve drug names and doses from clinical text records, using `av_from_text()`.
|
||||
contents:
|
||||
- "`as.av`"
|
||||
- "`av_property`"
|
||||
- "`av_from_text`"
|
||||
|
||||
- title: "Other: background information on included data"
|
||||
- title: "Modelling"
|
||||
desc: >
|
||||
Some pages about our package and its external sources. Be sure to read our [How To's](./../articles/index.html)
|
||||
for more information about how to work with functions in this package.
|
||||
Use AMR data types in `tidymodels` pipelines, and perform principal component analysis or distance calculations on resistance profiles.
|
||||
contents:
|
||||
- "`amr-tidymodels`"
|
||||
- "`pca`"
|
||||
- "`mean_amr_distance`"
|
||||
|
||||
- title: "Reference data"
|
||||
desc: >
|
||||
The data sets underlying this package, all of which can also be [downloaded in other formats](../articles/datasets.html).
|
||||
- subtitle: "Microorganisms"
|
||||
contents:
|
||||
- "`microorganisms`"
|
||||
- "`antimicrobials`"
|
||||
- "`clinical_breakpoints`"
|
||||
- "`example_isolates`"
|
||||
- "`esbl_isolates`"
|
||||
- "`microorganisms.codes`"
|
||||
- "`microorganisms.groups`"
|
||||
- "`intrinsic_resistant`"
|
||||
- "`dosage`"
|
||||
- subtitle: "Antimicrobials"
|
||||
contents:
|
||||
- "`antimicrobials`"
|
||||
- "`WHOCC`"
|
||||
- "`dosage`"
|
||||
- subtitle: "Breakpoints and intrinsic resistance"
|
||||
contents:
|
||||
- "`clinical_breakpoints`"
|
||||
- "`intrinsic_resistant`"
|
||||
- subtitle: "Example data"
|
||||
contents:
|
||||
- "`example_isolates`"
|
||||
- "`example_isolates_unclean`"
|
||||
- "`esbl_isolates`"
|
||||
- "`WHONET`"
|
||||
|
||||
- title: "Other: miscellaneous functions"
|
||||
- title: "Utilities"
|
||||
desc: >
|
||||
Miscellaneous functions that support various parts of an AMR analysis,
|
||||
such as working with ages, joining tables, principal component analysis,
|
||||
and other utilities. Especially the 'like' function can be useful:
|
||||
`if (x %like% y) {...}`.
|
||||
Helper functions for pattern matching with `%like%`, ages, joining and italicising taxonomy, generating random test results, and data export.
|
||||
contents:
|
||||
- "`age_groups`"
|
||||
- "`age`"
|
||||
- "`amr_course`"
|
||||
- "`export_ncbi_biosample`"
|
||||
- "`availability`"
|
||||
- "`get_AMR_locale`"
|
||||
- "`italicise_taxonomy`"
|
||||
- "`join`"
|
||||
- "`like`"
|
||||
- "`mo_matching_score`"
|
||||
- "`pca`"
|
||||
- "`age`"
|
||||
- "`age_groups`"
|
||||
- "`join`"
|
||||
- "`italicise_taxonomy`"
|
||||
- "`random`"
|
||||
|
||||
- title: "Other: statistical tests"
|
||||
desc: >
|
||||
Some statistical tests or methods usable for AMR analyses are not part of base R and were added to this package for convenience.
|
||||
- "`export_ncbi_biosample`"
|
||||
- subtitle: "Statistical tests"
|
||||
contents:
|
||||
- "`g.test`"
|
||||
- "`kurtosis`"
|
||||
- "`skewness`"
|
||||
|
||||
- title: "Other: deprecated functions/arguments/datasets"
|
||||
- title: "Deprecated functions"
|
||||
desc: >
|
||||
These objects are deprecated, meaning that they will still
|
||||
work but show a warning that they will be removed
|
||||
in a future version.
|
||||
These still work, but show a warning and will be removed in a future version.
|
||||
contents:
|
||||
- "`AMR-deprecated`"
|
||||
- "`resistance_predict`"
|
||||
@@ -5,7 +5,7 @@
|
||||
\alias{custom_eucast_rules}
|
||||
\alias{ab_class}
|
||||
\alias{ab_selector}
|
||||
\title{Deprecated Functions, Arguments, or Datasets}
|
||||
\title{Deprecated Functions, Arguments, or Data Sets}
|
||||
\usage{
|
||||
custom_eucast_rules(...)
|
||||
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
% Please edit documentation in R/aa_options.R
|
||||
\name{AMR-options}
|
||||
\alias{AMR-options}
|
||||
\title{Options for the AMR package}
|
||||
\title{Options for the AMR Package}
|
||||
\description{
|
||||
This is an overview of all the package-specific options you can set in the \code{AMR} package. Set them using the \code{\link[=options]{options()}} function, e.g.:
|
||||
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
\alias{ab_info}
|
||||
\alias{ab_url}
|
||||
\alias{set_ab_names}
|
||||
\title{Get Properties of an Antibiotic}
|
||||
\title{Get Properties of an Antimicrobial Drug}
|
||||
\usage{
|
||||
ab_name(x, language = get_AMR_locale(), tolower = FALSE, ...)
|
||||
|
||||
|
||||
@@ -147,4 +147,3 @@ if (require("tidymodels")) {
|
||||
\seealso{
|
||||
\code{\link[recipes:recipe]{recipes::recipe()}}, \code{\link[=as.sir]{as.sir()}}, \code{\link[=as.mic]{as.mic()}}, \code{\link[=as.disk]{as.disk()}}
|
||||
}
|
||||
\keyword{internal}
|
||||
+1
-1
@@ -6,7 +6,7 @@
|
||||
\alias{is.ab}
|
||||
\alias{ab_reset_session}
|
||||
\alias{NA_ab_}
|
||||
\title{Transform Input to an Antibiotic ID}
|
||||
\title{Transform Input to an Antimicrobial Drug ID}
|
||||
\usage{
|
||||
as.ab(
|
||||
x,
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
% Please edit documentation in R/guess_ab_col.R
|
||||
\name{guess_ab_col}
|
||||
\alias{guess_ab_col}
|
||||
\title{Guess Antibiotic Column}
|
||||
\title{Guess Antimicrobial Column}
|
||||
\usage{
|
||||
guess_ab_col(
|
||||
x = NULL,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
\name{italicise_taxonomy}
|
||||
\alias{italicise_taxonomy}
|
||||
\alias{italicize_taxonomy}
|
||||
\title{Italicise Taxonomic Families, Genera, Species, Subspecies}
|
||||
\title{Italicise Taxonomic Families, Genera, Species, and Subspecies}
|
||||
\usage{
|
||||
italicise_taxonomy(string, type = c("markdown", "ansi", "html"))
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
\alias{random_mic}
|
||||
\alias{random_disk}
|
||||
\alias{random_sir}
|
||||
\title{Random MIC Values/Disk Zones/SIR Generation}
|
||||
\title{Generate Random MIC Values, Disk Zones, or SIR Results}
|
||||
\usage{
|
||||
random_mic(
|
||||
size = NULL,
|
||||
|
||||
+203
-12
@@ -68,12 +68,56 @@
|
||||
--bs-dropdown-link-active-color: white !important;
|
||||
}
|
||||
|
||||
/* mode-dependent colours; light mode is enforced in _pkgdown.yml (light-switch: false), the dark values below are prepared for when it is enabled; they are set on :root only, since pkgdown also marks the navbar as dark */
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--amr-code-literal: var(--bs-dark);
|
||||
--amr-code-muted: var(--bs-gray-600);
|
||||
--amr-search-text: #0b3d33;
|
||||
--amr-search-placeholder: rgba(11, 61, 51, 0.65);
|
||||
--amr-accent: var(--amr-green-dark); /* green for text; --amr-green-dark is the brand colour for backgrounds such as the navbar */
|
||||
--amr-accent-rgb: var(--amr-green-dark-rgb);
|
||||
--amr-text-muted: #5b6770;
|
||||
--amr-ref-border: #e3e8e6;
|
||||
--amr-filter-border: #c4cdca;
|
||||
--amr-filter-placeholder: #7b8783;
|
||||
--amr-filter-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237b8783' stroke-width='1.75' stroke-linecap='round'%3E%3Ccircle cx='6.75' cy='6.75' r='5'/%3E%3Cpath d='M10.5 10.5l4 4'/%3E%3C/svg%3E");
|
||||
--amr-filter-clear: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%237b8783' stroke-width='1.75' stroke-linecap='round'%3E%3Cpath d='M4 4l8 8M12 4l-8 8'/%3E%3C/svg%3E");
|
||||
--amr-chip-bg: #f4f6f5;
|
||||
--amr-chip-border: #dde3e1;
|
||||
--amr-chip-match-bg: rgba(var(--amr-green-light-rgb), 0.5);
|
||||
--amr-badge-bg: var(--amr-green-dark);
|
||||
--amr-badge-text: white;
|
||||
}
|
||||
:root[data-bs-theme="dark"] {
|
||||
color-scheme: dark;
|
||||
--amr-accent: #4fc3a1;
|
||||
--amr-accent-rgb: 79, 195, 161;
|
||||
--bs-link-color: var(--amr-accent) !important;
|
||||
--bs-link-color-rgb: var(--amr-accent-rgb) !important;
|
||||
--amr-green-middle: #8fd1c1;
|
||||
--amr-green-middle-rgb: 143, 209, 193;
|
||||
--amr-code-literal: var(--bs-gray-300);
|
||||
--amr-code-muted: var(--bs-gray-500);
|
||||
--amr-text-muted: var(--bs-gray-400);
|
||||
--amr-ref-border: rgba(255, 255, 255, 0.1);
|
||||
--amr-filter-border: rgba(255, 255, 255, 0.25);
|
||||
--amr-filter-placeholder: var(--bs-gray-500);
|
||||
--amr-filter-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23adb5bd' stroke-width='1.75' stroke-linecap='round'%3E%3Ccircle cx='6.75' cy='6.75' r='5'/%3E%3Cpath d='M10.5 10.5l4 4'/%3E%3C/svg%3E");
|
||||
--amr-filter-clear: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23adb5bd' stroke-width='1.75' stroke-linecap='round'%3E%3Cpath d='M4 4l8 8M12 4l-8 8'/%3E%3C/svg%3E");
|
||||
--amr-chip-bg: rgba(255, 255, 255, 0.04);
|
||||
--amr-chip-border: rgba(255, 255, 255, 0.14);
|
||||
--amr-chip-match-bg: rgba(var(--amr-accent-rgb), 0.25);
|
||||
}
|
||||
|
||||
/* Python page */
|
||||
body.amr-for-python * {
|
||||
--amr-green-light: #FFD43B; /* Python yellow */
|
||||
--amr-green-light-rgb: 255, 212, 59;
|
||||
--amr-green-dark: #306998; /* Python blue */
|
||||
--amr-green-dark-rgb: 48, 105, 152;
|
||||
--amr-accent: var(--amr-green-dark);
|
||||
--amr-accent-rgb: var(--amr-green-dark-rgb);
|
||||
--amr-green-middle: #b1bc5e; /* Adjusted middle yellow */
|
||||
--amr-green-middle-rgb: 177, 188, 94;
|
||||
--bs-success: var(--amr-green-dark) !important;
|
||||
@@ -114,13 +158,16 @@ body.amr-for-python * {
|
||||
opacity: 0.75;
|
||||
font-size: 0.85em;
|
||||
}
|
||||
input[type="search"] {
|
||||
color: var(--bs-tertiary-bg) !important;
|
||||
.navbar input[type="search"] {
|
||||
color: var(--amr-search-text) !important;
|
||||
background-color: var(--amr-green-light) !important;
|
||||
max-width: 160px;
|
||||
max-width: 220px;
|
||||
border-color: var(--amr-green-dark) !important;
|
||||
border-radius: 2px !important;
|
||||
}
|
||||
.navbar input[type="search"]::placeholder {
|
||||
color: var(--amr-search-placeholder) !important;
|
||||
}
|
||||
.dropdown-item:hover,
|
||||
.dropdown-item:focus {
|
||||
background-color: var(--bs-tertiary-bg) !important;
|
||||
@@ -149,6 +196,8 @@ blockquote {
|
||||
}
|
||||
p {
|
||||
text-align: justify;
|
||||
/* pkgdown only hyphenates on small screens; justified text needs it on all screens */
|
||||
hyphens: auto;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -167,10 +216,152 @@ this shows on top of every sidebar to the right
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
/* REFERENCE INDEX ('Manual'), see pkgdown/templates/content-reference-index.html */
|
||||
.template-reference-index {
|
||||
--amr-navbar-height: 72px; /* set exactly by extra.js */
|
||||
}
|
||||
.template-reference-index .section-desc {
|
||||
font-style: italic;
|
||||
text-align: justify;
|
||||
font-size: 16px;
|
||||
hyphens: auto;
|
||||
color: var(--amr-text-muted);
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
.template-reference-index h2 {
|
||||
margin-top: 2.5rem;
|
||||
padding-bottom: 0.3rem;
|
||||
border-bottom: 2px solid var(--amr-green-dark);
|
||||
}
|
||||
.amr-ref-filter + .section h2 {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.template-reference-index h3 {
|
||||
margin-top: 1.25rem;
|
||||
font-size: 1.1rem;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: var(--amr-accent);
|
||||
}
|
||||
/* while filtering, sub-headings show the title of their section, as the section heading may be far above */
|
||||
.amr-ref-filtering main h3[data-amr-parent]::before {
|
||||
content: attr(data-amr-parent) " \203A";
|
||||
display: block;
|
||||
font-size: 0.8rem;
|
||||
font-weight: normal;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
color: var(--amr-text-muted);
|
||||
}
|
||||
/* filter field, sticky below the navbar */
|
||||
.amr-ref-filter {
|
||||
clear: right; /* start below the package logo, which pkgdown lets hang below the page header */
|
||||
position: sticky;
|
||||
top: var(--amr-navbar-height);
|
||||
z-index: 10;
|
||||
padding: 0.75rem 0;
|
||||
background: var(--bs-body-bg);
|
||||
}
|
||||
.amr-ref-filter.amr-ref-stuck {
|
||||
box-shadow: 0 1px 0 var(--amr-ref-border);
|
||||
}
|
||||
#amr-ref-filter-input {
|
||||
width: 100%;
|
||||
max-width: none;
|
||||
padding-left: 2.5rem;
|
||||
color: var(--bs-body-color);
|
||||
background: var(--bs-body-bg) var(--amr-filter-icon) no-repeat left 0.85rem center / 1rem 1rem;
|
||||
border: 1px solid var(--amr-filter-border);
|
||||
border-radius: 2px;
|
||||
}
|
||||
#amr-ref-filter-input::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
background: var(--amr-filter-clear) no-repeat center / 1rem 1rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
#amr-ref-filter-input::placeholder {
|
||||
color: var(--amr-filter-placeholder);
|
||||
}
|
||||
#amr-ref-filter-input:focus {
|
||||
border-color: var(--amr-accent);
|
||||
box-shadow: 0 0 0 1px var(--amr-accent) !important;
|
||||
}
|
||||
.amr-ref-filter-status {
|
||||
font-size: 0.85rem;
|
||||
padding-top: 0.35rem;
|
||||
color: var(--amr-text-muted);
|
||||
}
|
||||
.amr-ref-filter-status:empty {
|
||||
display: none;
|
||||
}
|
||||
/* topics: title first, function names as chips below */
|
||||
.amr-ref-list {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.amr-ref-item {
|
||||
padding: 0.6rem 0 0.35rem;
|
||||
border-bottom: 1px solid var(--amr-ref-border);
|
||||
}
|
||||
.amr-ref-item dt {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
column-gap: 0.5rem;
|
||||
font-weight: bold !important;
|
||||
margin-bottom: 0.3rem;
|
||||
}
|
||||
.amr-ref-item dt a {
|
||||
color: var(--bs-body-color);
|
||||
}
|
||||
.amr-ref-item dt a:hover {
|
||||
color: var(--amr-accent);
|
||||
}
|
||||
.template-reference-index .amr-ref-item dd {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 0.85rem;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.amr-ref-item dd code {
|
||||
display: inline-block;
|
||||
margin: 0 0.25rem 0.3rem 0;
|
||||
padding: 0 0.4rem;
|
||||
background: var(--amr-chip-bg);
|
||||
border: 1px solid var(--amr-chip-border);
|
||||
border-radius: 2px;
|
||||
}
|
||||
.amr-ref-item dd code.amr-ref-match {
|
||||
background: var(--amr-chip-match-bg);
|
||||
border-color: var(--amr-accent);
|
||||
}
|
||||
.amr-ref-item:not(.amr-ref-expanded) dd code.amr-ref-extra:not(.amr-ref-match) {
|
||||
display: none;
|
||||
}
|
||||
.amr-ref-more {
|
||||
border: none;
|
||||
background: none;
|
||||
padding: 0;
|
||||
font-size: 0.85rem;
|
||||
color: var(--amr-accent);
|
||||
cursor: pointer;
|
||||
}
|
||||
.amr-ref-more:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.amr-ref-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
.amr-ref-textmatch dt::after {
|
||||
content: "mentioned on this page";
|
||||
padding: 0 0.45rem;
|
||||
font-weight: bold;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.6;
|
||||
color: var(--amr-badge-text);
|
||||
background: var(--amr-badge-bg);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@media (max-width: 575.98px) {
|
||||
@@ -192,7 +383,7 @@ this shows on top of every sidebar to the right
|
||||
|
||||
.template-reference-topic h3,
|
||||
.template-reference-topic h3 code {
|
||||
color: var(--amr-green-dark) !important;
|
||||
color: var(--amr-accent) !important;
|
||||
}
|
||||
.template-reference-topic h3 {
|
||||
font-weight: normal;
|
||||
@@ -232,11 +423,11 @@ code, .code {
|
||||
.ot, .dv, .fl, .cn, .at,
|
||||
.op a {
|
||||
/* numbers, TRUE/FALSE and operators */
|
||||
color: var(--bs-dark) !important;
|
||||
color: var(--amr-code-literal) !important;
|
||||
}
|
||||
pre .fu, .fu {
|
||||
/* functions */
|
||||
color: var(--amr-green-dark) !important;
|
||||
color: var(--amr-accent) !important;
|
||||
}
|
||||
pre .fu a:hover, .fu a:hover {
|
||||
/* functions */
|
||||
@@ -249,18 +440,18 @@ pre .st, .st {
|
||||
}
|
||||
pre .co, .co {
|
||||
/* comments */
|
||||
color: var(--amr-green-dark) !important;
|
||||
color: var(--amr-accent) !important;
|
||||
font-style: italic !important;
|
||||
}
|
||||
div.sourceCode pre .co,
|
||||
div.sourceCode .co {
|
||||
/* comments in example sections, since functions are already green too */
|
||||
color: var(--bs-gray-600) !important;
|
||||
color: var(--amr-code-muted) !important;
|
||||
}
|
||||
pre code .r-out,
|
||||
pre code .r-msg {
|
||||
/* output of functions */
|
||||
color: var(--bs-gray-600) !important;
|
||||
color: var(--amr-code-muted) !important;
|
||||
font-style: normal !important;
|
||||
}
|
||||
code a[href],
|
||||
@@ -269,7 +460,7 @@ pre a[href],
|
||||
a code[href],
|
||||
a pre[href] {
|
||||
/* adjusted colour for all real links; having href attribute */
|
||||
color: var(--amr-green-dark);
|
||||
color: var(--amr-accent);
|
||||
text-decoration: none;
|
||||
}
|
||||
a[href] {
|
||||
|
||||
@@ -64,6 +64,177 @@ $(function () {
|
||||
document.title = document.title.replace("Package index", "Manual");
|
||||
}
|
||||
|
||||
// reference index ('Manual'): collapse long function lists and filter topics, see pkgdown/templates/content-reference-index.html
|
||||
if ($(".amr-ref-item").length > 0) {
|
||||
const maxAliases = 8;
|
||||
const $body = $(".template-reference-index");
|
||||
const $input = $("#amr-ref-filter-input");
|
||||
const $status = $("#amr-ref-filter-status");
|
||||
const $items = $(".amr-ref-item");
|
||||
const pageText = {}; // full text per reference page, from search.json
|
||||
let pageTextLoaded = false;
|
||||
|
||||
// keep the sticky filter field directly below the navbar, which hides when scrolling down
|
||||
const navbar = document.querySelector(".navbar.fixed-top");
|
||||
const filterBar = document.querySelector(".amr-ref-filter");
|
||||
function placeFilter() {
|
||||
const navBottom = navbar ? Math.max(0, navbar.getBoundingClientRect().bottom) : 0;
|
||||
$body.css("--amr-navbar-height", navBottom + "px");
|
||||
$(filterBar).toggleClass("amr-ref-stuck", filterBar.getBoundingClientRect().top <= navBottom + 1 && window.scrollY > 0);
|
||||
}
|
||||
let placing = false;
|
||||
$(window).on("scroll resize", function () {
|
||||
if (placing) return;
|
||||
placing = true;
|
||||
// follow the navbar during its slide transition
|
||||
const start = performance.now();
|
||||
(function step(now) {
|
||||
placeFilter();
|
||||
if (now - start < 400) requestAnimationFrame(step); else placing = false;
|
||||
})(start);
|
||||
});
|
||||
placeFilter();
|
||||
|
||||
// headings that are jumped to (e.g. from 'On this page') must end up below the filter field, and below the navbar
|
||||
// when jumping up, since the navbar only shows when scrolling up
|
||||
$(document).on("click", 'a[href^="#"]', function () {
|
||||
const target = document.getElementById(decodeURIComponent($(this).attr("href").slice(1)));
|
||||
if (!target) return;
|
||||
const up = target.getBoundingClientRect().top < 0;
|
||||
document.documentElement.style.scrollPaddingTop = ((up && navbar ? navbar.offsetHeight : 0) + filterBar.offsetHeight + 8) + "px";
|
||||
});
|
||||
// the same when opening a link to a section, as the browser jumps before this script runs
|
||||
if (window.location.hash) {
|
||||
const target = document.getElementById(decodeURIComponent(window.location.hash.slice(1)));
|
||||
if (target) {
|
||||
document.documentElement.style.scrollPaddingTop = (filterBar.offsetHeight + 8) + "px";
|
||||
target.scrollIntoView();
|
||||
}
|
||||
}
|
||||
|
||||
function updateMoreButton($item) {
|
||||
const nHidden = $item.find("code.amr-ref-extra:not(.amr-ref-match)").length;
|
||||
$item.find(".amr-ref-more").text("+ " + nHidden + " more").toggle(nHidden > 0);
|
||||
}
|
||||
|
||||
$items.each(function () {
|
||||
const $item = $(this);
|
||||
const $codes = $item.find("dd code");
|
||||
// pkgdown puts backticks around non-syntactic names, e.g. `%like%`
|
||||
$codes.find("a").each(function () {
|
||||
const name = $(this).text();
|
||||
if (/^`.+`$/.test(name)) $(this).text(name.slice(1, -1));
|
||||
});
|
||||
$item.data("page", $item.find("dt a").attr("href"));
|
||||
$item.data("text", ($item.find("dt").text() + " " + $item.find("dd").text()).toLowerCase());
|
||||
// do not offer to show only one or two more
|
||||
if ($codes.length > maxAliases + 2) {
|
||||
$codes.slice(maxAliases).addClass("amr-ref-extra");
|
||||
$item.find("dd").append('<button type="button" class="amr-ref-more"></button>');
|
||||
updateMoreButton($item);
|
||||
}
|
||||
});
|
||||
let h2Title = "";
|
||||
$(".template-reference-index main").find("h2, h3").each(function () {
|
||||
if (this.tagName === "H2") h2Title = $(this).text().trim();
|
||||
else $(this).attr("data-amr-parent", h2Title);
|
||||
});
|
||||
$(".amr-ref-more").on("click", function () {
|
||||
$(this).closest(".amr-ref-item").addClass("amr-ref-expanded");
|
||||
$(this).remove();
|
||||
});
|
||||
|
||||
function loadPageText() {
|
||||
if (pageTextLoaded) return;
|
||||
pageTextLoaded = true;
|
||||
$.getJSON($("#search-input").data("search-index") || "../search.json", function (data) {
|
||||
data.forEach(function (x) {
|
||||
if (x.dir !== "Reference") return;
|
||||
const page = x.path.split("/").pop();
|
||||
pageText[page] = (pageText[page] || "") + " " + (x.what + " " + x.text + " " + x.code).toLowerCase();
|
||||
});
|
||||
filter();
|
||||
});
|
||||
}
|
||||
|
||||
function filter() {
|
||||
const terms = $.trim($input.val()).toLowerCase().split(/\s+/).filter(Boolean);
|
||||
$body.toggleClass("amr-ref-filtering", terms.length > 0);
|
||||
let nDirect = 0;
|
||||
let nText = 0;
|
||||
$items.each(function () {
|
||||
const $item = $(this);
|
||||
const $codes = $item.find("dd code");
|
||||
const direct = terms.length > 0 && terms.every(t => $item.data("text").includes(t));
|
||||
const text = terms.length > 0 && !direct && terms.every(t => (pageText[$item.data("page")] || "").includes(t));
|
||||
$item.toggleClass("amr-ref-hidden", terms.length > 0 && !direct && !text);
|
||||
$item.toggleClass("amr-ref-textmatch", text);
|
||||
// highlight the function names that match, which also reveals them if collapsed
|
||||
$codes.each(function () {
|
||||
const name = $(this).text().toLowerCase();
|
||||
$(this).toggleClass("amr-ref-match", direct && terms.some(t => name.includes(t)));
|
||||
});
|
||||
updateMoreButton($item);
|
||||
if (direct) nDirect++;
|
||||
if (text) nText++;
|
||||
});
|
||||
// hide headings (with their descriptions) that have no visible topic before the next heading of the same or a higher level;
|
||||
// this follows the document order, since pkgdown puts a heading and its topics in separate sibling blocks
|
||||
const nVisible = new Map();
|
||||
let h2 = null;
|
||||
let h3 = null;
|
||||
$(".template-reference-index main").find("h2, h3, .amr-ref-item").each(function () {
|
||||
if (this.tagName === "H2") {
|
||||
h2 = this;
|
||||
h3 = null;
|
||||
nVisible.set(this, 0);
|
||||
} else if (this.tagName === "H3") {
|
||||
h3 = this;
|
||||
nVisible.set(this, 0);
|
||||
} else if (!$(this).hasClass("amr-ref-hidden")) {
|
||||
if (h2) nVisible.set(h2, nVisible.get(h2) + 1);
|
||||
if (h3) nVisible.set(h3, nVisible.get(h3) + 1);
|
||||
}
|
||||
});
|
||||
nVisible.forEach((n, heading) => $(heading).closest(".section").toggleClass("amr-ref-hidden", n === 0));
|
||||
// blocks that only hold topics
|
||||
$(".template-reference-index main .section").not(":has(h2, h3)").each(function () {
|
||||
$(this).toggleClass("amr-ref-hidden", $(this).find(".amr-ref-item:not(.amr-ref-hidden)").length === 0);
|
||||
});
|
||||
const topics = n => n + (n === 1 ? " topic" : " topics");
|
||||
if (terms.length === 0) {
|
||||
$status.text("");
|
||||
} else if (nDirect + nText === 0) {
|
||||
$status.text(pageTextLoaded ? "No topics found" : "Searching...");
|
||||
} else if (nText === 0) {
|
||||
$status.text(topics(nDirect) + " found by name or title");
|
||||
} else if (nDirect === 0) {
|
||||
$status.text("No topics found by name or title, but " + topics(nText) + " mention it");
|
||||
} else {
|
||||
$status.text(topics(nDirect) + " found by name or title, and " + nText + " more mention it");
|
||||
}
|
||||
placeFilter();
|
||||
}
|
||||
|
||||
$input.on("input", function () {
|
||||
loadPageText();
|
||||
filter();
|
||||
});
|
||||
$input.on("keydown", function (e) {
|
||||
if (e.key === "Escape") {
|
||||
$input.val("");
|
||||
filter();
|
||||
}
|
||||
});
|
||||
// press '/' anywhere to focus the filter field
|
||||
$(document).on("keydown", function (e) {
|
||||
if (e.key === "/" && !$(e.target).is("input, textarea")) {
|
||||
e.preventDefault();
|
||||
$input.trigger("focus");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// remove leading newline in code examples on changelog
|
||||
if ($("body .template-news").length > 0) {
|
||||
$("body .template-news").html($("body .template-news").html().replaceAll('sourceCode R">\n<span', 'sourceCode R"><span'));
|
||||
@@ -160,6 +331,23 @@ $(function () {
|
||||
// add lines between collaborator types
|
||||
$('.template-citation-authors li:contains("Contributor")').first().before('<hr>');
|
||||
$('.template-citation-authors li:contains("Former doctoral advisor")').first().before('<hr>');
|
||||
|
||||
// dark variants of figures: list a file name here and put a file with '_dark' before its extension next to it in pkgdown/assets,
|
||||
// e.g. "logo_umcg.svg" requires "logo_umcg_dark.svg"; images are swapped when the theme is dark, also after switching theme
|
||||
const darkVariants = [];
|
||||
function applyDarkVariants() {
|
||||
const dark = document.documentElement.getAttribute("data-bs-theme") === "dark";
|
||||
$("img").each(function () {
|
||||
const src = $(this).attr("src") || "";
|
||||
const file = src.split(/[?#]/)[0].split("/").pop();
|
||||
const base = file.replace(/_dark(\.\w+)$/, "$1");
|
||||
if (!darkVariants.includes(base)) return;
|
||||
const target = dark ? base.replace(/(\.\w+)$/, "_dark$1") : base;
|
||||
if (file !== target) $(this).attr("src", src.replace(file, target));
|
||||
});
|
||||
}
|
||||
applyDarkVariants();
|
||||
new MutationObserver(applyDarkVariants).observe(document.documentElement, { attributes: true, attributeFilter: ["data-bs-theme"] });
|
||||
});
|
||||
|
||||
$('head').append("<!-- Matomo --><script type='text/javascript'> var _paq = _paq || []; /* tracker methods like 'setCustomDimension' should be called before 'trackPageView' */ _paq.push(['setDomains', ['*.amr-for-r.org']]); _paq.push(['enableCrossDomainLinking']); _paq.push(['trackPageView']); _paq.push(['enableLinkTracking']); (function() { var u='https://analyse.uscloud.nl/'; _paq.push(['setTrackerUrl', u+'piwik.php']); _paq.push(['setSiteId', '3']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); })();</script><!-- End Matomo Code -->");
|
||||
@@ -0,0 +1,33 @@
|
||||
<!-- AMR: adapted from pkgdown's BS5 template, with titles first, function names second, and a filter field (see pkgdown/extra.js) -->
|
||||
<div class="row">
|
||||
<main id="main" class="col-md-9">
|
||||
<div class="page-header">
|
||||
{{#logo}}<img src="{{logo.src}}" class="logo" alt="" >{{/logo}}
|
||||
<h1>{{{pagetitle}}}</h1>
|
||||
</div>
|
||||
|
||||
<div class="amr-ref-filter">
|
||||
<input type="search" id="amr-ref-filter-input" class="form-control" placeholder="Filter, e.g. mo_gramstain or WISCA" aria-label="Filter the manual" autocomplete="off" spellcheck="false">
|
||||
<div id="amr-ref-filter-status" class="amr-ref-filter-status" aria-live="polite"></div>
|
||||
</div>
|
||||
|
||||
{{#rows}}<div {{#slug}}id="{{.}}"{{/slug}} class="section level2">
|
||||
{{#title}}<h2>{{{.}}}</h2>{{/title}}
|
||||
{{#subtitle}}<h3>{{{.}}}</h3>{{/subtitle}}
|
||||
{{#desc}}<div class="section-desc">{{{desc}}}</div>{{/desc}}
|
||||
|
||||
<dl class="amr-ref-list">{{#topics}}
|
||||
<div class="amr-ref-item">
|
||||
<dt><a href="{{path}}">{{{title}}}</a>{{#lifecycle}} <span class="badge lifecycle lifecycle-{{.}}">{{.}}</span>{{/lifecycle}}</dt>
|
||||
<dd>{{#aliases}}<code><a href="{{path}}">{{{.}}}</a></code> {{/aliases}}</dd>
|
||||
</div>
|
||||
{{/topics}}</dl>
|
||||
</div>{{/rows}}
|
||||
</main>
|
||||
|
||||
<aside class="col-md-3">
|
||||
<nav id="toc" aria-label="{{#translate}}{{toc}}{{/translate}}">
|
||||
<h2>{{#translate}}{{on_this_page}}{{/translate}}</h2>
|
||||
</nav>
|
||||
</aside>
|
||||
</div>
|
||||
Reference in new issue
Block a user