Skip to content

feature(visualizeNetworksWithHTML): Add INDRA link into javascript visualization#57

Merged
tonywu1999 merged 3 commits intodevelfrom
open-url
Sep 5, 2025
Merged

feature(visualizeNetworksWithHTML): Add INDRA link into javascript visualization#57
tonywu1999 merged 3 commits intodevelfrom
open-url

Conversation

@tonywu1999
Copy link
Copy Markdown
Contributor

@tonywu1999 tonywu1999 commented Sep 5, 2025

User description

Motivation and Context

Please include relevant motivation and context of the problem along with a short summary of the solution.

Changes

Please provide a detailed bullet point list of your changes.

Testing

Please describe any unit tests you added or modified to verify your changes.

Checklist Before Requesting a Review

  • I have read the MSstats contributing guidelines
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules
  • Ran styler::style_pkg(transformers = styler::tidyverse_style(indent_by = 4))
  • Ran devtools::document()

PR Type

Enhancement


Description

  • Add evidenceLink to edge data

  • Enable opening INDRA evidence pages


Diagram Walkthrough

flowchart LR
  Rfn["R/visualizeNetworksWithHTML.R"]
  EdgeFn["createEdgeElements()"]
  EdgeData["Edge JSON data includes evidenceLink"]
  INDRA["Open INDRA evidence pages"]

  Rfn -- modifies --> EdgeFn
  EdgeFn -- adds field --> EdgeData
  EdgeData -- enables --> INDRA
Loading

File Walkthrough

Relevant files
Enhancement
visualizeNetworksWithHTML.R
Add evidenceLink field to edge JSON payload                           

R/visualizeNetworksWithHTML.R

  • Extend edge JSON with evidenceLink.
  • Propagate row$evidenceLink into Cytoscape data.
  • Prepare edges for opening INDRA URLs.
+1/-0     

Summary by CodeRabbit

  • New Features
    • Network visualizations now include an evidence link for each edge, enabling templates or displays to reference supporting evidence.
  • Bug Fixes / Behavior Changes
    • Empty or missing evidence is now represented as an empty value (not “NA”).
    • Evidence links are safely sanitized when embedded to prevent formatting issues.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 5, 2025

Walkthrough

Adds sanitization and embedding of an optional evidenceLink into edge data emitted by createEdgeElements in R/visualizeNetworksWithHTML.R; introduces an internal helper escape_js_string. NA/"NA" evidenceLink values are serialized as an empty string. No public signatures changed.

Changes

Cohort / File(s) Summary of edits
Edge data serialization
R/visualizeNetworksWithHTML.R
Added extraction of evidenceLink from each row (falling back to NA_character_), normalize NA/"NA" to "", JS-escape via new helper, and inserted evidenceLink into the edge_data string immediately after category (before color).
Internal helper
R/visualizeNetworksWithHTML.R
Added escape_js_string helper to escape backslashes, single quotes, newlines, and carriage returns for safe embedding into JS single-quoted literals; returns "" for NULL.

Sequence Diagram(s)

sequenceDiagram
    participant R as R createEdgeElements
    participant Helper as escape_js_string
    participant JS as Output HTML/JS

    R->>R: read row$evidenceLink (or NA)
    R->>R: normalize NA/"NA" -> ""
    R->>Helper: escape_js_string(evidence_link)
    Helper-->>R: escaped string
    R->>JS: build edge_data including evidenceLink (after category, before color)
    JS-->>R: serialized edge objects embedded in HTML
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

I hop through graphs with careful sight,
A tiny link now tucked in tight,
Escaped and neat, it rides each edge,
From node to node across the ledge.
I stamp the change and bound away—🐇✨

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch open-url

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@tonywu1999 tonywu1999 changed the title [Feature] Add INDRA link into javascript visualization feature(visualizeNetworksWithHTML): Add INDRA link into javascript visualization Sep 5, 2025
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Sep 5, 2025

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 Security concerns

Open redirect / XSS risk:
If evidenceLink comes from external or untrusted data and is later used to build clickable links in the browser, ensure it is validated to be an expected URL (e.g., https://indra...); also escape quotes to prevent breaking out of the string and injecting JS.

⚡ Recommended focus areas for review

Data Sanitization

The new evidenceLink field is interpolated directly into a JavaScript object string. If evidenceLink can contain quotes or special characters, it may break the generated JS or HTML. Consider escaping or encoding the value before concatenation.

"', evidenceLink: '", row$evidenceLink,
"', color: '", style$color,
"', line_style: '", style$style,
Missing Null Handling

If evidenceLink is NA or empty, the constructed JS may contain 'evidenceLink: 'NA'' which could be unintended. Consider defaulting to an empty string or omitting the field when not available.

"', evidenceLink: '", row$evidenceLink,
"', color: '", style$color,
"', line_style: '", style$style,

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Sep 5, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Sanitize evidence URL string

Guard against missing or unsafe characters in row$evidenceLink to avoid generating
invalid JavaScript/JSON. Coerce NA to an empty string and escape embedded single
quotes and backslashes before concatenation.

R/visualizeNetworksWithHTML.R [266-268]

 "', category: '", row$category,
-"', evidenceLink: '", row$evidenceLink,
+"', evidenceLink: '", gsub("(['\\\\])", "\\\\\\1", ifelse(is.na(row$evidenceLink), "", row$evidenceLink)),
 "', color: '", style$color,
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly targets the newly added evidenceLink field and proposes escaping unsafe characters and handling NA, improving robustness of the generated JS object. Impact is moderate as it prevents malformed output but isn't a critical bug fix.

Medium

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
R/visualizeNetworksWithHTML.R (1)

261-271: Escape and sanitize evidenceLink to avoid broken JS and potential injection

row$evidenceLink is concatenated into JavaScript without escaping; quotes or newlines will break the script, and NA becomes the literal string "NA". Precompute a sanitized value and use it.

Apply this diff within the loop to sanitize and use evidence_link:

 for (i in 1:nrow(consolidated_edges)) {
   row <- consolidated_edges[i,]
   edge_key <- paste(row$source, row$target, row$interaction, sep = "-")
 
   # Get styling for this edge
   style <- getEdgeStyle(row$interaction, row$category, row$edge_type)
 
+  # Sanitize optional evidenceLink
+  evidence_link <- if ("evidenceLink" %in% names(row)) row$evidenceLink else NA_character_
+  evidence_link <- ifelse(is.na(evidence_link) | evidence_link == "NA", "", evidence_link)
+  evidence_link <- escape_js_string(evidence_link)
+
   # Create edge data with styling information
   edge_data <- paste0("{ data: { source: '", row$source, 
                       "', target: '", row$target, 
                       "', id: '", edge_key,
                       "', interaction: '", row$interaction,
                       "', edge_type: '", row$edge_type,
                       "', category: '", row$category,
-                      "', evidenceLink: '", row$evidenceLink,
+                      "', evidenceLink: '", evidence_link,
                       "', color: '", style$color,
                       "', line_style: '", style$style,
                       "', arrow_shape: '", style$arrow,
                       "', width: ", style$width, " } }")

Add this helper (outside the loop, e.g., near other helpers):

# Helper to safely embed strings into JS single-quoted literals
escape_js_string <- function(x) {
  if (is.null(x)) return("")
  x <- as.character(x)
  x <- gsub("\\\\", "\\\\\\\\", x)  # backslashes
  x <- gsub("'", "\\\\'", x)        # single quotes
  x <- gsub("\r", "\\\\r", x)
  x <- gsub("\n", "\\\\n", x)
  x
}

I can wire this up across node labels too to harden the whole serializer.

🧹 Nitpick comments (1)
R/visualizeNetworksWithHTML.R (1)

261-271: Optionally omit evidenceLink when empty to reduce noise

If evidence_link is empty, consider omitting the key entirely instead of emitting evidenceLink: ''.

Example tweak inside the loop:

evidence_part <- if (nzchar(evidence_link)) paste0("', evidenceLink: '", evidence_link, "'") else ""
edge_data <- paste0("{ data: { source: '", row$source,
                    "', target: '", row$target,
                    "', id: '", edge_key,
                    "', interaction: '", row$interaction,
                    "', edge_type: '", row$edge_type,
                    "', category: '", row$category,
                    evidence_part,
                    "', color: '", style$color,  # note leading quote stays balanced when evidence_part is empty
                    "', line_style: '", style$style,
                    "', arrow_shape: '", style$arrow,
                    "', width: ", style$width, " } }")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f41191a and bf477a9.

📒 Files selected for processing (1)
  • R/visualizeNetworksWithHTML.R (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: pkgdown
  • GitHub Check: build
  • GitHub Check: test-coverage
🔇 Additional comments (1)
R/visualizeNetworksWithHTML.R (1)

261-271: Confirmed evidenceLink presence and type
Edges always include an evidenceLink character column (documented in R/visualizeNetworks.R and man pages, populated with a default "" upstream in both utils_getSubnetworkFromIndra.R and getPathwaysFromIndra.R, and covered by tests), so no additional handling is required downstream.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Sep 5, 2025

Codecov Report

❌ Patch coverage is 90.90909% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 57.36%. Comparing base (f41191a) to head (240951c).

Files with missing lines Patch % Lines
R/visualizeNetworksWithHTML.R 90.90% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            devel      #57      +/-   ##
==========================================
+ Coverage   57.06%   57.36%   +0.30%     
==========================================
  Files           8        8              
  Lines        1211     1222      +11     
==========================================
+ Hits          691      701      +10     
- Misses        520      521       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
R/visualizeNetworksWithHTML.R (1)

265-276: Escape all string fields in edge payload, not just evidenceLink.

Only evidenceLink is escaped; other fields can contain quotes or backslashes (or user-provided text) and may break the JS literal or enable injection. Please escape all string-valued fields before concatenation.

         # Create edge data with styling information
-        edge_data <- paste0("{ data: { source: '", row$source, 
-                            "', target: '", row$target, 
-                            "', id: '", edge_key,
-                            "', interaction: '", row$interaction,
-                            "', edge_type: '", row$edge_type,
-                            "', category: '", row$category,
+        # Sanitize string fields
+        src   <- escape_js_string(row$source)
+        tgt   <- escape_js_string(row$target)
+        itx   <- escape_js_string(row$interaction)
+        etype <- escape_js_string(row$edge_type)
+        catg  <- escape_js_string(row$category)
+        ekey  <- escape_js_string(edge_key)
+
+        edge_data <- paste0("{ data: { source: '", src,
+                            "', target: '", tgt,
+                            "', id: '", ekey,
+                            "', interaction: '", itx,
+                            "', edge_type: '", etype,
+                            "', category: '", catg,
                             "', evidenceLink: '", evidence_link,
                             "', color: '", style$color,
                             "', line_style: '", style$style,
                             "', arrow_shape: '", style$arrow,
                             "', width: ", style$width, " } }")

Note: If any of these fields can be non-character types (e.g., factors), escape_js_string() already coerces them safely.

🧹 Nitpick comments (3)
R/visualizeNetworksWithHTML.R (3)

260-264: Good addition; tighten scalar/NA handling and consider allowlisting schemes.

The NA/"NA" normalization and escaping look right. Since evidence_link here is scalar, prefer short-circuit evaluation to avoid any vectorization surprises, and optionally normalize whitespace. Also consider (optional) validating that links are http(s) before serializing.

-        evidence_link <- ifelse(is.na(evidence_link) | evidence_link == "NA", "", evidence_link)
+        evidence_link <- if (isTRUE(is.na(evidence_link) || identical(evidence_link, "NA"))) "" else evidence_link
+        evidence_link <- trimws(evidence_link)

Would you like this PR to enforce http/https only (and optionally an INDRA domain allowlist), or should we defer that to click-time checks?


866-869: Wire up the evidence link on edge tap (opens in new tab).

Optional, but completes the feature so users can click through directly.

 cy.on("tap", "edge", function(evt) {
   var edge = evt.target;
-  console.log("Edge clicked:", edge.data());
+  console.log("Edge clicked:", edge.data());
+  var link = edge.data("evidenceLink");
+  if (link) {
+    try {
+      // Optional: basic scheme check
+      var u = new URL(link);
+      if (u.protocol === "http:" || u.protocol === "https:") {
+        window.open(u.href, "_blank", "noopener,noreferrer");
+      }
+    } catch (_) { /* ignore invalid URLs */ }
+  }
 });

If you prefer not to change default behavior, we can expose this as a default edge_click handler that users can override.


121-149: Potential loss of reverse-edge evidence when consolidating.

When consolidating bidirectional/undirected edges, only the first direction’s extra columns are copied. If each direction carries distinct evidenceLinks, one will be dropped.

If needed, merge both directions’ links (e.g., deduped, semicolon-delimited, or as a JSON array) during consolidation.

Also applies to: 114-119

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bf477a9 and 240951c.

📒 Files selected for processing (1)
  • R/visualizeNetworksWithHTML.R (2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: pkgdown
  • GitHub Check: test-coverage
  • GitHub Check: build

Comment on lines +284 to +294
# Helper to safely embed strings into JS single-quoted literals
escape_js_string <- function(x) {
if (is.null(x)) return("")
x <- as.character(x)
x <- gsub("\\\\", "\\\\\\\\", x) # backslashes
x <- gsub("'", "\\\\'", x) # single quotes
x <- gsub("\r", "\\\\r", x)
x <- gsub("\n", "\\\\n", x)
x
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Harden escaping against </script> termination and JS line-separator chars.

Current escaping doesn’t neutralize </script> or U+2028/U+2029, which can prematurely terminate the script tag or break JS parsing. Add these transformations.

 escape_js_string <- function(x) {
     if (is.null(x)) return("")
     x <- as.character(x)
     x <- gsub("\\\\", "\\\\\\\\", x)  # backslashes
     x <- gsub("'", "\\\\'", x)        # single quotes
     x <- gsub("\r", "\\\\r", x)
     x <- gsub("\n", "\\\\n", x)
+    # Prevent </script> tag breakouts and line-separator issues
+    x <- gsub("</", "<\\\\/", x, fixed = TRUE)
+    x <- gsub(intToUtf8(0x2028), "\\\\u2028", x, fixed = TRUE)
+    x <- gsub(intToUtf8(0x2029), "\\\\u2029", x, fixed = TRUE)
     x
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Helper to safely embed strings into JS single-quoted literals
escape_js_string <- function(x) {
if (is.null(x)) return("")
x <- as.character(x)
x <- gsub("\\\\", "\\\\\\\\", x) # backslashes
x <- gsub("'", "\\\\'", x) # single quotes
x <- gsub("\r", "\\\\r", x)
x <- gsub("\n", "\\\\n", x)
x
}
# Helper to safely embed strings into JS single-quoted literals
escape_js_string <- function(x) {
if (is.null(x)) return("")
x <- as.character(x)
x <- gsub("\\\\", "\\\\\\\\", x) # backslashes
x <- gsub("'", "\\\\'", x) # single quotes
x <- gsub("\r", "\\\\r", x)
x <- gsub("\n", "\\\\n", x)
# Prevent </script> tag breakouts and line-separator issues
x <- gsub("</", "<\\\\/", x, fixed = TRUE)
x <- gsub(intToUtf8(0x2028), "\\\\u2028", x, fixed = TRUE)
x <- gsub(intToUtf8(0x2029), "\\\\u2029", x, fixed = TRUE)
x
}
🤖 Prompt for AI Agents
In R/visualizeNetworksWithHTML.R around lines 284-294, the escape_js_string
helper must also neutralize occurrences of "</script>" and JS line-separator
characters U+2028 and U+2029; update the function to (after current
backslash/single-quote and CR/LF escapes) replace any case of "</script>" with
"<\\/script>" (or otherwise break the closing tag) and replace U+2028 and U+2029
characters with their escaped Unicode forms "\\u2028" and "\\u2029" so the
returned string cannot prematurely terminate the script tag or break JS parsing.

@tonywu1999 tonywu1999 merged commit a293ce0 into devel Sep 5, 2025
4 checks passed
@tonywu1999 tonywu1999 deleted the open-url branch September 5, 2025 19:38
@coderabbitai coderabbitai Bot mentioned this pull request Sep 11, 2025
5 tasks
@coderabbitai coderabbitai Bot mentioned this pull request Feb 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants