main c6f9cac1dc21 cached
48 files
2.2 MB
582.5k tokens
3 symbols
1 requests
Download .txt
Showing preview only (2,330K chars total). Download the full file or copy to clipboard to get everything.
Repository: prisma-flowdiagram/PRISMA2020
Branch: main
Commit: c6f9cac1dc21
Files: 48
Total size: 2.2 MB

Directory structure:
gitextract_rzi0l72b/

├── .Rbuildignore
├── .github/
│   ├── .gitignore
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       ├── build-and-check-CRAN.yml
│       ├── check-and-deploy.yml
│       └── docker-build-push.yml
├── .gitignore
├── CITATION.cff
├── DESCRIPTION
├── Dockerfile
├── LICENSE
├── LICENSE.md
├── NAMESPACE
├── PRISMA2020.Rproj
├── R/
│   ├── PRISMA_flowdiagram.R
│   ├── globals.R
│   └── utils.R
├── README.md
├── code-of-conduct.md
├── contributing.md
├── inst/
│   ├── CITATION
│   ├── extdata/
│   │   ├── PRISMA.csv
│   │   ├── Template.html
│   │   └── citation.ris
│   └── shiny-examples/
│       └── PRISMA_flowdiagram/
│           ├── app.R
│           ├── rsconnect/
│           │   └── shinyapps.io/
│           │       └── estech/
│           │           └── prisma_flowdiagram.dcf
│           └── www/
│               ├── Haddaway_et_al_2022.ris
│               ├── PRISMA.csv
│               ├── kofi.js
│               └── labels.js
├── man/
│   ├── PRISMA_add_hyperlink_.Rd
│   ├── PRISMA_calc_filetype_.Rd
│   ├── PRISMA_data.Rd
│   ├── PRISMA_flowdiagram.Rd
│   ├── PRISMA_format_number_.Rd
│   ├── PRISMA_format_reasons_.Rd
│   ├── PRISMA_gen_tmp_svg_.Rd
│   ├── PRISMA_get_height_.Rd
│   ├── PRISMA_get_pos_.Rd
│   ├── PRISMA_insert_js_.Rd
│   ├── PRISMA_interactive_.Rd
│   ├── PRISMA_parse_reasons_.Rd
│   ├── PRISMA_save.Rd
│   ├── read_PRISMAdata.Rd
│   └── sr_flow_interactive.Rd
└── shiny-server.conf

================================================
FILE CONTENTS
================================================

================================================
FILE: .Rbuildignore
================================================
^.*\.Rproj$
^\.Rproj\.user$
^\.github$
.png
inst/shiny-examples
LICENSE.md
CITATION.cff
code-of-conduct.md
contributing.md
Dockerfile
shiny-server.conf

================================================
FILE: .github/.gitignore
================================================
*.html


================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
open_collective: esmarconf
ko_fi: chriscpritchard



================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error

**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.

**Desktop (please complete the following information):**
 - OS: [e.g. iOS]
 - Browser [e.g. chrome, safari]
 - Version [e.g. 22]

**Smartphone (please complete the following information):**
 - Device: [e.g. iPhone6]
 - OS: [e.g. iOS8.1]
 - Browser [e.g. stock browser, safari]
 - Version [e.g. 22]

**Additional context**
Add any other context about the problem here.


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''

---

**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .github/workflows/build-and-check-CRAN.yml
================================================
on:
  push:
    tags:
      - 'v*'
name: Publish Release, Build & Check for CRAN
jobs:
  R-CMD-Build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: r-lib/actions/setup-r@v2
        with:
          r-version: 'release'
          use-public-rspm: true
      - uses: r-lib/actions/setup-pandoc@v2
      - uses: r-lib/actions/setup-tinytex@v2
      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: |
            devtools
            rcmdcheck
      - name: Build
        run: R CMD build .
      - uses: actions/upload-artifact@v3
        with:
          name: package
          path: "*.tar.gz"
  R-CMD-Check-As-CRAN:
    runs-on: ubuntu-latest
    needs: R-CMD-Build
    steps:
      - uses: actions/checkout@v3
      - uses: r-lib/actions/setup-r@v2
        with:
          r-version: 'devel'
          use-public-rspm: true
      - uses: r-lib/actions/setup-pandoc@v2
      - uses: r-lib/actions/setup-tinytex@v2
      - uses: r-lib/actions/setup-r-dependencies@v2
        with:
          extra-packages: |
            devtools
            rcmdcheck
      - uses: actions/download-artifact@v3
        with:
          name: package
      - name: Check
        run: R CMD check --as-cran *.tar.gz
      - uses: actions/upload-artifact@v3
        with:
          name: check
          path: "*.Rcheck"
  release:
    runs-on: ubuntu-latest
    needs: R-CMD-Check-As-CRAN
    permissions:
      contents: write
    steps:
    - uses: actions/checkout@v3
    - uses: actions/download-artifact@v3
    - uses: ncipollo/release-action@v1
      with:
        artifacts: "**/*.tar.gz,**/*.Rcheck/*.log,**/*.Rcheck/*-manual.pdf"
  deploy-release:
    needs: release
    uses: prisma-flowdiagram/r-workflows/.github/workflows/deploy.yml@v1
    with:
      install-package: true
      rsconnect-account-name: "estech"
      rsconnect-app-name: "PRISMA_flowdiagram"
      working-directory: "./inst/shiny-examples/PRISMA_flowdiagram"
      environment: "release"
      renvironment-contents: |
        PRISMA_ANALYTICS=TRUE   
        KOFI_DONATE=TRUE 
    secrets:
      rsconnect-account-token: ${{ secrets.TOKEN }}
      rsconnect-account-secret: ${{ secrets.SECRET }}

================================================
FILE: .github/workflows/check-and-deploy.yml
================================================
on:
  release:
    types: [released]
  pull_request:
    types: [opened, synchronize, reopened]
  issue_comment:
    types: [created]
  push:
    branches:
      - main
      - master
name: Check & Deploy
jobs:
  R-CMD-Check:
    if: (github.event_name != 'issue_comment')
    uses: prisma-flowdiagram/r-workflows/.github/workflows/R-CMD-check.yml@v1
  pkgdown:
    needs: R-CMD-check
    if: (github.event_name == 'push')
    uses: prisma-flowdiagram/r-workflows/.github/workflows/pkgdown.yml@v1
  deploy-latest:
    needs: pkgdown
    if: (github.event_name == 'push')
    uses: prisma-flowdiagram/r-workflows/.github/workflows/deploy.yml@v1
    with:
      install-package: true
      rsconnect-account-name: "estech"
      rsconnect-app-name: "PRISMA_flowdiagram_latest"
      working-directory: "./inst/shiny-examples/PRISMA_flowdiagram"
      environment: "latest"
      renvironment-contents: |
        PRISMA_ANALYTICS=TRUE     
        KOFI_DONATE=TRUE 
    secrets:
      rsconnect-account-token: ${{ secrets.TOKEN }}
      rsconnect-account-secret: ${{ secrets.SECRET }}
  check-pr-deploy:
    runs-on: ubuntu-latest
    if: github.event_name == 'issue_comment'
    outputs:
      triggered: ${{ steps.check-pr.outputs.triggered }}
    steps:
      - uses: khan/pull-request-comment-trigger@v1.1.0
        id: check-pr
        with:
          trigger: '!deploy'
          reaction: rocket
        env:
          GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
  get-pull-ref:
    runs-on: ubuntu-latest
    needs: check-pr-deploy
    if: (github.event_name == 'issue_comment'  && github.event.issue.pull_request)
    outputs:
      repository: ${{ fromJson(steps.get-repo.outputs.data).head.repo.full_name }}
      ref: ${{ fromJson(steps.get-repo.outputs.data).head.ref }}
    steps:
      - name: get-pull-request-ref
        id: get-repo
        uses: octokit/request-action@v2.x
        with:
          route: GET /repos/:repository/pulls/:issue_id
          repository: ${{ github.repository }}
          issue_id: ${{ github.event.issue.number }}
        env:
          GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
  R-CMD-check-PR:
    needs: [check-pr-deploy,get-pull-ref]
    if: needs.check-pr-deploy.outputs.triggered == 'true'
    uses: prisma-flowdiagram/r-workflows/.github/workflows/R-CMD-check.yml@v1
    with:
      repository: ${{ needs.get-pull-ref.outputs.repository || github.repository }}
      ref: ${{ needs.get-pull-ref.outputs.ref || github.ref }}
  deploy-pr-comment:
    needs: [get-pull-ref,R-CMD-check-PR]
    uses: prisma-flowdiagram/r-workflows/.github/workflows/deploy.yml@v1
    with:
      repository: ${{ needs.get-pull-ref.outputs.repository || github.repository }}
      ref: ${{ needs.get-pull-ref.outputs.ref || github.ref }}
      install-package: true
      rsconnect-account-name: "prismaflow-test"
      rsconnect-app-name: "PRISMA_flowdiagram"
      working-directory: "./inst/shiny-examples/PRISMA_flowdiagram"
      environment: "pr"
    secrets:
      rsconnect-account-token: ${{ secrets.TOKEN }}
      rsconnect-account-secret: ${{ secrets.SECRET }}

================================================
FILE: .github/workflows/docker-build-push.yml
================================================
name: Docker

on:
  push:
    branches:
      - master
    tags:
      - v*

env:
  IMAGE_NAME: prisma-flowdiagram/prisma-flowdiagram-shinyapp

jobs:
  docker:
    runs-on: ubuntu-latest
    if: github.event_name == 'push'

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Determine target image name
        id: image-name
        run: |
          IMAGE_ID=ghcr.io/$IMAGE_NAME

          # Strip git ref prefix from version
          VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')

          # Strip "v" prefix from tag name
          [[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')

          # Use Docker `latest` tag convention
          [ "$VERSION" == "master" ] && VERSION=latest

          IMAGES=
          IMAGES="$IMAGE_ID:$VERSION"$'\n'$IMAGES

          # debug output
          echo images $IMAGES
          echo ::set-output name=images::"$IMAGES"

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v1

      - name: Login to registry
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v2
        with:
          context: .
          platforms: linux/amd64,linux/arm64,linux/arm/v7
          push: true
          tags: ${{ steps.image-name.outputs.images }}


================================================
FILE: .gitignore
================================================
.Rproj.user
.Rhistory
.RData
.Ruserdata
.vscode/launch.json
**/.DS_Store

================================================
FILE: CITATION.cff
================================================
cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
  - family-names: Haddaway
    given-names: Neal
    orcid: https://orcid.org/0000-0003-3902-2234
  - family-names: McGuinness
    given-names: Luke A
    orcid: https://orcid.org/0000-0001-8730-9761
  - family-names: Pritchard
    given-names: Chris C
    orcid: https://orcid.org/0000-0002-1143-9751
title: "PRISMA2020: R package and ShinyApp for producing PRISMA 2020 compliant flow diagrams"
version: 1.1.0
doi: 10.5281/zenodo.4287834
date-released: 2023-02-06
license: MIT
url: "https://github.com/prisma-flowdiagram/PRISMA2020"
preferred-citation:
  type: article
  authors:
  - family-names: Haddaway
    given-names: Neal
    orcid: https://orcid.org/0000-0003-3902-2234
  - family-names: Page
    given-names: Matthew J
    orcid: https://orcid.org/0000-0002-4242-7526
  - family-names: Pritchard
    given-names: Chris C
    orcid: https://orcid.org/0000-0002-1143-9751
  - family-names: McGuinness
    given-names: Luke A
    orcid: https://orcid.org/0000-0001-8730-9761
  doi: "10.1002/cl2.1230"
  journal: "Campbell Systematic Reviews"
  title: "PRISMA2020: an R package and Shiny app for producing PRISMA 2020-compliant flow diagrams, with interactivity for optimised digital transparency and Open Synthesis"
  year: 2022

================================================
FILE: DESCRIPTION
================================================
Package: PRISMA2020
Title: Make Interactive 'PRISMA' Flow Diagrams
Version: 1.1.2
Authors@R: c(
    person(given = "Neal",
           family = "Haddaway",
           role = "aut",
           email = "nealhaddaway@gmail.com",
           comment = c(ORCID = "0000-0003-3902-2234")),
    person("Luke", "McGuinness", role = "aut",
           email = "luke.mcguinness@bristol.ac.uk",
           comment = c(ORCID = "0000-0001-8730-9761")),
    person("Chris", "Pritchard", role = c("aut", "cre"),
            email = "chris.pritchard@ntu.ac.uk",
            comment = c(ORCID = "0000-0002-1143-9751")),
    person("Brennan", "Chapman", role = "ctb"),
    person("Hossam", "Hammady", role= "ctb"))
Description: Systematic reviews should be described in a high degree of 
    methodological detail. The 'PRISMA' Statement calls for a high level of 
    reporting detail in systematic reviews and meta-analyses. An integral part 
    of the methodological description of a review is a flow diagram. 
    This package produces an interactive flow diagram that conforms to the 
    'PRISMA2020' preprint. When made interactive, the reader/user can click 
    on each box and be directed to another website or file online (e.g. a 
    detailed description of the screening methods, or a list of excluded full 
    texts), with a mouse-over tool tip that describes the information linked 
    to in more detail. Interactive versions can be saved as HTML files, 
    whilst static versions for inclusion in manuscripts can be saved as 
    HTML, PDF, PNG, SVG, PS or WEBP files.
Imports:
    DiagrammeR,
    DiagrammeRsvg,
    htmltools,
    htmlwidgets,
    rsvg,
    scales,
    shiny,
    shinyjs,
    stats,
    stringr,
    utils,
    xml2,
    webp,
    DT,
    rio,
    tools,
    zip
License: MIT + file LICENSE
URL: https://github.com/prisma-flowdiagram/PRISMA2020
BugReports: https://github.com/prisma-flowdiagram/PRISMA2020/issues
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2


================================================
FILE: Dockerfile
================================================
FROM rocker/shiny:latest

LABEL maintainer="Hossam Hammady <hossam@rayyan.ai>"

# Install system dependencies
RUN apt-get update -qq && \
    apt-get install -y \
        libssl-dev \
        libfontconfig1-dev \
        libcurl4-openssl-dev \
        libxml2-dev \
        libharfbuzz-dev \
        libfribidi-dev \
        libgit2-dev \
        libfreetype6-dev \
        libpng-dev \
        libtiff-dev \
        libv8-dev \
        librsvg2-dev \
        libwebp-dev \
        pandoc

# Install R packages
RUN Rscript -e 'install.packages(c("DiagrammeR", "DiagrammeRsvg", "htmltools", "htmlwidgets", "scales", "shiny", "shinyjs", "stringr", "xml2", "DT", "rio", "zip", "rsvg", "webp", "devtools"))'

# Copy the shiny server configuration
COPY shiny-server.conf /etc/shiny-server/shiny-server.conf

# Install the PRISMA2020 package
COPY . /tmp/app
RUN R CMD INSTALL /tmp/app

# Copy the shiny app files
RUN mkdir -p /srv/shiny-server/prisma/app && \
    echo "OK" > /srv/shiny-server/prisma/healthz.txt
COPY inst/shiny-examples/PRISMA_flowdiagram/. /srv/shiny-server/prisma/app/

# Clean up downloaded files
RUN rm -rf /tmp/*/downloaded_packages /tmp/app


================================================
FILE: LICENSE
================================================
YEAR: 2020
COPYRIGHT HOLDER: Neal R Haddaway

================================================
FILE: LICENSE.md
================================================
Copyright 2020 Neal R Haddaway

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

================================================
FILE: NAMESPACE
================================================
# Generated by roxygen2: do not edit by hand

export(PRISMA_data)
export(PRISMA_flowdiagram)
export(PRISMA_save)
importFrom(DT,addRow)
importFrom(rio,import)
importFrom(shiny,column)
importFrom(shinyjs,alert)
importFrom(stats,median)
importFrom(utils,apropos)
importFrom(webp,read_webp)


================================================
FILE: PRISMA2020.Rproj
================================================
Version: 1.0

RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: Sweave
LaTeX: pdfLaTeX

BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
PackageRoxygenize: rd,collate,namespace


================================================
FILE: R/PRISMA_flowdiagram.R
================================================
# Suppress R CMD check note
#' @importFrom DT addRow
#' @importFrom rio import
#' @importFrom shiny column
#' @importFrom shinyjs alert
#' @importFrom stats median
#' @importFrom utils apropos
#' @importFrom webp read_webp
NULL
#' Plot interactive flow diagrams for systematic reviews
#' @description Produces a PRISMA2020 style flow diagram
#' for systematic reviews, with the option to add
#' interactivity through tooltips (mouseover popups) and
#' hyperlink URLs to each box.
#' Data can be imported from the standard CSV template provided.
#' @param data List of data inputs including numbers of studies,
#' box text, tooltips, and urls for hyperlinks.
#' Data inputted via the [PRISMA_data()] function.
#' If inputting individually, see the necessary parameters
#' listed in the  [PRISMA_data()]) function and
#' combine them in a list using `data <- list()`.
#' @param interactive Logical argument TRUE or FALSE
#' whether to plot interactivity (tooltips and hyperlinked boxes).
#' @param previous Logical argument (TRUE or FALSE) specifying whether previous
#' studies were sought.
#' @param other Logical argument (TRUE or FALSE) specifying whether
#' other studies were sought.
#' @param detail_databases Logical argument (TRUE or FALSE) specifying whether
#' to list specific databases.
#' @param detail_registers Logical argument (TRUE or FALSE) specifying whether
#' to list specific registers.
#' @param meta_analysis Logical argument (TRUE or FALSE) specifying whether to
#' display a box for meta-analysis
#' @param font The font for text in each box. The default is 'Helvetica'.
#' @param fontsize The font size for text in each box. The default is '12'.
#' @param title_colour The colour for the upper middle title box (new studies).
#' The default is 'Goldenrod1'. See 'DiagrammeR' colour scheme.
#' <http://rich-iannone.github.io/DiagrammeR/graphviz_and_mermaid.html#colors>.
#' @param greybox_colour The colour for the left and right column boxes. The
#' default is 'Gainsboro'. See 'DiagrammeR' colour scheme
#' <http://rich-iannone.github.io/DiagrammeR/graphviz_and_mermaid.html#colors>.
#' @param main_colour The colour for the main box borders. The default is
#' 'Black'. See 'DiagrammeR' colour scheme
#' <http://rich-iannone.github.io/DiagrammeR/graphviz_and_mermaid.html#colors>.
#' @param arrow_colour The colour for the connecting lines. The default
#' is 'Black'. See 'DiagrammeR' colour scheme
#' <http://rich-iannone.github.io/DiagrammeR/graphviz_and_mermaid.html#colors>.
#' @param arrow_head The head shape for the line connectors. The default is
#' 'normal'. See DiagrammeR arrow shape specification
#' <http://rich-iannone.github.io/DiagrammeR/graphviz_and_mermaid.html#arrow-shapes>. #nolint
#' @param arrow_tail The tail shape for the line connectors. The default is
#' 'none'. See DiagrammeR arrow shape specification
#' <http://rich-iannone.github.io/DiagrammeR/graphviz_and_mermaid.html#arrow-shapes>. #nolint
#' @param side_boxes Whether or not to include the
#' blue label boxes along the side
#' @return A flow diagram plot.
#' @examples
#' csvFile <- system.file("extdata", "PRISMA.csv", package = "PRISMA2020")
#' data <- read.csv(csvFile);
#' data <- PRISMA_data(data);
#' plot <- PRISMA_flowdiagram(data,
#'                 fontsize = 12,
#'                 interactive = TRUE,
#'                 previous = FALSE,
#'                 other = TRUE);
#' plot
#' @export
PRISMA_flowdiagram <- function( #nolint
  data,
  interactive = FALSE,
  previous = TRUE,
  other = TRUE,
  detail_databases = FALSE,
  detail_registers = FALSE,
  meta_analysis = FALSE,
  fontsize = 7,
  font = "Helvetica",
  title_colour = "Goldenrod1",
  greybox_colour = "Gainsboro",
  main_colour = "Black",
  arrow_colour = "Black",
  arrow_head = "normal",
  arrow_tail = "none",
  side_boxes = TRUE) {
  # removes the need to attach() the data
  # https://stackoverflow.com/a/11505637
  for (var in seq_len(length(data))) {
    assign(names(data)[var], data[[var]])
  }
  # positional attributes, in inches
  diagram_start_x <- 0
  diagram_start_y <- 0
  prev_study_width <- 0
  prev_study_offset <- 0
  prev_study_height <- 0
  total_studies_height <- 0
  total_ma_height <- 0
  other_identified_height <- 0
  other_sought_reports_height <- 0
  other_notretrieved_height <- 0
  other_assessed_height <- 0
  other_excluded_height <- 0
  default_box_width <- 3.5
  min_box_height <- 0.5
  default_box_spacing <- 0.5
  section_label_length <- 0.4
  top_box_width <- default_box_width * 2 + default_box_spacing
  A <- "" #nolint
  Aedge <- "" #nolint
  bottomedge <- ""
  previous_nodes <- ""
  finalnode <- ""
  metanode <- ""
  prev_rank1 <- ""
  prevnode1 <- ""
  prevnode2 <- ""

  #wrap exclusion reasons
  dbr_excluded[, 1] <- stringr::str_wrap(
    dbr_excluded[, 1],
    width = 35
  )
  other_excluded[, 1] <- stringr::str_wrap(
    other_excluded[, 1],
    width = 35
  )
  # wrap specific database registers
  database_specific_results[, 1] <- stringr::str_wrap(
    database_specific_results[, 1],
    width = 35
  )
  register_specific_results[, 1] <- stringr::str_wrap(
    register_specific_results[, 1],
    width = 35
  )
  #remove previous box if both values are zero
  if (is.na(previous_studies) == TRUE && is.na(previous_reports) == TRUE) {
    previous <- FALSE
  }
  if (previous == TRUE) {
    #conditional studies and reports - empty text if blank
    if (is.na(previous_studies) == TRUE) {
      cond_prevstud <- ""
    } else {
      cond_prevstud <- stringr::str_wrap(
        paste0(
            previous_studies_text,
          " (n = ", previous_studies, ")"
        ),
        width = 40)
    }
    if (is.na(previous_reports) == TRUE) {
      cond_prevrep <- ""
    } else {
      cond_prevrep <- paste0(
        stringr::str_wrap(
          previous_reports_text,
          width = 40
        ),
        "\n(n = ", previous_reports, ")"
      )
    }
    if (is.na(previous_studies) == TRUE || is.na(previous_reports) == TRUE) {
      dbl_br <- ""
    } else {
      dbl_br <- "\n"
    }
    prev_study_label <- paste0(cond_prevstud, dbl_br, cond_prevrep)
    total_studies_label <- paste0(
      stringr::str_wrap(
        paste0(
          total_studies_text,
          " (n = ", total_studies, ")"
        ),
        width = 33
      ),
      "\n",
      stringr::str_wrap(
        paste0(
          total_reports_text,
          " (n = ", total_reports, ")"
        ),
        width = 33
      )
    )
    # we multiply by 2 because we need the width
    # from the start, not just the centre
    prev_study_width <- default_box_width * 2
    prev_study_offset <- default_box_spacing
    prev_box_x <- PRISMA_get_pos_(
      diagram_start_x,
      default_box_spacing,
      default_box_width,
      prev_study_offset
    )
    prev_study_height <- PRISMA_get_height_(
      stringr::str_count(prev_study_label, "\n"),
      min_box_height
    )
    total_studies_height <- PRISMA_get_height_(
      stringr::str_count(total_studies_label, "\n"),
      min_box_height
    )
  }
  # conditionals for the node labels
  if (
    is.na(website_results) == TRUE &&
    is.na(organisation_results) == TRUE &&
    is.na(citations_results) == TRUE
  ) {
    other <- FALSE
  }
  if (other == TRUE) {
    # conditionals for the node labels
    if (is.na(website_results) == FALSE) {
      cond_websites <- paste0(
        "\n",
        website_results_text,
        " (n = ", website_results, ")"
      )
    } else {
      cond_websites <- ""
    }
    if (is.na(organisation_results) == FALSE) {
      cond_organisation <- paste0(
        "\n",
        organisation_results_text,
        " (n = ", organisation_results, ")"
      )
    } else {
      cond_organisation <- ""
    }
    if (is.na(citations_results) == FALSE) {
      cond_citation <- paste0(
        "\n",
        citations_results_text,
        " (n = ", citations_results, ")"
      )
    } else {
      cond_citation <- ""
    }
    other_excluded_data <- PRISMA_format_reasons_(other_excluded) #nolint
    # labels
    other_identified_label <- paste0(
      "Records identified from:",
      cond_websites,
      cond_organisation,
      cond_citation
    )
    other_sought_reports_label <- paste0(
      other_sought_reports_text,
      "\n(n = ",
        other_sought_reports,
      ")"
    )
    other_notretrieved_label <- paste0(
      other_notretrieved_reports_text,
      "\n(n = ",
        other_notretrieved_reports,
      ")"
    )
    other_assessed_label <- paste0(
      other_assessed_text,
      "\n(n = ",
        other_assessed,
      ")"
    )
    other_excluded_label <- paste0(
       other_excluded_text, other_excluded_data
    )
    # heights
    other_identified_height <- PRISMA_get_height_(
      stringr::str_count(other_identified_label, "\n"),
      min_box_height
    )
    other_sought_reports_height <- PRISMA_get_height_(
      stringr::str_count(other_sought_reports_label, "\n"),
      min_box_height
    )
    other_notretrieved_height <- PRISMA_get_height_(
      stringr::str_count(other_notretrieved_label, "\n"),
      min_box_height
    )
    other_assessed_height <- PRISMA_get_height_(
      stringr::str_count(other_assessed_label, "\n"),
      min_box_height
    )
    other_excluded_height <- PRISMA_get_height_(
      stringr::str_count(other_excluded_label, "\n"),
      min_box_height
    )
  }
  if (is.na(new_studies) == FALSE) {
    cond_newstud <- paste0(
      stringr::str_wrap(new_studies_text, width = 40),
      "\n(n = ", new_studies, ")\n"
    )
  } else {
    cond_newstud <- ""
  }
  if (is.na(new_reports) == FALSE) {
    cond_newreports <- paste0(
      stringr::str_wrap(new_reports_text, width = 40),
      "\n(n = ", new_reports, ")"
    )
  } else {
    cond_newreports <- ""
  }
  if (is.na(total_studies_ma) == FALSE) {
    cond_total_studies_ma <- paste0(
      stringr::str_wrap(
        paste0(
          total_studies_ma_text,
          " (n = ", total_studies_ma, ")"
        ),
        width = 33
      ),
      "\n"
    )
  } else {
    cond_total_studies_ma <- ""
  }
  if (is.na(total_reports_ma) == FALSE) {
    cond_total_reports_ma <- stringr::str_wrap(
      paste0(
        total_reports_ma_text,
        " (n = ", total_reports_ma, ")"
      ),
      width = 33
    )
  } else {
    cond_total_reports_ma <- ""
  }
  if (detail_databases == TRUE) {
    db_specific_data <- PRISMA_format_reasons_(database_specific_results) #nolint
  } else {
    db_specific_data <- ""
    db_specific_data_nr <- ""
  }
  if (detail_registers == TRUE) {
    reg_specific_data <- PRISMA_format_reasons_(register_specific_results) #nolint
  } else {
    reg_specific_data <- ""
    reg_specific_data_nr <- ""
  }
  if (is.na(database_results) == FALSE) {
    cond_database <- paste0(
      "\n",
      database_results_text,
      " (n = ", database_results, ")", db_specific_data)
  } else {
    cond_database <- paste0("", db_specific_data_nr)
  }
  if (is.na(register_results) == FALSE) {
    cond_register <- paste0(
      "\n",
      register_results_text,
      " (n = ",  register_results, ")", reg_specific_data)
  } else {
    cond_register <- paste0("", reg_specific_data_nr)
  }
  dbr_excluded_data <- PRISMA_format_reasons_(dbr_excluded) #nolint
  if (is.na(duplicates) == FALSE) {
    cond_duplicates <- paste0(
      stringr::str_wrap(
        paste0(
          duplicates_text,
          " (n = ", duplicates, ")"
        ),
        width = 42
      ),
      "\n"
    )
  } else {
    cond_duplicates <- ""
  }
  if (is.na(excluded_automatic) == FALSE) {
    cond_automatic <- paste0(
      stringr::str_wrap(
        paste0(
          excluded_automatic_text,
          " (n = ", excluded_automatic, ")"
        ),
        width = 42
      ),
      "\n"
    )
  } else {
    cond_automatic <- ""
  }
  if (is.na(excluded_other) == FALSE) {
    cond_exclother <- paste0(
      stringr::str_wrap(
        paste0(
          excluded_other_text,
          " (n = ", excluded_other, ")"
        ),
        width = 42
      )
    )
  } else {
    cond_exclother <- ""
  }
  if (
    is.na(duplicates) == TRUE &&
    is.na(excluded_automatic) == TRUE &&
    is.na(excluded_other) == TRUE
  ) {
    cond_duplicates <- "(n = 0)"
  }
  # labels for the nodes
  newstudy_newreports_label <- paste0(cond_newstud, cond_newreports)
  total_ma_label <- paste0(cond_total_studies_ma, cond_total_reports_ma)
  dbr_assessed_label <- paste0(
    dbr_assessed_text,
    "\n(n = ",
      dbr_assessed,
    ")"
  )
  dbr_sought_label <- paste0(
    dbr_sought_reports_text,
    "\n(n = ",
      dbr_sought_reports,
    ")"
  )
  dbr_screened_label <- paste0(
    records_screened_text,
    "\n(n = ",
      records_screened,
    ")"
  )
  dbr_identified_label <- paste0(
    "Records identified from:",
      cond_database,
      cond_register
  )
  dbr_excluded_label <- paste0(
    dbr_excluded_text,
    dbr_excluded_data
  )
  dbr_notretrieved_label <- paste0(
    dbr_notretrieved_reports_text,
    "\n(n = ",
      dbr_notretrieved_reports,
    ")"
  )
  dbr_screened_excluded_label <- paste0(
    records_excluded_text,
    "\n(n = ",
      records_excluded,
    ")"
  )
  dbr_notscreened_label <- paste0(
    "Records removed before screening:\n",
      cond_duplicates,
      cond_automatic,
      cond_exclother
  )
  # we set the height of various nodes here
  newstudy_newreports_height <- PRISMA_get_height_(
    stringr::str_count(newstudy_newreports_label, "\n"),
    min_box_height
  )
  if (is.na(total_reports_ma) == TRUE && is.na(total_studies_ma) == TRUE) {
    meta_analysis <- FALSE
  }
  if (meta_analysis == TRUE) {
    total_ma_height <- PRISMA_get_height_(
      stringr::str_count(total_ma_label, "\n"),
      min_box_height
    )
  }
  dbr_assessed_height <- PRISMA_get_height_(
    stringr::str_count(dbr_assessed_label, "\n"),
    min_box_height
  )
  dbr_sought_height <- PRISMA_get_height_(
    stringr::str_count(dbr_sought_label, "\n"),
    min_box_height
  )
  dbr_screened_height <- PRISMA_get_height_(
    stringr::str_count(dbr_screened_label, "\n"),
    min_box_height
  )
  dbr_identified_height <- PRISMA_get_height_(
    stringr::str_count(dbr_identified_label, "\n"),
    min_box_height
  )
  dbr_excluded_height <- PRISMA_get_height_(
    stringr::str_count(dbr_excluded_label, "\n"),
    min_box_height
  )
  dbr_notretrieved_height <- PRISMA_get_height_(
    stringr::str_count(dbr_notretrieved_label, "\n"),
    min_box_height
  )
  dbr_screened_excluded_height <- PRISMA_get_height_(
    stringr::str_count(dbr_screened_excluded_label, "\n"),
    min_box_height
  )
  dbr_notscreened_height <- PRISMA_get_height_(
    stringr::str_count(dbr_notscreened_label, "\n"),
    min_box_height
  )
  screening_box_height <- max(
      c(
        dbr_screened_height,
        dbr_screened_excluded_height
      )
    ) + max(
      c(
        dbr_notretrieved_height,
        dbr_sought_height,
        other_sought_reports_height,
        other_notretrieved_height
      )
    ) + max(
      c(
        dbr_assessed_height,
        dbr_excluded_height,
        other_assessed_height,
        other_excluded_height
      )
    ) +
    default_box_spacing * 2
  identification_box_height <- 
    max(
      c(
        dbr_identified_height,
        dbr_notscreened_height,
        prev_study_height,
        other_identified_height
      )
    ) +
    default_box_spacing
  included_box_height <-
    newstudy_newreports_height +
    total_studies_height +
    total_ma_height +
    default_box_spacing * 3
  assessed_height <- max(
    c(
      dbr_assessed_height,
      other_assessed_height,
      dbr_excluded_height,
      other_excluded_height
    )
  )
  sought_height <- max(
    c(
      dbr_sought_height,
      other_sought_reports_height,
      dbr_notretrieved_height,
      other_notretrieved_height
    )
  )
  screened_height <- max(
    c(
      dbr_screened_height,
      dbr_screened_excluded_height
    )
  )
  identified_height <- max(
    c(
      dbr_identified_height,
      dbr_notscreened_height,
      other_identified_height,
      prev_study_height
    )
  )
  warning(included_box_height)
  # here we set the x and y co-ordinates for new studies
  # (other items depend on this being created)
  dbr_box_x <- PRISMA_get_pos_(
    diagram_start_x,
    prev_study_offset + default_box_spacing,
    prev_study_width,
    default_box_width
  )
  dbr_removed_x <- PRISMA_get_pos_(
    dbr_box_x,
    default_box_spacing,
    default_box_width,
    default_box_width
  )
  newstudy_newreports_y <- PRISMA_get_pos_(
    diagram_start_y,
    default_box_spacing,
    total_studies_height,
    newstudy_newreports_height
  )
  if (previous == TRUE) {
    total_ma_y <- PRISMA_get_pos_(
      diagram_start_y,
      default_box_spacing,
      total_studies_height,
      total_ma_height,
      negative_offset = TRUE
    )
  } else {
    total_ma_y <- PRISMA_get_pos_(
      newstudy_newreports_y,
      default_box_spacing,
      newstudy_newreports_height,
      total_ma_height,
      negative_offset = TRUE
    )
  }
  assessed_y <- PRISMA_get_pos_(
    newstudy_newreports_y,
    default_box_spacing * 2,
    newstudy_newreports_height,
    assessed_height
  )
  sought_y <- PRISMA_get_pos_(
    assessed_y,
    default_box_spacing,
    assessed_height,
    sought_height
  )
  screened_y <- PRISMA_get_pos_(
    sought_y,
    default_box_spacing,
    sought_height,
    screened_height
  )
  identified_y <- PRISMA_get_pos_(
    screened_y,
    default_box_spacing * 2,
    screened_height,
    identified_height
  )
  top_box_y <- PRISMA_get_pos_(
    identified_y,
    default_box_spacing,
    identified_height,
    section_label_length
  )
  screening_y <-
    mean(
      c(
        (screened_y + (screened_height / 2)),
        (assessed_y - (dbr_excluded_height / 2))
      )
    )
  included_y <- if (total_studies_height > 0 && total_ma_height > 0) {
    mean(c(diagram_start_y, newstudy_newreports_y, total_ma_y))
  } else if (total_studies_height > 0) {
    mean(c(diagram_start_y, newstudy_newreports_y))
  } else if (total_ma_height > 0) {
    mean(c(newstudy_newreports_y, total_ma_y))
  } else {
    newstudy_newreports_y
  }
  if (side_boxes == TRUE) {
    sidebox <- paste0(
      "node [
        shape = box,
        fontsize = ", fontsize, ",
        fontname = ", font, ",
        color = ", title_colour, "
      ]
      identification [
        color = LightSteelBlue2,
        label = ' ',
        style = 'filled,rounded',
        pos = '", diagram_start_x, ",", identified_y, "!',
        width = ", section_label_length, ",
        height = ", identification_box_height, ",
        tooltip = '", tooltips["identification"], "'
      ];
      screening [
        color = LightSteelBlue2,
        label = ' ',
        style = 'filled,rounded',
        pos = '", diagram_start_x, ",", screening_y, "!',
        width = ", section_label_length, ",
        height = ", screening_box_height, ",
        tooltip = '", tooltips["screening"], "'
      ];
      included [
        color = LightSteelBlue2,
        label = ' ',
        style = 'filled,rounded',
        pos = '", diagram_start_x, ",", included_y, "!',
        width = ", section_label_length, ",
        height = ", included_box_height, ",
        tooltip = '", tooltips["included"], "'
      ];\n"
    )
  } else {
    sidebox <- ""
  }
  if (previous == TRUE) {
        A <- paste0( #nolint
      "A [
        label = '',
        pos = '", prev_box_x, ",", diagram_start_y + 0, "!',
        tooltip = ''
      ]"
    )
    Aedge <- paste0( #nolint
      "subgraph cluster0 {
        edge [
          color = White,
          arrowhead = none,
          arrowtail = none
        ]
        1->2;
        edge [
          color = ", arrow_colour, ",
          arrowhead = none,
          arrowtail = ", arrow_tail, "
        ]
        2->A;
        edge [
          color = ", arrow_colour, ",
          arrowhead = ", arrow_head, ",
          arrowtail = none,
          constraint = FALSE
        ]
        A->19;
      }"
    )
    bottomedge <- paste0(
      "edge [
        color = '", arrow_colour, "',
        arrowhead = '", arrow_head, "',
        arrowtail = '", arrow_tail, "'
      ]
      12->19;\n"
    )
    previous_nodes <- paste0(
      "node [
        shape = box,
        fontsize = ", fontsize, ",
        fontname = ", font, ",
        color = ", greybox_colour, "
      ]
      1 [
        label = '", previous_text, "',
        style = 'rounded,filled',
        width = ", default_box_width, ",
        height = ", section_label_length, ",
        pos = '",
          prev_box_x,
          ",",
          top_box_y,
          "!',
        tooltip = '", tooltips["prevstud"], "'
      ]
      node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour, "
      ]
      2 [
        label = '", prev_study_label, "',
        style = 'filled',
        width = ", default_box_width, ",
        height = ", prev_study_height, ",
        fixed = 'true',
        pos = '", prev_box_x, ",", identified_y, "!',
        tooltip = '", tooltips["previous_studies"], "'
      ]"
    )
    finalnode <- paste0(
      "node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour, "
      ]
      19 [
        label = '", total_studies_label, "',
        style = 'filled',
        width = ", default_box_width, ",
        height = ", total_studies_height, ",
        fixedsize = 'true',
        pos = '",
          PRISMA_get_pos_(
            diagram_start_x,
            prev_study_offset + default_box_spacing,
            prev_study_width,
            default_box_width
          ),
          ",",
          diagram_start_y,
          "!',
        tooltip = '", tooltips["total_studies"], "'
      ]"
    )
    prev_rank1 <- "{rank = same; A; 19}"
    prevnode1 <- "1; "
    prevnode2 <- "2; "
  }
  if (other == TRUE) {
    # positions
    other_box_x <- PRISMA_get_pos_(
      dbr_removed_x,
      default_box_spacing,
      default_box_width,
      default_box_width
    )
    other_removed_x <- PRISMA_get_pos_(
      other_box_x,
      default_box_spacing,
      default_box_width,
      default_box_width
    )
    B <- paste0( #nolint
      "B [
        label = '',
        pos = '", other_box_x, ",", newstudy_newreports_y, "!',
        tooltip = ''
      ]"
    )
    cluster2 <- paste0(
      "subgraph cluster2 {
        edge [
          color = White,
          arrowhead = none,
          arrowtail = none
        ]
        13->14;
        edge [
          color = ", arrow_colour, ",
          arrowhead = ", arrow_head, ",
          arrowtail = ", arrow_tail,
        "]
        14->15;
        15->16;
        15->17;
        17->18;
        edge [
          color = ", arrow_colour, ",
          arrowhead = none,
          arrowtail = ", arrow_tail,
        "]
        17->B;
        edge [
          color = ", arrow_colour, ",
          arrowhead = ", arrow_head, ",
          arrowtail = none,
          constraint = FALSE
        ]
        B->12;
      }"
    )
    othernodes <- paste0(
      "node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour,
      "]
      13 [
        label = '", other_text, "',
        style = 'rounded,filled',
        width = ", top_box_width, ",
        height = ", section_label_length, ",
        pos = '",
          mean(c(other_box_x, other_removed_x)),
          ",",
          top_box_y,
          "!',
        tooltip = '", tooltips["othstud"], "'
      ]
      node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour,
      "]
      14 [
        label = '", other_identified_label, "',
        style = 'filled',
        width = ", default_box_width, ",
        height = ", other_identified_height, ",
        pos = '", other_box_x, ",", identified_y, "!',
        tooltip = '", tooltips["website_results"], "'
      ]
      node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour,
      "]
      15 [
        label = '", other_sought_reports_label, "',
        style = 'filled',
        width = ", default_box_width, ",
        height = ", other_sought_reports_height, ",
        pos = '", other_box_x, ",", sought_y, "!',
        tooltip = '", tooltips["other_sought_reports"], "'
      ]
      node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour,
      "]
      16 [
        label = '", other_notretrieved_label, "',
        style = 'filled',
        width = ", default_box_width, ",
        height = ", other_notretrieved_height, ",
        pos = '", other_removed_x, ",", sought_y, "!',
        tooltip = '", tooltips["other_notretrieved_reports"], "'
      ]
      node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour, "
      ]
      17 [
        label = '", other_assessed_label, "',
        style = 'filled',
        width = ", default_box_width, ",
        height = ", other_assessed_height, ",
        pos = '", other_box_x, ",", assessed_y, "!',
        tooltip = '", tooltips["other_assessed"], "'
      ]
      node [
        shape = box,
        fontname = ", font, ",
        color = ", greybox_colour,
      "]
      18 [
        label = '", other_excluded_label, "',
        style = 'filled',
        width = ", default_box_width, ",
        height = ", other_excluded_height, ",
        pos = '",
          other_removed_x,
          ",",
          assessed_y,
        "!',
        tooltip = '", tooltips["other_excluded"], "'
      ]\n"
    )
    extraedges <- "16->18;"
    othernode13 <- "; 13"
    othernode14 <- "; 14"
    othernode1516 <- "; 15; 16"
    othernode1718 <- "; 17; 18"
    othernodeB <- "; B" #nolint
  } else {
    B <- "" #nolint
    cluster2 <- ""
    othernodes <- ""
    extraedges <- ""
    othernode13 <- ""
    othernode14 <- ""
    othernode1516 <- ""
    othernode1718 <- ""
    othernodeB <- "" #nolint
  }
  if (meta_analysis == TRUE) {
    metanode <- paste0("node [
      shape = box,
      fontname = ", font, ",
      color = ", main_colour, ",
      fillcolor = '',
      style = solid
    ]
    23 [
      label = '", total_ma_label, "',
      width = ", default_box_width, ",
      height = ", total_ma_height, ",
      pos = '", dbr_box_x, ",", total_ma_y, "!',
      tooltip = '", tooltips["total_studies_ma"], "'
    ]")
    if (previous == TRUE) {
      bottomedge <- paste0(
        bottomedge, "edge [
          color = '", arrow_colour, "',
          arrowhead = '", arrow_head, "',
          arrowtail = '", arrow_tail, "'
        ]
        19->23;\n"
      )
    } else {
      bottomedge <- paste0(
        bottomedge, "edge [
          color = '", arrow_colour, "',
          arrowhead = '", arrow_head, "',
          arrowtail = '", arrow_tail, "'
        ]
        12->23;\n"
      )
    }
  }
  x <- DiagrammeR::grViz(
    paste0(
      "digraph TD {
        graph[
          splines = ortho,
          layout = neato,
          tooltip = 'Click the boxes for further information',
          outputorder = edgesfirst,
        ]",
        sidebox,
        previous_nodes,
        "node [
          shape = box,
          fontsize = ", fontsize, ",
          fontname = ", font, ",
          color = ", title_colour,
        "]
        3 [
          label = '", newstud_text, "',
          style = 'rounded,filled',
          width = ", top_box_width, ",
          height = ", section_label_length, ",
          pos = '",
            mean(c(dbr_box_x, dbr_removed_x)),
            ",",
            top_box_y,
            "!',
          tooltip = '", tooltips["newstud"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour,
        "]
        4 [
          label = '", dbr_identified_label, "',
          width = ", default_box_width, ",
          height = ", dbr_identified_height, ",
          pos = '", dbr_box_x, ",", identified_y, "!',
          tooltip = '", tooltips["database_results"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour,
        "]
        5 [
          label = '", dbr_notscreened_label, "',
          width = ", default_box_width, ",
          height = ", min_box_height, ",
          pos = '", dbr_removed_x, ",", identified_y, "!',
          tooltip = '", tooltips["duplicates"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour, "
        ]
        6 [
          label = '", dbr_screened_label, "',
          width = ", default_box_width, ",
          height = ", dbr_screened_height, ",
          pos = '", dbr_box_x, ",", screened_y, "!',
          tooltip = '", tooltips["records_screened"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour, "
        ]
        7 [
          label = '", dbr_screened_excluded_label, "',
          width = ", default_box_width, ",
          height = ", min_box_height, ",
          pos = '", dbr_removed_x, ",", screened_y, "!',
          tooltip = '", tooltips["records_excluded"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour,
        "]
        8 [
          label = '", dbr_sought_label, "',
          width = ", default_box_width, ",
          height = ", dbr_sought_height, ",
          pos = '", dbr_box_x, ",", sought_y, "!',
          tooltip = '", tooltips["dbr_sought_reports"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour,
        "]
        9 [
          label = '", dbr_notretrieved_label, "',
          width = ", default_box_width, ",
          height = ", min_box_height, ",
          pos = '", dbr_removed_x, ",", sought_y, "!',
          tooltip = '", tooltips["dbr_notretrieved_reports"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour,
        "]
        10 [
          label = '", dbr_assessed_label, "',
          width = ", default_box_width, ",
          height = ", dbr_assessed_height, ",
          pos = '", dbr_box_x, ",", assessed_y, "!',
          tooltip = '", tooltips["dbr_assessed"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour, ",
          fillcolor = White,
          style = filled
        ]
        11 [
          label = '", dbr_excluded_label, "',
          width = ", default_box_width, ",
          height = ", min_box_height, ",
          pos = '",
            dbr_removed_x,
            ",",
            assessed_y,
          "!',
          tooltip = '", tooltips["dbr_excluded"], "'
        ]
        node [
          shape = box,
          fontname = ", font, ",
          color = ", main_colour, ",
          fillcolor = '',
          style = solid
        ]
        12 [
          label = '", newstudy_newreports_label, "',
          width = ", default_box_width, ",
          height = ", newstudy_newreports_height, ",
          pos = '", dbr_box_x, ",", newstudy_newreports_y, "!',
          tooltip = '", tooltips["new_studies"], "'
        ]",
        othernodes,
        finalnode,
        metanode,
        "node [
          shape = square,
          width = 0,
          color=White
        ]\n",
        A,
        "\n",
        B,
        "\n",
        Aedge,
        "node [
          shape = square,
          width = 0,
          style=invis
        ]
        C [
          label = '',
          width = ", default_box_width, ",
          height = ", min_box_height, ",
          pos = '", dbr_removed_x, ",", assessed_y, "!',
          tooltip = ''
        ]
        subgraph cluster1 {
          edge [
            style = invis
          ]
          3->4;
          3->5;
          edge [
            color = ", arrow_colour, ",
            arrowhead = ", arrow_head, ",
            arrowtail = ", arrow_tail, ",
            style = filled
          ]
          4->5;
          4->6;
          6->7;
          6->8;
          8->9;
          8->10;
          10->C;
          10->12;
          edge [
            style = invis
          ]
          5->7;
          7->9;
          9->11;
          ", extraedges, "
        }",
        cluster2,
        "\n",
        bottomedge,
        "\n\n",
        prev_rank1,
        "\n",
        "{
          rank = same; ",
          prevnode1,
          "3",
          othernode13,
        "}
        {
          rank = same; ",
          prevnode2,
          "4; 5",
          othernode14,
        "}
        {
          rank = same; 6; 7
        }
        {
          rank = same; 8; 9",
          othernode1516,
        "}
        {
          rank = same; 10; 11",
          othernode1718,
        "}
        {
          rank = same; 12",
          othernodeB,
        "}
      }"
    )
  )
  if (side_boxes == TRUE) {
    x <- PRISMA_insert_js_(
      x,
      identification_text = identification_text,
      screening_text = screening_text,
      included_text = included_text
    )
  }
  if (interactive == TRUE) {
    x <- PRISMA_interactive_(
      x,
      urls,
      previous = previous,
      other = other
    )
  }
  return(x)
}


#' Read in PRISMA flow diagram data
#'
#' @description Read in a template CSV containing data for the flow diagram
#' @param data File to read in.
#' @return A list of objects needed to plot the flow diagram
#' @examples
#' csvFile <- system.file("extdata", "PRISMA.csv", package = "PRISMA2020")
#' data <- read.csv(csvFile);
#' data <- PRISMA_data(data);
#' @export
PRISMA_data <- function(data) { #nolint
  # Ensure data is a df, not a tibble;
  # tibbles do not return vectors using df[, 1].
  data <- as.data.frame(data)
  #Set parameters
  previous_studies <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "previous_studies",
          data[, 1]
        ),
      ]$n
    )
  )
  previous_reports <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "previous_reports",
          data[, 1]
        ),
      ]$n
    )
  )
  register_results <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "register_results",
          data[, 1]
        ),
      ]$n
    )
  )
  database_results <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "database_results",
          data[, 1]
        ),
      ]$n
    )
  )
  database_specific_results <- PRISMA_parse_reasons_(data[ #nolint
      grep(
        "database_specific_results",
        data[, 1]
      ),
    ]$n
  )
  register_specific_results <- PRISMA_parse_reasons_(data[ #nolint
      grep(
        "register_specific_results",
        data[, 1]
      ),
    ]$n
  )
  website_results <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "website_results",
          data[, 1]
        ),
      ]$n
    )
  )
  organisation_results <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "organisation_results",
          data[, 1]
        ),
      ]$n
    )
  )
  citations_results <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "citations_results",
          data[, 1]
        ),
      ]$n
    )
  )
  duplicates <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "duplicates",
          data[, 1]
        ),
      ]$n
    )
  )
    excluded_automatic <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "excluded_automatic",
          data[, 1]
        ),
      ]$n
    )
  )
  excluded_other <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "excluded_other",
          data[, 1]
        ),
      ]$n
    )
  )
  records_screened <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "records_screened",
          data[, 1]
        ),
      ]$n
    )
  )
  records_excluded <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "records_excluded",
          data[, 1]
        ),
      ]$n
    )
  )
  dbr_sought_reports <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "dbr_sought_reports",
          data[, 1]
        ),
      ]$n
    )
  )
  dbr_notretrieved_reports <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "dbr_notretrieved_reports",
          data[, 1]
        ),
      ]$n
    )
  )
  other_sought_reports <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "other_sought_reports",
          data[, 1]
        ),
      ]$n
    )
  )
  other_notretrieved_reports <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "other_notretrieved_reports",
          data[, 1]
        ),
      ]$n
    )
  )
  dbr_assessed <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "dbr_assessed",
          data[, 1]
        ),
      ]$n
    )
  )
  dbr_excluded <- PRISMA_parse_reasons_(data[ #nolint
      grep(
        "dbr_excluded",
        data[, 1]
      ),
    ]$n
  )
  other_assessed <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "other_assessed",
          data[, 1]
        ),
      ]$n
    )
  )
  other_excluded <- PRISMA_parse_reasons_(data[ #nolint
      grep(
        "other_excluded",
        data[, 1]
      ),
    ]$n
  )
  new_studies <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "new_studies",
          data[, 1]
        ),
      ]$n
    )
  )
  new_reports <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "new_reports",
          data[, 1]
        ),
      ]$n
    )
  )
  total_studies <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "total_studies$",
          data[, 1]
        ),
      ]$n
    )
  )
  total_reports <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "total_reports$",
          data[, 1]
        ),
      ]$n
    )
  )
  total_studies_ma <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "total_studies_ma",
          data[, 1]
        ),
      ]$n
    )
  )
  total_reports_ma <- scales::comma(
    PRISMA_format_number_( #nolint
      data[
        grep(
          "total_reports_ma",
          data[, 1]
        ),
      ]$n
    )
  )
  tooltips <- list()
  for (i in seq_len(nrow(data))) {
    if (!is.na(data[i, ]$tooltips)) {
      if (is.na(data[i, ]$data)) {
        name <- data[i, ]$box
      } else {
        name <- data[i, ]$data
      }
      tooltips[[name]] <- data[i, ]$tooltips
    }
  }

  urls <- data.frame(
    box = data[!duplicated(data$box), ]$box,
    url = data[!duplicated(data$box), ]$url
  )
  #set text - if text >33 characters,
  previous_text <- data[grep("prevstud", data[, 3]), ]$boxtext
  newstud_text <- data[grep("newstud", data[, 3]), ]$boxtext
  other_text <- data[grep("othstud", data[, 3]), ]$boxtext
  previous_studies_text <- data[grep("previous_studies", data[, 1]), ]$boxtext
  previous_reports_text <- data[grep("previous_reports", data[, 1]), ]$boxtext
  register_results_text <- data[grep("register_results", data[, 1]), ]$boxtext
  database_results_text <- data[grep("database_results", data[, 1]), ]$boxtext
  website_results_text <- data[grep("website_results", data[, 1]), ]$boxtext
  organisation_results_text <- data[
    grep(
      "organisation_results",
      data[, 1]
    ),
  ]$boxtext
  citations_results_text <- data[grep("citations_results", data[, 1]), ]$boxtext
  duplicates_text <- data[grep("duplicates", data[, 1]), ]$boxtext
  excluded_automatic_text <- data[
    grep(
      "excluded_automatic",
      data[, 1]
    ),
  ]$boxtext
  excluded_other_text <- data[grep("excluded_other", data[, 1]), ]$boxtext
  records_screened_text <- data[grep("records_screened", data[, 1]), ]$boxtext
  records_excluded_text <- data[grep("records_excluded", data[, 1]), ]$boxtext
  dbr_sought_reports_text <- data[
    grep(
      "dbr_sought_reports",
      data[, 1]
    ),
  ]$boxtext
  dbr_notretrieved_reports_text <- data[
    grep(
      "dbr_notretrieved_reports",
      data[, 1]
    ),
  ]$boxtext
  other_sought_reports_text <- data[
    grep(
      "other_sought_reports",
      data[, 1]
    ),
  ]$boxtext
  other_notretrieved_reports_text <- data[ #nolint
    grep(
      "other_notretrieved_reports",
      data[, 1]
    ),
  ]$boxtext
  dbr_assessed_text <- data[grep("dbr_assessed", data[, 1]), ]$boxtext
  dbr_excluded_text <- data[grep("dbr_excluded", data[, 1]), ]$boxtext
  other_assessed_text <- data[grep("other_assessed", data[, 1]), ]$boxtext
  other_excluded_text <- data[grep("other_excluded", data[, 1]), ]$boxtext
  new_studies_text <- data[grep("new_studies", data[, 1]), ]$boxtext
  new_reports_text <- data[grep("new_reports", data[, 1]), ]$boxtext
  total_studies_text <- data[grep("total_studies$", data[, 1]), ]$boxtext
  total_reports_text <- data[grep("total_reports$", data[, 1]), ]$boxtext
  identification_text <- data[grep("identification", data[, 1]), ]$boxtext
  screening_text <- data[grep("screening", data[, 1]), ]$boxtext
  included_text <- data[grep("included", data[, 1]), ]$boxtext
  total_studies_ma_text <- data[grep("total_studies_ma", data[, 1]), ]$boxtext
  total_reports_ma_text <- data[grep("total_reports_ma", data[, 1]), ]$boxtext
  x <- list(
    previous_studies = previous_studies,
    previous_reports = previous_reports,
    register_results = register_results,
    database_results = database_results,
    database_specific_results = database_specific_results,
    register_specific_results = register_specific_results,
    website_results = website_results,
    organisation_results = organisation_results,
    citations_results = citations_results,
    duplicates = duplicates,
    excluded_automatic = excluded_automatic,
    excluded_other = excluded_other,
    records_screened = records_screened,
    records_excluded = records_excluded,
    dbr_sought_reports = dbr_sought_reports,
    dbr_notretrieved_reports = dbr_notretrieved_reports,
    other_sought_reports = other_sought_reports,
    other_notretrieved_reports = other_notretrieved_reports,
    dbr_assessed = dbr_assessed,
    dbr_excluded = dbr_excluded,
    other_assessed = other_assessed,
    other_excluded = other_excluded,
    new_studies = new_studies,
    new_reports = new_reports,
    total_studies = total_studies,
    total_reports = total_reports,
    total_studies_ma = total_studies_ma,
    total_reports_ma = total_reports_ma,
    previous_text = previous_text,
    newstud_text = newstud_text,
    other_text = other_text,
    previous_studies_text = previous_studies_text,
    previous_reports_text = previous_reports_text,
    register_results_text = register_results_text,
    database_results_text = database_results_text,
    website_results_text = website_results_text,
    organisation_results_text = organisation_results_text,
    citations_results_text = citations_results_text,
    duplicates_text = duplicates_text,
    excluded_automatic_text = excluded_automatic_text,
    excluded_other_text = excluded_other_text,
    records_screened_text = records_screened_text,
    records_excluded_text = records_excluded_text,
    dbr_sought_reports_text = dbr_sought_reports_text,
    dbr_notretrieved_reports_text = dbr_notretrieved_reports_text,
    other_sought_reports_text = other_sought_reports_text,
    other_notretrieved_reports_text = other_notretrieved_reports_text,
    dbr_assessed_text = dbr_assessed_text,
    dbr_excluded_text = dbr_excluded_text,
    other_assessed_text = other_assessed_text,
    other_excluded_text = other_excluded_text,
    new_studies_text = new_studies_text,
    new_reports_text = new_reports_text,
    total_studies_text = total_studies_text,
    total_reports_text = total_reports_text,
    total_studies_ma_text = total_studies_ma_text,
    total_reports_ma_text = total_reports_ma_text,
    identification_text = identification_text,
    screening_text = screening_text,
    included_text = included_text,
    tooltips = tooltips,
    urls = urls
  )
  return(x)
}

#' Save PRISMA2020 flow diagram
#' @description Save the output from [PRISMA_flowdiagram()] to the
#' working directory.
#' @param plotobj A plot produced using [PRISMA_flowdiagram()].
#' @param filename The filename to save (including extension)
#' @param filetype The filetype to save the plot in, supports:
#' HTML, ZIP, PDF, PNG, SVG, PS and WEBP
#' (if NA, the filetype will be calculated out based on the file extension)
#' HTML files maintain hyperlinks and tooltips
#' The ZIP option creates an archive containing the HTML file,
#' alongside supporting javascript and css files in an adjacent folder,
#' instead of embedded base64 within the HTML file
#' @param overwrite if TRUE, will overwrite an existing file
#' @param width passed as the width argument to
#' [rsvg::rsvg()] and similar functions
#' @param height passed as the height argument to
#' [rsvg::rsvg()] and similar functions
#' @param css passed as the css argument to
#' [rsvg::rsvg()] and similar functions
#' @return the absolute filename of the saved diagram plot.
#' @examples
#' csvFile <- system.file("extdata", "PRISMA.csv", package = "PRISMA2020")
#' data <- read.csv(csvFile);
#' data <- PRISMA_data(data);
#' plot <- PRISMA_flowdiagram(data,
#'                 fontsize = 12,
#'                 interactive = TRUE,
#'                 previous = FALSE,
#'                 other = TRUE);
#' PRISMA_save(plot, filename = tempfile(), filetype="html");
#' @export
PRISMA_save <- function( #nolint
  plotobj,
  filename = "PRISMA2020_flowdiagram.html",
  filetype = NA,
  overwrite = FALSE,
  width = NULL,
  height = NULL,
  css = NULL
) {
  if (!file.exists(filename) || overwrite == TRUE) {
    format_real <- PRISMA_calc_filetype_(filename, filetype) #nolint
    switch(
      format_real,
      "HTML" = {
        tmp_html <- tempfile(
          pattern = "PRISMA2020_",
          tmpdir = tempdir(),
          fileext = ".html"
        )
        htmlwidgets::saveWidget(
          plotobj,
          file = tmp_html,
          title = "PRISMA2020 Flowdiagram"
        )
        if (!(file.copy(tmp_html, filename, overwrite = TRUE))) {
          stop("Error saving HTML")
        }
        file.remove(tmp_html)
      },
      "ZIP" = {
        curr_wd <- getwd()
        tmp_dir <- tempdir()
        setwd(tmp_dir)
        tmp_zipfile <- tempfile(
          pattern = "PRISMA2020_",
          tmpdir = tempdir(),
          fileext = ".zip"
        )
        tmp_html <- paste0(
          tools::file_path_sans_ext(basename(filename)),
          ".html"
        )
        tmp_libdir <- paste0(tmp_html, "_files")
        htmlwidgets::saveWidget(
          plotobj,
          file = tmp_html,
          libdir = tmp_libdir,
          selfcontained = FALSE,
          title = "PRISMA2020 Flowdiagram"
        )
        zip::zip(zipfile = tmp_zipfile, files = c(tmp_html, tmp_libdir))
        setwd(curr_wd)
        if (!(file.copy(paste0(tmp_zipfile), filename, overwrite = TRUE))) {
          stop("Error saving ZIP File")
        }
      },
      "PDF" = {
        tmp_svg <- PRISMA_gen_tmp_svg_(plotobj) #nolint
        rsvg::rsvg_pdf(
          tmp_svg,
          filename,
          width = width,
          height = height,
          css = css
        )
        file.remove(tmp_svg)
      },
      "PNG" = {
        tmp_svg <- PRISMA_gen_tmp_svg_(plotobj) #nolint
        rsvg::rsvg_png(
          tmp_svg,
          filename,
          width = width,
          height = height,
          css = css
        )
        file.remove(tmp_svg)
      },
      "SVG" = {
        tmp_svg <- PRISMA_gen_tmp_svg_(plotobj) #nolint
        if (!(file.copy(tmp_svg, filename, overwrite = TRUE))) {
          stop("Error saving SVG")
        }
        file.remove(tmp_svg)
      },
      "PS" = {
        tmp_svg <- PRISMA_gen_tmp_svg_(plotobj) #nolint
        rsvg::rsvg_ps(
          tmp_svg,
          filename,
          width = width,
          height = height,
          css = css
        )
        file.remove(tmp_svg)
      },
      "WEBP" = {
        tmp_svg <- PRISMA_gen_tmp_svg_(plotobj) #nolint
        rsvg::rsvg_webp(
          tmp_svg,
          filename,
          width = width,
          height = height,
          css = css
        )
        file.remove(tmp_svg)
      },
      stop("Please choose one of the supported file types")
    )
    return(tools::file_path_as_absolute(filename))
  } else {
    stop("File exists, please set overwite = TRUE to overwrite")
  }
}

#' Defunct function - replaced by "PRISMA_interactive_"
#' @description Defunct function - replaced by "PRISMA_interactive_"
#' @seealso [PRISMA_interactive_()]
#' @param plot A plot object from [PRISMA_flowdiagram()].
#' @param urls A dataframe consisting of two columns: nodes and urls. The first
#' column should contain 19 rows for the nodes from node1 to node19. The second
#' column should contain a corresponding URL for each node.
#' @param previous Logical argument (TRUE or FALSE) (supplied through
#' [PRISMA_flowdiagram()]) specifying whether previous studies were sought.
#' @param other Logical argument (TRUE or FALSE) (supplied through
#' [PRISMA_flowdiagram()]) specifying whether other studies were sought.
sr_flow_interactive <- function(plot,
                                urls,
                                previous,
                                other) {
  .Defunct("PRISMA_interactive_")
}

#' Defunct function - replaced by "PRISMA_data"
#' @description Defunct function - replaced by "PRISMA_data"
#' @seealso [PRISMA_data()]
#' @param data File to read in.
read_PRISMAdata <- function(data){ #nolint
  .Defunct("PRISMA_data")
}


================================================
FILE: R/globals.R
================================================
utils::globalVariables(c("previous_studies",
                         "previous_reports",
                         "register_results",
                         "database_results",
                         "website_results",
                         "organisation_results",
                         "citations_results",
                         "duplicates",
                         "excluded_automatic",
                         "excluded_other",
                         "records_screened",
                         "records_excluded",
                         "dbr_sought_reports",
                         "dbr_notretrieved_reports",
                         "other_sought_reports",
                         "other_notretrieved_reports",
                         "dbr_assessed",
                         "dbr_excluded",
                         "other_assessed",
                         "other_excluded",
                         "new_studies",
                         "new_reports",
                         "total_studies",
                         "total_reports",
                         "total_studies_ma",
                         "total_reports_ma",
                         "previous_text",
                         "newstud_text",
                         "other_text",
                         "previous_studies_text",
                         "previous_reports_text",
                         "register_results_text",
                         "database_results_text",
                         "website_results_text",
                         "organisation_results_text",
                         "citations_results_text",
                         "duplicates_text",
                         "excluded_automatic_text",
                         "excluded_other_text",
                         "records_screened_text",
                         "records_excluded_text",
                         "dbr_sought_reports_text",
                         "dbr_notretrieved_reports_text",
                         "other_sought_reports_text",
                         "other_notretrieved_reports_text",
                         "dbr_assessed_text",
                         "dbr_excluded_text",
                         "other_assessed_text",
                         "other_excluded_text",
                         "new_studies_text",
                         "new_reports_text",
                         "total_studies_text",
                         "total_reports_text",
                         "tooltips",
                         "urls",
                         "identification_text",
                         "included_text",
                         "screening_text",
                         "total_studies_ma_text",
                         "total_reports_ma_text"))

================================================
FILE: R/utils.R
================================================
# Utility functions for PRISMA_flowdiagram

#' Calculate the correct height of a box from a list (e.g. of exclusion reasons)
#' @description Get the correct height for a box
#' @param n the number of rows of text in the label
#' @param offset the offset height (e.g. 3.5)
#' @param min the minimum number of rows before adjusting
#' @return the height of the box
#' @keywords internal
PRISMA_get_height_ <- function (n, offset, min = 2) { #nolint
  lines <- n + 1
  if (lines > min) {
    height <- offset + (lines * 0.25) - (min * 0.25)
  } else {
    height <- offset
  }
  return(height)
}

#' Calculate the correct position of a node
#' @description Get the correct position for a node
#' @param first_box_location the location of the first node
#' @param offset the offset from the first node
#' @param length_orig the width/height of the original node
#' @param length_new the width/height of the new node
#' @param negative_offset is the offset negative (defaults to false)
#' @return the position of the node
#' @keywords internal
PRISMA_get_pos_ <- function (first_box_location, offset, length_orig, length_new, negative_offset = FALSE) { #nolint
  if (negative_offset == FALSE) {
    pos <- first_box_location + offset + (length_orig / 2) + (length_new / 2)
  } else {
    pos <- first_box_location - offset - (length_orig / 2) - (length_new / 2)
  }
  return(pos)
}

#' Generate / insert JS for labels
#' @description Generate the javascript method to insert the side labels
#' @param plot the plot object (without side labels)
#' @param identification_text the text to use as the "identification" label
#' @param screening_text the text to use as the "screening" label
#' @param included_text the text to use as the "identification" label
#' @return the plot object (with JS to generate side labels)
#' @keywords internal
PRISMA_insert_js_ <- function ( #nolint
  plot,
  identification_text,
  screening_text,
  included_text
) {
    # This JS loops through each node, and
    # locates the relevent <text> tag containing the label
    # The blank label is replaced with the relevent descriptive label
    # This is done in the loop as positioning due
    # to rotation otherwise being difficult
    # we rotate the text and adjust the position to ensure that
    # the now rotated text is displayed correctly
    javascript <- htmltools::HTML(paste0('
       const nodeMap = new Map([["node1","',
        identification_text,
      '"], ["node2","',
        screening_text,
      '"], ["node3","',
        included_text,
      '"]]);
       for (const [node, label] of nodeMap) {
         var theDiv = document.getElementById(node);
         var theText = theDiv.querySelector("text");
         var attrX = theText.getAttribute("x");
         var attrY = theText.getAttribute("y");
         theText.setAttribute("y",parseFloat(attrX))
         theText.setAttribute("x",parseFloat(attrY)*-1)
         theText.setAttribute("style","transform: rotate(-90deg);")
         theText.setAttribute("dominant-baseline", "middle")
         theText.innerHTML = label;
       }
    '))
    plot <- htmlwidgets::appendContent(
      plot, htmlwidgets::onStaticRenderComplete(javascript)
    )
    return(plot)
}

#' Add the hyperlink to the given node
#'
#' @description Generate the javascript method to insert the side labels
#' @param node the relevent node
#' @param url the URL the node should link to
#' @return An interactive flow diagram plot.
#' @keywords internal
PRISMA_add_hyperlink_ <- function( #nolint
  node,
  url
) {
  t <- paste0( #nolint
    "const ",
      node,
    ' = document.getElementById("',
      node,
    '");
    var link',
      node,
    ' = "<a href=\'',
      url,
    '\' target=\'_blank\'>" + ',
      node,
    '.innerHTML + "</a>";',
    "\n",
      node,
    ".innerHTML = link",
      node,
    ";"
  )
}

#' Plot interactive flow diagram for systematic reviews
#' @description Converts a PRISMA systematic review flow diagram into an
#' interactive HTML plot, for embedding links from each box.
#' @seealso [PRISMA_interactive_()]
#' @param plot A plot object from [PRISMA_flowdiagram()].
#' @param urls A dataframe consisting of two columns: nodes and urls. The first
#' column should contain 19 rows for the nodes from node1 to node19. The second
#' column should contain a corresponding URL for each node.
#' @param previous Logical argument (TRUE or FALSE) (supplied through
#' [PRISMA_flowdiagram()]) specifying whether previous studies were sought.
#' @param other Logical argument (TRUE or FALSE) (supplied through
#' [PRISMA_flowdiagram()]) specifying whether other studies were sought.
#' @return An interactive flow diagram plot.
#' @keywords internal
PRISMA_interactive_ <- function( #nolint
  plot,
  urls,
  previous,
  other
) {
  if (previous == TRUE && other == TRUE) {
    link <- data.frame(
      boxname = c(
        "identification",
        "screening",
        "included",
        "prevstud",
        "box1",
        "newstud",
        "box2",
        "box3",
        "box4",
        "box5",
        "box6",
        "box7",
        "box8",
        "box9",
        "box10",
        "othstud",
        "box11",
        "box12",
        "box13",
        "box14",
        "box15",
        "box16",
        "A",
        "B"
      ),
      node = paste0("node", seq(1, 24))
    )
    target <- c(
      "node1",
      "node2",
      "node3",
      "node4",
      "node5",
      "node23",
      "node6",
      "node7",
      "node8",
      "node9",
      "node10",
      "node11",
      "node12",
      "node13",
      "node14",
      "node15",
      "node22",
      "node16",
      "node17",
      "node18",
      "node19",
      "node20",
      "node21",
      "node24"
    )
  } else if (previous == FALSE && other == TRUE) {
    link <- data.frame(
      boxname = c(
        "identification",
        "screening",
        "included",
        "newstud",
        "box2",
        "box3",
        "box4",
        "box5",
        "box6",
        "box7",
        "box8",
        "box9",
        "box10",
        "othstud",
        "box11",
        "box12",
        "box13",
        "box14",
        "box15",
        "B"
      ),
      node = paste0("node", seq(1, 20))
    )
    target <- c(
      "node1",
      "node2",
      "node3",
      "node4",
      "node5",
      "node6",
      "node7",
      "node8",
      "node9",
      "node10",
      "node11",
      "node12",
      "node13",
      "node14",
      "node15",
      "node16",
      "node17",
      "node18",
      "node19",
      "node20"
    )
  } else if (previous == TRUE && other == FALSE) {
    link <- data.frame(
      boxname = c(
        "identification",
        "screening",
        "included",
        "prevstud",
        "box1",
        "newstud",
        "box2",
        "box3",
        "box4",
        "box5",
        "box6",
        "box7",
        "box8",
        "box9",
        "box10",
        "box16",
        "A"
      ),
      node = paste0("node", seq(1, 17))
    )
    target <- c(
      "node1",
      "node2",
      "node3",
      "node4",
      "node5",
      "node6",
      "node7",
      "node8",
      "node9",
      "node10",
      "node11",
      "node12",
      "node13",
      "node14",
      "node15",
      "node16",
      "node17"
    )
  } else {
    link <- data.frame(
      boxname = c(
        "identification",
        "screening",
        "included",
        "newstud",
        "box2",
        "box3",
        "box4",
        "box5",
        "box6",
        "box7",
        "box8",
        "box9",
        "box10"
      ),
      node = paste0("node", seq(1, 13))
    )
    target <- c(
      "node1",
      "node2",
      "node3",
      "node4",
      "node5",
      "node6",
      "node7",
      "node8",
      "node9",
      "node10",
      "node11",
      "node12",
      "node13"
    )
  }
  link <- merge(link, urls, by.x = "boxname", by.y = "box", all.x = TRUE)
  link <- link[match(target, link$node), ]
  node <- link$node
  url <- link$url
  #the following code adds the location link for the new window
  javascript <- htmltools::HTML(
    paste(
      mapply(
        PRISMA_add_hyperlink_,
        node,
        url
      ),
      collapse = "\n"
    )
  )
  htmlwidgets::prependContent(
    plot,
    htmlwidgets::onStaticRenderComplete(javascript)
  )
}

#' Calculate the correct filetime
#'
#' @description Work out the correct filetype to save the file as
#' @param fn The filename (including extension)
#' @param ft The filetype (which can be NA or NULL)
#' @return the filetype taken from the filename, or overriden by the ft param
#' @keywords internal
PRISMA_calc_filetype_ <- function(fn, ft) { #nolint
    # if the filetype is set, return that, otherwise
    # calculate the filetype from the extension (HTM becomes HTML)
    if (!is.na(ft) && !is.null(ft)) {
      the_ft <- toupper(ft)
    } else {
      the_ft <- toupper(tools::file_ext(fn))
      if (the_ft == "HTM") {
        the_ft <- "HTML"
      }
    }
    return(the_ft)
}

#' Format numbers with commas into numbers
#'
#' @description Turn strings containing numbers +/- commas into numbers
#' @param x the number to format
#' @return the number with commas removed
#' @keywords internal
PRISMA_format_number_ <- function(x) { #nolint
    if (is.character(x)) {
      x <- gsub(",", "", x)
      x <- gsub("[^0-9.]", "", x)
    }
    return(as.numeric(x))
}

#' Parse an exclusion reason into a data frame
#'
#' @description Parse an exclusion reason string and returns a dataframe
#' containing reasons and number
#' @param reasons the string to parse
#' @return a dataframe containing reasons and number applicable
#' @keywords internal
#'
PRISMA_parse_reasons_ <- function(reasons) { #nolint
    reasons_out <- NA
    if (grepl("[^0-9,]", as.character(reasons))) {
      reasons_out <- data.frame(
        reason = gsub(
          ",.*$",
          "",
          unlist(
            strsplit(
              as.character(reasons),
              split = "(;)( )?"
            )
          )
        ),
        n = scales::comma(
          PRISMA_format_number_( #nolint
            gsub(
              ".*?,([ 0-9,]*)|.*()",
              "\\1",
              unlist(
                strsplit(
                  as.character(reasons),
                  split = "(;)( )?"
                )
              )
            )
          )
        )
      )
    } else {
      reasons_out <- data.frame(
        reason = "",
        n = scales::comma(
          PRISMA_format_number_(as.character(reasons))
        )
      )
    }
    return(reasons_out)
}

#' Formats multiple exclusion reasons properly for printing
#'
#' @description Parse an exclusion reason dataframe from
#' [PRISMA2020::PRISMA_parse_reasons_()] and returns a properly formatted string
#' @param df the dataframe to parse
#' @return a string ready for printing
#' @keywords internal
#'
PRISMA_format_reasons_ <- function(df) { #nolint
    out_string <- paste0(
      ":",
      paste(
        paste(
          "\n",
          df[, 1],
          " (n = ", df[, 2], ")",
        sep = ""
        ),
      collapse = ""
      )
    )
  return(out_string)
}


#' Generate a temporary SVG from a plot object
#'
#' @description Generate and save a temporary SVG from a plot object
#' @param obj the plot object
#' @return the full path to the saved SVG
#' @keywords internal
PRISMA_gen_tmp_svg_ <- function(obj) { #nolint
    # generate temporary filenames
    tmpfilehtml <- tempfile(
      pattern = "PRISMA2020_",
      tmpdir = tempdir(),
      fileext = ".html"
    )
    tmpfilesvg <- tempfile(
      pattern = "PRISMA2020_",
      tmpdir = tempdir(),
      fileext = ".svg"
    )
    # save the widget as HTML and read it into a variable
    htmlwidgets::saveWidget(obj, file = tmpfilehtml)
    htmldata <- xml2::read_html(tmpfilehtml)
    # extract our labelling javascript using xml_find_first and xpath
    # it finds the first script element follwing the grViz class
    # this looks to be quite fragile if we change our injected JS
    js <- xml2::xml_text(
      xml2::xml_find_first(
        htmldata,
        '//div[contains(@class, "grViz")]//following-sibling::script'
      )
    )
    # use DiagrammeRsvg to export an SVG from the htmlwidgets code
    # this uses the V8 engine in the background so takes time
    # then read the SVG's XML into a variable
    svg <- DiagrammeRsvg::export_svg(obj)
    svg <- xml2::read_xml(svg)
    # we need to extract the node names and the label values from our JS
    # so find the appropriate part of the code
    # (again, sensitive to script changes)
    # we then extract the node names and labels and insert them into the SVG
    # in a similar manner to the original JS code
    jsnode <- stringr::str_split(
      stringr::str_remove_all(
        stringr::str_match(
          js, "const nodeMap = new Map\\(\\[(.*)\\]\\);"
        )[1, 2],
        "\\[|\"|]"
      ),
      ",\\s",
      simplify = TRUE
    )
    len <- length(jsnode)
    for (i in 1:len) {
      matsp <- stringr::str_split_fixed(jsnode[i], ",", 2)
      namespace <- xml2::xml_ns(svg)
      xml_text_node <- xml2::xml_find_first(
        svg,
        paste0('//d1:g[@id="', matsp[, 1], '"]//d1:text'),
        namespace
      )
      attr_x <- xml2::xml_attr(xml_text_node, "x")
      attr_y <- xml2::xml_attr(xml_text_node, "y")
      xml2::xml_attr(xml_text_node, "x") <- as.double(attr_y) * -1
      xml2::xml_attr(xml_text_node, "y") <- as.double(attr_x) + 2
      # libRSVG does not support css transforms
      # so we need to use the native SVG transform attribute
      xml2::xml_attr(xml_text_node, "transform") <- "rotate(-90)"
      xml2::xml_text(xml_text_node) <- matsp[, 2]
    }
    xml2::write_xml(svg, file = tmpfilesvg)
    return(tmpfilesvg)
}

================================================
FILE: README.md
================================================
<!-- badges: start -->
[![Check & Deploy](https://github.com/prisma-flowdiagram/PRISMA2020/actions/workflows/check-and-deploy.yml/badge.svg)](https://github.com/prisma-flowdiagram/PRISMA2020/actions/workflows/check-and-deploy.yml)
![GitHub release (latest by date)](https://img.shields.io/github/v/release/prisma-flowdiagram/PRISMA2020)
![GitHub Repo stars](https://img.shields.io/github/stars/prisma-flowdiagram/PRISMA2020?style=social)
[![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.4287834.svg)](https://doi.org/10.5281/zenodo.4287834)
[![DOI](https://zenodo.org/badge/DOI/10.1002/cl2.1230.svg)](https://doi.org/10.1002/cl2.1230)
[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/O5O4JQJ5W)
<!-- badges: end -->

# PRISMA2020 Flow Diagram <img src="https://raw.githubusercontent.com/prisma-flowdiagram/PRISMA2020/master/PRISMA2020-hex.png" align="right" width="15%"/>

You can use this package to produce a flow diagram that conforms to the PRISMA 2020 standards using the `PRISMA_flowdiagram()` function. The data can be manually entered into the function, or loaded up using the template CSV file provided in 'INST/EXTDATA/'. The function, (if 'interactive = TRUE') produces an interactive HTML ouput with each box linking to a specific page (e.g. of search results or methods details), and hover-over tooltips for further information. 
<br>
<img src="https://raw.githubusercontent.com/prisma-flowdiagram/PRISMA2020/master/inst/extdata/PRISMA.png" width="70%" />
<br>

The 'Previous' and 'Other' study arms of the flowchart can be toggled on and off and removed or added to the diagram by specifying this in the function inputs.

A static version is produced otherwise.  

<a href="https://srflowdiagram.github.io/template.html" target="_blank">See the interactive template here.</a><br>


<a href="https://estech.shinyapps.io/prisma_flowdiagram/" target="_blank">Visit the web-based Shiny app for a point-and-click user interface here.</a>

---
## Docker Installation

You can quickly install the PRISMA2020 package and run the included
example shinyapp using [Docker](https://docs.docker.com/engine/install/).

```bash
docker build . -t prisma-shiny:1
docker run -it --rm -p 3838:3838 prisma-shiny:1
```

Then visit http://localhost:3838/app in your web browser.
To stop the app, press `Ctrl+C` in the terminal.

---

Please cite as:<br>
 Haddaway, N. R., Page, M. J., Pritchard, C. C., & McGuinness, L. A. (2022). PRISMA2020: An R package and Shiny app for producing PRISMA 2020-compliant flow diagrams, with interactivity for optimised digital transparency and Open Synthesis. Campbell Systematic Reviews, 18, e1230. <a href=https://doi.org/10.1002/cl2.1230>https://doi.org/10.1002/cl2.1230</a><br>
<a id="raw-url" href="https://raw.githubusercontent.com/nealhaddaway/PRISMA2020/master/inst/extdata/citation.ris">Citation in .ris format (right click 'Save Link As')</a>


================================================
FILE: code-of-conduct.md
================================================
# Contributor Code of Conduct

As contributors and maintainers of this project, we pledge to respect all people who 
contribute through reporting issues, posting feature requests, updating documentation,
submitting pull requests or patches, and other activities.

We are committed to making participation in this project a harassment-free experience for
everyone, regardless of level of experience, gender, gender identity and expression,
sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.

Examples of unacceptable behavior by participants include the use of sexual language or
imagery, derogatory comments or personal attacks, trolling, public or private harassment,
insults, or other unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this 
Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 
from the project team.

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 
opening an issue, emailing the project lead , Neal Haddaway (<nealhaddaway@gmail.com>), or one of the core developers.

This Code of Conduct is adapted from the Contributor Covenant 
(http://contributor-covenant.org), version 1.0.0, available at 
http://contributor-covenant.org/version/1/0/0/


================================================
FILE: contributing.md
================================================
# Contributing to PRISMA2020

The goal of this guide is to help you get up and contributing to PRISMA2020 as 
quickly as possible.

Please note that PRISMA2020 is released with a [Contributor Code of Conduct](code-of-conduct.md). By contributing to this project, you agree to abide by its terms.


### Fixing typos
Small typos or grammatical errors in documentation may be edited directly using
the GitHub web interface, so long as the changes are made in the _source_ file.

*  DO: edit a roxygen comment in a `.R` file below `R/`.
*  DO NOT: edit an `.Rd` file below `man/`.

Similarly, typos/errors in the supporting documents (e.g. these contributing guidelines, code-of-conduct.md)
may be edited directly using the GitHub web interface.

The exception to the above is when typos/errors occur in the README.md document. To correct these:

  * Fork the respository to your personal GitHub account
  * Edit the README.Rmd document to fix the error
  * Knit the README.Rmd document to produce the corrected README.md
  * Commit changes and push both corrected documents to your forked respository
  * Issue a pull request (see the section on [Pull Requests](#pull-requests), below).
  

### Filing an issue

When filing an issue, the most important thing is to include a minimal 
reproducible example so that we can quickly verify the problem, and then figure 
out how to fix it. See "[Writing a good reproducible example](https://reprex.tidyverse.org/articles/reprex-dos-and-donts.html)".


1.  **Packages** should be loaded at the top of the script, so it's easy to
    see which ones the example needs.
  
1.  Spend a little bit of time ensuring that your **code** is easy for others to
    read:
  
    * make sure you've used spaces and your variable names are concise, but
      informative
  
    * use comments generously to indicate where your problem lies
  
    * do your best to remove everything that is not related to the problem.  

You can check you have actually made a reproducible example by starting up a 
fresh R session and pasting your script in.


### Pull Requests

#### Getting Started
* Make sure you have a [GitHub account](https://github.com/signup/free).
* Familiarise yourself with Git and Github, using the [resources](#additional-resources) at the end of this page.

#### Prerequisites
Before you make a substantial pull request, you should always file an issue and
make sure someone from the team agrees that it’s a problem. If you’ve found a
bug, create an associated issue and illustrate the bug with a minimal 
[reproducible example](https://reprex.tidyverse.org/articles/reprex-dos-and-donts.html).

#### Pull request process
*  We recommend that you create a Git branch for each pull request (PR).  
*  Look at the Travis and AppVeyor build status before and after making changes.
The `README` should contain badges for any continuous integration services used
by the package.  
*  New code should follow the tidyverse [style guide](http://style.tidyverse.org).
You can use the [styler](https://CRAN.R-project.org/package=styler) package to
apply these styles, but please don't restyle code that has nothing to do with 
your PR.  
*  We use [roxygen2](https://cran.r-project.org/package=roxygen2), with
[Markdown syntax](https://cran.r-project.org/web/packages/roxygen2/vignettes/markdown.html), 
for documentation.  
*  We use [testthat](https://cran.r-project.org/package=testthat). Contributions
with test cases included are easier to accept.  

### Additional Resources

  * The [Git and Github](http://r-pkgs.had.co.nz/git.html) section of the __R Packages__ book by Hadley Wickham
  * [Happy Git and GitHub for the useR](https://happygitwithr.com/)
  * General GitHub [documentation](https://help.github.com/)
  * GitHub pull request [documentation]](https://help.github.com/articles/creating-a-pull-request/)









================================================
FILE: inst/CITATION
================================================
bibentry(
  header = "To cite PRISMA2020 in publications, please use:",
  bibtype    = "Article",
  title    = "PRISMA2020: An R package and Shiny app for producing PRISMA 2020-compliant flow diagrams, with interactivity for optimised digital transparency and Open Synthesis",
  author   = "Neal R Haddaway, Matthew J Page, Chris C Pritchard and Luke A McGuinness",
  year     = "2022",
  doi      = "10.1002/cl2.1230",
  journal  = "Campbell Systematic Reviews",
  number   = "2",
  volume   = "18",
  pages    = "e1230",
)

================================================
FILE: inst/extdata/PRISMA.csv
================================================
data,node,box,description,boxtext,tooltips,url,n
NA,node4,prevstud,Grey title box; Previous studies,Previous studies,Grey title box; Previous studies,prevstud.html,0
previous_studies,node5,box1,Studies included in previous version of review,Studies included in previous version of review,Studies included in previous version of review,previous_studies.html,0
previous_reports,NA,box1,Reports of studies included in previous version of review,Reports of studies included in previous version of review,NA,previous_reports.html,0
NA,node6,newstud,Yellow title box; Identification of new studies via databases and registers,Identification of new studies via databases and registers,Yellow title box; Identification of new studies via databases and registers,newstud.html,0
database_results,node7,box2,Records identified from: Databases,Databases,Records identified from: Databases and Registers,database_results.html,0
database_specific_results,NA,box2,Records identified from: specific databases,Specific Databases,NA,database_results.html,"Database 1, xxx; Database 2, xxx; Database 3, xxx"
register_results,NA,box2,Records identified from: Registers,Registers,NA,NA,0
register_specific_results,NA,box2,Records identified from: specific registers,Specific Registers,NA,database_results.html,"Register 1, xxx; Register 2, xxx; Register 3, xxx"
NA,node16,othstud,Grey title box; Identification of new studies via other methods,Identification of new studies via other methods,Grey title box; Identification of new studies via other methods,othstud.html,0
website_results,node17,box11,Records identified from: Websites,Websites,"Records identified from: Websites, Organisations and Citation Searching",website_results.html,0
organisation_results,,box11,Records identified from: Organisations,Organisations,NA,NA,0
citations_results,NA,box11,Records identified from: Citation searching,Citation searching,NA,NA,0
duplicates,node8,box3,Duplicate records,Duplicate records,Duplicate records,duplicates.html,0
excluded_automatic,NA,box3,Records marked as ineligible by automation tools,Records marked as ineligible by automation tools,NA,NA,0
excluded_other,NA,box3,Records removed for other reasons,Records removed for other reasons,NA,NA,0
records_screened,node9,box4,Records screened (databases and registers),Records screened,Records screened (databases and registers),records_screened.html,0
records_excluded,node10,box5,Records excluded (databases and registers),Records excluded,Records excluded (databases and registers),records_excluded.html,0
dbr_sought_reports,node11,box6,Reports sought for retrieval (databases and registers),Reports sought for retrieval,Reports sought for retrieval (databases and registers),dbr_sought_reports.html,0
dbr_notretrieved_reports,node12,box7,Reports not retrieved (databases and registers),Reports not retrieved,Reports not retrieved (databases and registers),dbr_notretrieved_reports.html,0
other_sought_reports,node18,box12,Reports sought for retrieval (other),Reports sought for retrieval,Reports sought for retrieval (other),other_sought_reports.html,0
other_notretrieved_reports,node19,box13,Reports not retrieved (other),Reports not retrieved,Reports not retrieved (other),other_notretrieved_reports.html,0
dbr_assessed,node13,box8,Reports assessed for eligibility (databases and registers),Reports assessed for eligibility,Reports assessed for eligibility (databases and registers),dbr_assessed.html,0
dbr_excluded,node14,box9,"Reports excluded (databases and registers): [separate reasons and numbers using ; e.g. Reason1, xxx; Reason2, xxx; Reason3, xxx]",Reports excluded,Reports excluded (databases and registers),dbrexcludedrecords.html,"Reason1, xxx; Reason2, xxx; Reason3, xxx"
other_assessed,node20,box14,Reports assessed for eligibility (other),Reports assessed for eligibility,Reports assessed for eligibility (other),other_assessed.html,0
other_excluded,node21,box15,"Reports excluded (other): [separate reasons and numbers using ; e.g. Reason1, xxx; Reason2, xxx; Reason3, xxx]",Reports excluded,Reports excluded (other),other_excluded.html,"Reason1, xxx; Reason2, xxx; Reason3, xxx"
new_studies,node15,box10,New studies included in review,New studies included in review,New studies included in review,new_studies.html,0
new_reports,NA,box10,Reports of new included studies,Reports of new included studies,NA,NA,0
total_studies,node22,box16,Total studies included in review,Total studies included in review,Total studies included in review,total_studies.html,0
total_reports,NA,box16,Reports of total included studies,Reports of total included studies,NA,NA,0
identification,node1,identification,Blue identification box,Identification,Blue identification box,identification.html,0
screening,node2,screening,Blue screening box,Screening,Blue screening box,screening.html,0
included,node3,included,Blue included box,Included,Blue included box,included.html,0
total_studies_ma,node23,box17,Total studies included in meta-analysis,Total studies included in meta-analysis,Total studies included in meta-analysis,total_studies_meta_analysis.html,0
total_reports_ma,NA,box17,Reports of total included studies in meta-analysis,Reports of total included studies in meta-analysis,NA,NA,0

================================================
FILE: inst/extdata/Template.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<style>body{background-color:white;}</style>
<script>(function() {
  // If window.HTMLWidgets is already defined, then use it; otherwise create a
  // new object. This allows preceding code to set options that affect the
  // initialization process (though none currently exist).
  window.HTMLWidgets = window.HTMLWidgets || {};

  // See if we're running in a viewer pane. If not, we're in a web browser.
  var viewerMode = window.HTMLWidgets.viewerMode =
      /\bviewer_pane=1\b/.test(window.location);

  // See if we're running in Shiny mode. If not, it's a static document.
  // Note that static widgets can appear in both Shiny and static modes, but
  // obviously, Shiny widgets can only appear in Shiny apps/documents.
  var shinyMode = window.HTMLWidgets.shinyMode =
      typeof(window.Shiny) !== "undefined" && !!window.Shiny.outputBindings;

  // We can't count on jQuery being available, so we implement our own
  // version if necessary.
  function querySelectorAll(scope, selector) {
    if (typeof(jQuery) !== "undefined" && scope instanceof jQuery) {
      return scope.find(selector);
    }
    if (scope.querySelectorAll) {
      return scope.querySelectorAll(selector);
    }
  }

  function asArray(value) {
    if (value === null)
      return [];
    if ($.isArray(value))
      return value;
    return [value];
  }

  // Implement jQuery's extend
  function extend(target /*, ... */) {
    if (arguments.length == 1) {
      return target;
    }
    for (var i = 1; i < arguments.length; i++) {
      var source = arguments[i];
      for (var prop in source) {
        if (source.hasOwnProperty(prop)) {
          target[prop] = source[prop];
        }
      }
    }
    return target;
  }

  // IE8 doesn't support Array.forEach.
  function forEach(values, callback, thisArg) {
    if (values.forEach) {
      values.forEach(callback, thisArg);
    } else {
      for (var i = 0; i < values.length; i++) {
        callback.call(thisArg, values[i], i, values);
      }
    }
  }

  // Replaces the specified method with the return value of funcSource.
  //
  // Note that funcSource should not BE the new method, it should be a function
  // that RETURNS the new method. funcSource receives a single argument that is
  // the overridden method, it can be called from the new method. The overridden
  // method can be called like a regular function, it has the target permanently
  // bound to it so "this" will work correctly.
  function overrideMethod(target, methodName, funcSource) {
    var superFunc = target[methodName] || function() {};
    var superFuncBound = function() {
      return superFunc.apply(target, arguments);
    };
    target[methodName] = funcSource(superFuncBound);
  }

  // Add a method to delegator that, when invoked, calls
  // delegatee.methodName. If there is no such method on
  // the delegatee, but there was one on delegator before
  // delegateMethod was called, then the original version
  // is invoked instead.
  // For example:
  //
  // var a = {
  //   method1: function() { console.log('a1'); }
  //   method2: function() { console.log('a2'); }
  // };
  // var b = {
  //   method1: function() { console.log('b1'); }
  // };
  // delegateMethod(a, b, "method1");
  // delegateMethod(a, b, "method2");
  // a.method1();
  // a.method2();
  //
  // The output would be "b1", "a2".
  function delegateMethod(delegator, delegatee, methodName) {
    var inherited = delegator[methodName];
    delegator[methodName] = function() {
      var target = delegatee;
      var method = delegatee[methodName];

      // The method doesn't exist on the delegatee. Instead,
      // call the method on the delegator, if it exists.
      if (!method) {
        target = delegator;
        method = inherited;
      }

      if (method) {
        return method.apply(target, arguments);
      }
    };
  }

  // Implement a vague facsimilie of jQuery's data method
  function elementData(el, name, value) {
    if (arguments.length == 2) {
      return el["htmlwidget_data_" + name];
    } else if (arguments.length == 3) {
      el["htmlwidget_data_" + name] = value;
      return el;
    } else {
      throw new Error("Wrong number of arguments for elementData: " +
        arguments.length);
    }
  }

  // http://stackoverflow.com/questions/3446170/escape-string-for-use-in-javascript-regex
  function escapeRegExp(str) {
    return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
  }

  function hasClass(el, className) {
    var re = new RegExp("\\b" + escapeRegExp(className) + "\\b");
    return re.test(el.className);
  }

  // elements - array (or array-like object) of HTML elements
  // className - class name to test for
  // include - if true, only return elements with given className;
  //   if false, only return elements *without* given className
  function filterByClass(elements, className, include) {
    var results = [];
    for (var i = 0; i < elements.length; i++) {
      if (hasClass(elements[i], className) == include)
        results.push(elements[i]);
    }
    return results;
  }

  function on(obj, eventName, func) {
    if (obj.addEventListener) {
      obj.addEventListener(eventName, func, false);
    } else if (obj.attachEvent) {
      obj.attachEvent(eventName, func);
    }
  }

  function off(obj, eventName, func) {
    if (obj.removeEventListener)
      obj.removeEventListener(eventName, func, false);
    else if (obj.detachEvent) {
      obj.detachEvent(eventName, func);
    }
  }

  // Translate array of values to top/right/bottom/left, as usual with
  // the "padding" CSS property
  // https://developer.mozilla.org/en-US/docs/Web/CSS/padding
  function unpackPadding(value) {
    if (typeof(value) === "number")
      value = [value];
    if (value.length === 1) {
      return {top: value[0], right: value[0], bottom: value[0], left: value[0]};
    }
    if (value.length === 2) {
      return {top: value[0], right: value[1], bottom: value[0], left: value[1]};
    }
    if (value.length === 3) {
      return {top: value[0], right: value[1], bottom: value[2], left: value[1]};
    }
    if (value.length === 4) {
      return {top: value[0], right: value[1], bottom: value[2], left: value[3]};
    }
  }

  // Convert an unpacked padding object to a CSS value
  function paddingToCss(paddingObj) {
    return paddingObj.top + "px " + paddingObj.right + "px " + paddingObj.bottom + "px " + paddingObj.left + "px";
  }

  // Makes a number suitable for CSS
  function px(x) {
    if (typeof(x) === "number")
      return x + "px";
    else
      return x;
  }

  // Retrieves runtime widget sizing information for an element.
  // The return value is either null, or an object with fill, padding,
  // defaultWidth, defaultHeight fields.
  function sizingPolicy(el) {
    var sizingEl = document.querySelector("script[data-for='" + el.id + "'][type='application/htmlwidget-sizing']");
    if (!sizingEl)
      return null;
    var sp = JSON.parse(sizingEl.textContent || sizingEl.text || "{}");
    if (viewerMode) {
      return sp.viewer;
    } else {
      return sp.browser;
    }
  }

  // @param tasks Array of strings (or falsy value, in which case no-op).
  //   Each element must be a valid JavaScript expression that yields a
  //   function. Or, can be an array of objects with "code" and "data"
  //   properties; in this case, the "code" property should be a string
  //   of JS that's an expr that yields a function, and "data" should be
  //   an object that will be added as an additional argument when that
  //   function is called.
  // @param target The object that will be "this" for each function
  //   execution.
  // @param args Array of arguments to be passed to the functions. (The
  //   same arguments will be passed to all functions.)
  function evalAndRun(tasks, target, args) {
    if (tasks) {
      forEach(tasks, function(task) {
        var theseArgs = args;
        if (typeof(task) === "object") {
          theseArgs = theseArgs.concat([task.data]);
          task = task.code;
        }
        var taskFunc = tryEval(task);
        if (typeof(taskFunc) !== "function") {
          throw new Error("Task must be a function! Source:\n" + task);
        }
        taskFunc.apply(target, theseArgs);
      });
    }
  }

  // Attempt eval() both with and without enclosing in parentheses.
  // Note that enclosing coerces a function declaration into
  // an expression that eval() can parse
  // (otherwise, a SyntaxError is thrown)
  function tryEval(code) {
    var result = null;
    try {
      result = eval(code);
    } catch(error) {
      if (!error instanceof SyntaxError) {
        throw error;
      }
      try {
        result = eval("(" + code + ")");
      } catch(e) {
        if (e instanceof SyntaxError) {
          throw error;
        } else {
          throw e;
        }
      }
    }
    return result;
  }

  function initSizing(el) {
    var sizing = sizingPolicy(el);
    if (!sizing)
      return;

    var cel = document.getElementById("htmlwidget_container");
    if (!cel)
      return;

    if (typeof(sizing.padding) !== "undefined") {
      document.body.style.margin = "0";
      document.body.style.padding = paddingToCss(unpackPadding(sizing.padding));
    }

    if (sizing.fill) {
      document.body.style.overflow = "hidden";
      document.body.style.width = "100%";
      document.body.style.height = "100%";
      document.documentElement.style.width = "100%";
      document.documentElement.style.height = "100%";
      if (cel) {
        cel.style.position = "absolute";
        var pad = unpackPadding(sizing.padding);
        cel.style.top = pad.top + "px";
        cel.style.right = pad.right + "px";
        cel.style.bottom = pad.bottom + "px";
        cel.style.left = pad.left + "px";
        el.style.width = "100%";
        el.style.height = "100%";
      }

      return {
        getWidth: function() { return cel.offsetWidth; },
        getHeight: function() { return cel.offsetHeight; }
      };

    } else {
      el.style.width = px(sizing.width);
      el.style.height = px(sizing.height);

      return {
        getWidth: function() { return el.offsetWidth; },
        getHeight: function() { return el.offsetHeight; }
      };
    }
  }

  // Default implementations for methods
  var defaults = {
    find: function(scope) {
      return querySelectorAll(scope, "." + this.name);
    },
    renderError: function(el, err) {
      var $el = $(el);

      this.clearError(el);

      // Add all these error classes, as Shiny does
      var errClass = "shiny-output-error";
      if (err.type !== null) {
        // use the classes of the error condition as CSS class names
        errClass = errClass + " " + $.map(asArray(err.type), function(type) {
          return errClass + "-" + type;
        }).join(" ");
      }
      errClass = errClass + " htmlwidgets-error";

      // Is el inline or block? If inline or inline-block, just display:none it
      // and add an inline error.
      var display = $el.css("display");
      $el.data("restore-display-mode", display);

      if (display === "inline" || display === "inline-block") {
        $el.hide();
        if (err.message !== "") {
          var errorSpan = $("<span>").addClass(errClass);
          errorSpan.text(err.message);
          $el.after(errorSpan);
        }
      } else if (display === "block") {
        // If block, add an error just after the el, set visibility:none on the
        // el, and position the error to be on top of the el.
        // Mark it with a unique ID and CSS class so we can remove it later.
        $el.css("visibility", "hidden");
        if (err.message !== "") {
          var errorDiv = $("<div>").addClass(errClass).css("position", "absolute")
            .css("top", el.offsetTop)
            .css("left", el.offsetLeft)
            // setting width can push out the page size, forcing otherwise
            // unnecessary scrollbars to appear and making it impossible for
            // the element to shrink; so use max-width instead
            .css("maxWidth", el.offsetWidth)
            .css("height", el.offsetHeight);
          errorDiv.text(err.message);
          $el.after(errorDiv);

          // Really dumb way to keep the size/position of the error in sync with
          // the parent element as the window is resized or whatever.
          var intId = setInterval(function() {
            if (!errorDiv[0].parentElement) {
              clearInterval(intId);
              return;
            }
            errorDiv
              .css("top", el.offsetTop)
              .css("left", el.offsetLeft)
              .css("maxWidth", el.offsetWidth)
              .css("height", el.offsetHeight);
          }, 500);
        }
      }
    },
    clearError: function(el) {
      var $el = $(el);
      var display = $el.data("restore-display-mode");
      $el.data("restore-display-mode", null);

      if (display === "inline" || display === "inline-block") {
        if (display)
          $el.css("display", display);
        $(el.nextSibling).filter(".htmlwidgets-error").remove();
      } else if (display === "block"){
        $el.css("visibility", "inherit");
        $(el.nextSibling).filter(".htmlwidgets-error").remove();
      }
    },
    sizing: {}
  };

  // Called by widget bindings to register a new type of widget. The definition
  // object can contain the following properties:
  // - name (required) - A string indicating the binding name, which will be
  //   used by default as the CSS classname to look for.
  // - initialize (optional) - A function(el) that will be called once per
  //   widget element; if a value is returned, it will be passed as the third
  //   value to renderValue.
  // - renderValue (required) - A function(el, data, initValue) that will be
  //   called with data. Static contexts will cause this to be called once per
  //   element; Shiny apps will cause this to be called multiple times per
  //   element, as the data changes.
  window.HTMLWidgets.widget = function(definition) {
    if (!definition.name) {
      throw new Error("Widget must have a name");
    }
    if (!definition.type) {
      throw new Error("Widget must have a type");
    }
    // Currently we only support output widgets
    if (definition.type !== "output") {
      throw new Error("Unrecognized widget type '" + definition.type + "'");
    }
    // TODO: Verify that .name is a valid CSS classname

    // Support new-style instance-bound definitions. Old-style class-bound
    // definitions have one widget "object" per widget per type/class of
    // widget; the renderValue and resize methods on such widget objects
    // take el and instance arguments, because the widget object can't
    // store them. New-style instance-bound definitions have one widget
    // object per widget instance; the definition that's passed in doesn't
    // provide renderValue or resize methods at all, just the single method
    //   factory(el, width, height)
    // which returns an object that has renderValue(x) and resize(w, h).
    // This enables a far more natural programming style for the widget
    // author, who can store per-instance state using either OO-style
    // instance fields or functional-style closure variables (I guess this
    // is in contrast to what can only be called C-style pseudo-OO which is
    // what we required before).
    if (definition.factory) {
      definition = createLegacyDefinitionAdapter(definition);
    }

    if (!definition.renderValue) {
      throw new Error("Widget must have a renderValue function");
    }

    // For static rendering (non-Shiny), use a simple widget registration
    // scheme. We also use this scheme for Shiny apps/documents that also
    // contain static widgets.
    window.HTMLWidgets.widgets = window.HTMLWidgets.widgets || [];
    // Merge defaults into the definition; don't mutate the original definition.
    var staticBinding = extend({}, defaults, definition);
    overrideMethod(staticBinding, "find", function(superfunc) {
      return function(scope) {
        var results = superfunc(scope);
        // Filter out Shiny outputs, we only want the static kind
        return filterByClass(results, "html-widget-output", false);
      };
    });
    window.HTMLWidgets.widgets.push(staticBinding);

    if (shinyMode) {
      // Shiny is running. Register the definition with an output binding.
      // The definition itself will not be the output binding, instead
      // we will make an output binding object that delegates to the
      // definition. This is because we foolishly used the same method
      // name (renderValue) for htmlwidgets definition and Shiny bindings
      // but they actually have quite different semantics (the Shiny
      // bindings receive data that includes lots of metadata that it
      // strips off before calling htmlwidgets renderValue). We can't
      // just ignore the difference because in some widgets it's helpful
      // to call this.renderValue() from inside of resize(), and if
      // we're not delegating, then that call will go to the Shiny
      // version instead of the htmlwidgets version.

      // Merge defaults with definition, without mutating either.
      var bindingDef = extend({}, defaults, definition);

      // This object will be our actual Shiny binding.
      var shinyBinding = new Shiny.OutputBinding();

      // With a few exceptions, we'll want to simply use the bindingDef's
      // version of methods if they are available, otherwise fall back to
      // Shiny's defaults. NOTE: If Shiny's output bindings gain additional
      // methods in the future, and we want them to be overrideable by
      // HTMLWidget binding definitions, then we'll need to add them to this
      // list.
      delegateMethod(shinyBinding, bindingDef, "getId");
      delegateMethod(shinyBinding, bindingDef, "onValueChange");
      delegateMethod(shinyBinding, bindingDef, "onValueError");
      delegateMethod(shinyBinding, bindingDef, "renderError");
      delegateMethod(shinyBinding, bindingDef, "clearError");
      delegateMethod(shinyBinding, bindingDef, "showProgress");

      // The find, renderValue, and resize are handled differently, because we
      // want to actually decorate the behavior of the bindingDef methods.

      shinyBinding.find = function(scope) {
        var results = bindingDef.find(scope);

        // Only return elements that are Shiny outputs, not static ones
        var dynamicResults = results.filter(".html-widget-output");

        // It's possible that whatever caused Shiny to think there might be
        // new dynamic outputs, also caused there to be new static outputs.
        // Since there might be lots of different htmlwidgets bindings, we
        // schedule execution for later--no need to staticRender multiple
        // times.
        if (results.length !== dynamicResults.length)
          scheduleStaticRender();

        return dynamicResults;
      };

      // Wrap renderValue to handle initialization, which unfortunately isn't
      // supported natively by Shiny at the time of this writing.

      shinyBinding.renderValue = function(el, data) {
        Shiny.renderDependencies(data.deps);
        // Resolve strings marked as javascript literals to objects
        if (!(data.evals instanceof Array)) data.evals = [data.evals];
        for (var i = 0; data.evals && i < data.evals.length; i++) {
          window.HTMLWidgets.evaluateStringMember(data.x, data.evals[i]);
        }
        if (!bindingDef.renderOnNullValue) {
          if (data.x === null) {
            el.style.visibility = "hidden";
            return;
          } else {
            el.style.visibility = "inherit";
          }
        }
        if (!elementData(el, "initialized")) {
          initSizing(el);

          elementData(el, "initialized", true);
          if (bindingDef.initialize) {
            var result = bindingDef.initialize(el, el.offsetWidth,
              el.offsetHeight);
            elementData(el, "init_result", result);
          }
        }
        bindingDef.renderValue(el, data.x, elementData(el, "init_result"));
        evalAndRun(data.jsHooks.render, elementData(el, "init_result"), [el, data.x]);
      };

      // Only override resize if bindingDef implements it
      if (bindingDef.resize) {
        shinyBinding.resize = function(el, width, height) {
          // Shiny can call resize before initialize/renderValue have been
          // called, which doesn't make sense for widgets.
          if (elementData(el, "initialized")) {
            bindingDef.resize(el, width, height, elementData(el, "init_result"));
          }
        };
      }

      Shiny.outputBindings.register(shinyBinding, bindingDef.name);
    }
  };

  var scheduleStaticRenderTimerId = null;
  function scheduleStaticRender() {
    if (!scheduleStaticRenderTimerId) {
      scheduleStaticRenderTimerId = setTimeout(function() {
        scheduleStaticRenderTimerId = null;
        window.HTMLWidgets.staticRender();
      }, 1);
    }
  }

  // Render static widgets after the document finishes loading
  // Statically render all elements that are of this widget's class
  window.HTMLWidgets.staticRender = function() {
    var bindings = window.HTMLWidgets.widgets || [];
    forEach(bindings, function(binding) {
      var matches = binding.find(document.documentElement);
      forEach(matches, function(el) {
        var sizeObj = initSizing(el, binding);

        if (hasClass(el, "html-widget-static-bound"))
          return;
        el.className = el.className + " html-widget-static-bound";

        var initResult;
        if (binding.initialize) {
          initResult = binding.initialize(el,
            sizeObj ? sizeObj.getWidth() : el.offsetWidth,
            sizeObj ? sizeObj.getHeight() : el.offsetHeight
          );
          elementData(el, "init_result", initResult);
        }

        if (binding.resize) {
          var lastSize = {
            w: sizeObj ? sizeObj.getWidth() : el.offsetWidth,
            h: sizeObj ? sizeObj.getHeight() : el.offsetHeight
          };
          var resizeHandler = function(e) {
            var size = {
              w: sizeObj ? sizeObj.getWidth() : el.offsetWidth,
              h: sizeObj ? sizeObj.getHeight() : el.offsetHeight
            };
            if (size.w === 0 && size.h === 0)
              return;
            if (size.w === lastSize.w && size.h === lastSize.h)
              return;
            lastSize = size;
            binding.resize(el, size.w, size.h, initResult);
          };

          on(window, "resize", resizeHandler);

          // This is needed for cases where we're running in a Shiny
          // app, but the widget itself is not a Shiny output, but
          // rather a simple static widget. One example of this is
          // an rmarkdown document that has runtime:shiny and widget
          // that isn't in a render function. Shiny only knows to
          // call resize handlers for Shiny outputs, not for static
          // widgets, so we do it ourselves.
          if (window.jQuery) {
            window.jQuery(document).on(
              "shown.htmlwidgets shown.bs.tab.htmlwidgets shown.bs.collapse.htmlwidgets",
              resizeHandler
            );
            window.jQuery(document).on(
              "hidden.htmlwidgets hidden.bs.tab.htmlwidgets hidden.bs.collapse.htmlwidgets",
              resizeHandler
            );
          }

          // This is needed for the specific case of ioslides, which
          // flips slides between display:none and display:block.
          // Ideally we would not have to have ioslide-specific code
          // here, but rather have ioslides raise a generic event,
          // but the rmarkdown package just went to CRAN so the
          // window to getting that fixed may be long.
          if (window.addEventListener) {
            // It's OK to limit this to window.addEventListener
            // browsers because ioslides itself only supports
            // such browsers.
            on(document, "slideenter", resizeHandler);
            on(document, "slideleave", resizeHandler);
          }
        }

        var scriptData = document.querySelector("script[data-for='" + el.id + "'][type='application/json']");
        if (scriptData) {
          var data = JSON.parse(scriptData.textContent || scriptData.text);
          // Resolve strings marked as javascript literals to objects
          if (!(data.evals instanceof Array)) data.evals = [data.evals];
          for (var k = 0; data.evals && k < data.evals.length; k++) {
            window.HTMLWidgets.evaluateStringMember(data.x, data.evals[k]);
          }
          binding.renderValue(el, data.x, initResult);
          evalAndRun(data.jsHooks.render, initResult, [el, data.x]);
        }
      });
    });

    invokePostRenderHandlers();
  }


  function has_jQuery3() {
    if (!window.jQuery) {
      return false;
    }
    var $version = window.jQuery.fn.jquery;
    var $major_version = parseInt($version.split(".")[0]);
    return $major_version >= 3;
  }

  /*
  / Shiny 1.4 bumped jQuery from 1.x to 3.x which means jQuery's
  / on-ready handler (i.e., $(fn)) is now asyncronous (i.e., it now
  / really means $(setTimeout(fn)).
  / https://jquery.com/upgrade-guide/3.0/#breaking-change-document-ready-handlers-are-now-asynchronous
  /
  / Since Shiny uses $() to schedule initShiny, shiny>=1.4 calls initShiny
  / one tick later than it did before, which means staticRender() is
  / called renderValue() earlier than (advanced) widget authors might be expecting.
  / https://github.com/rstudio/shiny/issues/2630
  /
  / For a concrete example, leaflet has some methods (e.g., updateBounds)
  / which reference Shiny methods registered in initShiny (e.g., setInputValue).
  / Since leaflet is privy to this life-cycle, it knows to use setTimeout() to
  / delay execution of those methods (until Shiny methods are ready)
  / https://github.com/rstudio/leaflet/blob/18ec981/javascript/src/index.js#L266-L268
  /
  / Ideally widget authors wouldn't need to use this setTimeout() hack that
  / leaflet uses to call Shiny methods on a staticRender(). In the long run,
  / the logic initShiny should be broken up so that method registration happens
  / right away, but binding happens later.
  */
  function maybeStaticRenderLater() {
    if (shinyMode && has_jQuery3()) {
      window.jQuery(window.HTMLWidgets.staticRender);
    } else {
      window.HTMLWidgets.staticRender();
    }
  }

  if (document.addEventListener) {
    document.addEventListener("DOMContentLoaded", function() {
      document.removeEventListener("DOMContentLoaded", arguments.callee, false);
      maybeStaticRenderLater();
    }, false);
  } else if (document.attachEvent) {
    document.attachEvent("onreadystatechange", function() {
      if (document.readyState === "complete") {
        document.detachEvent("onreadystatechange", arguments.callee);
        maybeStaticRenderLater();
      }
    });
  }


  window.HTMLWidgets.getAttachmentUrl = function(depname, key) {
    // If no key, default to the first item
    if (typeof(key) === "undefined")
      key = 1;

    var link = document.getElementById(depname + "-" + key + "-attachment");
    if (!link) {
      throw new Error("Attachment " + depname + "/" + key + " not found in document");
    }
    return link.getAttribute("href");
  };

  window.HTMLWidgets.dataframeToD3 = function(df) {
    var names = [];
    var length;
    for (var name in df) {
        if (df.hasOwnProperty(name))
            names.push(name);
        if (typeof(df[name]) !== "object" || typeof(df[name].length) === "undefined") {
            throw new Error("All fields must be arrays");
        } else if (typeof(length) !== "undefined" && length !== df[name].length) {
            throw new Error("All fields must be arrays of the same length");
        }
        length = df[name].length;
    }
    var results = [];
    var item;
    for (var row = 0; row < length; row++) {
        item = {};
        for (var col = 0; col < names.length; col++) {
            item[names[col]] = df[names[col]][row];
        }
        results.push(item);
    }
    return results;
  };

  window.HTMLWidgets.transposeArray2D = function(array) {
      if (array.length === 0) return array;
      var newArray = array[0].map(function(col, i) {
          return array.map(function(row) {
              return row[i]
          })
      });
      return newArray;
  };
  // Split value at splitChar, but allow splitChar to be escaped
  // using escapeChar. Any other characters escaped by escapeChar
  // will be included as usual (including escapeChar itself).
  function splitWithEscape(value, splitChar, escapeChar) {
    var results = [];
    var escapeMode = false;
    var currentResult = "";
    for (var pos = 0; pos < value.length; pos++) {
      if (!escapeMode) {
        if (value[pos] === splitChar) {
          results.push(currentResult);
          currentResult = "";
        } else if (value[pos] === escapeChar) {
          escapeMode = true;
        } else {
          currentResult += value[pos];
        }
      } else {
        currentResult += value[pos];
        escapeMode = false;
      }
    }
    if (currentResult !== "") {
      results.push(currentResult);
    }
    return results;
  }
  // Function authored by Yihui/JJ Allaire
  window.HTMLWidgets.evaluateStringMember = function(o, member) {
    var parts = splitWithEscape(member, '.', '\\');
    for (var i = 0, l = parts.length; i < l; i++) {
      var part = parts[i];
      // part may be a character or 'numeric' member name
      if (o !== null && typeof o === "object" && part in o) {
        if (i == (l - 1)) { // if we are at the end of the line then evalulate
          if (typeof o[part] === "string")
            o[part] = tryEval(o[part]);
        } else { // otherwise continue to next embedded object
          o = o[part];
        }
      }
    }
  };

  // Retrieve the HTMLWidget instance (i.e. the return value of an
  // HTMLWidget binding's initialize() or factory() function)
  // associated with an element, or null if none.
  window.HTMLWidgets.getInstance = function(el) {
    return elementData(el, "init_result");
  };

  // Finds the first element in the scope that matches the selector,
  // and returns the HTMLWidget instance (i.e. the return value of
  // an HTMLWidget binding's initialize() or factory() function)
  // associated with that element, if any. If no element matches the
  // selector, or the first matching element has no HTMLWidget
  // instance associated with it, then null is returned.
  //
  // The scope argument is optional, and defaults to window.document.
  window.HTMLWidgets.find = function(scope, selector) {
    if (arguments.length == 1) {
      selector = scope;
      scope = document;
    }

    var el = scope.querySelector(selector);
    if (el === null) {
      return null;
    } else {
      return window.HTMLWidgets.getInstance(el);
    }
  };

  // Finds all elements in the scope that match the selector, and
  // returns the HTMLWidget instances (i.e. the return values of
  // an HTMLWidget binding's initialize() or factory() function)
  // associated with the elements, in an array. If elements that
  // match the selector don't have an associated HTMLWidget
  // instance, the returned array will contain nulls.
  //
  // The scope argument is optional, and defaults to window.document.
  window.HTMLWidgets.findAll = function(scope, selector) {
    if (arguments.length == 1) {
      selector = scope;
      scope = document;
    }

    var nodes = scope.querySelectorAll(selector);
    var results = [];
    for (var i = 0; i < nodes.length; i++) {
      results.push(window.HTMLWidgets.getInstance(nodes[i]));
    }
    return results;
  };

  var postRenderHandlers = [];
  function invokePostRenderHandlers() {
    while (postRenderHandlers.length) {
      var handler = postRenderHandlers.shift();
      if (handler) {
        handler();
      }
    }
  }

  // Register the given callback function to be invoked after the
  // next time static widgets are rendered.
  window.HTMLWidgets.addPostRenderHandler = function(callback) {
    postRenderHandlers.push(callback);
  };

  // Takes a new-style instance-bound definition, and returns an
  // old-style class-bound definition. This saves us from having
  // to rewrite all the logic in this file to accomodate both
  // types of definitions.
  function createLegacyDefinitionAdapter(defn) {
    var result = {
      name: defn.name,
      type: defn.type,
      initialize: function(el, width, height) {
        return defn.factory(el, width, height);
      },
      renderValue: function(el, x, instance) {
        return instance.renderValue(x);
      },
      resize: function(el, width, height, instance) {
        return instance.resize(width, height);
      }
    };

    if (defn.find)
      result.find = defn.find;
    if (defn.renderError)
      result.renderError = defn.renderError;
    if (defn.clearError)
      result.clearError = defn.clearError;

    return result;
  }
})();

</script>
<script>/*
Viz.js 1.8.2 (Graphviz 2.40.1, Expat 2.2.5, Emscripten 1.37.33)
Copyright (c) 2014-2018 Michael Daines
Licensed under MIT license

This distribution contains other software in object code form:

Graphviz
Licensed under Eclipse Public License - v 1.0
http://www.graphviz.org

Expat
Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd and Clark Cooper
Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
Licensed under MIT license
http://www.libexpat.org

zlib
Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler
http://www.zlib.net/zlib_license.html
*/
(function(global) {
var Module = function(Module) {
  Module = Module || {};
var Module=typeof Module!=="undefined"?Module:{};var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}Module["arguments"]=[];Module["thisProgram"]="./this.program";Module["quit"]=(function(status,toThrow){throw toThrow});Module["preRun"]=[];Module["postRun"]=[];var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;if(Module["ENVIRONMENT"]){if(Module["ENVIRONMENT"]==="WEB"){ENVIRONMENT_IS_WEB=true}else if(Module["ENVIRONMENT"]==="WORKER"){ENVIRONMENT_IS_WORKER=true}else if(Module["ENVIRONMENT"]==="NODE"){ENVIRONMENT_IS_NODE=true}else if(Module["ENVIRONMENT"]==="SHELL"){ENVIRONMENT_IS_SHELL=true}else{throw new Error("Module['ENVIRONMENT'] value is not valid. must be one of: WEB|WORKER|NODE|SHELL.")}}else{ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof require==="function"&&!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER;ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER}if(ENVIRONMENT_IS_NODE){var nodeFS;var nodePath;Module["read"]=function shell_read(filename,binary){var ret;ret=tryParseAsDataURI(filename);if(!ret){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);ret=nodeFS["readFileSync"](filename)}return binary?ret:ret.toString()};Module["readBinary"]=function readBinary(filename){var ret=Module["read"](filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){Module["thisProgram"]=process["argv"][1].replace(/\\/g,"/")}Module["arguments"]=process["argv"].slice(2);if(typeof module!=="undefined"){module["exports"]=Module}process["on"]("uncaughtException",(function(ex){if(!(ex instanceof ExitStatus)){throw ex}}));process["on"]("unhandledRejection",(function(reason,p){process["exit"](1)}));Module["inspect"]=(function(){return"[Emscripten Module object]"})}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){Module["read"]=function shell_read(f){var data=tryParseAsDataURI(f);if(data){return intArrayToString(data)}return read(f)}}Module["readBinary"]=function readBinary(f){var data;data=tryParseAsDataURI(f);if(data){return data}if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){Module["arguments"]=scriptArgs}else if(typeof arguments!="undefined"){Module["arguments"]=arguments}if(typeof quit==="function"){Module["quit"]=(function(status,toThrow){quit(status)})}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){Module["read"]=function shell_read(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText}catch(err){var data=tryParseAsDataURI(url);if(data){return intArrayToString(data)}throw err}};if(ENVIRONMENT_IS_WORKER){Module["readBinary"]=function readBinary(url){try{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}catch(err){var data=tryParseAsDataURI(url);if(data){return data}throw err}}}Module["readAsync"]=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}var data=tryParseAsDataURI(url);if(data){onload(data.buffer);return}onerror()};xhr.onerror=onerror;xhr.send(null)};if(typeof arguments!="undefined"){Module["arguments"]=arguments}Module["setWindowTitle"]=(function(title){document.title=title})}Module["print"]=typeof console!=="undefined"?console.log:typeof print!=="undefined"?print:null;Module["printErr"]=typeof printErr!=="undefined"?printErr:typeof console!=="undefined"&&console.warn||Module["print"];Module.print=Module["print"];Module.printErr=Module["printErr"];for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=undefined;var STACK_ALIGN=16;function staticAlloc(size){assert(!staticSealed);var ret=STATICTOP;STATICTOP=STATICTOP+size+15&-16;return ret}function dynamicAlloc(size){assert(DYNAMICTOP_PTR);var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;if(end>=TOTAL_MEMORY){var success=enlargeMemory();if(!success){HEAP32[DYNAMICTOP_PTR>>2]=ret;return 0}}return ret}function alignMemory(size,factor){if(!factor)factor=STACK_ALIGN;var ret=size=Math.ceil(size/factor)*factor;return ret}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=parseInt(type.substr(1));assert(bits%8===0);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;Module.printErr(text)}}var functionPointers=new Array(0);var funcWrappers={};function dynCall(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}else{return Module["dynCall_"+sig].call(null,ptr)}}var GLOBAL_BASE=8;var ABORT=0;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}var JSfuncs={"stackSave":(function(){stackSave()}),"stackRestore":(function(){stackRestore()}),"arrayToC":(function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}),"stringToC":(function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret})};var toC={"string":JSfuncs["stringToC"],"array":JSfuncs["arrayToC"]};function ccall(ident,returnType,argTypes,args,opts){var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i<args.length;i++){var converter=toC[argTypes[i]];if(converter){if(stack===0)stack=stackSave();cArgs[i]=converter(args[i])}else{cArgs[i]=args[i]}}}var ret=func.apply(null,cArgs);if(returnType==="string")ret=Pointer_stringify(ret);if(stack!==0){stackRestore(stack)}return ret}function setValue(ptr,value,type,noSafe){type=type||"i8";if(type.charAt(type.length-1)==="*")type="i32";switch(type){case"i1":HEAP8[ptr>>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=+1?tempDouble>+0?(Math_min(+Math_floor(tempDouble/+4294967296),+4294967295)|0)>>>0:~~+Math_ceil((tempDouble- +(~~tempDouble>>>0))/+4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}var ALLOC_STATIC=2;var ALLOC_NONE=4;function allocate(slab,types,allocator,ptr){var zeroinit,size;if(typeof slab==="number"){zeroinit=true;size=slab}else{zeroinit=false;size=slab.length}var singleType=typeof types==="string"?types:null;var ret;if(allocator==ALLOC_NONE){ret=ptr}else{ret=[typeof _malloc==="function"?_malloc:staticAlloc,stackAlloc,staticAlloc,dynamicAlloc][allocator===undefined?ALLOC_STATIC:allocator](Math.max(size,singleType?1:types.length))}if(zeroinit){var stop;ptr=ret;assert((ret&3)==0);stop=ret+(size&~3);for(;ptr<stop;ptr+=4){HEAP32[ptr>>2]=0}stop=ret+size;while(ptr<stop){HEAP8[ptr++>>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i<size){var curr=slab[i];type=singleType||types[i];if(type===0){i++;continue}if(type=="i64")type="i32";setValue(ret+i,curr,type);if(previousType!==type){typeSize=getNativeTypeSize(type);previousType=type}i+=typeSize}return ret}function Pointer_stringify(ptr,length){if(length===0||!ptr)return"";var hasUtf=0;var t;var i=0;while(1){t=HEAPU8[ptr+i>>0];hasUtf|=t;if(t==0&&!length)break;i++;if(length&&i==length)break}if(!length)length=i;var ret="";if(hasUtf<128){var MAX_CHUNK=1024;var curr;while(length>0){curr=String.fromCharCode.apply(String,HEAPU8.subarray(ptr,ptr+Math.min(length,MAX_CHUNK)));ret=ret?ret+curr:curr;ptr+=MAX_CHUNK;length-=MAX_CHUNK}return ret}return UTF8ToString(ptr)}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(u8Array,idx){var endPtr=idx;while(u8Array[endPtr])++endPtr;if(endPtr-idx>16&&u8Array.subarray&&UTF8Decoder){return UTF8Decoder.decode(u8Array.subarray(idx,endPtr))}else{var u0,u1,u2,u3,u4,u5;var str="";while(1){u0=u8Array[idx++];if(!u0)return str;if(!(u0&128)){str+=String.fromCharCode(u0);continue}u1=u8Array[idx++]&63;if((u0&224)==192){str+=String.fromCharCode((u0&31)<<6|u1);continue}u2=u8Array[idx++]&63;if((u0&240)==224){u0=(u0&15)<<12|u1<<6|u2}else{u3=u8Array[idx++]&63;if((u0&248)==240){u0=(u0&7)<<18|u1<<12|u2<<6|u3}else{u4=u8Array[idx++]&63;if((u0&252)==248){u0=(u0&3)<<24|u1<<18|u2<<12|u3<<6|u4}else{u5=u8Array[idx++]&63;u0=(u0&1)<<30|u1<<24|u2<<18|u3<<12|u4<<6|u5}}}if(u0<65536){str+=String.fromCharCode(u0)}else{var ch=u0-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}}}}function UTF8ToString(ptr){return UTF8ArrayToString(HEAPU8,ptr)}function stringToUTF8Array(str,outU8Array,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){if(outIdx>=endIdx)break;outU8Array[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;outU8Array[outIdx++]=192|u>>6;outU8Array[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;outU8Array[outIdx++]=224|u>>12;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=2097151){if(outIdx+3>=endIdx)break;outU8Array[outIdx++]=240|u>>18;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else if(u<=67108863){if(outIdx+4>=endIdx)break;outU8Array[outIdx++]=248|u>>24;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}else{if(outIdx+5>=endIdx)break;outU8Array[outIdx++]=252|u>>30;outU8Array[outIdx++]=128|u>>24&63;outU8Array[outIdx++]=128|u>>18&63;outU8Array[outIdx++]=128|u>>12&63;outU8Array[outIdx++]=128|u>>6&63;outU8Array[outIdx++]=128|u&63}}outU8Array[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i<str.length;++i){var u=str.charCodeAt(i);if(u>=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127){++len}else if(u<=2047){len+=2}else if(u<=65535){len+=3}else if(u<=2097151){len+=4}else if(u<=67108863){len+=5}else{len+=6}}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function demangle(func){return func}function demangleAll(text){var regex=/__Z[\w\d_]+/g;return text.replace(regex,(function(x){var y=demangle(x);return x===y?x:x+" ["+y+"]"}))}function jsStackTrace(){var err=new Error;if(!err.stack){try{throw new Error(0)}catch(e){err=e}if(!err.stack){return"(no stack trace available)"}}return err.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}var PAGE_SIZE=16384;var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferViews(){Module["HEAP8"]=HEAP8=new Int8Array(buffer);Module["HEAP16"]=HEAP16=new Int16Array(buffer);Module["HEAP32"]=HEAP32=new Int32Array(buffer);Module["HEAPU8"]=HEAPU8=new Uint8Array(buffer);Module["HEAPU16"]=HEAPU16=new Uint16Array(buffer);Module["HEAPU32"]=HEAPU32=new Uint32Array(buffer);Module["HEAPF32"]=HEAPF32=new Float32Array(buffer);Module["HEAPF64"]=HEAPF64=new Float64Array(buffer)}var STATIC_BASE,STATICTOP,staticSealed;var STACK_BASE,STACKTOP,STACK_MAX;var DYNAMIC_BASE,DYNAMICTOP_PTR;STATIC_BASE=STATICTOP=STACK_BASE=STACKTOP=STACK_MAX=DYNAMIC_BASE=DYNAMICTOP_PTR=0;staticSealed=false;function abortOnCannotGrowMemory(){abort("Cannot enlarge memory arrays. Either (1) compile with  -s TOTAL_MEMORY=X  with X higher than the current value "+TOTAL_MEMORY+", (2) compile with  -s ALLOW_MEMORY_GROWTH=1  which allows increasing the size at runtime but prevents some optimizations, (3) set Module.TOTAL_MEMORY to a higher value before the program runs, or (4) if you want malloc to return NULL (0) instead of this abort, compile with  -s ABORTING_MALLOC=0 ")}function enlargeMemory(){abortOnCannotGrowMemory()}var TOTAL_STACK=Module["TOTAL_STACK"]||5242880;var TOTAL_MEMORY=Module["TOTAL_MEMORY"]||134217728;if(TOTAL_MEMORY<TOTAL_STACK)Module.printErr("TOTAL_MEMORY should be larger than TOTAL_STACK, was "+TOTAL_MEMORY+"! (TOTAL_STACK="+TOTAL_STACK+")");if(Module["buffer"]){buffer=Module["buffer"]}else{{buffer=new ArrayBuffer(TOTAL_MEMORY)}Module["buffer"]=buffer}updateGlobalBufferViews();function getTotalMemory(){return TOTAL_MEMORY}HEAP32[0]=1668509029;HEAP16[1]=25459;if(HEAPU8[2]!==115||HEAPU8[3]!==99)throw"Runtime error: expected the system to be little-endian!";function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback();continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){Module["dynCall_v"](func)}else{Module["dynCall_vi"](func,callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function ensureInitRuntime(){if(runtimeInitialized)return;runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){callRuntimeCallbacks(__ATEXIT__);runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i<str.length;++i){HEAP8[buffer++>>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}if(!Math["imul"]||Math["imul"](4294967295,5)!==-5)Math["imul"]=function imul(a,b){var ah=a>>>16;var al=a&65535;var bh=b>>>16;var bl=b&65535;return al*bl+(ah*bl+al*bh<<16)|0};Math.imul=Math["imul"];if(!Math["clz32"])Math["clz32"]=(function(x){x=x>>>0;for(var i=0;i<32;i++){if(x&1<<31-i)return i}return 32});Math.clz32=Math["clz32"];if(!Math["trunc"])Math["trunc"]=(function(x){return x<0?Math.ceil(x):Math.floor(x)});Math.trunc=Math["trunc"];var Math_abs=Math.abs;var Math_cos=Math.cos;var Math_sin=Math.sin;var Math_tan=Math.tan;var Math_acos=Math.acos;var Math_asin=Math.asin;var Math_atan=Math.atan;var Math_atan2=Math.atan2;var Math_exp=Math.exp;var Math_log=Math.log;var Math_sqrt=Math.sqrt;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_pow=Math.pow;var Math_imul=Math.imul;var Math_fround=Math.fround;var Math_round=Math.round;var Math_min=Math.min;var Math_max=Math.max;var Math_clz32=Math.clz32;var Math_trunc=Math.trunc;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};var memoryInitializer=null;var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return String.prototype.startsWith?filename.startsWith(dataURIPrefix):filename.indexOf(dataURIPrefix)===0}var ASM_CONSTS=[(function($0,$1){var path=Pointer_stringify($0);var data=Pointer_stringify($1);FS.createPath("/",PATH.dirname(path));FS.writeFile(PATH.join("/",path),data)})];function _emscripten_asm_const_iii(code,a0,a1){return ASM_CONSTS[code](a0,a1)}STATIC_BASE=GLOBAL_BASE;STATICTOP=STATIC_BASE+197232;__ATINIT__.push();memoryInitializer="data:application/octet-stream;base64,AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/AAAAAAAA8D8AAAAAAADwPwAAAAAAAPA/ACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAIMEAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSQAAAAAAAAFJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkAAIMEAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSQAAAAAAAAFJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkACEAAAAAAAAAAAAAAAABBAoC8AAAgAAAABAAAAAAAAAAIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICWQAAAAAAAgJZABJDDAAAAAAAAAAAAAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWEAAAAAAAABYQAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYQAAAAAAAAFhAAAAAAAAAAAAAAAAAAAAQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUkAAAAAAAABSQAAgAwIAAAAAAAAAAAAAEEAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAAAABCQAAAAAAAAEJAAAAAAAAgg0AAAAAAAMCIQAAAAAAAAFJAAAAAAAAAUkAAAAAAAAAAAAAAAAAAAEJAAAAAAAAAQkAAAAAAACCDQAAAAAAAwIhAAAAAAAAAUkAAAAAAAABSQACwwQAAAAAAAAAAAAAAEEBANgAAkwAAAAEAAAAAAAAAQAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkAAEAACAAAAAAAAAAAAABBAAAAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYQAAAAAAAAFhAALDBAAAAAAAAAAAAAAAAABw6AAAQAAAAAQAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWEAAAAAAAABYQEAgPgMAAAAAAAAAAAAAEEAkOwAAegAAAAEAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFJAAAAAAAAAUkAAAAAAAAAAAAAAAAAAABBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABSQAAAAAAAAFJA////////73/////////vf////////+//////////7/8AAAAAAAD4PzMzMzMzM9M/PAAAAAAAAACamZmZmZmpPwEAAAAAAAAAAQAAAAAAAAAAAAAAAADwPwEAAAAAAAAAAgAAAAAAAAAAAAAAAADwPwIAAAAAAAAAAwAAAAAAAAAAAAAAAADgPwMAAAAAAAAABAAAAAAAAAAAAAAAAADwPwQAAAAAAAAABQAAAAAAAAAzMzMzMzPzPwUAAAAAAAAABgAAAAAAAACamZmZmZnpPwYAAAAAAAAABwAAAAAAAAAAAAAAAADwPwcAAAAAAAAACAAAAAAAAAAAAAAAAADgPwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAAAAAAAAAAAAAAAMzMzMzMz078AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAgEZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAmpmZmZmZ2b8AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMzMzMzPjPwAAAAAAAAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAAAAAexSuR+F65L8AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAAAAAAAAEAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABr4VQAAAQAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAAAAAAAAAAAAAAgGZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAgGZAmpmZmZmZ2b8AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAgGZAexSuR+F65L8AAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAgEZAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAQAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAQAAAAEAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABIAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABUAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABYAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcAAAAAAAAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAAAEAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwVQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPC/AAAAAAAAAQAAAAAAAAAAAAAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAAAADQPwAAAAAAANA/AAAAAAAA0D8AAAAA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YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8YTLjP1HaG3xhMuM/UdobfGEy4z9R2ht8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AQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAwAAAAEAAAABAAAAAgAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAIAAAABAAAABAAAAAUAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAAGAAAAAQAAAAEAAAAHAAAACAAAAAkAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAACgAAAAoAAAAKAAAAAQAAAAEAAAALAAAAAQAAAAwAAAABAAAADQAAAA4AAAAPAAAAEAAAABEAAAASAAAAEwAAABQAAAAVAAAAFgAAABMAAAATAAAAEwAAABMAAAAXAAAAGAAAABkAAAATAAAAGgAAABsAAAAcAAAAHQAAABMAAAATAAAAEwAAABMAAAATAAAAAQAAAB4AAAABAAAAAQAAABMAAAABAAAAHwAAACAAAAAhAAAAIgAAACMAAAATAAAAJAAAACUAAAAmAAAAEwAAABMAAAATAAAAEwAAACcAAAAoAAAAKQAAABMAAAAqAAAAKwAAACwAAAAtAAAAEwAAABMAAAATAAAAEwAAABMAAAABAAAAAQAAAAEAAAABAAAAAQAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAALgAAABMAAAATAAAAEwAAAC8AAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAA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
Download .txt
gitextract_rzi0l72b/

├── .Rbuildignore
├── .github/
│   ├── .gitignore
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   └── workflows/
│       ├── build-and-check-CRAN.yml
│       ├── check-and-deploy.yml
│       └── docker-build-push.yml
├── .gitignore
├── CITATION.cff
├── DESCRIPTION
├── Dockerfile
├── LICENSE
├── LICENSE.md
├── NAMESPACE
├── PRISMA2020.Rproj
├── R/
│   ├── PRISMA_flowdiagram.R
│   ├── globals.R
│   └── utils.R
├── README.md
├── code-of-conduct.md
├── contributing.md
├── inst/
│   ├── CITATION
│   ├── extdata/
│   │   ├── PRISMA.csv
│   │   ├── Template.html
│   │   └── citation.ris
│   └── shiny-examples/
│       └── PRISMA_flowdiagram/
│           ├── app.R
│           ├── rsconnect/
│           │   └── shinyapps.io/
│           │       └── estech/
│           │           └── prisma_flowdiagram.dcf
│           └── www/
│               ├── Haddaway_et_al_2022.ris
│               ├── PRISMA.csv
│               ├── kofi.js
│               └── labels.js
├── man/
│   ├── PRISMA_add_hyperlink_.Rd
│   ├── PRISMA_calc_filetype_.Rd
│   ├── PRISMA_data.Rd
│   ├── PRISMA_flowdiagram.Rd
│   ├── PRISMA_format_number_.Rd
│   ├── PRISMA_format_reasons_.Rd
│   ├── PRISMA_gen_tmp_svg_.Rd
│   ├── PRISMA_get_height_.Rd
│   ├── PRISMA_get_pos_.Rd
│   ├── PRISMA_insert_js_.Rd
│   ├── PRISMA_interactive_.Rd
│   ├── PRISMA_parse_reasons_.Rd
│   ├── PRISMA_save.Rd
│   ├── read_PRISMAdata.Rd
│   └── sr_flow_interactive.Rd
└── shiny-server.conf
Download .txt
SYMBOL INDEX (3 symbols across 1 files)

FILE: inst/shiny-examples/PRISMA_flowdiagram/www/labels.js
  function renderLabel (line 5) | function renderLabel(node, label) {
  function waitForAddedNode (line 22) | function waitForAddedNode(id, parent, recursive, done) {
  function createLabels (line 39) | function createLabels(nodeMap) {
Condensed preview — 48 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (2,336K chars).
[
  {
    "path": ".Rbuildignore",
    "chars": 151,
    "preview": "^.*\\.Rproj$\n^\\.Rproj\\.user$\n^\\.github$\n.png\ninst/shiny-examples\nLICENSE.md\nCITATION.cff\ncode-of-conduct.md\ncontributing."
  },
  {
    "path": ".github/.gitignore",
    "chars": 7,
    "preview": "*.html\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 97,
    "preview": "# These are supported funding model platforms\nopen_collective: esmarconf\nko_fi: chriscpritchard\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 834,
    "preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 595,
    "preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
  },
  {
    "path": ".github/workflows/build-and-check-CRAN.yml",
    "chars": 2234,
    "preview": "on:\n  push:\n    tags:\n      - 'v*'\nname: Publish Release, Build & Check for CRAN\njobs:\n  R-CMD-Build:\n    runs-on: ubunt"
  },
  {
    "path": ".github/workflows/check-and-deploy.yml",
    "chars": 3105,
    "preview": "on:\n  release:\n    types: [released]\n  pull_request:\n    types: [opened, synchronize, reopened]\n  issue_comment:\n    typ"
  },
  {
    "path": ".github/workflows/docker-build-push.yml",
    "chars": 1544,
    "preview": "name: Docker\n\non:\n  push:\n    branches:\n      - master\n    tags:\n      - v*\n\nenv:\n  IMAGE_NAME: prisma-flowdiagram/prism"
  },
  {
    "path": ".gitignore",
    "chars": 72,
    "preview": ".Rproj.user\n.Rhistory\n.RData\n.Ruserdata\n.vscode/launch.json\n**/.DS_Store"
  },
  {
    "path": "CITATION.cff",
    "chars": 1325,
    "preview": "cff-version: 1.2.0\nmessage: \"If you use this software, please cite it as below.\"\nauthors:\n  - family-names: Haddaway\n   "
  },
  {
    "path": "DESCRIPTION",
    "chars": 1996,
    "preview": "Package: PRISMA2020\nTitle: Make Interactive 'PRISMA' Flow Diagrams\nVersion: 1.1.2\nAuthors@R: c(\n    person(given = \"Neal"
  },
  {
    "path": "Dockerfile",
    "chars": 1159,
    "preview": "FROM rocker/shiny:latest\n\nLABEL maintainer=\"Hossam Hammady <hossam@rayyan.ai>\"\n\n# Install system dependencies\nRUN apt-ge"
  },
  {
    "path": "LICENSE",
    "chars": 44,
    "preview": "YEAR: 2020\nCOPYRIGHT HOLDER: Neal R Haddaway"
  },
  {
    "path": "LICENSE.md",
    "chars": 1054,
    "preview": "Copyright 2020 Neal R Haddaway\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this sof"
  },
  {
    "path": "NAMESPACE",
    "chars": 287,
    "preview": "# Generated by roxygen2: do not edit by hand\n\nexport(PRISMA_data)\nexport(PRISMA_flowdiagram)\nexport(PRISMA_save)\nimportF"
  },
  {
    "path": "PRISMA2020.Rproj",
    "chars": 343,
    "preview": "Version: 1.0\n\nRestoreWorkspace: Default\nSaveWorkspace: Default\nAlwaysSaveHistory: Default\n\nEnableCodeIndexing: Yes\nUseSp"
  },
  {
    "path": "R/PRISMA_flowdiagram.R",
    "chars": 50234,
    "preview": "# Suppress R CMD check note\n#' @importFrom DT addRow\n#' @importFrom rio import\n#' @importFrom shiny column\n#' @importFro"
  },
  {
    "path": "R/globals.R",
    "chars": 2783,
    "preview": "utils::globalVariables(c(\"previous_studies\",\n                         \"previous_reports\",\n                         \"regi"
  },
  {
    "path": "R/utils.R",
    "chars": 13806,
    "preview": "# Utility functions for PRISMA_flowdiagram\n\n#' Calculate the correct height of a box from a list (e.g. of exclusion reas"
  },
  {
    "path": "README.md",
    "chars": 2906,
    "preview": "<!-- badges: start -->\n[![Check & Deploy](https://github.com/prisma-flowdiagram/PRISMA2020/actions/workflows/check-and-d"
  },
  {
    "path": "code-of-conduct.md",
    "chars": 1437,
    "preview": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, we pledge to respect all people who \ncon"
  },
  {
    "path": "contributing.md",
    "chars": 3863,
    "preview": "# Contributing to PRISMA2020\n\nThe goal of this guide is to help you get up and contributing to PRISMA2020 as \nquickly as"
  },
  {
    "path": "inst/CITATION",
    "chars": 524,
    "preview": "bibentry(\n  header = \"To cite PRISMA2020 in publications, please use:\",\n  bibtype    = \"Article\",\n  title    = \"PRISMA20"
  },
  {
    "path": "inst/extdata/PRISMA.csv",
    "chars": 5264,
    "preview": "data,node,box,description,boxtext,tooltips,url,n\r\nNA,node4,prevstud,Grey title box; Previous studies,Previous studies,Gr"
  },
  {
    "path": "inst/extdata/Template.html",
    "chars": 2164650,
    "preview": "<!DOCTYPE html>\n<html>\n<head>\n<meta charset=\"utf-8\" />\n<style>body{background-color:white;}</style>\n<script>(function() "
  },
  {
    "path": "inst/extdata/citation.ris",
    "chars": 3202,
    "preview": "TY  - JOUR\nT1  - PRISMA2020: An R package and Shiny app for producing PRISMA 2020-compliant flow diagrams, with interact"
  },
  {
    "path": "inst/shiny-examples/PRISMA_flowdiagram/app.R",
    "chars": 33260,
    "preview": "library(shiny)\nlibrary(shinyjs)\nlibrary(rsvg)\nlibrary(DT) #nolint\nlibrary(rio)\nlibrary(devtools)\nlibrary(PRISMA2020) #no"
  },
  {
    "path": "inst/shiny-examples/PRISMA_flowdiagram/rsconnect/shinyapps.io/estech/prisma_flowdiagram.dcf",
    "chars": 256,
    "preview": "name: prisma_flowdiagram\ntitle:\nusername:\naccount: estech\nserver: shinyapps.io\nhostUrl: https://api.shinyapps.io/v1\nappI"
  },
  {
    "path": "inst/shiny-examples/PRISMA_flowdiagram/www/Haddaway_et_al_2022.ris",
    "chars": 3202,
    "preview": "TY  - JOUR\nT1  - PRISMA2020: An R package and Shiny app for producing PRISMA 2020-compliant flow diagrams, with interact"
  },
  {
    "path": "inst/shiny-examples/PRISMA_flowdiagram/www/PRISMA.csv",
    "chars": 5264,
    "preview": "data,node,box,description,boxtext,tooltips,url,n\r\nNA,node4,prevstud,Grey title box; Previous studies,Previous studies,Gr"
  },
  {
    "path": "inst/shiny-examples/PRISMA_flowdiagram/www/kofi.js",
    "chars": 298,
    "preview": "/** \n *\tKo-fi button\n*/\nkofiWidgetOverlay.draw(\n    'chriscpritchard', {\n        'type': 'floating-chat',\n        'float"
  },
  {
    "path": "inst/shiny-examples/PRISMA_flowdiagram/www/labels.js",
    "chars": 1554,
    "preview": "/** \n *\t@param {HTMLElement} node the node to label \n *  @param {string} label the label for the node\n*/\nfunction render"
  },
  {
    "path": "man/PRISMA_add_hyperlink_.Rd",
    "chars": 458,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_add_hyperlink_}\n\\alia"
  },
  {
    "path": "man/PRISMA_calc_filetype_.Rd",
    "chars": 497,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_calc_filetype_}\n\\alia"
  },
  {
    "path": "man/PRISMA_data.Rd",
    "chars": 526,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/PRISMA_flowdiagram.R\n\\name{PRISMA_data}\n\\a"
  },
  {
    "path": "man/PRISMA_flowdiagram.Rd",
    "chars": 3700,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/PRISMA_flowdiagram.R\n\\name{PRISMA_flowdiag"
  },
  {
    "path": "man/PRISMA_format_number_.Rd",
    "chars": 405,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_format_number_}\n\\alia"
  },
  {
    "path": "man/PRISMA_format_reasons_.Rd",
    "chars": 513,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_format_reasons_}\n\\ali"
  },
  {
    "path": "man/PRISMA_gen_tmp_svg_.Rd",
    "chars": 399,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_gen_tmp_svg_}\n\\alias{"
  },
  {
    "path": "man/PRISMA_get_height_.Rd",
    "chars": 540,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_get_height_}\n\\alias{P"
  },
  {
    "path": "man/PRISMA_get_pos_.Rd",
    "chars": 703,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_get_pos_}\n\\alias{PRIS"
  },
  {
    "path": "man/PRISMA_insert_js_.Rd",
    "chars": 689,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_insert_js_}\n\\alias{PR"
  },
  {
    "path": "man/PRISMA_interactive_.Rd",
    "chars": 1185,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_interactive_}\n\\alias{"
  },
  {
    "path": "man/PRISMA_parse_reasons_.Rd",
    "chars": 473,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/utils.R\n\\name{PRISMA_parse_reasons_}\n\\alia"
  },
  {
    "path": "man/PRISMA_save.Rd",
    "chars": 1823,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/PRISMA_flowdiagram.R\n\\name{PRISMA_save}\n\\a"
  },
  {
    "path": "man/read_PRISMAdata.Rd",
    "chars": 390,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/PRISMA_flowdiagram.R\n\\name{read_PRISMAdata"
  },
  {
    "path": "man/sr_flow_interactive.Rd",
    "chars": 1073,
    "preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/PRISMA_flowdiagram.R\n\\name{sr_flow_interac"
  },
  {
    "path": "shiny-server.conf",
    "chars": 394,
    "preview": "run_as shiny;\n\n# Define a server that listens on port 3838\nserver {\n  listen 3838;\n\n  # Define a location at the base UR"
  }
]

About this extraction

This page contains the full source code of the prisma-flowdiagram/PRISMA2020 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 48 files (2.2 MB), approximately 582.5k tokens, and a symbol index with 3 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!