mirror of
https://github.com/alamion/obsidian-jira-sync.git
synced 2026-07-22 05:43:04 +00:00
Fix:
- multiple fixes and code refactors for last feats to work correctly - added Jira api_version variable to field mapping context
This commit is contained in:
parent
75dd9d75cd
commit
a3211bcdb2
13 changed files with 129 additions and 81 deletions
|
|
@ -96,6 +96,7 @@ Currently, the plugin provides the following commands:
|
|||
- `Update work log in Jira manually` - enables manual time tracking for a task. Currently, this is not reflected in the file, but it will be available in future updates.
|
||||
- `Update work log in Jira by batch` - enables batch time tracking. If the formatter contains `jira_worklog_batch`, a batch of data from `jira_worklog_batch` will be sent, updating each listed entity.
|
||||
- `Update issue status in Jira` - allows updating a task's status by selecting one of the available options.
|
||||
- `Add comment to Jira` - allows adding a comment to the current task in Jira.
|
||||
|
||||
### Advanced Usage
|
||||
|
||||
|
|
@ -110,12 +111,14 @@ Similarly, you can configure the `progressPercentage` shown in the example. This
|
|||
|
||||
Additionally, you can use some of the built-in functions:
|
||||
|
||||
- `jiraToMarkdown` - converts Jira markup to Markdown.
|
||||
- `markdownToJira` - converts Markdown to Jira markup.
|
||||
- `jiraToMarkdown` - converts Jira markup to Markdown. (for Jira API v2)
|
||||
- `markdownToJira` - converts Markdown to Jira markup. (for Jira API v2)
|
||||
- `markdownToAdf` - converts Markdown to Atlassian Document Format (ADF). (for Jira API v3)
|
||||
- `adfToMarkdown` - converts ADF to Markdown. (for Jira API v3)
|
||||
- `JSON.parse` - converts a JSON string to an object.
|
||||
- `JSON.stringify` - converts an object to a JSON string.
|
||||
|
||||
and modules: (original Javascript syntax)
|
||||
and modules: (original JavaScript syntax)
|
||||
|
||||
- `Math` - provides access to mathematical functions, such as `Math.round()`.
|
||||
- `Date` - provides access to date functions, such as `Date.now()`.
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ Bob
|
|||
- `Update work log in Jira manually` - позволяет вести учёт потраченного на задачу времени вручную. В данный момент он никак не отображается в файле, это будет в ближайших обновлениях.
|
||||
- `Update work log in Jira by batch` - позволяет вести учёт потраченного на задачу времени батчем. Если в файле в formatter есть `jira_worklog_batch`, то вместо ручного заполнения будет послан батч данных из `jira_worklog_batch` с обновлением каждой из представленных сущностей.
|
||||
- `Update issue status in Jira` - позволяет обновить статус задачи, выбрав один из возможных вариантов.
|
||||
- `Add comment to Jira` - позволяет добавить комментарий в выбранную задачу.
|
||||
|
||||
### Продвинутое использование
|
||||
|
||||
|
|
@ -109,12 +110,14 @@ Bob
|
|||
|
||||
Кроме того, вы можете использовать некоторые встроенные функции:
|
||||
|
||||
- `jiraToMarkdown` - преобразует разметку Jira в Markdown.
|
||||
- `markdownToJira` - преобразует Markdown в разметку Jira.
|
||||
- `jiraToMarkdown` - преобразует разметку Jira в Markdown. (Jira API v2)
|
||||
- `markdownToJira` - преобразует Markdown в разметку Jira. (Jira API v2)
|
||||
- `markdownToAdf` - преобразует Markdown в ADF. (Jira API v3)
|
||||
- `adfToMarkdown` - преобразует ADF в Markdown. (Jira API v3)
|
||||
- `JSON.parse` - преобразует строку JSON в объект.
|
||||
- `JSON.stringify` - преобразует объект в строку JSON.
|
||||
|
||||
и модули: (исходный синтаксис Javascript)
|
||||
и модули: (исходный синтаксис JavaScript)
|
||||
|
||||
- `Math` - предоставляет доступ к математическим функциям, таким как `Math.round()`.
|
||||
- `Date` - предоставляет доступ к функциям даты, таким как `Date.now()`.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"id": "jira-sync",
|
||||
"name": "Jira Issue Manager",
|
||||
"version": "1.5.2",
|
||||
"version": "1.6.0",
|
||||
"minAppVersion": "1.10.1",
|
||||
"description": "Get Jira issues, create and update them. Issue status and worklog management.",
|
||||
"author": "Alamion",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "obsidian-jira-sync",
|
||||
"version": "1.5.2",
|
||||
"version": "1.6.0",
|
||||
"packageManager": "yarn@1.22.22",
|
||||
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
|
||||
"main": "main.js",
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
import { JiraIssue } from '../interfaces';
|
||||
import { jiraToMarkdown } from '../tools/markdownHtml';
|
||||
import { adfToMarkdown } from '../tools/markdownToAdf';
|
||||
import { jiraToMarkdown, markdownToJira } from '../tools/markdownHtml';
|
||||
import { adfToMarkdown, markdownToAdf } from '../tools/markdownToAdf';
|
||||
|
||||
export interface FieldMapping {
|
||||
toJira: (value: any) => any;
|
||||
fromJira: (issue: JiraIssue, data_source: Record<string, any> | null) => any;
|
||||
toJira: (value: any, api_version?: '2' | '3') => any;
|
||||
fromJira: (issue: JiraIssue, api_version?: '2' | '3', data_source?: Record<string, any>) => any;
|
||||
}
|
||||
export const TO_JIRA_PARAMS = ['value', 'api_version'];
|
||||
export const FROM_JIRA_PARAMS = ['issue', 'api_version', 'data_source'];
|
||||
|
||||
export const obsidianJiraFieldMappings: Record<string, FieldMapping> = {
|
||||
summary: {
|
||||
|
|
@ -13,8 +15,9 @@ export const obsidianJiraFieldMappings: Record<string, FieldMapping> = {
|
|||
fromJira: (issue) => issue.fields.summary,
|
||||
},
|
||||
description: {
|
||||
toJira: () => null,
|
||||
fromJira: (issue) => jiraToMarkdown(issue.fields.description),
|
||||
toJira: (value, api_version) => (api_version === '3' ? markdownToAdf(value) : markdownToJira(value)),
|
||||
fromJira: (issue, api_version) =>
|
||||
api_version === '3' ? adfToMarkdown(issue.fields.description) : jiraToMarkdown(issue.fields.description),
|
||||
},
|
||||
key: {
|
||||
toJira: () => null,
|
||||
|
|
@ -78,14 +81,14 @@ export const obsidianJiraFieldMappings: Record<string, FieldMapping> = {
|
|||
},
|
||||
comments: {
|
||||
toJira: () => null,
|
||||
fromJira: (issue) => {
|
||||
fromJira: (issue, api_version) => {
|
||||
const comments = issue.fields.comment?.comments;
|
||||
if (!comments?.length) return '';
|
||||
return comments
|
||||
.map((c: any) => {
|
||||
const author = c.author?.displayName ?? 'Unknown';
|
||||
const date = c.created ? c.created.replace('T', ' ').substring(0, 19) : '';
|
||||
const body = adfToMarkdown(c.body) ?? '';
|
||||
const body = api_version === '3' ? adfToMarkdown(c.body) : c.body;
|
||||
const calloutBody = body
|
||||
.split('\n')
|
||||
.map((l: string) => (l === '' ? '>' : `> ${l}`))
|
||||
|
|
|
|||
|
|
@ -9,15 +9,20 @@ import { obsidianJiraFieldMappings } from '../default/obsidianJiraFieldsMapping'
|
|||
export async function updateIssueFromFile(plugin: JiraPlugin, file: TFile): Promise<string> {
|
||||
let fields = await prepareJiraFieldsFromFile(plugin, file);
|
||||
const issueKey = fields.key;
|
||||
const apiVersion = plugin.getCurrentConnection()?.apiVersion;
|
||||
|
||||
if (!issueKey) {
|
||||
throw new Error('No issue key found in frontmatter');
|
||||
}
|
||||
|
||||
fields = localToJiraFields(fields, {
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
});
|
||||
fields = localToJiraFields(
|
||||
fields,
|
||||
{
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
},
|
||||
apiVersion,
|
||||
);
|
||||
await updateJiraIssue(plugin, issueKey, fields);
|
||||
return issueKey;
|
||||
}
|
||||
|
|
@ -27,13 +32,18 @@ export async function createIssueFromFile(
|
|||
file: TFile,
|
||||
fields?: Record<string, any>,
|
||||
): Promise<string> {
|
||||
const apiVersion = plugin.getCurrentConnection()?.apiVersion;
|
||||
if (!fields) {
|
||||
fields = await prepareJiraFieldsFromFile(plugin, file);
|
||||
}
|
||||
fields = localToJiraFields(fields, {
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
});
|
||||
fields = localToJiraFields(
|
||||
fields,
|
||||
{
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
},
|
||||
apiVersion,
|
||||
);
|
||||
// Create the issue
|
||||
const issueData = await createJiraIssue(plugin, fields);
|
||||
const issueKey = issueData.key;
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ desc: |
|
|||
|
||||
To Jira:
|
||||
- value - the value of field in your .md file - can be a text string from file contents or a field value from frontmatter
|
||||
- api_version - Jira API version used in current connection (could be either '2' or '3')
|
||||
|
||||
From Jira:
|
||||
- issue - raw data from Jira (can be seen in lower `Fetch issue settings` section)
|
||||
- api_version - the same as `To Jira`
|
||||
- data_source - either parsed sections or frontmatter data in dictionary format, where keys are field names and values are field values
|
||||
fv:
|
||||
name: Enable field validation
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@ desc: |
|
|||
|
||||
В Jira:
|
||||
- value — значение поля в .md файле — это может быть текст из содержимого файла или значение поля из frontmatter
|
||||
- api_version - Jira API версия используемая в текущем коннекторе (может быть '2' или '3')
|
||||
|
||||
Из Jira:
|
||||
- issue — необработанные данные из Jira (можно увидеть в нижнем разделе "Настройка получаемых полей")
|
||||
- api_version - То же самое что и в "В Jira"
|
||||
- data_source — либо спаршенные секции данных из файла, либо данные frontmatter. Показывается в формате словаря, где ключи — это названия полей, а значения — данные из файла
|
||||
fv:
|
||||
name: Включить проверку полей
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { validateField } from '../tools/fieldValidation';
|
||||
import { useTranslations } from '../../localization/translator';
|
||||
import { FROM_JIRA_PARAMS, TO_JIRA_PARAMS } from '../../default/obsidianJiraFieldsMapping';
|
||||
|
||||
const t = useTranslations('settings.fm').t;
|
||||
/**
|
||||
|
|
@ -82,7 +83,8 @@ export class FieldMappingItem {
|
|||
this.toJiraInput = toJiraContainer.createEl('textarea', {
|
||||
cls: 'to-jira-input',
|
||||
});
|
||||
this.toJiraInput.placeholder = '(value) => {\n // Transform Obsidian value to Jira\n return value;\n}';
|
||||
this.toJiraInput.placeholder =
|
||||
'(value, api_version) => {\n // Transform Obsidian value to Jira\n return value;\n}';
|
||||
this.toJiraInput.value = toJira;
|
||||
|
||||
// Create fromJira function input
|
||||
|
|
@ -98,7 +100,7 @@ export class FieldMappingItem {
|
|||
});
|
||||
this.fromJiraInput.value = fromJira;
|
||||
this.fromJiraInput.placeholder =
|
||||
'(issue, data_source) => {\n // Extract value from Jira issue\n return issue.fields.fieldName;\n}';
|
||||
'(issue, api_version, data_source) => {\n // Extract value from Jira issue\n return issue.fields.fieldName;\n}';
|
||||
|
||||
// Add remove button
|
||||
const removeBtn = this.fieldContainer.createEl('button', {
|
||||
|
|
@ -139,8 +141,8 @@ export class FieldMappingItem {
|
|||
*/
|
||||
async setupValidation(enableValidation: boolean) {
|
||||
await validateField(this.fieldNameInput, enableValidation, 'string');
|
||||
await validateField(this.toJiraInput, enableValidation, 'function', ['value']);
|
||||
await validateField(this.fromJiraInput, enableValidation, 'function', ['issue', 'data_source']);
|
||||
await validateField(this.toJiraInput, enableValidation, 'function', TO_JIRA_PARAMS);
|
||||
await validateField(this.fromJiraInput, enableValidation, 'function', FROM_JIRA_PARAMS);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -315,6 +315,12 @@ export class FieldMappingsComponent implements SettingsComponent {
|
|||
toJira: '({ key: value })',
|
||||
fromJira: 'issue.fields.project ? issue.fields.project.key : ""',
|
||||
},
|
||||
{
|
||||
name: 'description',
|
||||
toJira: 'api_version === "3" ? markdownToAdf(value) : markdownToJira(value)',
|
||||
fromJira:
|
||||
'api_version === "3" ? adfToMarkdown(issue.fields.description) : jiraToMarkdown(issue.fields.description)',
|
||||
},
|
||||
];
|
||||
|
||||
examples.forEach((example) => {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import { Notice } from 'obsidian';
|
|||
import { JiraIssue } from '../interfaces';
|
||||
import { parse } from 'acorn';
|
||||
import { debugLog } from './debugLogging';
|
||||
import { FieldMapping } from '../default/obsidianJiraFieldsMapping';
|
||||
import { FieldMapping, FROM_JIRA_PARAMS, TO_JIRA_PARAMS } from '../default/obsidianJiraFieldsMapping';
|
||||
import { defaultIssue } from '../default/defaultIssue';
|
||||
import { jiraToMarkdown, markdownToJira } from './markdownHtml';
|
||||
import { markdownToAdf, adfToMarkdown } from './markdownToAdf';
|
||||
|
|
@ -57,6 +57,7 @@ export function validateFunctionStringBrowser(
|
|||
const varDeclarations = approved_vars
|
||||
.map((varName) => {
|
||||
if (varName === 'issue') return `${varName} = ${JSON.stringify(defaultIssue)}`;
|
||||
if (varName === 'api_version') return `${varName} = "2"`;
|
||||
if (varName === 'value') return `${varName} = "test value"`;
|
||||
if (varName === 'data_source') return `${varName} = {}`;
|
||||
return `${varName} = {}`;
|
||||
|
|
@ -91,6 +92,7 @@ export function validateFunctionStringBrowser(
|
|||
|
||||
const testArgs = approved_vars.map((varName) => {
|
||||
if (varName === 'issue') return defaultIssue;
|
||||
if (varName === 'api_version') return '2';
|
||||
if (varName === 'value') return 'test value';
|
||||
if (varName === 'data_source') return {};
|
||||
return {};
|
||||
|
|
@ -180,7 +182,7 @@ export async function safeStringToFunction(
|
|||
if (extraValidate) {
|
||||
const validation = await validateFunctionString(
|
||||
exprString,
|
||||
type === 'fromJira' ? ['issue', 'data_source'] : ['value'],
|
||||
type === 'fromJira' ? FROM_JIRA_PARAMS : TO_JIRA_PARAMS,
|
||||
);
|
||||
if (!validation.isValid) {
|
||||
console.warn(`Invalid function: ${validation.errorMessage}`);
|
||||
|
|
@ -216,9 +218,9 @@ export async function safeStringToFunction(
|
|||
};
|
||||
|
||||
if (type === 'toJira') {
|
||||
return function (value: any) {
|
||||
return function (value: any, api_version?: '2' | '3') {
|
||||
const fn = new Function(
|
||||
'value',
|
||||
...TO_JIRA_PARAMS,
|
||||
'context',
|
||||
`
|
||||
with (context) {
|
||||
|
|
@ -232,14 +234,13 @@ export async function safeStringToFunction(
|
|||
`,
|
||||
);
|
||||
|
||||
return fn.call(context, value, context);
|
||||
return fn.call(context, value, api_version, context);
|
||||
};
|
||||
} else {
|
||||
// fromJira
|
||||
return function (issue: JiraIssue, data_source: Record<string, any> | null) {
|
||||
return function (issue: JiraIssue, api_version?: '2' | '3', data_source?: Record<string, any>) {
|
||||
const fn = new Function(
|
||||
'issue',
|
||||
'data_source',
|
||||
...FROM_JIRA_PARAMS,
|
||||
'context',
|
||||
`
|
||||
with (context) {
|
||||
|
|
@ -253,7 +254,7 @@ export async function safeStringToFunction(
|
|||
`,
|
||||
);
|
||||
|
||||
return fn.call(context, issue, data_source, context);
|
||||
return fn.call(context, issue, api_version, data_source, context);
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -272,29 +273,22 @@ export function jiraFunctionToString(fn: (...args: any[]) => any, isFromJira: bo
|
|||
|
||||
const paramMatch = fnStr.match(/^\s*(?:\(?([^)]*)\)?\s*=>|\s*function\s*\(([^)]*)\))/);
|
||||
if (paramMatch) {
|
||||
if (isFromJira) {
|
||||
const params = (paramMatch[1] || paramMatch[2] || '').split(',').map((p) => p.trim());
|
||||
const params = (paramMatch[1] || paramMatch[2] || '').split(',').map((p) => p.trim());
|
||||
let resultStr = baseStr;
|
||||
|
||||
let resultStr = baseStr;
|
||||
|
||||
if (params.length >= 1 && params[0]) {
|
||||
const regex1 = new RegExp(`\\b${params[0]}\\b`, 'g');
|
||||
resultStr = resultStr.replace(regex1, 'issue');
|
||||
}
|
||||
if (params.length >= 2 && params[1]) {
|
||||
const regex2 = new RegExp(`\\b${params[1]}\\b`, 'g');
|
||||
resultStr = resultStr.replace(regex2, 'data_source');
|
||||
}
|
||||
|
||||
return resultStr;
|
||||
} else {
|
||||
const param = (paramMatch[1] || paramMatch[2] || '').trim();
|
||||
|
||||
if (param) {
|
||||
const regex = new RegExp(`\\b${param}\\b`, 'g');
|
||||
return baseStr.replace(regex, 'value');
|
||||
}
|
||||
if (params.length >= 1 && params[0]) {
|
||||
const regex1 = new RegExp(`\\b${params[0]}\\b`, 'g');
|
||||
resultStr = isFromJira ? resultStr.replace(regex1, 'issue') : resultStr.replace(regex1, 'value');
|
||||
}
|
||||
if (params.length >= 2 && params[1]) {
|
||||
const regex2 = new RegExp(`\\b${params[1]}\\b`, 'g');
|
||||
resultStr = resultStr.replace(regex2, 'api_version');
|
||||
}
|
||||
if (params.length >= 3 && params[2]) {
|
||||
const regex3 = new RegExp(`\\b${params[2]}\\b`, 'g');
|
||||
resultStr = resultStr.replace(regex3, 'data_source');
|
||||
}
|
||||
return resultStr;
|
||||
}
|
||||
|
||||
return baseStr;
|
||||
|
|
@ -351,8 +345,12 @@ export async function transform_string_to_functions_mappings(
|
|||
|
||||
if (toJiraFn && fromJiraFn) {
|
||||
transformedMappings[fieldName] = {
|
||||
toJira: (await toJiraFn) as (value: any) => any,
|
||||
fromJira: (await fromJiraFn) as (issue: JiraIssue, data_source: Record<string, any> | null) => any,
|
||||
toJira: (await toJiraFn) as (value: any, api_version?: '2' | '3') => any,
|
||||
fromJira: (await fromJiraFn) as (
|
||||
issue: JiraIssue,
|
||||
api_version?: '2' | '3',
|
||||
data_source?: Record<string, any>,
|
||||
) => any,
|
||||
};
|
||||
} else {
|
||||
console.warn(`Invalid function in field: ${fieldName}`);
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import { debugLog } from './debugLogging';
|
|||
export function localToJiraFields(
|
||||
data_source: Record<string, any>,
|
||||
customFieldMappings: Record<string, FieldMapping>,
|
||||
apiVersion?: '2' | '3',
|
||||
): Record<string, any> {
|
||||
const jiraFields: Record<string, any> = {};
|
||||
|
||||
|
|
@ -23,10 +24,12 @@ export function localToJiraFields(
|
|||
const mapping = customFieldMappings[key];
|
||||
|
||||
try {
|
||||
// Skip fields that shouldn't be sent to Jira
|
||||
if (mapping.toJira(value) === null) continue;
|
||||
const result = mapping.toJira(value, apiVersion);
|
||||
|
||||
jiraFields[key] = mapping.toJira(value);
|
||||
// Skip fields that shouldn't be sent to Jira
|
||||
if (result === null) continue;
|
||||
|
||||
jiraFields[key] = result;
|
||||
} catch (e) {
|
||||
console.error(`Error mapping for ${key}: ${e}`);
|
||||
new Notice(`Error mapping for ${key}: ${e}`);
|
||||
|
|
@ -42,13 +45,19 @@ export function localToJiraFields(
|
|||
}
|
||||
|
||||
export async function updateJiraToLocal(plugin: JiraPlugin, file: TFile, issue: JiraIssue): Promise<void> {
|
||||
const apiVersion = plugin.getCurrentConnection()?.apiVersion;
|
||||
// First, update the frontmatter using processFrontMatter
|
||||
await plugin.app.fileManager.processFrontMatter(file, (frontmatter) => {
|
||||
// Update frontmatter with Jira data
|
||||
applyJiraDataToLocal(frontmatter, issue, {
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
});
|
||||
applyJiraDataToLocal(
|
||||
frontmatter,
|
||||
issue,
|
||||
{
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
},
|
||||
apiVersion,
|
||||
);
|
||||
});
|
||||
|
||||
// Then, process the file content to update sync sections
|
||||
|
|
@ -57,10 +66,15 @@ export async function updateJiraToLocal(plugin: JiraPlugin, file: TFile, issue:
|
|||
const syncSections = extractAllJiraSyncValuesFromContent(fileContent);
|
||||
|
||||
// Update sync sections with Jira data
|
||||
applyJiraDataToLocal(syncSections, issue, {
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
});
|
||||
applyJiraDataToLocal(
|
||||
syncSections,
|
||||
issue,
|
||||
{
|
||||
...obsidianJiraFieldMappings,
|
||||
...plugin.settings.fieldMapping.fieldMappings,
|
||||
},
|
||||
apiVersion,
|
||||
);
|
||||
|
||||
// Update content sections from Jira fields
|
||||
let updatedContent = fileContent;
|
||||
|
|
@ -80,10 +94,11 @@ export function applyJiraDataToLocal(
|
|||
localData: Record<string, any>,
|
||||
issue: JiraIssue,
|
||||
fieldMappings: Record<string, FieldMapping>,
|
||||
apiVersion?: '2' | '3',
|
||||
): void {
|
||||
// Process existing fields in local data
|
||||
for (const key of Object.keys(localData)) {
|
||||
updateFieldFromJira(key, localData, issue, fieldMappings);
|
||||
updateFieldFromJira(key, localData, issue, fieldMappings, apiVersion);
|
||||
}
|
||||
|
||||
// Ensure required fields are always processed
|
||||
|
|
@ -100,13 +115,14 @@ function updateFieldFromJira(
|
|||
targetObject: Record<string, any>,
|
||||
issue: JiraIssue,
|
||||
fieldMappings: Record<string, FieldMapping>,
|
||||
apiVersion?: '2' | '3',
|
||||
): void {
|
||||
try {
|
||||
let value = issue.fields[key];
|
||||
|
||||
// Apply custom mapping if available
|
||||
if (key in fieldMappings) {
|
||||
value = fieldMappings[key].fromJira(issue, targetObject);
|
||||
value = fieldMappings[key].fromJira(issue, apiVersion, targetObject);
|
||||
}
|
||||
// debugLog(`Updating field: ${key}: ${issue.fields[key]}`);
|
||||
|
||||
|
|
@ -128,14 +144,14 @@ function logMappingDebugInfo(key: string, error: Error, fieldMappings: Record<st
|
|||
new Notice(`Error mapping for ${key}: ${error}`);
|
||||
|
||||
// Create debug info about available mappings
|
||||
const mappingInfo: Record<string, { hasToJira: string; hasFromJira: string }> = {};
|
||||
const mappingInfo: Record<string, { toJira: string; fromJira: string }> = {};
|
||||
|
||||
for (const mappingKey of Object.keys(fieldMappings)) {
|
||||
mappingInfo[mappingKey] = {
|
||||
hasToJira: typeof fieldMappings[mappingKey].toJira,
|
||||
hasFromJira: typeof fieldMappings[mappingKey].fromJira,
|
||||
toJira: fieldMappings[mappingKey].toJira.toString().trim(),
|
||||
fromJira: fieldMappings[mappingKey].fromJira.toString().trim(),
|
||||
};
|
||||
}
|
||||
|
||||
console.debug(`Available mappings: ${JSON.stringify(mappingInfo)}`);
|
||||
console.debug(`Available mappings:`, mappingInfo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ interface AdfDoc {
|
|||
|
||||
function parseInline(text: string): AdfInlineContent[] {
|
||||
const nodes: AdfInlineContent[] = [];
|
||||
const regex = /(\*\*(.+?)\*\*|\*(.+?)\*|`([^`]+)`|\[([^\]]+)\]\(([^)]+)\)|\[\[[^\]]+\]\])/g;
|
||||
const regex = /(\*\*\*(.+?)\*\*\*|\*\*(.+?)\*\*|\*(.+?)\*|`([^`]+)`|\[([^\]]+)\]\(([^)]+)\)|\[\[[^\]]+\]\])/g;
|
||||
let lastIndex = 0;
|
||||
let match: RegExpExecArray | null;
|
||||
|
||||
|
|
@ -83,15 +83,18 @@ function parseInline(text: string): AdfInlineContent[] {
|
|||
nodes.push({ type: 'text', text: text.slice(lastIndex, match.index) });
|
||||
}
|
||||
if (match[2] !== undefined) {
|
||||
// ***bold+italic***
|
||||
nodes.push({ type: 'text', text: match[2], marks: [{ type: 'strong' }, { type: 'em' }] });
|
||||
} else if (match[3] !== undefined) {
|
||||
// **bold**
|
||||
nodes.push({ type: 'text', text: match[2], marks: [{ type: 'strong' }] });
|
||||
} else if (match[3] !== undefined) {
|
||||
} else if (match[4] !== undefined) {
|
||||
// *italic*
|
||||
nodes.push({ type: 'text', text: match[3], marks: [{ type: 'em' }] });
|
||||
} else if (match[4] !== undefined) {
|
||||
} else if (match[5] !== undefined) {
|
||||
// `code`
|
||||
nodes.push({ type: 'text', text: match[4], marks: [{ type: 'code' }] });
|
||||
} else if (match[5] !== undefined) {
|
||||
} else if (match[6] !== undefined) {
|
||||
// [text](url) — convert to ADF link mark
|
||||
nodes.push({ type: 'text', text: match[5], marks: [{ type: 'link', attrs: { href: match[6] } }] });
|
||||
} else {
|
||||
|
|
|
|||
Loading…
Reference in a new issue