From 2580677946f47229f1663b4a44e072414fe97018 Mon Sep 17 00:00:00 2001 From: John Konecny <24961694+jfkonecn@users.noreply.github.com> Date: Mon, 17 Feb 2025 14:30:30 -0500 Subject: [PATCH] Added markdown news support --- package.json | 3 + scripts/generate-news-sections.js | 359 ++++++++++++++++++ src/main/webapp/app/config/constants.tsx | 1 + .../webapp/app/pages/newsPage/NewsList.tsx | 130 ++++--- .../webapp/app/pages/newsPage/NewsPage.tsx | 1 + .../app/pages/newsPage/NewsPageContent.tsx | 5 + .../code-generated/NewsContent01302025.tsx | 197 ++++++++++ .../newsPage/markdown/NewsContent01302025.md | 28 ++ yarn.lock | 62 +++ 9 files changed, 723 insertions(+), 63 deletions(-) create mode 100644 scripts/generate-news-sections.js create mode 100644 src/main/webapp/app/pages/newsPage/code-generated/NewsContent01302025.tsx create mode 100644 src/main/webapp/app/pages/newsPage/markdown/NewsContent01302025.md diff --git a/package.json b/package.json index a1b721fe2..e81e4db4b 100644 --- a/package.json +++ b/package.json @@ -89,6 +89,7 @@ "@types/classnames": "^2.2.9", "@types/enzyme": "3.10.5", "@types/jest": "25.2.1", + "@types/markdown-it": "^14.1.2", "@types/node": "13.13.4", "@types/pluralize": "0.0.29", "@types/react": "16.9.34", @@ -143,6 +144,7 @@ "lint-staged": "8.2.1", "mini-css-extract-plugin": "0.9.0", "moment-locales-webpack-plugin": "1.2.0", + "markdown-it": "^14.1.0", "node-sass": "^4.12.0", "optimize-css-assets-webpack-plugin": "5.0.3", "postcss-loader": "3.0.0", @@ -190,6 +192,7 @@ "updateAPI": "yarn run fetchAPI && yarn run buildAPI", "fetchAPI": "curl http://localhost:9095/v2/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > src/main/webapp/app/shared/api/generated/API-docs.json", "buildAPI": "node scripts/generate-api.js src/main/webapp/app/shared/api/generated API", + "buildNewPages": "node scripts/generate-news-sections.js -f src/main/webapp/app/pages/newsPage/markdown -o src/main/webapp/app/pages/newsPage/code-generated && yarn run prettier --write \"{,src/main/webapp/app/pages/newsPage/code-generated/**/}*.{md,json,ts,tsx,css,scss,yml}\"", "updateOncoKbAPI": "yarn run fetchOncoKbAPI && yarn run buildOncoKbAPI", "fetchOncoKbAPI": "curl http://localhost:8080/oncokb-public/api/v1/v2/api-docs?group=Private%20APIs | json | grep -v basePath | grep -v termsOfService | grep -v host > src/main/webapp/app/shared/api/generated/OncoKbAPI-docs.json && curl http://localhost:8080/oncokb-public/api/private/v2/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > src/main/webapp/app/shared/api/generated/OncoKbPrivateAPI-docs.json", "buildOncoKbAPI": "node scripts/generate-api.js src/main/webapp/app/shared/api/generated OncoKbAPI OncoKbPrivateAPI", diff --git a/scripts/generate-news-sections.js b/scripts/generate-news-sections.js new file mode 100644 index 000000000..588a5a9fe --- /dev/null +++ b/scripts/generate-news-sections.js @@ -0,0 +1,359 @@ +const fs = require('fs'); +const path = require('path'); +const MarkdownIt = require('markdown-it'); + +const oncokbBaseUrls = [ + 'https://oncokb.org', + 'http://oncokb.org', + 'https://www.oncokb.org', + 'http://www.oncokb.org', +]; + +const objectPropertyMark = '-------------------'; +const objectPropertyMarkRegex = new RegExp( + `"${objectPropertyMark}(.*)${objectPropertyMark}"`, + 'gm' +); + +/** + * Escapes special characters in a string to be used in a regular expression. + * + * This ensures that characters such as `.*+?^${}()|[]\` are treated as literals. + * + * @param {string} string - The input string to escape. + * @returns {string} - The escaped string safe for use in a regex. + * + * @example + * const escaped = escapeRegExp("Hello (world)!"); + * console.log(escaped); // "Hello \\(world\\)!" + */ +function escapeRegExp(string) { + return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string +} + +/** + * Replaces all occurrences of a substring in a given string. + * + * Since `String.prototype.replaceAll()` is not available in older Node.js versions, + * this function uses `RegExp` with the global flag. + * + * @param {string} str - The original string. + * @param {string} match - The substring to be replaced. + * @param {string} replacement - The replacement string. + * @returns {string} - The modified string with all occurrences replaced. + * + * @example + * const result = replaceAll("Hello world, world!", "world", "Earth"); + * console.log(result); // "Hello Earth, Earth!" + */ +function replaceAll(str, match, replacement) { + return str.replace(new RegExp(escapeRegExp(match), 'g'), () => replacement); +} + +/** + * Decodes specific HTML entities in a given string. + * + * This function currently only replaces `"` with `"`. + * Extend this function if more entities need to be decoded. + * + * @param {string} text - The input string containing HTML entities. + * @returns {string} - The decoded string. + * + * @example + * const decoded = decodeHtmlEntities("This is "quoted" text."); + * console.log(decoded); // 'This is "quoted" text.' + */ +function decodeHtmlEntities(text) { + return replaceAll(text, '"', '"'); +} + +/** + * Fixes HTML-escaped entities in a specific pattern within a string. + * + * This function finds occurrences matching `objectPropertyMarkRegex`, + * extracts the inner content, decodes HTML entities, and wraps it in `{}`. + * + * @param {string} htmlString - The input HTML string to process. + * @returns {string} - The fixed string with decoded entities. + * + * @example + * const fixed = fixHtmlString('"----["Example"]----"'); + * console.log(fixed); // '{["Example]"}' + */ +function fixHtmlString(htmlString) { + return htmlString.replace(objectPropertyMarkRegex, (_, group) => { + return `{${decodeHtmlEntities(group)}}`; + }); +} + +/** + * @param {import('markdown-it')} md - The markdown-it instance used for parsing. + * @param {import('markdown-it').StateCore} state - The state object containing Markdown parsing tokens. + * @returns {boolean | undefined} - The modified string with all occurrences replaced. + * + * @throws {Error} If a mutation is found in a row without an associated gene. + */ +function newlyAddedGenes(md, state) { + let foundNewlyAddedGenes = false; + let index = 0; + let toRemoveStart = -1; + let toRemoveEnd = -1; + const genes = []; + for (const token of state.tokens) { + if (token.content.toLowerCase().includes('new gene')) { + foundNewlyAddedGenes = true; + toRemoveStart = index; + } else if (foundNewlyAddedGenes && token.type === 'bullet_list_close') { + toRemoveEnd = index; + break; + } else if (foundNewlyAddedGenes && token.type === 'inline') { + genes.push(token.content); + } + index++; + } + if (toRemoveStart < 0 && toRemoveEnd < 0) { + return true; + } else if (toRemoveStart < 0 || toRemoveEnd < 0) { + throw new Error( + `Found one remove gene index, but not the other (${toRemoveStart}, ${toRemoveEnd})` + ); + } + + const alterationPageLinkTags = createMarkdownToken( + md, + 'NewlyAddedGenesListItem' + ); + alterationPageLinkTags[0].attrSet( + 'genes', + `${objectPropertyMark}${JSON.stringify(genes)}${objectPropertyMark}` + ); + alterationPageLinkTags[1].tag = 'NewlyAddedGenesListItem'; + + state.tokens = state.tokens.filter( + (_, idx) => idx < toRemoveStart || idx > toRemoveEnd + ); + state.tokens.splice(toRemoveStart, 0, ...alterationPageLinkTags); + + return true; +} + +/** + * @param {import('markdown-it').StateCore} state - The state object containing Markdown parsing tokens. + * @returns {boolean | undefined} - The modified string with all occurrences replaced. + * + * @throws {Error} If a mutation is found in a row without an associated gene. + */ +function fixLinks(state) { + for (const token of state.tokens) { + if (token.type === 'inline') { + let foundLocalLink = false; + for (const child of token.children) { + if (child.type === 'link_close' && foundLocalLink) { + foundLocalLink = false; + child.tag = 'Link'; + continue; + } else if (child.type !== 'link_open') { + continue; + } + const hrefIndex = child.attrIndex('href'); + if (hrefIndex < 0) { + continue; + } + const currentUrl = child.attrs[hrefIndex][1]; + let replaceUrlString = ''; + for (const url of oncokbBaseUrls) { + if (currentUrl.startsWith(url)) { + replaceUrlString = url; + foundLocalLink = true; + break; + } + } + if (foundLocalLink) { + child.tag = 'Link'; + const attr = child.attrs[hrefIndex]; + attr[0] = 'to'; + attr[1] = currentUrl.replace(replaceUrlString, ''); + } + } + } + } +} + +/** + * @param {import('markdown-it')} md - The markdown-it instance used for token processing. + * @param {import('markdown-it').StateCore} state - The state object containing Markdown parsing tokens. + * @returns {boolean | undefined} - The modified string with all occurrences replaced. + * + * @throws {Error} If a mutation is found in a row without an associated gene. + */ +function addAutoTableLinks(md, state) { + let inTh = false; + let inTd = false; + let columnIdx = 0; + let geneIdx = -1; + let mutationIdx = -1; + let currentGene = ''; + for (const token of state.tokens) { + if (token.type === 'th_open') { + inTh = true; + } else if (token.type === 'th_close') { + inTh = false; + columnIdx++; + } else if (token.type === 'td_open') { + inTd = true; + } else if (token.type === 'td_close') { + inTd = false; + columnIdx++; + } else if (token.type === 'tr_open') { + columnIdx = 0; + currentGene = ''; + } else if (inTd && columnIdx === geneIdx && token.type === 'inline') { + const child = token.children[0]; + currentGene = child.content; + child.content = `{getAlternativeGenePageLinks('${child.content}')}`; + } else if (inTd && columnIdx === mutationIdx && token.type === 'inline') { + const child = token.children[0]; + if (currentGene === '') { + throw new Error(`No gene for this row and mutation "${child.content}"`); + } + const alterationPageLinkTags = createMarkdownToken( + md, + 'AlterationPageLink' + ); + alterationPageLinkTags[0].attrSet('hugoSymbol', currentGene); + alterationPageLinkTags[0].attrSet('alteration', child.content); + token.children = alterationPageLinkTags; + } else if (inTh && token.content === 'Gene') { + geneIdx = columnIdx; + } else if (inTh && token.content === 'Mutation') { + mutationIdx = columnIdx; + } + } +} + +/** + * Creates a Markdown token with a specified tag. + * + * @param {import('markdown-it')} md - The markdown-it instance used for parsing. + * @param {string} tag - The tag to set on the first non-text token. + * @returns {import('markdown-it').Token[]} - An array of markdown-it token objects with the modified tag. + * + * @example + * const md = require('markdown-it')(); + * const tokens = createMarkdownToken(md, 'custom-tag'); + * console.log(tokens); + */ +function createMarkdownToken(md, tag) { + // can't figure out how to make a token on my own so I'm forcing + // markdown-it to make me one + const alterationPageLinkTags = md + .parse('[placeholder](placeholder)', {})[1] + .children.filter(x => x.type !== 'text'); + alterationPageLinkTags[0].type = 'para'; + alterationPageLinkTags[0].tag = tag; + alterationPageLinkTags[0].attrs = []; + alterationPageLinkTags[1].tag = tag; + return alterationPageLinkTags; +} + +const md = new MarkdownIt({ + html: true, + linkify: true, + breaks: true, +}).use(md => { + // https://markdown-it.github.io/markdown-it + // https://github.com/markdown-it/markdown-it/blob/master/docs/examples/renderer_rules.md + md.renderer.rules.table_open = function () { + return '
\n'; + }; + + md.renderer.rules.table_close = function () { + return '
\n
'; + }; + + md.core.ruler.push('add-auto-table-links', state => { + addAutoTableLinks(md, state); + }); + + md.core.ruler.push('fix-links', state => fixLinks(state)); + md.core.ruler.push('fix-styles', state => { + for (const token of state.tokens) { + if (token.attrs != null && token.attrs.length > 0) { + token.attrs = token.attrs.filter(([name]) => name !== 'style'); + } + if (token.type === 'table_open') { + token.attrSet('className', 'table'); + } + } + return true; + }); + md.core.ruler.push('newly-added-genes', state => { + newlyAddedGenes(md, state); + }); +}); + +const args = process.argv.slice(2); +let inputFolder = null; +let outputFolder = null; + +for (let i = 0; i < args.length; i++) { + if (args[i] === '-f' && args[i + 1]) { + inputFolder = path.resolve(args[i + 1]); + } else if (args[i] === '-o' && args[i + 1]) { + outputFolder = path.resolve(args[i + 1]); + } +} + +if (!inputFolder || !outputFolder) { + console.error( + 'Error: Both -f (input folder) and -o (output folder) arguments are required.' + ); + process.exit(1); +} + +// Ensure input folder exists +if (!fs.existsSync(inputFolder) || !fs.statSync(inputFolder).isDirectory()) { + console.error( + `Error: Input folder "${inputFolder}" does not exist or is not a directory.` + ); + process.exit(1); +} + +// Ensure output folder exists, or create it +if (!fs.existsSync(outputFolder)) { + fs.mkdirSync(outputFolder, { recursive: true }); +} + +// Read all Markdown files in the input folder +const files = fs.readdirSync(inputFolder).filter(file => file.endsWith('.md')); + +if (files.length === 0) { + console.warn(`Warning: No markdown files found in "${inputFolder}".`); +} + +files.forEach(file => { + const filePath = path.join(inputFolder, file); + const content = fs.readFileSync(filePath, 'utf-8'); + const htmlContent = fixHtmlString(md.render(content)); + + const componentName = path + .basename(file, '.md') + .replace(/[^a-zA-Z0-9]/g, '_'); + + const tsxContent = `import React from 'react'; +import { Link } from 'react-router-dom'; +import { AlterationPageLink, getAlternativeGenePageLinks } from 'app/shared/utils/UrlUtils'; +import { NewlyAddedGenesListItem } from 'app/pages/newsPage/NewlyAddedGenesListItem'; + +export default function ${componentName}() { + return ( + <> + ${htmlContent} + + ); +}`; + + const outputFilePath = path.join(outputFolder, `${componentName}.tsx`); + fs.writeFileSync(outputFilePath, tsxContent, 'utf-8'); + console.log(`Generated: ${outputFilePath}`); +}); diff --git a/src/main/webapp/app/config/constants.tsx b/src/main/webapp/app/config/constants.tsx index 105bb6bc1..d95031af8 100644 --- a/src/main/webapp/app/config/constants.tsx +++ b/src/main/webapp/app/config/constants.tsx @@ -866,6 +866,7 @@ export type DataRelease = { }; export const DATA_RELEASES: DataRelease[] = [ + { date: '02302025', version: 'v4.26' }, { date: '01302025', version: 'v4.25' }, { date: '12192024', version: 'v4.24' }, { date: '11262024', version: 'v4.23' }, diff --git a/src/main/webapp/app/pages/newsPage/NewsList.tsx b/src/main/webapp/app/pages/newsPage/NewsList.tsx index 717d7b50a..2767d2ca0 100644 --- a/src/main/webapp/app/pages/newsPage/NewsList.tsx +++ b/src/main/webapp/app/pages/newsPage/NewsList.tsx @@ -19,6 +19,7 @@ import HashLink from 'app/shared/links/HashLink'; import { RouterStore } from 'mobx-react-router'; import { observable } from 'mobx'; import { observer } from 'mobx-react'; +import NewsContent01302025 from './code-generated/NewsContent01302025'; export type NewsListProps = { date: string; @@ -100,69 +101,72 @@ export default class NewsList extends React.Component { {this.props.children ? ( this.props.children ) : newsData ? ( - + <> + {newsData?.markdown} + + ) : undefined} diff --git a/src/main/webapp/app/pages/newsPage/NewsPage.tsx b/src/main/webapp/app/pages/newsPage/NewsPage.tsx index 9f7899756..cd7fced2a 100644 --- a/src/main/webapp/app/pages/newsPage/NewsPage.tsx +++ b/src/main/webapp/app/pages/newsPage/NewsPage.tsx @@ -86,6 +86,7 @@ export default class NewsPage extends React.Component<{
+ diff --git a/src/main/webapp/app/pages/newsPage/NewsPageContent.tsx b/src/main/webapp/app/pages/newsPage/NewsPageContent.tsx index b2afa656d..0d3bfa5ed 100644 --- a/src/main/webapp/app/pages/newsPage/NewsPageContent.tsx +++ b/src/main/webapp/app/pages/newsPage/NewsPageContent.tsx @@ -45,6 +45,7 @@ import { PMALink } from 'app/shared/links/PMALink'; import OptimizedImage from 'app/shared/image/OptimizedImage'; import { AnnotationColumnHeaderType } from './ChangedAnnotationListItem'; import { linkableMutationName, convertGeneInputToLinks } from './Util'; +import NewsContent01302025 from './code-generated/NewsContent01302025'; export type ChangedAnnotation = { content: (ElementType | ElementType[])[][]; @@ -55,6 +56,7 @@ export type ChangedAnnotation = { }; export type NewsData = { + markdown?: JSX.Element; priorityNews?: ElementType[]; news?: ElementType[]; newlyAddedGenes?: string[]; @@ -301,6 +303,9 @@ const EVIDENCE_COLUMN_SEPARATOR = '; '; // https://stackoverflow.com/questions/41947168/is-it-possible-to-use-keyof-operator-on-literals-instead-of-interfaces export const NEWS_BY_DATE: { [date: string]: NewsData } = { + '02282025': { + markdown: , + }, '01302025': { priorityNews: [ diff --git a/src/main/webapp/app/pages/newsPage/code-generated/NewsContent01302025.tsx b/src/main/webapp/app/pages/newsPage/code-generated/NewsContent01302025.tsx new file mode 100644 index 000000000..adc9a33f3 --- /dev/null +++ b/src/main/webapp/app/pages/newsPage/code-generated/NewsContent01302025.tsx @@ -0,0 +1,197 @@ +import React from 'react'; +import { Link } from 'react-router-dom'; +import { + AlterationPageLink, + getAlternativeGenePageLinks, +} from 'app/shared/utils/UrlUtils'; +import { NewlyAddedGenesListItem } from 'app/pages/newsPage/NewlyAddedGenesListItem'; + +export default function NewsContent01302025() { + return ( + <> +
    +
  • + Happy New Year! As of January X, 2025, fifteen Level 1, twelve Level + 2, eighteen Level 3 and eleven Level 4 treatments for unique + biomarker-selected indications were added to OncoKB. A table + summarizing these changes can be found{' '} + here. The “Precision + Oncology: 2024 in Review” article can be found{' '} + + here + + . +
  • +
+

+ Updated Therapeutic Implications +

+
    +
  • New alteration(s) with a tumor type-specific level of evidence
  • +
+
+ + + + + + + + + + + + + + + + + + + + + +
LevelGeneMutationCancer TypeDrug(s)Evidence
2{getAlternativeGenePageLinks('ERBB2')} + + Cervical CancerNeratinib + Inclusion in Cervical Cancer NCCN Guidelines V1.2025; PMID:{' '} + 38211393 +
+
+

+
    +
  • + Promotion of tumor type-specific level of evidence for an alteration +
  • +
+
+ + + + + + + + + + + + + + + + + + + + + + + +
GeneMutationCancer TypeDrug(s)Previous LevelUpdated LevelEvidence
{getAlternativeGenePageLinks('KRAS')} + + Small Bowel Cancer + Drug(s) promoted in OncoKB™: Adagrasib (Level 2, + previously Level 3A) Drug(s) added to OncoKB™:{' '} + Sotorasib (Level 2) + 3A2 + Inclusion in Small Bowel Adenocarcinoma NCCN Guidelines V1.2025; + PMID:{' '} + 32955176 + ,{' '} + 37099736 + ,{' '} + 36546659 + ,{' '} + 34919824 +
+
+
    +
  • + Addition of drug(s) associated with a tumor type-specific leveled + alteration(s) currently in OncoKB™ (without changing the alteration's + highest level of evidence) +
  • +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LevelGeneMutationCancer TypeLevel-Associated Drug(s) in OncoKB™Drug(s) Updated in OncoKBTMEvidence
1{getAlternativeGenePageLinks('ALK')} + + Non-Small Cell Lung Cancer + Alectinib, Brigatinib, Certinib, Crizotinib, Lorlatinib (Level + 1) NVL-655 (Level 3A) + Ensartinib (Level 1) + + FDA approval of ensartinib + + ; PMID:{' '} + 34473194 +
1{getAlternativeGenePageLinks('KRAS')} + + Colorectal Cancer + Sensitivity Adagrasib + Cetuximab (Level 1) Adagrasib + + Panitumumab, Sotorasib + Cetuximab, Sotorasib + Panitumumab + (Level 2) Binimetinib, Cobimetinib, Trametinib (Level 4) + Resistance Cetuximab, Panitumumab, Tucatinib + Trastuzumab + (Level R1) + Sotorasib + Panitumumab (Level 1) + + FDA approval of sotorasib with panitumumab + + ; PMID:{' '} + 37870968 +
+
+
    +
  • + +
  • +
+ + ); +} diff --git a/src/main/webapp/app/pages/newsPage/markdown/NewsContent01302025.md b/src/main/webapp/app/pages/newsPage/markdown/NewsContent01302025.md new file mode 100644 index 000000000..e53b998ea --- /dev/null +++ b/src/main/webapp/app/pages/newsPage/markdown/NewsContent01302025.md @@ -0,0 +1,28 @@ +- Happy New Year\! As of January X, 2025, fifteen Level 1, twelve Level 2, eighteen Level 3 and eleven Level 4 treatments for unique biomarker-selected indications were added to OncoKB. A table summarizing these changes can be found [here](https://www.oncokb.org/year-end-summary#2024). The “Precision Oncology: 2024 in Review” article can be found [here](https://aacrjournals.org/cancerdiscovery/article/14/12/2332/750142/Precision-Oncology-2024-in-ReviewPrecision). + +**Updated Therapeutic Implications** + +- New alteration(s) with a tumor type-specific level of evidence + +| Level | Gene | Mutation | Cancer Type | Drug(s) | Evidence | +| :---- | :---- | :------------------ | :-------------- | :-------- | :---------------------------------------------------------------------------------------------------------------- | +| 2 | ERBB2 | Oncogenic Mutations | Cervical Cancer | Neratinib | Inclusion in Cervical Cancer NCCN Guidelines V1.2025; PMID: [38211393](https://pubmed.ncbi.nlm.nih.gov/38211393/) | + +#### + +- Promotion of tumor type-specific level of evidence for an alteration + +| Gene | Mutation | Cancer Type | Drug(s) | Previous Level | Updated Level | Evidence | +| :--- | :------- | :----------------- | :----------------------------------------------------------------------------------------------------------------------- | :------------- | :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| KRAS | G12C | Small Bowel Cancer | _Drug(s) promoted in OncoKB™:_ Adagrasib (Level 2, previously Level 3A) _Drug(s) added to OncoKB™:_ Sotorasib (Level 2\) | 3A | 2 | Inclusion in Small Bowel Adenocarcinoma NCCN Guidelines V1.2025; PMID: [32955176](https://pubmed.ncbi.nlm.nih.gov/37099736/), [37099736](https://pubmed.ncbi.nlm.nih.gov/32955176/), [36546659](https://pubmed.ncbi.nlm.nih.gov/36546659/), [34919824](https://pubmed.ncbi.nlm.nih.gov/34919824/) | + +- Addition of drug(s) associated with a tumor type-specific leveled alteration(s) currently in OncoKB™ (without changing the alteration's highest level of evidence) + +| Level | Gene | Mutation | Cancer Type | Level-Associated Drug(s) in OncoKB™ | Drug(s) Updated in OncoKBTM | Evidence | +| :---- | :--- | :------- | :------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | ALK | Fusions | Non-Small Cell Lung Cancer | Alectinib, Brigatinib, Certinib, Crizotinib, Lorlatinib (Level 1\) NVL-655 (Level 3A) | Ensartinib (Level 1\) | [FDA approval of ensartinib](https://www.fda.gov/drugs/resources-information-approved-drugs/fda-approves-ensartinib-alk-positive-locally-advanced-or-metastatic-non-small-cell-lung-cancer); PMID: [34473194](https://pubmed.ncbi.nlm.nih.gov/34473194/) | +| 1 | KRAS | G12C | Colorectal Cancer | Sensitivity Adagrasib \+ Cetuximab (Level 1\) Adagrasib \+ Panitumumab, Sotorasib \+ Cetuximab, Sotorasib \+ Panitumumab (Level 2\) Binimetinib, Cobimetinib, Trametinib (Level 4\) Resistance Cetuximab, Panitumumab, Tucatinib \+ Trastuzumab (Level R1) | Sotorasib \+ Panitumumab (Level 1\) | [FDA approval of sotorasib with panitumumab](https://www.fda.gov/drugs/resources-information-approved-drugs/fda-approves-sotorasib-panitumumab-kras-g12c-mutated-colorectal-cancer); PMID: [37870968](https://pubmed.ncbi.nlm.nih.gov/37870968/) | + +- Addition of new genes: + - AKT1S1 + - ALOX15B diff --git a/yarn.lock b/yarn.lock index f9d82c1c7..8aff57461 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2515,6 +2515,24 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/linkify-it@^5": + version "5.0.0" + resolved "https://registry.yarnpkg.com/@types/linkify-it/-/linkify-it-5.0.0.tgz#21413001973106cda1c3a9b91eedd4ccd5469d76" + integrity sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q== + +"@types/markdown-it@^14.1.2": + version "14.1.2" + resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-14.1.2.tgz#57f2532a0800067d9b934f3521429a2e8bfb4c61" + integrity sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog== + dependencies: + "@types/linkify-it" "^5" + "@types/mdurl" "^2" + +"@types/mdurl@^2": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-2.0.0.tgz#d43878b5b20222682163ae6f897b20447233bdfd" + integrity sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg== + "@types/minimatch@*", "@types/minimatch@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -3398,6 +3416,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + arr-diff@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" @@ -7409,6 +7432,11 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== +entities@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" + integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== + env-paths@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" @@ -11490,6 +11518,13 @@ lines-and-columns@^1.1.6: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= +linkify-it@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-5.0.0.tgz#9ef238bfa6dc70bd8e7f9572b52d369af569b421" + integrity sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ== + dependencies: + uc.micro "^2.0.0" + lint-staged@8.2.1: version "8.2.1" resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-8.2.1.tgz#752fcf222d9d28f323a3b80f1e668f3654ff221f" @@ -12027,6 +12062,18 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +markdown-it@^14.1.0: + version "14.1.0" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-14.1.0.tgz#3c3c5992883c633db4714ccb4d7b5935d98b7d45" + integrity sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg== + dependencies: + argparse "^2.0.1" + entities "^4.4.0" + linkify-it "^5.0.0" + mdurl "^2.0.0" + punycode.js "^2.3.1" + uc.micro "^2.1.0" + matcher@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.1.tgz#51d8301e138f840982b338b116bb0c09af62c1c2" @@ -12058,6 +12105,11 @@ mdn-data@2.0.4: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== +mdurl@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-2.0.0.tgz#80676ec0433025dd3e17ee983d0fe8de5a2237e0" + integrity sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w== + measure-text@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/measure-text/-/measure-text-0.0.4.tgz#2bfbc3d903b2b1f247d187a29617f807104f0a52" @@ -14762,6 +14814,11 @@ pumpify@^1.3.3: inherits "^2.0.3" pump "^2.0.0" +punycode.js@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7" + integrity sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA== + punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" @@ -18236,6 +18293,11 @@ ua-parser-js@0.7.17: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.17.tgz#e9ec5f9498b9ec910e7ae3ac626a805c4d09ecac" integrity sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g== +uc.micro@^2.0.0, uc.micro@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-2.1.0.tgz#f8d3f7d0ec4c3dea35a7e3c8efa4cb8b45c9e7ee" + integrity sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A== + uglify-js@3.4.x: version "3.4.10" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"