Issue ID parsing small refactor
This commit is contained in:
@@ -0,0 +1,84 @@
|
|||||||
|
export const BLANK_ISSUE_ID = 'BLANK-000000';
|
||||||
|
|
||||||
|
const ISSUE_ID_CORE_PATTERN = '[A-Z][A-Z0-9]{1,15}-\\d{3,8}';
|
||||||
|
|
||||||
|
export const ISSUE_ID_PATTERN = new RegExp(`(${ISSUE_ID_CORE_PATTERN})`, 'i');
|
||||||
|
export const ISSUE_ID_LIST_PREFIX_PATTERN = new RegExp(
|
||||||
|
`^\\s*((?:${ISSUE_ID_CORE_PATTERN})(?:\\s*(?:,|and|&)\\s*(?:${ISSUE_ID_CORE_PATTERN}))*)`,
|
||||||
|
'i'
|
||||||
|
);
|
||||||
|
export const ISSUE_ID_LINE_PATTERN = new RegExp(`^(${ISSUE_ID_CORE_PATTERN})\\s*[:\\-]?\\s*(.*)$`, 'i');
|
||||||
|
|
||||||
|
export function normalizeWhitespace(value) {
|
||||||
|
return String(value || '').replace(/\s+/g, ' ').trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeIssueId(value) {
|
||||||
|
return normalizeWhitespace(value).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBlankIssueMarker(value) {
|
||||||
|
return /^[\u2014\u2013\-]+$/.test(String(value || '').trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
export function extractIssueIds(value) {
|
||||||
|
const ids = [];
|
||||||
|
const seen = new Set();
|
||||||
|
const matches = String(value || '').matchAll(new RegExp(ISSUE_ID_PATTERN.source, 'ig'));
|
||||||
|
|
||||||
|
for (const match of matches) {
|
||||||
|
const normalizedId = normalizeIssueId(match[1] || '');
|
||||||
|
if (!normalizedId || seen.has(normalizedId)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
seen.add(normalizedId);
|
||||||
|
ids.push(normalizedId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseIssueIdCell(value) {
|
||||||
|
const text = normalizeWhitespace(value);
|
||||||
|
const issueIdListMatch = text.match(ISSUE_ID_LIST_PREFIX_PATTERN);
|
||||||
|
const blankId = !issueIdListMatch && isBlankIssueMarker(text);
|
||||||
|
|
||||||
|
if (!issueIdListMatch && !blankId) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blankId) {
|
||||||
|
return {
|
||||||
|
issueIds: [BLANK_ISSUE_ID],
|
||||||
|
metadataText: '',
|
||||||
|
isBlankId: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const issueIds = extractIssueIds(String(issueIdListMatch[1] || ''));
|
||||||
|
const metadataText = normalizeWhitespace(text.slice(issueIdListMatch[0].length)).replace(/^[-:;,.\s]+/, '');
|
||||||
|
|
||||||
|
return {
|
||||||
|
issueIds,
|
||||||
|
metadataText,
|
||||||
|
isBlankId: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseIssueLine(value) {
|
||||||
|
const text = String(value || '').trim();
|
||||||
|
const match = text.match(ISSUE_ID_LINE_PATTERN);
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
return {
|
||||||
|
id: '',
|
||||||
|
summary: text
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: normalizeIssueId(match[1] || ''),
|
||||||
|
summary: (match[2] || '').trim()
|
||||||
|
};
|
||||||
|
}
|
||||||
+13
-24
@@ -1,4 +1,10 @@
|
|||||||
import { stripMarkdownFrontmatter } from './markdown.js';
|
import { stripMarkdownFrontmatter } from './markdown.js';
|
||||||
|
import {
|
||||||
|
BLANK_ISSUE_ID,
|
||||||
|
normalizeIssueId,
|
||||||
|
normalizeWhitespace,
|
||||||
|
parseIssueLine as parseIssueLineValue
|
||||||
|
} from './issue-id.js';
|
||||||
import { marked, Renderer } from '../vendor/marked.esm.js';
|
import { marked, Renderer } from '../vendor/marked.esm.js';
|
||||||
|
|
||||||
const summaryMarkdownRenderer = new Renderer();
|
const summaryMarkdownRenderer = new Renderer();
|
||||||
@@ -12,7 +18,6 @@ export function clearIssues() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let socialRefsByIssueId = new Map();
|
let socialRefsByIssueId = new Map();
|
||||||
const ISSUE_ID_LINE_PATTERN = /^([A-Z][A-Z0-9]{1,15}-\d{3,8})\s*[:\-]?\s*(.*)$/i;
|
|
||||||
const socialRefsReady = loadSocialRefs();
|
const socialRefsReady = loadSocialRefs();
|
||||||
const issueFileDataCache = new Map();
|
const issueFileDataCache = new Map();
|
||||||
const issueFilePromiseCache = new Map();
|
const issueFilePromiseCache = new Map();
|
||||||
@@ -436,36 +441,20 @@ function dedupeIssues(issues, versionKey) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getIssueDedupeKey(id, summary, resolved, caveat) {
|
function getIssueDedupeKey(id, summary, resolved, caveat) {
|
||||||
const normalizedId = String(id || '').trim().toUpperCase();
|
const normalizedId = normalizeIssueId(id);
|
||||||
|
|
||||||
if (normalizedId !== 'BLANK-000000') {
|
if (normalizedId !== BLANK_ISSUE_ID) {
|
||||||
return normalizedId;
|
return normalizedId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const normalizedSummary = normalizeWhitespace(String(summary || ''));
|
const normalizedSummary = normalizeWhitespace(summary);
|
||||||
const normalizedResolved = normalizeWhitespace(String(resolved || ''));
|
const normalizedResolved = normalizeWhitespace(resolved);
|
||||||
const normalizedCaveat = normalizeWhitespace(String(caveat || ''));
|
const normalizedCaveat = normalizeWhitespace(caveat);
|
||||||
return `${normalizedId}|${normalizedSummary}|${normalizedResolved}|${normalizedCaveat}`;
|
return `${normalizedId}|${normalizedSummary}|${normalizedResolved}|${normalizedCaveat}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeWhitespace(text) {
|
|
||||||
return String(text || '').replace(/\s+/g, ' ').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseIssueLine(text) {
|
function parseIssueLine(text) {
|
||||||
const value = String(text || '').trim();
|
return parseIssueLineValue(text);
|
||||||
const match = value.match(ISSUE_ID_LINE_PATTERN);
|
|
||||||
if (match) {
|
|
||||||
return {
|
|
||||||
id: match[1].toUpperCase(),
|
|
||||||
summary: (match[2] || '').trim()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: '',
|
|
||||||
summary: value
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSourceVersionFromFileName(fileName) {
|
function getSourceVersionFromFileName(fileName) {
|
||||||
@@ -506,7 +495,7 @@ function renderSummaryCell(cell, issue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getSocialRefsForIssue(issueId) {
|
function getSocialRefsForIssue(issueId) {
|
||||||
const normalizedIssueId = String(issueId || '').trim().toUpperCase();
|
const normalizedIssueId = normalizeIssueId(issueId);
|
||||||
if (!normalizedIssueId) {
|
if (!normalizedIssueId) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-18
@@ -1,4 +1,8 @@
|
|||||||
import { buildIssueMarkdownDocument } from './markdown.js';
|
import { buildIssueMarkdownDocument } from './markdown.js';
|
||||||
|
import {
|
||||||
|
normalizeWhitespace,
|
||||||
|
parseIssueIdCell
|
||||||
|
} from './issue-id.js';
|
||||||
|
|
||||||
if (typeof document !== 'undefined') {
|
if (typeof document !== 'undefined') {
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
@@ -14,8 +18,6 @@ if (typeof document !== 'undefined') {
|
|||||||
|
|
||||||
let activeDownloadUrl = null;
|
let activeDownloadUrl = null;
|
||||||
const PROCESS_FORM_STATE_KEY = 'bugmedley.process.formState.v1';
|
const PROCESS_FORM_STATE_KEY = 'bugmedley.process.formState.v1';
|
||||||
const ISSUE_ID_PATTERN = /([A-Z][A-Z0-9]{1,15}-\d{3,8})/i;
|
|
||||||
const ISSUE_ID_LIST_PREFIX_PATTERN = /^\s*((?:[A-Z][A-Z0-9]{1,15}-\d{3,8})(?:\s*(?:,|and|&)\s*(?:[A-Z][A-Z0-9]{1,15}-\d{3,8}))*)/i;
|
|
||||||
const BLOCK_CONTAINER_TAGS = new Set(['ARTICLE', 'ASIDE', 'BLOCKQUOTE', 'DIV', 'P', 'PRE', 'SECTION']);
|
const BLOCK_CONTAINER_TAGS = new Set(['ARTICLE', 'ASIDE', 'BLOCKQUOTE', 'DIV', 'P', 'PRE', 'SECTION']);
|
||||||
const TEXT_NODE = 3;
|
const TEXT_NODE = 3;
|
||||||
const ELEMENT_NODE = 1;
|
const ELEMENT_NODE = 1;
|
||||||
@@ -135,26 +137,18 @@ export function parseIssuesFromHtmlTable(htmlText, options = {}) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const issueIdListMatch = leftCellText.match(ISSUE_ID_LIST_PREFIX_PATTERN);
|
const issueIdData = parseIssueIdCell(leftCellText);
|
||||||
const isBlankId = !issueIdListMatch && /^[\u2014\u2013\-]+$/.test(leftCellText.trim());
|
if (!issueIdData) {
|
||||||
|
|
||||||
if (!issueIdListMatch && !isBlankId) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const issueIds = isBlankId
|
const issueIds = issueIdData.issueIds;
|
||||||
? ['BLANK-000000']
|
|
||||||
: Array.from(String(issueIdListMatch[1] || '').matchAll(new RegExp(ISSUE_ID_PATTERN.source, 'ig')))
|
|
||||||
.map(match => String(match[1] || '').toUpperCase())
|
|
||||||
.filter(Boolean);
|
|
||||||
|
|
||||||
if (issueIds.length === 0) {
|
if (issueIds.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const metadataText = isBlankId
|
const metadataText = issueIdData.metadataText;
|
||||||
? ''
|
|
||||||
: normalizeWhitespace(leftCellText.slice(issueIdListMatch[0].length)).replace(/^[-:;,.\s]+/, '');
|
|
||||||
const resolved = isResolvedMetadataText(metadataText) ? metadataText : '';
|
const resolved = isResolvedMetadataText(metadataText) ? metadataText : '';
|
||||||
const description = rightCellText;
|
const description = rightCellText;
|
||||||
|
|
||||||
@@ -509,10 +503,6 @@ function sanitizeTableCellText(text) {
|
|||||||
return normalizeWhitespace(text).replace(/\|/g, '\\|');
|
return normalizeWhitespace(text).replace(/\|/g, '\\|');
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeWhitespace(value) {
|
|
||||||
return value.replace(/\s+/g, ' ').trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
function setParseStatus(message, isError = false) {
|
function setParseStatus(message, isError = false) {
|
||||||
const status = document.getElementById('parseStatus');
|
const status = document.getElementById('parseStatus');
|
||||||
status.textContent = message;
|
status.textContent = message;
|
||||||
|
|||||||
Reference in New Issue
Block a user