mirror of
https://github.com/alamion/obsidian-jira-sync.git
synced 2026-07-22 05:43:04 +00:00
small fixes
- feedback if field can't be processed from jira format to string properly - found an in-code style, carried it to styles.css - replaced plugin.app.vault.modify() with plugin.app.vault.process() for atomization - html to markdown for description - now frontmatter data on update has priority over file content one as it saves it's initial type. - several changes for logging work, now it's more intuitive.
This commit is contained in:
parent
e9553967f4
commit
9248212425
19 changed files with 3290 additions and 439 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -10,7 +10,7 @@ node_modules
|
|||
|
||||
# Don't include the compiled main.js file in the repo.
|
||||
# They should be uploaded to GitHub releases instead.
|
||||
main.js
|
||||
*.js
|
||||
|
||||
# Exclude sourcemaps
|
||||
*.map
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ The template can consist of several different parts:
|
|||
|
||||
It is highly recommended to specify basic values in the template's formatter: `key` - the Jira task ID used for updates, `summary` - the Jira task title, and `status` - the current status of the task in Jira.
|
||||
|
||||
The body takes priority and will overwrite formatter values when updating a task in Jira if a field's value is present in both sections.
|
||||
The formatter takes priority and will overwrite file content values when updating a task in Jira if a field's value is present in both as formatter saves initial format of value and when putting it in body we parse it to string.
|
||||
|
||||
Not all fields are predefined, and some may need adjustments. For example, the template provided in [[docs/template_example.md]] will not correctly retrieve `progressPercent` and `creator` from Jira, even though these fields exist. To fix this, refer to the advanced usage section below.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
Настоятельно рекомендуется указать в formatter шаблоона базовые значения: `key` - id задачи в Jira, по которому производится обновление, `summary` - название задачи в Jira, `status` - текущий статус задачи в Jira.
|
||||
|
||||
body имеет приоритет и будет перезаписывать значения formatter при одновлении задачи в Jira, если значения для одного поля имеются в обоих местах.
|
||||
formatter имеет приоритет и будет перезаписывать значения body, если значения для одного поля имеются в обоих местах, так как formatter сохраняет изначальный тип переменной, а body конвертирует её в string.
|
||||
|
||||
Не все поля прописаны заранее и некоторые могут нуждаться в доработке. Пример предоставленный в [[docs/template_example.md]] например, не сможет подтянуть корректно `progressPercent` и `creator` из Jira, хотя такие поля существуют. Чтобы это исправить, нужно отбратиться к разделу продвинутого использования ниже.
|
||||
|
||||
|
|
|
|||
2023
package-lock.json
generated
Normal file
2023
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -21,5 +21,10 @@
|
|||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
},
|
||||
"dependencies": {}
|
||||
"dependencies": {
|
||||
"@types/turndown": "^5.0.5",
|
||||
"acorn": "^8.14.1",
|
||||
"turndown": "^7.2.0",
|
||||
"yaml": "^2.7.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { MarkdownView, Notice, TFile } from "obsidian";
|
||||
import { Notice, TFile } from "obsidian";
|
||||
import JiraPlugin from "../main";
|
||||
import { IssueTypeModal, ProjectModal } from "../modals";
|
||||
import { authenticate, fetchIssueTypes, fetchProjects } from "../api";
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ export async function prepareJiraFieldsFromFile(
|
|||
|
||||
// Convert frontmatter and sections to Jira fields
|
||||
fields = localToJiraFields(
|
||||
{...frontmatter, ...syncSections},
|
||||
{...syncSections, ...frontmatter},
|
||||
{...fieldMappings, ...plugin.settings.fieldMappings});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import JiraPlugin from "../main";
|
|||
import {TFile} from "obsidian";
|
||||
import {createJiraIssue, updateJiraIssue, updateJiraStatus} from "../api";
|
||||
import {prepareJiraFieldsFromFile} from "./common_prepareData";
|
||||
import {updateLocalFromJira} from "../tools/mappingObsidianJiraFields";
|
||||
import {updateJiraToLocal} from "../tools/mappingObsidianJiraFields";
|
||||
import {JiraIssue, JiraTransitionType} from "../interfaces";
|
||||
|
||||
/**
|
||||
|
|
@ -87,6 +87,6 @@ export async function updateStatusFromFile(plugin: JiraPlugin, file: TFile, tran
|
|||
}
|
||||
|
||||
await updateJiraStatus(plugin, issueKey, transition.id);
|
||||
await updateLocalFromJira(plugin, file, {fields: {status: {name: transition.status}}} as JiraIssue);
|
||||
await updateJiraToLocal(plugin, file, {fields: {status: {name: transition.status}}} as JiraIssue);
|
||||
return issueKey;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import JiraPlugin from "../main";
|
|||
import {JiraIssue} from "../interfaces";
|
||||
import {ensureIssuesFolder} from "../tools/filesUtils";
|
||||
import {sanitizeFileName} from "../tools/sanitizers";
|
||||
import {updateLocalFromJira} from "../tools/mappingObsidianJiraFields";
|
||||
import {updateJiraToLocal} from "../tools/mappingObsidianJiraFields";
|
||||
import {Notice, TFile} from "obsidian";
|
||||
|
||||
/**
|
||||
|
|
@ -25,7 +25,7 @@ export async function createOrUpdateIssueNote(plugin: JiraPlugin, issue: JiraIss
|
|||
|
||||
if (existingFile) {
|
||||
// File exists, update it
|
||||
await updateLocalFromJira(plugin, existingFile, issue)
|
||||
await updateJiraToLocal(plugin, existingFile, issue)
|
||||
|
||||
// Open the file
|
||||
await plugin.app.workspace.openLinkText(existingFile.path, "");
|
||||
|
|
@ -34,7 +34,7 @@ export async function createOrUpdateIssueNote(plugin: JiraPlugin, issue: JiraIss
|
|||
const newFile = await createNewIssueFile(plugin, filePath);
|
||||
|
||||
// Update it
|
||||
await updateLocalFromJira(plugin, newFile, issue)
|
||||
await updateJiraToLocal(plugin, newFile, issue)
|
||||
|
||||
// Open the file
|
||||
await plugin.app.workspace.openLinkText(newFile.path, "");
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export interface JiraSettings {
|
|||
templatePath: string;
|
||||
fieldMappings: Record<string, FieldMapping>;
|
||||
fieldMappingsStrings: Record<string, { toJira: string; fromJira: string }>;
|
||||
enableFieldValidation: boolean;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ export default class JiraPlugin extends Plugin {
|
|||
*/
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
this.settings.fieldMappings = transform_string_to_functions_mappings(this.settings.fieldMappingsStrings);
|
||||
this.settings.fieldMappings = await transform_string_to_functions_mappings(this.settings.fieldMappingsStrings);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ export class WorkLogModal extends Modal {
|
|||
private startDate: string = "";
|
||||
private workDescription: string = "";
|
||||
private displayDate: string = "";
|
||||
private timeSpentSetting: Setting;
|
||||
private dateSetting: Setting;
|
||||
|
||||
constructor(app: App, onSubmit: (timeSpent: string, startDate: string, workDescription: string) => void) {
|
||||
super(app);
|
||||
|
|
@ -67,7 +69,7 @@ export class WorkLogModal extends Modal {
|
|||
this.contentEl.createEl("h2", { text: "Add Work Log" });
|
||||
|
||||
// Time Spent field
|
||||
new Setting(this.contentEl)
|
||||
this.timeSpentSetting = new Setting(this.contentEl)
|
||||
.setName("Time Spent")
|
||||
.setDesc("Format: 3w 4d 12h 30m (weeks, days, hours, minutes)")
|
||||
.addText((text) =>
|
||||
|
|
@ -79,29 +81,41 @@ export class WorkLogModal extends Modal {
|
|||
})
|
||||
);
|
||||
|
||||
this.dateSetting = new Setting(this.contentEl)
|
||||
.setName("Start Time")
|
||||
.setDesc("Format: DD/MMM/YY HH:MM AM/PM")
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("e.g., 01/Feb/25 10:00 AM")
|
||||
.setValue(this.displayDate)
|
||||
.onChange((value) => {
|
||||
this.displayDate = value;
|
||||
})
|
||||
);
|
||||
|
||||
// Start Date field with date picker icon
|
||||
// const dateContainer = this.contentEl.createDiv("date-container");
|
||||
// dateContainer.style.display = "flex";
|
||||
// dateContainer.style.alignItems = "center";
|
||||
// dateContainer.style.gap = "10px";
|
||||
|
||||
const dateSetting = new Setting(this.contentEl)
|
||||
.setName("Date Started")
|
||||
.setDesc("Format: DD/MMM/YY HH:MM AM/PM")
|
||||
.addText((text) =>
|
||||
text
|
||||
.setPlaceholder("e.g., 01/Jun/21 09:00 AM")
|
||||
.setValue(this.displayDate)
|
||||
.onChange((value) => {
|
||||
this.displayDate = value;
|
||||
|
||||
// Parse display date and convert to ISO
|
||||
const parsedDate = this.parseDisplayDate(value);
|
||||
if (parsedDate) {
|
||||
this.startDate = parsedDate.toISOString().split('.')[0] + ".000+0000";
|
||||
}
|
||||
})
|
||||
);
|
||||
// const dateSetting = new Setting(this.contentEl)
|
||||
// .setName("Date Started")
|
||||
// .setDesc("Format: DD/MMM/YY HH:MM AM/PM")
|
||||
// .addText((text) =>
|
||||
// text
|
||||
// .setPlaceholder("e.g., 01/Jun/21 09:00 AM")
|
||||
// .setValue(this.displayDate)
|
||||
// .onChange((value) => {
|
||||
// this.displayDate = value;
|
||||
//
|
||||
// // Parse display date and convert to ISO
|
||||
// const parsedDate = this.parseDisplayDate(value);
|
||||
// if (parsedDate) {
|
||||
// this.startDate = parsedDate.toISOString().split('.')[0] + ".000+0000";
|
||||
// }
|
||||
// })
|
||||
// );
|
||||
|
||||
// Add date picker later
|
||||
// const datePickerButton = dateContainer.createEl("button", { cls: "date-picker-button" });
|
||||
|
|
@ -160,7 +174,6 @@ export class WorkLogModal extends Modal {
|
|||
const textareaComponent = this.contentEl.querySelector(".work-description-container textarea");
|
||||
if (textareaComponent) {
|
||||
(textareaComponent as HTMLTextAreaElement).rows = 5;
|
||||
(textareaComponent as HTMLTextAreaElement).style.width = "100%";
|
||||
}
|
||||
|
||||
// Submit button
|
||||
|
|
@ -185,11 +198,7 @@ export class WorkLogModal extends Modal {
|
|||
private validateInputs(): boolean {
|
||||
if (!this.timeSpent.trim()) {
|
||||
new Notice("Time spent is required");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.displayDate.trim()) {
|
||||
new Notice("Start date is required");
|
||||
this.timeSpentSetting.setClass('invalid');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -197,12 +206,20 @@ export class WorkLogModal extends Modal {
|
|||
const timeSpentPattern = /^(\d+[wdhm]\s*)+$/;
|
||||
if (!timeSpentPattern.test(this.timeSpent)) {
|
||||
new Notice("Invalid time format. Use combinations of w (weeks), d (days), h (hours), m (minutes)");
|
||||
this.timeSpentSetting.setClass('invalid');
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.displayDate.trim()) {
|
||||
new Notice("Start date is required");
|
||||
this.dateSetting.setClass('invalid');
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate date format by trying to parse it
|
||||
if (!this.parseDisplayDate(this.displayDate)) {
|
||||
new Notice("Invalid date format. Use DD/MMM/YY HH:MM AM/PM");
|
||||
this.dateSetting.setClass('invalid');
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import {App, normalizePath, PluginSettingTab, setIcon, Setting} from "obsidian";
|
||||
import {App, normalizePath, Notice, PluginSettingTab, setIcon, Setting} from "obsidian";
|
||||
import JiraPlugin from "../main";
|
||||
import {fieldMappings} from "../tools/mappingObsidianJiraFields";
|
||||
import {
|
||||
functionToExpressionString,
|
||||
transform_string_to_functions_mappings
|
||||
functionToExpressionString, transform_string_to_functions_mappings, validateFunctionString
|
||||
} from "../tools/convertFunctionString";
|
||||
import {debugLog} from "../tools/debugLogging";
|
||||
|
||||
|
|
@ -18,6 +17,48 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
// Function to save all field mappings
|
||||
async saveStringFieldMappings (element: HTMLDivElement) {
|
||||
debugLog(`From strings ${JSON.stringify(this.plugin.settings.fieldMappingsStrings)}\nand funcs ${JSON.stringify(this.plugin.settings.fieldMappings)}`)
|
||||
const mappings: Record<string, { toJira: string; fromJira: string }> = {};
|
||||
const fieldItems = element.querySelectorAll(".field-mapping-item");
|
||||
|
||||
fieldItems.forEach(item => {
|
||||
const fieldNameInput = item.querySelector(".field-name-input");
|
||||
const toJiraInput = item.querySelector(".to-jira-input");
|
||||
const fromJiraInput = item.querySelector(".from-jira-input");
|
||||
if (!fieldNameInput || !toJiraInput || !fromJiraInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const fieldName = fieldNameInput.value.trim();
|
||||
// @ts-ignore
|
||||
const toJira = toJiraInput.value.trim();
|
||||
// @ts-ignore
|
||||
const fromJira = fromJiraInput.value.trim();
|
||||
|
||||
// Only save valid mappings with all fields filled
|
||||
if (fieldName) {
|
||||
mappings[fieldName] = {
|
||||
toJira: toJira,
|
||||
fromJira: fromJira
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
debugLog(`Mappings: ${JSON.stringify(mappings)}`)
|
||||
|
||||
this.plugin.settings.fieldMappingsStrings = mappings;
|
||||
this.plugin.settings.fieldMappings = await transform_string_to_functions_mappings(mappings,
|
||||
this.plugin.settings.enableFieldValidation);
|
||||
|
||||
// Save the functional mappings
|
||||
debugLog(`To strings ${JSON.stringify(this.plugin.settings.fieldMappingsStrings)}\nand funcs ${JSON.stringify(this.plugin.settings.fieldMappings)}`)
|
||||
await this.plugin.saveSettings();
|
||||
};
|
||||
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
|
||||
|
|
@ -116,11 +157,87 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
text: "Configure how fields are mapped between Obsidian and Jira. Each field requires both a toJira and fromJira transformation function."
|
||||
});
|
||||
|
||||
new Setting(mappingSection)
|
||||
.setName('Enable Field validation')
|
||||
.setDesc('Check fields before saving as functions')
|
||||
.addToggle(toggle => toggle
|
||||
.setValue(this.plugin.settings.enableFieldValidation)
|
||||
.onChange(async (value) => {
|
||||
this.plugin.settings.enableFieldValidation = value;
|
||||
await this.plugin.saveSettings();
|
||||
const fieldItems = fieldsList.querySelectorAll(".field-mapping-item");
|
||||
|
||||
fieldItems.forEach(async item => {
|
||||
const fieldNameInput = item.querySelector(".field-name-input");
|
||||
const toJiraInput = item.querySelector(".to-jira-input");
|
||||
const fromJiraInput = item.querySelector(".from-jira-input");
|
||||
if (fieldNameInput) await fieldValidation(fieldNameInput as HTMLInputElement, value, 'string');
|
||||
if (fieldNameInput) await fieldValidation(toJiraInput as HTMLInputElement, value, 'function', ['value']);
|
||||
if (fieldNameInput) await fieldValidation(fromJiraInput as HTMLInputElement, value, 'function', ['issue', 'data_source']);
|
||||
});
|
||||
}));
|
||||
|
||||
// Add change listeners to update settings
|
||||
const pointInvalidField = (validation: { isValid: boolean; errorMessage?: string }, element: HTMLInputElement | HTMLTextAreaElement, console_output: boolean) => {
|
||||
if (!validation.isValid) {
|
||||
element.classList.add("invalid");
|
||||
if (console_output) {
|
||||
console.warn(`${validation.errorMessage}`);
|
||||
new Notice(`${validation.errorMessage}`);
|
||||
}
|
||||
} else {
|
||||
element.classList.remove("invalid");
|
||||
}
|
||||
}
|
||||
|
||||
async function fieldValidation(input: HTMLInputElement | HTMLTextAreaElement, requireValidating: boolean = true, type: string = 'string', validateParams: Array<string> = []) {
|
||||
const validatorFunction = async (event?: Event)=> {
|
||||
const console_output = !!event;
|
||||
let validation;
|
||||
switch(type) {
|
||||
case 'string':
|
||||
validation = input.value.length === 0? { isValid: false, errorMessage: "Field name cannot be empty" } : { isValid: true };
|
||||
break;
|
||||
case 'function':
|
||||
validation = await validateFunctionString(input.value, validateParams);
|
||||
break;
|
||||
default:
|
||||
validation = { isValid: true };
|
||||
break;
|
||||
}
|
||||
pointInvalidField(validation, input, console_output);
|
||||
}
|
||||
if (!input.hasOwnProperty('_validatorFunction')) {
|
||||
Object.defineProperty(input, '_validatorFunction', {
|
||||
value: validatorFunction,
|
||||
writable: true,
|
||||
configurable: true
|
||||
});
|
||||
} else {
|
||||
// @ts-ignore
|
||||
input.removeEventListener("change", input._validatorFunction);
|
||||
// @ts-ignore
|
||||
input._validatorFunction = validatorFunction;
|
||||
}
|
||||
|
||||
if (requireValidating) {
|
||||
// @ts-ignore
|
||||
input.addEventListener("change", input._validatorFunction);
|
||||
await validatorFunction(); // Run initial validation
|
||||
} else {
|
||||
// @ts-ignore
|
||||
input.removeEventListener("change", input._validatorFunction);
|
||||
pointInvalidField({ isValid: true}, input, false); // Clear any validation errors
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Create a list container for field mappings
|
||||
const fieldsList = mappingSection.createDiv({ cls: "field-mappings-list" });
|
||||
|
||||
// Function to add a new field mapping UI
|
||||
const addFieldMapping = (fieldName = "", toJira = "", fromJira = "") => {
|
||||
const addFieldMapping = async (fieldName = "", toJira = "", fromJira = "") => {
|
||||
const fieldContainer = fieldsList.createDiv({ cls: "field-mapping-item" });
|
||||
|
||||
// Field name input
|
||||
|
|
@ -135,22 +252,22 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
// toJira function input
|
||||
const toJiraContainer = fieldContainer.createDiv({ cls: "to-jira-container" });
|
||||
toJiraContainer.createEl("span", { text: "toJira:", cls: "field-mapping-label" });
|
||||
const toJiraInput = toJiraContainer.createEl("input", {
|
||||
type: "text",
|
||||
const toJiraInput = toJiraContainer.createEl("textarea", {
|
||||
value: toJira,
|
||||
placeholder: "(value) => value",
|
||||
placeholder: "(value) => null",
|
||||
cls: "to-jira-input"
|
||||
});
|
||||
toJiraInput.rows = 1;
|
||||
|
||||
// fromJira function input
|
||||
const fromJiraContainer = fieldContainer.createDiv({ cls: "from-jira-container" });
|
||||
fromJiraContainer.createEl("span", { text: "fromJira:", cls: "field-mapping-label" });
|
||||
const fromJiraInput = fromJiraContainer.createEl("input", {
|
||||
type: "text",
|
||||
const fromJiraInput = fromJiraContainer.createEl("textarea", {
|
||||
value: fromJira,
|
||||
placeholder: "(issue) => issue.fields.fieldName",
|
||||
placeholder: "(issue, data_source) => null",
|
||||
cls: "from-jira-input"
|
||||
});
|
||||
fromJiraInput.rows = 1;
|
||||
|
||||
// Add remove button
|
||||
const removeBtn = fieldContainer.createEl("button", {
|
||||
|
|
@ -161,57 +278,16 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
// Handle field removal
|
||||
removeBtn.addEventListener("click", () => {
|
||||
fieldContainer.remove();
|
||||
saveFieldMappings();
|
||||
// saveFieldMappings();
|
||||
});
|
||||
|
||||
// Add change listeners to update settings
|
||||
[fieldNameInput, toJiraInput, fromJiraInput].forEach(input => {
|
||||
input.addEventListener("change", () => {
|
||||
saveFieldMappings();
|
||||
});
|
||||
});
|
||||
await fieldValidation(fieldNameInput, this.plugin.settings.enableFieldValidation, 'string');
|
||||
await fieldValidation(toJiraInput, this.plugin.settings.enableFieldValidation, 'function', ['value']);
|
||||
await fieldValidation(fromJiraInput, this.plugin.settings.enableFieldValidation, 'function', ['issue', 'data_source']);
|
||||
|
||||
return { fieldNameInput, toJiraInput, fromJiraInput, container: fieldContainer };
|
||||
};
|
||||
|
||||
// Function to save all field mappings
|
||||
const saveFieldMappings = async () => {
|
||||
debugLog(`From strings ${JSON.stringify(this.plugin.settings.fieldMappingsStrings)}\n\n and funcs ${JSON.stringify(this.plugin.settings.fieldMappings)}`)
|
||||
const mappings: Record<string, { toJira: string; fromJira: string }> = {};
|
||||
const fieldItems = fieldsList.querySelectorAll(".field-mapping-item");
|
||||
|
||||
fieldItems.forEach(item => {
|
||||
const fieldNameInput = item.querySelector(".field-name-input");
|
||||
const toJiraInput = item.querySelector(".to-jira-input");
|
||||
const fromJiraInput = item.querySelector(".from-jira-input");
|
||||
if (!fieldNameInput || !toJiraInput || !fromJiraInput) {
|
||||
return;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const fieldName = fieldNameInput.value.trim();
|
||||
// @ts-ignore
|
||||
const toJira = toJiraInput.value.trim();
|
||||
// @ts-ignore
|
||||
const fromJira = fromJiraInput.value.trim();
|
||||
|
||||
// Only save valid mappings with all fields filled
|
||||
if (fieldName && toJira && fromJira) {
|
||||
mappings[fieldName] = {
|
||||
toJira: toJira,
|
||||
fromJira: fromJira
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
// Store the string representations directly in a separate property
|
||||
this.plugin.settings.fieldMappingsStrings = mappings;
|
||||
|
||||
// Save the functional mappings
|
||||
debugLog(`To strings ${JSON.stringify(this.plugin.settings.fieldMappingsStrings)}\n\nand funcs ${JSON.stringify(this.plugin.settings.fieldMappings)}`)
|
||||
await this.plugin.saveSettings();
|
||||
};
|
||||
|
||||
const buttonView = mappingSection.createDiv({ cls: "button-view" });
|
||||
|
||||
// Add button to add new field mapping
|
||||
|
|
@ -221,8 +297,8 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
});
|
||||
setIcon(addFieldBtn, "circle-plus")
|
||||
|
||||
addFieldBtn.addEventListener("click", () => {
|
||||
addFieldMapping();
|
||||
addFieldBtn.addEventListener("click", async () => {
|
||||
await addFieldMapping();
|
||||
});
|
||||
|
||||
const resetBtn = buttonView.createEl("button", {
|
||||
|
|
@ -230,11 +306,11 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
cls: "reset-field-mappings-btn"
|
||||
})
|
||||
setIcon(resetBtn, "refresh-cw")
|
||||
resetBtn.addEventListener("click", () => {
|
||||
resetBtn.addEventListener("click", async () => {
|
||||
this.plugin.settings.fieldMappings = {};
|
||||
this.plugin.settings.fieldMappingsStrings = {};
|
||||
loadExistingMappings();
|
||||
this.plugin.saveSettings();
|
||||
await loadExistingMappings();
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
|
||||
const reloadBtn = buttonView.createEl("button", {
|
||||
|
|
@ -242,7 +318,7 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
cls: "reset-field-mappings-btn"
|
||||
})
|
||||
setIcon(reloadBtn, "list-restart")
|
||||
reloadBtn.addEventListener("click", () => {
|
||||
reloadBtn.addEventListener("click", async () => {
|
||||
this.plugin.settings.fieldMappings = fieldMappings;
|
||||
|
||||
// Also reset the string representations with default values
|
||||
|
|
@ -255,12 +331,12 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
}
|
||||
this.plugin.settings.fieldMappingsStrings = defaultMappingsStrings;
|
||||
|
||||
loadExistingMappings();
|
||||
this.plugin.saveSettings();
|
||||
await loadExistingMappings();
|
||||
await this.plugin.saveSettings();
|
||||
});
|
||||
|
||||
// Load existing mappings if available
|
||||
const loadExistingMappings = () => {
|
||||
const loadExistingMappings = async () => {
|
||||
debugLog(`Loading mapping settings`)
|
||||
// Clear existing field list
|
||||
fieldsList.empty();
|
||||
|
|
@ -272,14 +348,15 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
const savedMappings = this.plugin.settings.fieldMappingsStrings;
|
||||
for (const [fieldName, mapping] of Object.entries(savedMappings)) {
|
||||
if (mapping && typeof mapping === 'object' && 'toJira' in mapping && 'fromJira' in mapping) {
|
||||
addFieldMapping(
|
||||
await addFieldMapping(
|
||||
fieldName,
|
||||
mapping.toJira,
|
||||
mapping.fromJira
|
||||
);
|
||||
}
|
||||
}
|
||||
this.plugin.settings.fieldMappings = transform_string_to_functions_mappings(this.plugin.settings.fieldMappingsStrings);
|
||||
this.plugin.settings.fieldMappings = await transform_string_to_functions_mappings(
|
||||
this.plugin.settings.fieldMappingsStrings, this.plugin.settings.enableFieldValidation);
|
||||
}
|
||||
// Otherwise, try to use the function mappings and convert them to strings
|
||||
else if (this.plugin.settings.fieldMappings &&
|
||||
|
|
@ -288,7 +365,7 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
const existingMappings = this.plugin.settings.fieldMappings;
|
||||
for (const [fieldName, mapping] of Object.entries(existingMappings)) {
|
||||
if (mapping && typeof mapping === 'object' && 'toJira' in mapping && 'fromJira' in mapping) {
|
||||
addFieldMapping(
|
||||
await addFieldMapping(
|
||||
fieldName,
|
||||
functionToExpressionString(mapping.toJira),
|
||||
functionToExpressionString(mapping.fromJira)
|
||||
|
|
@ -297,7 +374,7 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
}
|
||||
|
||||
// Create the string representations for future use
|
||||
saveFieldMappings();
|
||||
await this.saveStringFieldMappings(fieldsList);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -340,8 +417,8 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
item.createSpan({ text: `fromJira: ${example.fromJira}` });
|
||||
|
||||
|
||||
useBtn.addEventListener("click", () => {
|
||||
addFieldMapping(example.name, example.toJira, example.fromJira);
|
||||
useBtn.addEventListener("click", async () => {
|
||||
await addFieldMapping(example.name, example.toJira, example.fromJira);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -350,4 +427,12 @@ export class JiraSettingTab extends PluginSettingTab {
|
|||
securityNote.createEl("strong", { text: "⚠️ Security Note: " });
|
||||
securityNote.createSpan({ text: "Field mapping uses JavaScript function strings. Validate any shared mappings to prevent security issues." });
|
||||
}
|
||||
|
||||
hide() {
|
||||
const fieldsList = this.containerEl.querySelector(".field-mappings-list");
|
||||
if (fieldsList) {
|
||||
this.saveStringFieldMappings(fieldsList as HTMLDivElement);
|
||||
}
|
||||
super.hide();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export const DEFAULT_SETTINGS: JiraSettings = {
|
|||
sessionCookieName: "JSESSIONID",
|
||||
templatePath: "",
|
||||
fieldMappings: {},
|
||||
fieldMappingsStrings: {}
|
||||
fieldMappingsStrings: {},
|
||||
enableFieldValidation: true
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +1,174 @@
|
|||
import {Notice} from "obsidian";
|
||||
import { Notice } from "obsidian";
|
||||
import { FieldMapping } from "./mappingObsidianJiraFields";
|
||||
import { JiraIssue } from "../interfaces";
|
||||
import { parse } from "acorn";
|
||||
import {debugLog} from "./debugLogging";
|
||||
|
||||
const forbiddenPatterns = ["document", "window", "eval", "Function", "fetch"]; // Prevent unsafe code execution
|
||||
import {FieldMapping} from "./mappingObsidianJiraFields";
|
||||
import {JiraIssue} from "../interfaces";
|
||||
// Constants for validation and error messages
|
||||
const FORBIDDEN_PATTERNS = ["document", "window", "eval", "Function", "fetch", "setTimeout"]; // Prevent unsafe code execution
|
||||
const SYNTAX_KEYWORDS = ["return", "if", "else", "for", "while", "switch", "try", "catch"];
|
||||
|
||||
|
||||
function isValidFunctionBody(fnString: string): boolean {
|
||||
return !forbiddenPatterns.some(forbidden => fnString.includes(forbidden));
|
||||
}
|
||||
|
||||
export function safeStringToFunction(exprString: string): Function | null {
|
||||
try {
|
||||
// Check if the input is a full arrow function or just an expression
|
||||
const arrowFnMatch = exprString.match(/^\s*\((.*?)\)\s*=>\s*(.*)$/s);
|
||||
|
||||
// If it's an arrow function, extract just the body
|
||||
const body = arrowFnMatch ? arrowFnMatch[2].trim() : exprString.trim();
|
||||
|
||||
// Ensure function body does not contain unsafe references
|
||||
if (!isValidFunctionBody(body)) {
|
||||
console.warn(`Unsafe expression detected: ${exprString}`);
|
||||
new Notice(`Unsafe expression detected: ${exprString}`);
|
||||
return null;
|
||||
export function validateFunctionStringBrowser(fnString: string, approved_vars: string[] = []): Promise<{ isValid: boolean; errorMessage?: string }> {
|
||||
return new Promise((resolve) => {
|
||||
try {
|
||||
parse(fnString, { ecmaVersion: "latest" });
|
||||
} catch (error) {
|
||||
return resolve({ isValid: false, errorMessage: `Syntax error: ${(error as Error).message}` });
|
||||
}
|
||||
|
||||
// Create a function that has access to our utility functions
|
||||
return function(issue: any) {
|
||||
// Create a context with our utility functions
|
||||
const context = {
|
||||
// jiraToMarkdown,
|
||||
// markdownToJira
|
||||
};
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.style.display = "none";
|
||||
document.body.appendChild(iframe);
|
||||
const iframeWindow = iframe.contentWindow as Window;
|
||||
|
||||
// Create a new function with the utility functions in scope
|
||||
const fn = new Function(
|
||||
'issue',
|
||||
`
|
||||
// const jiraToMarkdown = this.jiraToMarkdown;
|
||||
// const markdownToJira = this.markdownToJira;
|
||||
return ${body};
|
||||
`
|
||||
);
|
||||
try {
|
||||
if (isSimpleExpression(fnString) || (fnString.startsWith("{") && fnString.endsWith("}") && !fnString.includes("return"))) {
|
||||
fnString = `(${approved_vars.map(varName => varName==='issue'?`${varName} = {fields: {}}`:`${varName} = {}`).join(', ')}) => ${fnString}`;
|
||||
}
|
||||
debugLog(`checking function: ${fnString}`);
|
||||
// @ts-ignore
|
||||
iframeWindow.eval(fnString);
|
||||
resolve({ isValid: true });
|
||||
} catch (error) {
|
||||
resolve({ isValid: false, errorMessage: `Runtime error: ${(error as Error).message}` });
|
||||
} finally {
|
||||
document.body.removeChild(iframe);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Execute the function with our context
|
||||
return fn.apply(context, [issue]);
|
||||
/**
|
||||
* Validates a function string for security and syntax issues
|
||||
* @param fnString - The function string to validate
|
||||
* @param approved_vars - An array of approved variable names
|
||||
* @returns An object with validation result and optional error message
|
||||
*/
|
||||
export async function validateFunctionString(fnString: string, approved_vars: string[] = []): Promise<{ isValid: boolean; errorMessage?: string }> {
|
||||
// Check for null, undefined or empty string
|
||||
if (!fnString || fnString.trim().length === 0) {
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
// Check for forbidden patterns (security)
|
||||
const foundForbidden = FORBIDDEN_PATTERNS.find(pattern => fnString.includes(pattern));
|
||||
if (foundForbidden) {
|
||||
return {
|
||||
isValid: false,
|
||||
errorMessage: `Unsafe reference detected: '${foundForbidden}' is not allowed`
|
||||
};
|
||||
}
|
||||
|
||||
return validateFunctionStringBrowser(fnString, approved_vars);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the function string is a simple expression or complex function body
|
||||
* @param fnString - The function string to analyze
|
||||
* @returns Whether the string is a simple expression (vs. a full function body)
|
||||
*/
|
||||
function isSimpleExpression(fnString: string): boolean {
|
||||
const trimmed = fnString.trim();
|
||||
|
||||
// Check if it's a full arrow function
|
||||
if (trimmed.match(/^\s*\(.*?\)\s*=>\s*.*$/s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if it has typical function body syntax elements
|
||||
const hasComplexSyntax = SYNTAX_KEYWORDS.some(keyword =>
|
||||
// Match full keywords, not substrings
|
||||
new RegExp(`\\b${keyword}\\b`).test(trimmed)
|
||||
);
|
||||
|
||||
// Has curly braces which might indicate a code block
|
||||
const hasCodeBlock = trimmed.includes("{") && trimmed.includes("}") && trimmed.includes("return");
|
||||
|
||||
return !hasComplexSyntax && !hasCodeBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely converts a string into a function that can be executed with proper context
|
||||
* @param exprString - The function or expression string to convert
|
||||
* @param type - The type of transformation function ('toJira' or 'fromJira')
|
||||
* @param extraValidate - Whether to validate the function string on syntax, type and other errors
|
||||
* @returns A wrapped function or null if conversion fails
|
||||
*/
|
||||
export async function safeStringToFunction(
|
||||
exprString: string,
|
||||
type: 'toJira' | 'fromJira' = 'toJira',
|
||||
extraValidate: boolean = true
|
||||
): Promise<Function | null> {
|
||||
try {
|
||||
if (exprString.trim().length === 0) {
|
||||
return () => null;
|
||||
}
|
||||
// First validate the string
|
||||
if (extraValidate) {
|
||||
const validation = await validateFunctionString(exprString, type === 'fromJira' ? ['issue', 'data_source'] : ['value']);
|
||||
if (!validation.isValid) {
|
||||
console.warn(`Invalid function: ${validation.errorMessage}`);
|
||||
// new Notice(`Invalid function: ${validation.errorMessage}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Extract just the function body if it's an arrow function
|
||||
const arrowFnMatch = exprString.match(/^\s*\((.*?)\)\s*=>\s*(.*)$/s);
|
||||
let body = arrowFnMatch ? arrowFnMatch[2].trim() : exprString.trim();
|
||||
|
||||
// If it's a simple expression, wrap it in a return statement
|
||||
if (isSimpleExpression(body)) {
|
||||
body = `return ${body};`;
|
||||
}
|
||||
|
||||
// If body is wrapped in curly braces but doesn't contain a return statement, add one
|
||||
if (body.startsWith("{") && body.endsWith("}") && !body.includes("return")) {
|
||||
// Remove the outer braces, add return and put the braces back
|
||||
body = `{ return ${body.slice(1, -1)} }`;
|
||||
}
|
||||
|
||||
// Create appropriate function based on the type
|
||||
if (type === 'toJira') {
|
||||
return function(value: any) {
|
||||
const context = {
|
||||
// Add utility functions that should be available in the executed function
|
||||
// markdownToJira: utility.markdownToJira
|
||||
};
|
||||
|
||||
const fn = new Function('value', `
|
||||
try {
|
||||
${body}
|
||||
} catch (e) {
|
||||
console.error("Error in toJira function:", e);
|
||||
return null;
|
||||
}
|
||||
`);
|
||||
|
||||
return fn.apply(context, [value]);
|
||||
};
|
||||
} else { // fromJira
|
||||
return function(issue: JiraIssue, data_source: Record<string, any> | null) {
|
||||
const context = {
|
||||
// Add utility functions for the fromJira context
|
||||
// jiraToMarkdown: utility.jiraToMarkdown
|
||||
};
|
||||
|
||||
const fn = new Function('issue', 'data_source', `
|
||||
try {
|
||||
${body}
|
||||
} catch (e) {
|
||||
console.error("Error in fromJira function:", e);
|
||||
return null;
|
||||
}
|
||||
`);
|
||||
|
||||
return fn.apply(context, [issue, data_source]);
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to parse expression:", error);
|
||||
console.error("Failed to parse function:", error);
|
||||
new Notice(`Failed to create function: ${(error as Error).message}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -75,6 +197,7 @@ export function functionToExpressionString(fn: Function): string {
|
|||
|
||||
// If we can't parse it properly, return empty string
|
||||
console.error("Failed to extract expression from function:", fnStr);
|
||||
new Notice("Failed to extract expression from function");
|
||||
return "";
|
||||
} catch (error) {
|
||||
console.error("Error converting function to expression string:", error);
|
||||
|
|
@ -82,18 +205,18 @@ export function functionToExpressionString(fn: Function): string {
|
|||
}
|
||||
}
|
||||
|
||||
export const transform_string_to_functions_mappings = (
|
||||
mappings: Record<string, { toJira: string; fromJira: string }>) => {
|
||||
export async function transform_string_to_functions_mappings (
|
||||
mappings: Record<string, { toJira: string; fromJira: string }>, extraValidate: boolean = true) {
|
||||
// Also convert to functions for runtime use
|
||||
const transformedMappings: Record<string, FieldMapping> = {};
|
||||
for (const [fieldName, { toJira, fromJira }] of Object.entries(mappings)) {
|
||||
const toJiraFn = safeStringToFunction(toJira);
|
||||
const fromJiraFn = safeStringToFunction(fromJira);
|
||||
const toJiraFn = safeStringToFunction(toJira, 'toJira', extraValidate);
|
||||
const fromJiraFn = safeStringToFunction(fromJira, 'fromJira', extraValidate);
|
||||
|
||||
if (toJiraFn && fromJiraFn) {
|
||||
transformedMappings[fieldName] = {
|
||||
toJira: toJiraFn as (value: any) => any,
|
||||
fromJira: fromJiraFn as (issue: JiraIssue, data_source: Record<string, any>) => any,
|
||||
toJira: await toJiraFn as (value: any) => any,
|
||||
fromJira: await fromJiraFn as (issue: JiraIssue, data_source: Record<string, any>) => any,
|
||||
};
|
||||
} else {
|
||||
console.warn(`Invalid function in field: ${fieldName}`);
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import { JiraIssue } from "../interfaces";
|
||||
import {jiraToMarkdown, markdownToJira} from "../markdown_html";
|
||||
import {htmlToMarkdown, jiraToMarkdown} from "./markdown_html";
|
||||
import {Notice, TFile} from "obsidian";
|
||||
import JiraPlugin from "../main";
|
||||
import {extractAllJiraSyncValuesFromContent, updateJiraSyncContent} from "./sectionTools";
|
||||
import {debugLog} from "./debugLogging";
|
||||
import YAML from 'yaml'
|
||||
|
||||
/**
|
||||
* Field mapping configurations
|
||||
|
|
@ -14,7 +14,7 @@ export interface FieldMapping {
|
|||
// Function to transform a value from Obsidian to Jira format
|
||||
toJira: (value: any) => any;
|
||||
// Function to transform a value from Jira to Obsidian format
|
||||
fromJira: (issue: JiraIssue, data_source: Record<string, any>) => any;
|
||||
fromJira: (issue: JiraIssue, data_source: Record<string, any> | null) => any;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -28,13 +28,17 @@ export const fieldMappings: Record<string, FieldMapping> = {
|
|||
fromJira: (issue) => issue.fields.summary,
|
||||
},
|
||||
"description": {
|
||||
toJira: (value) => value, // markdownToJira is applied separately
|
||||
fromJira: (issue) => issue.fields.description,
|
||||
toJira: () => null, // markdownToJira is applied separately
|
||||
fromJira: (issue) => htmlToMarkdown(issue.fields.description),
|
||||
},
|
||||
"key": {
|
||||
toJira: () => null, // Not sent to Jira
|
||||
fromJira: (issue) => issue.key,
|
||||
},
|
||||
"self": {
|
||||
toJira: () => null,
|
||||
fromJira: (issue) => issue.self,
|
||||
},
|
||||
"project": {
|
||||
toJira: (value) => ({ key: value }),
|
||||
fromJira: (issue) =>
|
||||
|
|
@ -65,6 +69,10 @@ export const fieldMappings: Record<string, FieldMapping> = {
|
|||
toJira: () => null,
|
||||
fromJira: (issue) => issue.fields["lastViewed"],
|
||||
},
|
||||
"link": {
|
||||
toJira: () => null,
|
||||
fromJira: (issue) => issue.self.replace(/(\w+:\/\/\S+?)\/.*/, `$1/browse/${issue.key}`),
|
||||
},
|
||||
// Add more fields as needed following the same pattern
|
||||
|
||||
// Forbidden
|
||||
|
|
@ -76,6 +84,10 @@ export const fieldMappings: Record<string, FieldMapping> = {
|
|||
toJira: () => null,
|
||||
fromJira: () => null,
|
||||
},
|
||||
"deadline": {
|
||||
toJira: () => null,
|
||||
fromJira: () => null,
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -95,6 +107,7 @@ export function isMappableField(fieldName: string, customFieldMappings: Record<s
|
|||
/**
|
||||
* Convert frontmatter and section fields to Jira fields structure
|
||||
* @param data_source The frontmatter + sections object
|
||||
* @param customFieldMappings The custom field mappings
|
||||
* @returns Object with Jira API compatible structure
|
||||
*/
|
||||
export function localToJiraFields(
|
||||
|
|
@ -133,100 +146,131 @@ export function localToJiraFields(
|
|||
return jiraFields;
|
||||
}
|
||||
|
||||
export async function updateLocalFromJira(
|
||||
export async function updateJiraToLocal(
|
||||
plugin: JiraPlugin,
|
||||
file: TFile,
|
||||
issue: JiraIssue
|
||||
): Promise<void> {
|
||||
// Read the current file content
|
||||
let fileContent = await plugin.app.vault.read(file);
|
||||
// Process the file atomically to avoid multiple read/writes
|
||||
await plugin.app.vault.process(file, (fileContent) => {
|
||||
// Extract existing sync sections
|
||||
const syncSections = extractAllJiraSyncValuesFromContent(fileContent);
|
||||
|
||||
// Extract existing sync sections
|
||||
const syncSections = extractAllJiraSyncValuesFromContent(fileContent);
|
||||
// Create a copy of frontmatter for processing
|
||||
let frontmatter = {};
|
||||
|
||||
// Update frontmatter
|
||||
await plugin.app.fileManager.processFrontMatter(file, (frontmatter) => {
|
||||
updateLocalRecordsFromJira(frontmatter, syncSections, issue,
|
||||
{...fieldMappings, ...plugin.settings.fieldMappings});
|
||||
// Extract and update frontmatter (we'll need to manually parse and re-add it)
|
||||
const frontmatterMatch = fileContent.match(/^---\n([\s\S]*?)\n---\n/);
|
||||
if (frontmatterMatch) {
|
||||
try {
|
||||
frontmatter = YAML.parse(frontmatterMatch[1]);
|
||||
// Update frontmatter with Jira data
|
||||
applyJiraDataToLocal(frontmatter, issue, {...fieldMappings, ...plugin.settings.fieldMappings});
|
||||
} catch (e) {
|
||||
console.error("Error parsing frontmatter:", e);
|
||||
new Notice("Error parsing frontmatter");
|
||||
}
|
||||
}
|
||||
|
||||
// Update sync sections with Jira data
|
||||
applyJiraDataToLocal(syncSections, issue, {...fieldMappings, ...plugin.settings.fieldMappings});
|
||||
|
||||
// Replace frontmatter in content
|
||||
let updatedContent = fileContent;
|
||||
if (frontmatterMatch) {
|
||||
const updatedFrontmatter = YAML.stringify(frontmatter);
|
||||
updatedContent = fileContent.replace(
|
||||
frontmatterMatch[0],
|
||||
`---\n${updatedFrontmatter}---\n`
|
||||
);
|
||||
}
|
||||
|
||||
// Update content sections from Jira fields
|
||||
for (const [fieldName, fieldValue] of Object.entries(syncSections)) {
|
||||
const markdownValue = jiraToMarkdown(fieldValue);
|
||||
updatedContent = updateJiraSyncContent(updatedContent, fieldName, markdownValue);
|
||||
}
|
||||
|
||||
return updatedContent;
|
||||
});
|
||||
|
||||
// Read the updated content (with new frontmatter)
|
||||
fileContent = await plugin.app.vault.read(file);
|
||||
|
||||
// Update sections from Jira fields if they exist
|
||||
for (const [fieldName, fieldValue] of Object.entries(syncSections)) {
|
||||
// Only update fields that can be in sections and only existing sections
|
||||
debugLog(`Updating ${fieldName} = ${fieldValue} in content`)
|
||||
const markdownValue = jiraToMarkdown(fieldValue);
|
||||
debugLog(`Converted from jira variant ${fieldValue} to md variant ${markdownValue}`)
|
||||
fileContent = updateJiraSyncContent(fileContent, fieldName, markdownValue);
|
||||
}
|
||||
|
||||
// Save the updated content
|
||||
await plugin.app.vault.modify(file, fileContent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update frontmatter and sections with values from Jira issue
|
||||
* @param frontmatter The frontmatter object to update
|
||||
* @param sections The sections object to update
|
||||
* @param issue The Jira issue
|
||||
* Apply Jira data to local records using field mappings
|
||||
* @param localData - The local data to update (frontmatter or sections)
|
||||
* @param issue - The Jira issue with source data
|
||||
* @param fieldMappings - Custom field mappings for transformations
|
||||
*/
|
||||
export function updateLocalRecordsFromJira(
|
||||
frontmatter: Record<string, any>,
|
||||
sections: Record<string, any>,
|
||||
export function applyJiraDataToLocal(
|
||||
localData: Record<string, any>,
|
||||
issue: JiraIssue,
|
||||
customFieldMappings: Record<string, FieldMapping>
|
||||
fieldMappings: Record<string, FieldMapping>
|
||||
): void {
|
||||
// Process known fields with mappings
|
||||
for (const key of Object.keys(frontmatter) as Array<string>) {
|
||||
|
||||
// Apply transformation if field exists in frontmatter or is required
|
||||
if (key in frontmatter || key === 'key' || key === 'summary') {
|
||||
let value = issue.fields[key];
|
||||
if (key in customFieldMappings) {
|
||||
try{
|
||||
value = customFieldMappings[key].fromJira(issue, {...frontmatter, ...sections});
|
||||
} catch (e) {
|
||||
console.error(`Error mapping for ${key}: ${e}`);
|
||||
new Notice(`Error mapping for ${key}: ${e}`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (value !== null && value !== undefined) {
|
||||
frontmatter[key] = value;
|
||||
}
|
||||
}
|
||||
// Process existing fields in local data
|
||||
for (const key of Object.keys(localData)) {
|
||||
updateFieldFromJira(key, localData, issue, fieldMappings);
|
||||
}
|
||||
|
||||
for (const key of Object.keys(sections) as Array<string>) {
|
||||
|
||||
// Apply transformation if field exists in frontmatter or is required
|
||||
if (key in sections) {
|
||||
let value = issue.fields[key];
|
||||
if (key in customFieldMappings) {
|
||||
try {
|
||||
value = customFieldMappings[key].fromJira(issue, {...frontmatter, ...sections});
|
||||
} catch (e) {
|
||||
const result: Record<string, {
|
||||
hasToJira: string,
|
||||
hasFromJira: string
|
||||
}> = {};
|
||||
|
||||
for (const key of Object.keys(customFieldMappings)) {
|
||||
result[key] = {
|
||||
hasToJira: typeof customFieldMappings[key].toJira,
|
||||
hasFromJira: typeof customFieldMappings[key].fromJira
|
||||
};
|
||||
}
|
||||
console.error(`Error mapping for ${key}: ${e}\n${JSON.stringify(result)}`);
|
||||
new Notice(`Error mapping for ${key}: ${e}`);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (value !== null && value !== undefined) {
|
||||
sections[key] = value;
|
||||
}
|
||||
// Ensure required fields are always processed
|
||||
const requiredFields = ['key', 'summary'];
|
||||
for (const field of requiredFields) {
|
||||
if (!(field in localData)) {
|
||||
updateFieldFromJira(field, localData, issue, fieldMappings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a single field from Jira data
|
||||
* @param key - The field key to update
|
||||
* @param targetObject - The object to update (frontmatter or sections)
|
||||
* @param issue - The Jira issue with source data
|
||||
* @param fieldMappings - Custom field mappings for transformations
|
||||
*/
|
||||
function updateFieldFromJira(
|
||||
key: string,
|
||||
targetObject: Record<string, any>,
|
||||
issue: JiraIssue,
|
||||
fieldMappings: Record<string, FieldMapping>
|
||||
): void {
|
||||
try {
|
||||
let value = issue.fields[key];
|
||||
|
||||
// Apply custom mapping if available
|
||||
if (key in fieldMappings) {
|
||||
value = fieldMappings[key].fromJira(issue, targetObject);
|
||||
}
|
||||
|
||||
// Only update if value exists
|
||||
if (value !== null && value !== undefined) {
|
||||
targetObject[key] = value;
|
||||
}
|
||||
} catch (e) {
|
||||
// Log available mappings for debugging
|
||||
logMappingDebugInfo(key, e, fieldMappings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log debug information for mapping errors
|
||||
*/
|
||||
function logMappingDebugInfo(
|
||||
key: string,
|
||||
error: Error,
|
||||
fieldMappings: Record<string, FieldMapping>
|
||||
): void {
|
||||
console.error(`Error mapping for ${key}: ${error}`);
|
||||
new Notice(`Error mapping for ${key}: ${error}`);
|
||||
|
||||
// Create debug info about available mappings
|
||||
const mappingInfo: Record<string, { hasToJira: string, hasFromJira: string }> = {};
|
||||
|
||||
for (const mappingKey of Object.keys(fieldMappings)) {
|
||||
mappingInfo[mappingKey] = {
|
||||
hasToJira: typeof fieldMappings[mappingKey].toJira,
|
||||
hasFromJira: typeof fieldMappings[mappingKey].fromJira
|
||||
};
|
||||
}
|
||||
|
||||
console.debug(`Available mappings: ${JSON.stringify(mappingInfo)}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,71 +1,95 @@
|
|||
import {Notice} from "obsidian";
|
||||
import TurndownService from 'turndown';
|
||||
|
||||
|
||||
export function htmlToMarkdown(str: any): string {
|
||||
if (str === null || str === undefined) return '';
|
||||
else if (typeof str === "number") {
|
||||
return str.toString()
|
||||
}
|
||||
else if (typeof str === "object") {
|
||||
return JSON.stringify(str)
|
||||
}
|
||||
const turndownService = new TurndownService();
|
||||
return turndownService.turndown(str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert Jira markup to Markdown
|
||||
* @param str The Jira markup string
|
||||
* @returns The Markdown string
|
||||
*/
|
||||
export function jiraToMarkdown(str: any): string {
|
||||
if (str === null || str === undefined) return '';
|
||||
else if (typeof str === "number") {
|
||||
str = str.toString()
|
||||
try {
|
||||
if (str === null || str === undefined) return '';
|
||||
else if (typeof str === "number") {
|
||||
str = str.toString()
|
||||
}
|
||||
else if (typeof str === "object") {
|
||||
str = JSON.stringify(str)
|
||||
}
|
||||
return (
|
||||
str
|
||||
// Un-Ordered Lists
|
||||
.replace(/^[ \t]*(\*+)\s+/gm, (match: string, stars: string) => {
|
||||
return `${Array(stars.length).fill('').join('')}* `;
|
||||
})
|
||||
// Ordered lists
|
||||
.replace(/^[ \t]*(#+)\s+/gm, (match: string, nums: string) => {
|
||||
return `${Array(nums.length).fill('').join('')}1. `;
|
||||
})
|
||||
// Headers 1-6
|
||||
.replace(/^h([0-6])\.(.*)$/gm, (match: string, level: string, content: string) => {
|
||||
return Array(parseInt(level, 10) + 1).join('#') + ' ' + content.trim();
|
||||
})
|
||||
// Bold (process before italic to avoid conflicts)
|
||||
.replace(/\*([^*\n]+)\*/g, '**$1**')
|
||||
// Italic
|
||||
.replace(/_([^_\n]+)_/g, '*$1*')
|
||||
// Monospaced text
|
||||
.replace(/\{\{([^}]+)\}\}/g, '`$1`')
|
||||
// Inserts
|
||||
.replace(/\+([^+]*)\+/g, '<ins>$1</ins>')
|
||||
// Superscript
|
||||
.replace(/\^([^^]*)\^/g, '<sup>$1</sup>')
|
||||
// Subscript
|
||||
.replace(/~([^~]*)~/g, '<sub>$1</sub>')
|
||||
// Strikethrough
|
||||
.replace(/(\s+)-(\S+.*?\S)-(\s+)/g, '$1~~$2~~$3')
|
||||
// Code Block
|
||||
.replace(
|
||||
/\{code(:([a-z]+))?([:|]?(title|borderStyle|borderColor|borderWidth|bgColor|titleBGColor)=.+?)*\}([^]*?)\n?\{code\}/gm,
|
||||
'```$2$5\n```'
|
||||
)
|
||||
// Pre-formatted text
|
||||
.replace(/{noformat}/g, '```')
|
||||
// Un-named Links
|
||||
.replace(/\[([^|]+?)\]/g, '<$1>')
|
||||
// Images
|
||||
.replace(/!(.+)!/g, '')
|
||||
// Named Links
|
||||
.replace(/\[(.+?)\|(.+?)\]/g, '[$1]($2)')
|
||||
// Single Paragraph Blockquote
|
||||
.replace(/^bq\.\s+/gm, '> ')
|
||||
// Remove color: unsupported in md
|
||||
.replace(/\{color:[^}]+\}([^]*?)\{color\}/gm, '$1')
|
||||
// panel into table
|
||||
.replace(/\{panel:title=([^}]*)\}\n?([^]*?)\n?\{panel\}/gm, '\n| $1 |\n| --- |\n| $2 |')
|
||||
// table header
|
||||
.replace(/^[ \t]*((?:\|\|.*?)+\|\|)[ \t]*$/gm, (match: string, headers: string) => {
|
||||
const singleBarred = headers.replace(/\|\|/g, '|');
|
||||
return `${singleBarred}\n${singleBarred.replace(/\|[^|]+/g, '| --- ')}`;
|
||||
})
|
||||
// remove leading-space of table headers and rows
|
||||
.replace(/^[ \t]*\|/gm, '|')
|
||||
);
|
||||
} catch (e) {
|
||||
new Notice(`Error converting Jira markup to Markdown\n${e}`);
|
||||
console.error(e);
|
||||
return typeof str === "string" ? str : str.toString();
|
||||
}
|
||||
else if (typeof str === "object") {
|
||||
str = JSON.stringify(str)
|
||||
}
|
||||
return (
|
||||
str
|
||||
// Un-Ordered Lists
|
||||
.replace(/^[ \t]*(\*+)\s+/gm, (match: string, stars: string) => {
|
||||
return `${Array(stars.length).fill('').join('')}* `;
|
||||
})
|
||||
// Ordered lists
|
||||
.replace(/^[ \t]*(#+)\s+/gm, (match: string, nums: string) => {
|
||||
return `${Array(nums.length).fill('').join('')}1. `;
|
||||
})
|
||||
// Headers 1-6
|
||||
.replace(/^h([0-6])\.(.*)$/gm, (match: string, level: string, content: string) => {
|
||||
return Array(parseInt(level, 10) + 1).join('#') + ' ' + content.trim();
|
||||
})
|
||||
// Bold (process before italic to avoid conflicts)
|
||||
.replace(/\*([^*\n]+)\*/g, '**$1**')
|
||||
// Italic
|
||||
.replace(/_([^_\n]+)_/g, '*$1*')
|
||||
// Monospaced text
|
||||
.replace(/\{\{([^}]+)\}\}/g, '`$1`')
|
||||
// Inserts
|
||||
.replace(/\+([^+]*)\+/g, '<ins>$1</ins>')
|
||||
// Superscript
|
||||
.replace(/\^([^^]*)\^/g, '<sup>$1</sup>')
|
||||
// Subscript
|
||||
.replace(/~([^~]*)~/g, '<sub>$1</sub>')
|
||||
// Strikethrough
|
||||
.replace(/(\s+)-(\S+.*?\S)-(\s+)/g, '$1~~$2~~$3')
|
||||
// Code Block
|
||||
.replace(
|
||||
/\{code(:([a-z]+))?([:|]?(title|borderStyle|borderColor|borderWidth|bgColor|titleBGColor)=.+?)*\}([^]*?)\n?\{code\}/gm,
|
||||
'```$2$5\n```'
|
||||
)
|
||||
// Pre-formatted text
|
||||
.replace(/{noformat}/g, '```')
|
||||
// Un-named Links
|
||||
.replace(/\[([^|]+?)\]/g, '<$1>')
|
||||
// Images
|
||||
.replace(/!(.+)!/g, '')
|
||||
// Named Links
|
||||
.replace(/\[(.+?)\|(.+?)\]/g, '[$1]($2)')
|
||||
// Single Paragraph Blockquote
|
||||
.replace(/^bq\.\s+/gm, '> ')
|
||||
// Remove color: unsupported in md
|
||||
.replace(/\{color:[^}]+\}([^]*?)\{color\}/gm, '$1')
|
||||
// panel into table
|
||||
.replace(/\{panel:title=([^}]*)\}\n?([^]*?)\n?\{panel\}/gm, '\n| $1 |\n| --- |\n| $2 |')
|
||||
// table header
|
||||
.replace(/^[ \t]*((?:\|\|.*?)+\|\|)[ \t]*$/gm, (match: string, headers: string) => {
|
||||
const singleBarred = headers.replace(/\|\|/g, '|');
|
||||
return `${singleBarred}\n${singleBarred.replace(/\|[^|]+/g, '| --- ')}`;
|
||||
})
|
||||
// remove leading-space of table headers and rows
|
||||
.replace(/^[ \t]*\|/gm, '|')
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
21
styles.css
21
styles.css
|
|
@ -13,25 +13,34 @@
|
|||
margin-bottom: 8px;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.work-description-container textarea {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.field-name-container {
|
||||
background-color: var(--background-primary);
|
||||
}
|
||||
|
||||
|
||||
.field-mapping-label {
|
||||
margin-right: 4px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.field-name-input, .to-jira-input, .from-jira-input {
|
||||
width: 100%;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
|
||||
.field-mapping-item .invalid,
|
||||
.setting-item.invalid input {
|
||||
background-color: rgba(var(--color-red-rgb), 0.2);
|
||||
}
|
||||
|
||||
.remove-field-btn {
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
background-color: var(--background-modifier-error);
|
||||
color: var(--text-on-accent);
|
||||
cursor: pointer;
|
||||
|
|
|
|||
787
yarn.lock
787
yarn.lock
|
|
@ -2,131 +2,88 @@
|
|||
# yarn lockfile v1
|
||||
|
||||
|
||||
"@esbuild/aix-ppc64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64"
|
||||
integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==
|
||||
"@codemirror/state@^6.0.0", "@codemirror/state@^6.5.0":
|
||||
version "6.5.2"
|
||||
resolved "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz"
|
||||
integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==
|
||||
dependencies:
|
||||
"@marijn/find-cluster-break" "^1.0.0"
|
||||
|
||||
"@esbuild/android-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f"
|
||||
integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==
|
||||
|
||||
"@esbuild/android-arm@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b"
|
||||
integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==
|
||||
|
||||
"@esbuild/android-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163"
|
||||
integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==
|
||||
|
||||
"@esbuild/darwin-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c"
|
||||
integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==
|
||||
|
||||
"@esbuild/darwin-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a"
|
||||
integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce"
|
||||
integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==
|
||||
|
||||
"@esbuild/freebsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7"
|
||||
integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==
|
||||
|
||||
"@esbuild/linux-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73"
|
||||
integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==
|
||||
|
||||
"@esbuild/linux-arm@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3"
|
||||
integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==
|
||||
|
||||
"@esbuild/linux-ia32@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19"
|
||||
integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==
|
||||
|
||||
"@esbuild/linux-loong64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7"
|
||||
integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==
|
||||
|
||||
"@esbuild/linux-mips64el@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1"
|
||||
integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==
|
||||
|
||||
"@esbuild/linux-ppc64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951"
|
||||
integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==
|
||||
|
||||
"@esbuild/linux-riscv64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987"
|
||||
integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==
|
||||
|
||||
"@esbuild/linux-s390x@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4"
|
||||
integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==
|
||||
|
||||
"@esbuild/linux-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a"
|
||||
integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==
|
||||
|
||||
"@esbuild/netbsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b"
|
||||
integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==
|
||||
|
||||
"@esbuild/netbsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b"
|
||||
integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7"
|
||||
integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==
|
||||
|
||||
"@esbuild/openbsd-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde"
|
||||
integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==
|
||||
|
||||
"@esbuild/sunos-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92"
|
||||
integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==
|
||||
|
||||
"@esbuild/win32-arm64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c"
|
||||
integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==
|
||||
|
||||
"@esbuild/win32-ia32@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079"
|
||||
integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==
|
||||
"@codemirror/view@^6.0.0":
|
||||
version "6.36.4"
|
||||
resolved "https://registry.npmjs.org/@codemirror/view/-/view-6.36.4.tgz"
|
||||
integrity sha512-ZQ0V5ovw/miKEXTvjgzRyjnrk9TwriUB1k4R5p7uNnHR9Hus+D1SXHGdJshijEzPFjU25xea/7nhIeSqYFKdbA==
|
||||
dependencies:
|
||||
"@codemirror/state" "^6.5.0"
|
||||
style-mod "^4.1.0"
|
||||
w3c-keyname "^2.2.4"
|
||||
|
||||
"@esbuild/win32-x64@0.25.0":
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b"
|
||||
resolved "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz"
|
||||
integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==
|
||||
|
||||
"@eslint-community/eslint-utils@^4.2.0":
|
||||
version "4.5.1"
|
||||
resolved "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz"
|
||||
integrity sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==
|
||||
dependencies:
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
|
||||
"@eslint-community/regexpp@^4.6.1":
|
||||
version "4.12.1"
|
||||
resolved "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz"
|
||||
integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
|
||||
|
||||
"@eslint/eslintrc@^2.1.4":
|
||||
version "2.1.4"
|
||||
resolved "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz"
|
||||
integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==
|
||||
dependencies:
|
||||
ajv "^6.12.4"
|
||||
debug "^4.3.2"
|
||||
espree "^9.6.0"
|
||||
globals "^13.19.0"
|
||||
ignore "^5.2.0"
|
||||
import-fresh "^3.2.1"
|
||||
js-yaml "^4.1.0"
|
||||
minimatch "^3.1.2"
|
||||
strip-json-comments "^3.1.1"
|
||||
|
||||
"@eslint/js@8.57.1":
|
||||
version "8.57.1"
|
||||
resolved "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz"
|
||||
integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==
|
||||
|
||||
"@humanwhocodes/config-array@^0.13.0":
|
||||
version "0.13.0"
|
||||
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz"
|
||||
integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==
|
||||
dependencies:
|
||||
"@humanwhocodes/object-schema" "^2.0.3"
|
||||
debug "^4.3.1"
|
||||
minimatch "^3.0.5"
|
||||
|
||||
"@humanwhocodes/module-importer@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz"
|
||||
integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
|
||||
|
||||
"@humanwhocodes/object-schema@^2.0.3":
|
||||
version "2.0.3"
|
||||
resolved "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz"
|
||||
integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
|
||||
|
||||
"@marijn/find-cluster-break@^1.0.0":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz"
|
||||
integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==
|
||||
|
||||
"@mixmark-io/domino@^2.2.0":
|
||||
version "2.2.0"
|
||||
resolved "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz"
|
||||
integrity sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz"
|
||||
|
|
@ -135,12 +92,12 @@
|
|||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
|
||||
"@nodelib/fs.walk@^1.2.3":
|
||||
"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8":
|
||||
version "1.2.8"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz"
|
||||
integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
|
||||
|
|
@ -177,6 +134,11 @@
|
|||
dependencies:
|
||||
"@types/estree" "*"
|
||||
|
||||
"@types/turndown@^5.0.5":
|
||||
version "5.0.5"
|
||||
resolved "https://registry.npmjs.org/@types/turndown/-/turndown-5.0.5.tgz"
|
||||
integrity sha512-TL2IgGgc7B5j78rIccBtlYAnkuv8nUQqhQc+DSYV5j9Be9XOcm/SKOVRuA47xAVI3680Tk9B1d8flK2GWT2+4w==
|
||||
|
||||
"@typescript-eslint/eslint-plugin@5.29.0":
|
||||
version "5.29.0"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.29.0.tgz"
|
||||
|
|
@ -192,7 +154,7 @@
|
|||
semver "^7.3.7"
|
||||
tsutils "^3.21.0"
|
||||
|
||||
"@typescript-eslint/parser@5.29.0":
|
||||
"@typescript-eslint/parser@^5.0.0", "@typescript-eslint/parser@5.29.0":
|
||||
version "5.29.0"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.29.0.tgz"
|
||||
integrity sha512-ruKWTv+x0OOxbzIw9nW5oWlUopvP/IQDjB5ZqmTglLIoDTctLlAJpAQFpNPJP/ZI7hTT9sARBosEfaKbcFuECw==
|
||||
|
|
@ -257,11 +219,66 @@
|
|||
"@typescript-eslint/types" "5.29.0"
|
||||
eslint-visitor-keys "^3.3.0"
|
||||
|
||||
"@ungap/structured-clone@^1.2.0":
|
||||
version "1.3.0"
|
||||
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz"
|
||||
integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==
|
||||
|
||||
acorn-jsx@^5.3.2:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||
|
||||
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.14.1, acorn@^8.9.0:
|
||||
version "8.14.1"
|
||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz"
|
||||
integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==
|
||||
|
||||
ajv@^6.12.4:
|
||||
version "6.12.6"
|
||||
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz"
|
||||
integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
|
||||
dependencies:
|
||||
fast-deep-equal "^3.1.1"
|
||||
fast-json-stable-stringify "^2.0.0"
|
||||
json-schema-traverse "^0.4.1"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz"
|
||||
integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
|
||||
|
||||
ansi-styles@^4.1.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz"
|
||||
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
array-union@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz"
|
||||
integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz"
|
||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz"
|
||||
integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
|
||||
dependencies:
|
||||
balanced-match "^1.0.0"
|
||||
concat-map "0.0.1"
|
||||
|
||||
braces@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz"
|
||||
|
|
@ -274,13 +291,57 @@ builtin-modules@3.3.0:
|
|||
resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz"
|
||||
integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
|
||||
|
||||
debug@^4.3.4:
|
||||
callsites@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
|
||||
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
|
||||
|
||||
chalk@^4.0.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
color-convert@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
|
||||
integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
|
||||
dependencies:
|
||||
color-name "~1.1.4"
|
||||
|
||||
color-name@~1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz"
|
||||
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz"
|
||||
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
|
||||
|
||||
cross-spawn@^7.0.2:
|
||||
version "7.0.6"
|
||||
resolved "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz"
|
||||
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||
dependencies:
|
||||
path-key "^3.1.0"
|
||||
shebang-command "^2.0.0"
|
||||
which "^2.0.1"
|
||||
|
||||
debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
|
||||
version "4.3.7"
|
||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz"
|
||||
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
|
||||
dependencies:
|
||||
ms "^2.1.3"
|
||||
|
||||
deep-is@^0.1.3:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
dir-glob@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz"
|
||||
|
|
@ -288,9 +349,16 @@ dir-glob@^3.0.1:
|
|||
dependencies:
|
||||
path-type "^4.0.0"
|
||||
|
||||
doctrine@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz"
|
||||
integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
esbuild@0.25.0:
|
||||
version "0.25.0"
|
||||
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz"
|
||||
integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==
|
||||
optionalDependencies:
|
||||
"@esbuild/aix-ppc64" "0.25.0"
|
||||
|
|
@ -319,6 +387,11 @@ esbuild@0.25.0:
|
|||
"@esbuild/win32-ia32" "0.25.0"
|
||||
"@esbuild/win32-x64" "0.25.0"
|
||||
|
||||
escape-string-regexp@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz"
|
||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||
|
||||
eslint-scope@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz"
|
||||
|
|
@ -327,6 +400,14 @@ eslint-scope@^5.1.1:
|
|||
esrecurse "^4.3.0"
|
||||
estraverse "^4.1.1"
|
||||
|
||||
eslint-scope@^7.2.2:
|
||||
version "7.2.2"
|
||||
resolved "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz"
|
||||
integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
|
||||
dependencies:
|
||||
esrecurse "^4.3.0"
|
||||
estraverse "^5.2.0"
|
||||
|
||||
eslint-utils@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz"
|
||||
|
|
@ -344,6 +425,76 @@ eslint-visitor-keys@^3.3.0:
|
|||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^3.4.1:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint-visitor-keys@^3.4.3:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz"
|
||||
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
|
||||
|
||||
eslint@*, "eslint@^6.0.0 || ^7.0.0 || ^8.0.0", "eslint@^6.0.0 || ^7.0.0 || >=8.0.0", eslint@>=5:
|
||||
version "8.57.1"
|
||||
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz"
|
||||
integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils" "^4.2.0"
|
||||
"@eslint-community/regexpp" "^4.6.1"
|
||||
"@eslint/eslintrc" "^2.1.4"
|
||||
"@eslint/js" "8.57.1"
|
||||
"@humanwhocodes/config-array" "^0.13.0"
|
||||
"@humanwhocodes/module-importer" "^1.0.1"
|
||||
"@nodelib/fs.walk" "^1.2.8"
|
||||
"@ungap/structured-clone" "^1.2.0"
|
||||
ajv "^6.12.4"
|
||||
chalk "^4.0.0"
|
||||
cross-spawn "^7.0.2"
|
||||
debug "^4.3.2"
|
||||
doctrine "^3.0.0"
|
||||
escape-string-regexp "^4.0.0"
|
||||
eslint-scope "^7.2.2"
|
||||
eslint-visitor-keys "^3.4.3"
|
||||
espree "^9.6.1"
|
||||
esquery "^1.4.2"
|
||||
esutils "^2.0.2"
|
||||
fast-deep-equal "^3.1.3"
|
||||
file-entry-cache "^6.0.1"
|
||||
find-up "^5.0.0"
|
||||
glob-parent "^6.0.2"
|
||||
globals "^13.19.0"
|
||||
graphemer "^1.4.0"
|
||||
ignore "^5.2.0"
|
||||
imurmurhash "^0.1.4"
|
||||
is-glob "^4.0.0"
|
||||
is-path-inside "^3.0.3"
|
||||
js-yaml "^4.1.0"
|
||||
json-stable-stringify-without-jsonify "^1.0.1"
|
||||
levn "^0.4.1"
|
||||
lodash.merge "^4.6.2"
|
||||
minimatch "^3.1.2"
|
||||
natural-compare "^1.4.0"
|
||||
optionator "^0.9.3"
|
||||
strip-ansi "^6.0.1"
|
||||
text-table "^0.2.0"
|
||||
|
||||
espree@^9.6.0, espree@^9.6.1:
|
||||
version "9.6.1"
|
||||
resolved "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz"
|
||||
integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
|
||||
dependencies:
|
||||
acorn "^8.9.0"
|
||||
acorn-jsx "^5.3.2"
|
||||
eslint-visitor-keys "^3.4.1"
|
||||
|
||||
esquery@^1.4.2:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz"
|
||||
integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
|
||||
dependencies:
|
||||
estraverse "^5.1.0"
|
||||
|
||||
esrecurse@^4.3.0:
|
||||
version "4.3.0"
|
||||
resolved "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz"
|
||||
|
|
@ -356,11 +507,26 @@ estraverse@^4.1.1:
|
|||
resolved "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz"
|
||||
integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==
|
||||
|
||||
estraverse@^5.1.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
|
||||
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
|
||||
|
||||
estraverse@^5.2.0:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz"
|
||||
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
|
||||
|
||||
esutils@^2.0.2:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz"
|
||||
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
|
||||
|
||||
fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz"
|
||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||
|
||||
fast-glob@^3.2.9:
|
||||
version "3.3.2"
|
||||
resolved "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz"
|
||||
|
|
@ -372,6 +538,16 @@ fast-glob@^3.2.9:
|
|||
merge2 "^1.3.0"
|
||||
micromatch "^4.0.4"
|
||||
|
||||
fast-json-stable-stringify@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz"
|
||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||
|
||||
fast-levenshtein@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz"
|
||||
integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
|
||||
|
||||
fastq@^1.6.0:
|
||||
version "1.17.1"
|
||||
resolved "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz"
|
||||
|
|
@ -379,6 +555,13 @@ fastq@^1.6.0:
|
|||
dependencies:
|
||||
reusify "^1.0.4"
|
||||
|
||||
file-entry-cache@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz"
|
||||
integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
|
||||
dependencies:
|
||||
flat-cache "^3.0.4"
|
||||
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz"
|
||||
|
|
@ -386,6 +569,33 @@ fill-range@^7.1.1:
|
|||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
find-up@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz"
|
||||
integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
|
||||
dependencies:
|
||||
locate-path "^6.0.0"
|
||||
path-exists "^4.0.0"
|
||||
|
||||
flat-cache@^3.0.4:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz"
|
||||
integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==
|
||||
dependencies:
|
||||
flatted "^3.2.9"
|
||||
keyv "^4.5.3"
|
||||
rimraf "^3.0.2"
|
||||
|
||||
flatted@^3.2.9:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz"
|
||||
integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==
|
||||
|
||||
fs.realpath@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
|
||||
|
||||
functional-red-black-tree@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz"
|
||||
|
|
@ -398,6 +608,32 @@ glob-parent@^5.1.2:
|
|||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
glob-parent@^6.0.2:
|
||||
version "6.0.2"
|
||||
resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz"
|
||||
integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
|
||||
dependencies:
|
||||
is-glob "^4.0.3"
|
||||
|
||||
glob@^7.1.3:
|
||||
version "7.2.3"
|
||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz"
|
||||
integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
|
||||
dependencies:
|
||||
fs.realpath "^1.0.0"
|
||||
inflight "^1.0.4"
|
||||
inherits "2"
|
||||
minimatch "^3.1.1"
|
||||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
globals@^13.19.0:
|
||||
version "13.24.0"
|
||||
resolved "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz"
|
||||
integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
|
||||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
globby@^11.1.0:
|
||||
version "11.1.0"
|
||||
resolved "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz"
|
||||
|
|
@ -410,17 +646,53 @@ globby@^11.1.0:
|
|||
merge2 "^1.4.1"
|
||||
slash "^3.0.0"
|
||||
|
||||
graphemer@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz"
|
||||
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
|
||||
|
||||
has-flag@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
ignore@^5.2.0:
|
||||
version "5.3.2"
|
||||
resolved "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz"
|
||||
integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
|
||||
|
||||
import-fresh@^3.2.1:
|
||||
version "3.3.1"
|
||||
resolved "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz"
|
||||
integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==
|
||||
dependencies:
|
||||
parent-module "^1.0.0"
|
||||
resolve-from "^4.0.0"
|
||||
|
||||
imurmurhash@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
|
||||
integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
|
||||
|
||||
inflight@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz"
|
||||
integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
|
||||
dependencies:
|
||||
once "^1.3.0"
|
||||
wrappy "1"
|
||||
|
||||
inherits@2:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||
|
||||
is-extglob@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz"
|
||||
integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
|
||||
|
||||
is-glob@^4.0.1, is-glob@^4.0.3:
|
||||
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz"
|
||||
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
|
||||
|
|
@ -432,6 +704,65 @@ is-number@^7.0.0:
|
|||
resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-path-inside@^3.0.3:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz"
|
||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||
|
||||
isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz"
|
||||
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
json-buffer@3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz"
|
||||
integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz"
|
||||
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
|
||||
|
||||
json-stable-stringify-without-jsonify@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz"
|
||||
integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
|
||||
|
||||
keyv@^4.5.3:
|
||||
version "4.5.4"
|
||||
resolved "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz"
|
||||
integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
|
||||
dependencies:
|
||||
json-buffer "3.0.1"
|
||||
|
||||
levn@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz"
|
||||
integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
|
||||
dependencies:
|
||||
prelude-ls "^1.2.1"
|
||||
type-check "~0.4.0"
|
||||
|
||||
locate-path@^6.0.0:
|
||||
version "6.0.0"
|
||||
resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz"
|
||||
integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
|
||||
dependencies:
|
||||
p-locate "^5.0.0"
|
||||
|
||||
lodash.merge@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz"
|
||||
integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
|
||||
|
||||
merge2@^1.3.0, merge2@^1.4.1:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz"
|
||||
|
|
@ -445,6 +776,13 @@ micromatch@^4.0.4:
|
|||
braces "^3.0.3"
|
||||
picomatch "^2.3.1"
|
||||
|
||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
||||
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||
dependencies:
|
||||
brace-expansion "^1.1.7"
|
||||
|
||||
moment@2.29.4:
|
||||
version "2.29.4"
|
||||
resolved "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz"
|
||||
|
|
@ -455,14 +793,74 @@ ms@^2.1.3:
|
|||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz"
|
||||
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
|
||||
|
||||
obsidian@latest:
|
||||
version "1.7.2"
|
||||
resolved "https://registry.npmjs.org/obsidian/-/obsidian-1.7.2.tgz"
|
||||
integrity sha512-k9hN9brdknJC+afKr5FQzDRuEFGDKbDjfCazJwpgibwCAoZNYHYV8p/s3mM8I6AsnKrPKNXf8xGuMZ4enWelZQ==
|
||||
version "1.8.7"
|
||||
resolved "https://registry.npmjs.org/obsidian/-/obsidian-1.8.7.tgz"
|
||||
integrity sha512-h4bWwNFAGRXlMlMAzdEiIM2ppTGlrh7uGOJS6w4gClrsjc+ei/3YAtU2VdFUlCiPuTHpY4aBpFJJW75S1Tl/JA==
|
||||
dependencies:
|
||||
"@types/codemirror" "5.60.8"
|
||||
moment "2.29.4"
|
||||
|
||||
once@^1.3.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz"
|
||||
integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
|
||||
dependencies:
|
||||
wrappy "1"
|
||||
|
||||
optionator@^0.9.3:
|
||||
version "0.9.4"
|
||||
resolved "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz"
|
||||
integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==
|
||||
dependencies:
|
||||
deep-is "^0.1.3"
|
||||
fast-levenshtein "^2.0.6"
|
||||
levn "^0.4.1"
|
||||
prelude-ls "^1.2.1"
|
||||
type-check "^0.4.0"
|
||||
word-wrap "^1.2.5"
|
||||
|
||||
p-limit@^3.0.2:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz"
|
||||
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
|
||||
dependencies:
|
||||
yocto-queue "^0.1.0"
|
||||
|
||||
p-locate@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz"
|
||||
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
|
||||
dependencies:
|
||||
p-limit "^3.0.2"
|
||||
|
||||
parent-module@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz"
|
||||
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
|
||||
dependencies:
|
||||
callsites "^3.0.0"
|
||||
|
||||
path-exists@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz"
|
||||
integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
|
||||
|
||||
path-is-absolute@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz"
|
||||
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
|
||||
|
||||
path-key@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz"
|
||||
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
|
||||
|
||||
path-type@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz"
|
||||
|
|
@ -473,6 +871,16 @@ picomatch@^2.3.1:
|
|||
resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz"
|
||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
||||
|
||||
prelude-ls@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz"
|
||||
integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
|
||||
|
||||
punycode@^2.1.0:
|
||||
version "2.3.1"
|
||||
resolved "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz"
|
||||
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
|
||||
|
|
@ -483,11 +891,23 @@ regexpp@^3.2.0:
|
|||
resolved "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz"
|
||||
integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==
|
||||
|
||||
resolve-from@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz"
|
||||
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
|
||||
|
||||
reusify@^1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz"
|
||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz"
|
||||
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
|
||||
dependencies:
|
||||
glob "^7.1.3"
|
||||
|
||||
run-parallel@^1.1.9:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz"
|
||||
|
|
@ -500,11 +920,52 @@ semver@^7.3.7:
|
|||
resolved "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz"
|
||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||
|
||||
shebang-command@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz"
|
||||
integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
|
||||
dependencies:
|
||||
shebang-regex "^3.0.0"
|
||||
|
||||
shebang-regex@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz"
|
||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz"
|
||||
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
|
||||
|
||||
strip-ansi@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
|
||||
strip-json-comments@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz"
|
||||
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||
|
||||
style-mod@^4.1.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.npmjs.org/style-mod/-/style-mod-4.1.2.tgz"
|
||||
integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==
|
||||
|
||||
supports-color@^7.1.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz"
|
||||
integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
|
||||
dependencies:
|
||||
has-flag "^4.0.0"
|
||||
|
||||
text-table@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz"
|
||||
integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz"
|
||||
|
|
@ -512,16 +973,16 @@ to-regex-range@^5.0.1:
|
|||
dependencies:
|
||||
is-number "^7.0.0"
|
||||
|
||||
tslib@2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz"
|
||||
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
||||
|
||||
tslib@^1.8.1:
|
||||
version "1.14.1"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz"
|
||||
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
|
||||
|
||||
tslib@2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz"
|
||||
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
|
||||
|
||||
tsutils@^3.21.0:
|
||||
version "3.21.0"
|
||||
resolved "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz"
|
||||
|
|
@ -529,7 +990,65 @@ tsutils@^3.21.0:
|
|||
dependencies:
|
||||
tslib "^1.8.1"
|
||||
|
||||
typescript@4.7.4:
|
||||
turndown@^7.2.0:
|
||||
version "7.2.0"
|
||||
resolved "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz"
|
||||
integrity sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==
|
||||
dependencies:
|
||||
"@mixmark-io/domino" "^2.2.0"
|
||||
|
||||
type-check@^0.4.0, type-check@~0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz"
|
||||
integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
|
||||
dependencies:
|
||||
prelude-ls "^1.2.1"
|
||||
|
||||
type-fest@^0.20.2:
|
||||
version "0.20.2"
|
||||
resolved "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz"
|
||||
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
|
||||
|
||||
"typescript@>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta", typescript@4.7.4:
|
||||
version "4.7.4"
|
||||
resolved "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz"
|
||||
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz"
|
||||
integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
|
||||
dependencies:
|
||||
punycode "^2.1.0"
|
||||
|
||||
w3c-keyname@^2.2.4:
|
||||
version "2.2.8"
|
||||
resolved "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz"
|
||||
integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==
|
||||
|
||||
which@^2.0.1:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz"
|
||||
integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
|
||||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
word-wrap@^1.2.5:
|
||||
version "1.2.5"
|
||||
resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz"
|
||||
integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz"
|
||||
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
|
||||
|
||||
yaml@^2.7.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz"
|
||||
integrity sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==
|
||||
|
||||
yocto-queue@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz"
|
||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||
|
|
|
|||
Loading…
Reference in a new issue