From ad06c8f4d804ab4cceb73ace76f5ebe17e3cadc3 Mon Sep 17 00:00:00 2001 From: Alamion Date: Wed, 3 Jun 2026 18:28:38 +0300 Subject: [PATCH] Fix: - `jira-sync-block-start-` docs fix - custom fields functions correct load on startup - jira values highlight rollback due to contributor dropped feature full realization. (In current state it's too buggy to release) --- docs/how_to_en.md | 4 +- docs/how_to_ru.md | 4 +- manifest.json | 2 +- package.json | 2 +- .../source/en/settings/general.yaml | 4 - .../source/ru/settings/general.yaml | 4 - src/main.ts | 11 ++- src/postprocessing/livePreview.ts | 74 ------------------- src/postprocessing/reading.ts | 65 +--------------- .../components/GeneralSettingsComponent.ts | 11 --- src/settings/default.ts | 2 - src/tools/convertFunctionString.ts | 8 +- styles.css | 15 ---- 13 files changed, 20 insertions(+), 186 deletions(-) diff --git a/docs/how_to_en.md b/docs/how_to_en.md index 5f6ff0d..7a38083 100644 --- a/docs/how_to_en.md +++ b/docs/how_to_en.md @@ -69,9 +69,9 @@ The responsible person for this task is `jira-sync-inline-start-assignee`Bob`jir Example: ```md -The responsible person for this task is `jira-sync-block-assignee` +The responsible person for this task is `jira-sync-block-start-assignee` Bob -`jira-sync-end`, and the description is `jira-sync-block-description` +`jira-sync-end`, and the description is `jira-sync-block-start-description` Some description `jira-sync-end`. ``` diff --git a/docs/how_to_ru.md b/docs/how_to_ru.md index 4ff68cb..9da95e2 100644 --- a/docs/how_to_ru.md +++ b/docs/how_to_ru.md @@ -68,9 +68,9 @@ Пример: ```md -Ответственным за эту задачу является `jira-sync-block-assignee` +Ответственным за эту задачу является `jira-sync-block-start-assignee` Bob -`jira-sync-end`, а описание — `jira-sync-block-description` +`jira-sync-end`, а описание — `jira-sync-block-start-description` Некоторое описание `jira-sync-end`. ``` diff --git a/manifest.json b/manifest.json index 2d2a9ce..5b1ae80 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "jira-sync", "name": "Jira Issue Manager", - "version": "1.7.0", + "version": "1.6.1", "minAppVersion": "1.10.1", "description": "Get Jira issues, create and update them. Issue status and worklog management.", "author": "Alamion", diff --git a/package.json b/package.json index 1f4ae18..22528b4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "obsidian-jira-sync", - "version": "1.7.0", + "version": "1.6.1", "packageManager": "yarn@1.22.22", "description": "This is a sample plugin for Obsidian (https://obsidian.md)", "main": "main.js", diff --git a/src/localization/source/en/settings/general.yaml b/src/localization/source/en/settings/general.yaml index 3170816..845408e 100644 --- a/src/localization/source/en/settings/general.yaml +++ b/src/localization/source/en/settings/general.yaml @@ -5,10 +5,6 @@ folder: desc: Folder where Jira issues will be stored and searched for placeholder: Jira Issues -highlight: - name: Highlight sync sections - desc: Highlight jira-sync-(line | inline | block) sections in file content. Reopen notes after toggling to see changes. - template: name: Template path desc: Select a template file for creating Jira tasks diff --git a/src/localization/source/ru/settings/general.yaml b/src/localization/source/ru/settings/general.yaml index 7625a22..6464133 100644 --- a/src/localization/source/ru/settings/general.yaml +++ b/src/localization/source/ru/settings/general.yaml @@ -5,10 +5,6 @@ folder: desc: Папка, в которой будут создаваться и искаться задачи Jira placeholder: Jira Issues -highlight: - name: Подсвечивать синхронизируемые разделы - desc: Подсвечивать jira-sync-(line | inline | block) разделы в файле. Переоткройте файл после переключения настройки чтобы увидеть изменения. - template: name: Путь к шаблону desc: Выберите файл шаблона для создания задач Jira diff --git a/src/main.ts b/src/main.ts index 9ed5a5b..72681c5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -47,7 +47,7 @@ export default class JiraPlugin extends Plugin { this.addSettingTab(new JiraSettingTab(this.app, this)); // Handle Reading mode (post-processor for rendered markdown) - this.registerMarkdownPostProcessor(hideJiraPointersReading(this)); + this.registerMarkdownPostProcessor(hideJiraPointersReading()); // Handle Live Preview/Edit mode (CodeMirror extension) this.registerEditorExtension(createJiraSyncExtension(this)); @@ -61,7 +61,14 @@ export default class JiraPlugin extends Plugin { // TODO: Cancel and delete migration check in future (approximately 2026-2027) const new_data = checkMigrateSettings(old_data, this.saveSettings); - this.settings = Object.assign({}, DEFAULT_SETTINGS, new_data); + this.settings = { + ...DEFAULT_SETTINGS, + ...new_data, + fieldMapping: { + ...DEFAULT_SETTINGS.fieldMapping, + ...(new_data?.fieldMapping || {}), + }, + }; this.settings.fieldMapping.fieldMappings = await transform_string_to_functions_mappings( this.settings.fieldMapping.fieldMappingsStrings, ); diff --git a/src/postprocessing/livePreview.ts b/src/postprocessing/livePreview.ts index 299a5d9..fae36ab 100644 --- a/src/postprocessing/livePreview.ts +++ b/src/postprocessing/livePreview.ts @@ -31,14 +31,10 @@ export function createJiraSyncExtension(plugin: JiraPlugin): Extension { buildDecorations(view: EditorView) { const builder = new RangeSetBuilder(); - const isHighlight = plugin.settings.global.highlightSyncSections; const sel = view.state.selection; const allDecs: Array<{ from: number; to: number; dec: Decoration }> = []; - // Scan full document for block pairs so long blocks work when scrolled - const blockRanges = isHighlight ? this.findBlockRanges(view) : []; - for (let { from, to } of view.visibleRanges) { const text = view.state.doc.sliceString(from, to); const codeBlocks = this.findCodeBlocks(text, from); @@ -59,52 +55,6 @@ export function createJiraSyncExtension(plugin: JiraPlugin): Extension { const cls = isActive ? 'jira-sync-hidden jira-sync-active' : 'jira-sync-hidden'; allDecs.push({ from: start, to: end, dec: Decoration.mark({ class: cls }) }); } - - if (!isHighlight) continue; - - // Inline content: `jira-sync-inline-start-*` ... `jira-sync-end` - for (let i = 0; i < markers.length; i++) { - const m = markers[i]; - if (!m.name.startsWith('jira-sync-inline-start-')) continue; - const endMarker = markers.find((em, j) => j > i && em.name === 'jira-sync-end'); - if (!endMarker || endMarker.start <= m.end) continue; - allDecs.push({ - from: m.end, - to: endMarker.start, - dec: Decoration.mark({ class: 'jira-sync-content' }), - }); - } - - // Line content: `jira-sync-line-*` followed by text to end of line - for (const m of markers) { - if (!m.name.startsWith('jira-sync-line-')) continue; - const line = view.state.doc.lineAt(m.end); - const nextOnLine = markers.find((nm) => nm.start > m.end && nm.start <= line.to); - const contentEnd = nextOnLine ? nextOnLine.start : line.to; - if (contentEnd > m.end) { - allDecs.push({ - from: m.end, - to: contentEnd, - dec: Decoration.mark({ class: 'jira-sync-content' }), - }); - } - } - - // Block content: decorate visible lines that fall within a full-document block range - const firstVisLine = view.state.doc.lineAt(from).number; - const lastVisLine = view.state.doc.lineAt(to).number; - for (const { startLine, endLine } of blockRanges) { - const decorStart = Math.max(startLine + 1, firstVisLine); - const decorEnd = Math.min(endLine - 1, lastVisLine); - for (let lineNum = decorStart; lineNum <= decorEnd; lineNum++) { - const line = view.state.doc.line(lineNum); - allDecs.push({ - from: line.from, - to: line.from, - dec: Decoration.line({ class: 'jira-sync-block-content' }), - }); - } - } } // RangeSetBuilder requires ranges in ascending order of `from`, then `to` @@ -116,30 +66,6 @@ export function createJiraSyncExtension(plugin: JiraPlugin): Extension { return builder.finish() as DecorationSet; } - findBlockRanges(view: EditorView): Array<{ startLine: number; endLine: number }> { - const fullText = view.state.doc.toString(); - const codeBlocks = this.findCodeBlocks(fullText, 0); - const ranges: Array<{ startLine: number; endLine: number }> = []; - const blockStarts: Array<{ pos: number }> = []; - - for (const match of fullText.matchAll(/`(jira-sync-[^`]+)`/g)) { - const start = match.index!; - const end = start + match[0].length; - if (this.isInsideCodeBlock(start, end, codeBlocks)) continue; - const name = match[1]; - if (name.startsWith('jira-sync-block-start-')) { - blockStarts.push({ pos: end }); - } else if (name === 'jira-sync-end' && blockStarts.length > 0) { - const bs = blockStarts.pop()!; - const startLine = view.state.doc.lineAt(bs.pos).number; - const endLine = view.state.doc.lineAt(start).number; - ranges.push({ startLine, endLine }); - } - } - - return ranges; - } - findCodeBlocks(text: string, offset: number) { const blocks = []; const regex = /```[\s\S]*?```/g; diff --git a/src/postprocessing/reading.ts b/src/postprocessing/reading.ts index ae35c3b..a712261 100644 --- a/src/postprocessing/reading.ts +++ b/src/postprocessing/reading.ts @@ -1,75 +1,12 @@ -import JiraPlugin from '../main'; - -export function hideJiraPointersReading(plugin: JiraPlugin) { +export function hideJiraPointersReading() { // eslint-disable-next-line @typescript-eslint/no-unused-vars return function (element: HTMLElement, _: any) { - const isHighlight = plugin.settings.global.highlightSyncSections; const codeElements = Array.from(element.querySelectorAll(':not(pre) > code')).filter((el) => el.textContent?.startsWith('jira-sync-'), ) as HTMLElement[]; for (const codeEl of codeElements) { - const text = codeEl.textContent || ''; codeEl.addClass('jira-sync-hidden'); - - if (!isHighlight) continue; - - if (text.startsWith('jira-sync-inline-start-')) { - wrapContentBetween(codeEl, 'jira-sync-end'); - } else if (text.startsWith('jira-sync-line-')) { - wrapContentAfter(codeEl); - } } }; } - -// Wrap sibling nodes between this element and the next jira-sync-end code element -function wrapContentBetween(startEl: HTMLElement, endMarker: string) { - const parent = startEl.parentElement; - if (!parent) return; - - const nodesToWrap: Node[] = []; - let node: Node | null = startEl.nextSibling; - - while (node) { - if (node.nodeType === Node.ELEMENT_NODE) { - const el = node as HTMLElement; - if (el.tagName === 'CODE' && (el.textContent || '').startsWith(endMarker)) break; - } - nodesToWrap.push(node); - node = node.nextSibling; - } - - if (nodesToWrap.length === 0) return; - const wrapper = createSpanWrapper(parent, nodesToWrap[0]); - for (const n of nodesToWrap) wrapper.appendChild(n); -} - -// Wrap all sibling nodes after this element (until next jira-sync marker) -function wrapContentAfter(lineEl: HTMLElement) { - const parent = lineEl.parentElement; - if (!parent) return; - - const nodesToWrap: Node[] = []; - let node: Node | null = lineEl.nextSibling; - - while (node) { - if (node.nodeType === Node.ELEMENT_NODE) { - const el = node as HTMLElement; - if (el.tagName === 'CODE' && (el.textContent || '').startsWith('jira-sync-')) break; - } - nodesToWrap.push(node); - node = node.nextSibling; - } - - if (nodesToWrap.length === 0) return; - const wrapper = createSpanWrapper(parent, nodesToWrap[0]); - for (const n of nodesToWrap) wrapper.appendChild(n); -} - -function createSpanWrapper(parent: HTMLElement, insertBefore: Node): HTMLElement { - const wrapper = document.createElement('span'); - wrapper.addClass('jira-sync-content'); - parent.insertBefore(wrapper, insertBefore); - return wrapper; -} diff --git a/src/settings/components/GeneralSettingsComponent.ts b/src/settings/components/GeneralSettingsComponent.ts index 86ab99b..b24c024 100644 --- a/src/settings/components/GeneralSettingsComponent.ts +++ b/src/settings/components/GeneralSettingsComponent.ts @@ -38,17 +38,6 @@ export class GeneralSettingsComponent implements SettingsComponent { new FolderSuggest(plugin.app, search.inputEl, onChange); }); - // Highlight sync sections toggle - new Setting(containerEl) - .setName(t('highlight.name')) - .setDesc(t('highlight.desc')) - .addToggle((toggle) => - toggle.setValue(plugin.settings.global.highlightSyncSections).onChange(async (value) => { - plugin.settings.global.highlightSyncSections = value; - await plugin.saveSettings(); - }), - ); - // Template path setting with native search const templateInfo = this.detectTemplatePlugins(plugin.app); diff --git a/src/settings/default.ts b/src/settings/default.ts index b16495f..8e07765 100644 --- a/src/settings/default.ts +++ b/src/settings/default.ts @@ -14,7 +14,6 @@ export interface ConnectionSettingsInterface { export interface GlobalSettingsInterface { issuesFolder: string; templatePath: string; - highlightSyncSections: boolean; } export interface FieldMappingSettingsInterface { @@ -86,7 +85,6 @@ export const DEFAULT_SETTINGS: JiraSettingsInterface = { global: { issuesFolder: 'jira-issues', templatePath: '', - highlightSyncSections: false, }, fieldMapping: { diff --git a/src/tools/convertFunctionString.ts b/src/tools/convertFunctionString.ts index cff5130..dbee388 100644 --- a/src/tools/convertFunctionString.ts +++ b/src/tools/convertFunctionString.ts @@ -340,13 +340,13 @@ export async function transform_string_to_functions_mappings( // Also convert to functions for runtime use const transformedMappings: Record = {}; for (const [fieldName, { toJira, fromJira }] of Object.entries(mappings)) { - const toJiraFn = safeStringToFunction(toJira, 'toJira', extraValidate); - const fromJiraFn = safeStringToFunction(fromJira, 'fromJira', extraValidate); + const toJiraFn = await safeStringToFunction(toJira, 'toJira', extraValidate); + const fromJiraFn = await safeStringToFunction(fromJira, 'fromJira', extraValidate); if (toJiraFn && fromJiraFn) { transformedMappings[fieldName] = { - toJira: (await toJiraFn) as (value: any, api_version?: '2' | '3') => any, - fromJira: (await fromJiraFn) as ( + toJira: toJiraFn as (value: any, api_version?: '2' | '3') => any, + fromJira: fromJiraFn as ( issue: JiraIssue, api_version?: '2' | '3', data_source?: Record, diff --git a/styles.css b/styles.css index 4ed9b79..b69fd0a 100644 --- a/styles.css +++ b/styles.css @@ -947,21 +947,6 @@ code.hljs { padding: 0 !important; } -/* Inline / line synced content highlight */ -.jira-sync-content { - background: color-mix(in srgb, var(--interactive-accent) 12%, transparent); - border-radius: 3px; - padding: 0 2px; - outline: 1px solid color-mix(in srgb, var(--interactive-accent) 35%, transparent); - outline-offset: 1px; -} - -/* Block content lines — left accent border */ -.jira-sync-block-content { - box-shadow: inset 3px 0 0 var(--interactive-accent) !important; - background: color-mix(in srgb, var(--interactive-accent) 5%, transparent) !important; -} - /* JQL Preview Container */ .jql-preview-container { margin-top: 1rem;