Skip to content

Commit b9401dd

Browse files
authored
Merge pull request #9 from QoderAI/fix/obsidian-review-createel
Fix/obsidian review createel
2 parents ec90b9c + 069c169 commit b9401dd

17 files changed

Lines changed: 255 additions & 212 deletions

File tree

eslint.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const stagedObsidianRules = {
3434
'obsidianmd/platform': obsidianRuleSeverity,
3535
'obsidianmd/prefer-abstract-input-suggest': obsidianRuleSeverity,
3636
'obsidianmd/prefer-active-doc': obsidianRuleSeverity,
37+
'obsidianmd/prefer-create-el': obsidianRuleSeverity,
3738
'obsidianmd/prefer-file-manager-trash-file': obsidianRuleSeverity,
3839
'obsidianmd/prefer-get-language': obsidianRuleSeverity,
3940
'obsidianmd/prefer-instanceof': obsidianRuleSeverity,

package-lock.json

Lines changed: 27 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"esbuild": "0.28.1",
4343
"eslint": "^10.2.0",
4444
"eslint-plugin-jest": "^29.15.1",
45-
"eslint-plugin-obsidianmd": "^0.3.0",
45+
"eslint-plugin-obsidianmd": "^0.4.1",
4646
"eslint-plugin-simple-import-sort": "^12.1.1",
4747
"jest": "^30.3.0",
4848
"jest-environment-jsdom": "^30.3.0",

src/features/chat/chat-view.ts

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -219,12 +219,9 @@ export class QoderianView extends ItemView {
219219
* The wrapper is moved to the active tab's nav row on tab switches.
220220
*/
221221
private buildNavRowContent(): HTMLElement {
222-
const activeDocument = this.containerEl.ownerDocument;
223-
224-
const fragment = activeDocument.createDocumentFragment();
222+
const wrapper = createDiv({ cls: 'qoderian-input-nav-content' });
225223

226-
this.tabBarContainerEl = activeDocument.createElement('div');
227-
this.tabBarContainerEl.className = 'qoderian-tab-bar-container';
224+
this.tabBarContainerEl = wrapper.createDiv({ cls: 'qoderian-tab-bar-container' });
228225
this.tabBar = new TabBar(this.tabBarContainerEl, {
229226
onTabClick: (tabId) => this.handleTabClick(tabId),
230227
onTabClose: (tabId) => {
@@ -234,10 +231,8 @@ export class QoderianView extends ItemView {
234231
void this.createNewTab().catch(() => new Notice('Failed to create tab'));
235232
},
236233
});
237-
fragment.appendChild(this.tabBarContainerEl);
238234

239-
const navActionsEl = activeDocument.createElement('div');
240-
navActionsEl.className = 'qoderian-input-nav-actions';
235+
const navActionsEl = wrapper.createDiv({ cls: 'qoderian-input-nav-actions' });
241236

242237
this.newTabButtonEl = navActionsEl.createDiv({ cls: 'qoderian-input-nav-btn qoderian-new-tab-btn' });
243238
setIcon(this.newTabButtonEl, 'square-plus');
@@ -269,11 +264,6 @@ export class QoderianView extends ItemView {
269264
this.toggleHistoryDropdown();
270265
});
271266

272-
fragment.appendChild(navActionsEl);
273-
274-
const wrapper = activeDocument.createElement('div');
275-
wrapper.className = 'qoderian-input-nav-content';
276-
wrapper.appendChild(fragment);
277267
return wrapper;
278268
}
279269

src/features/chat/controllers/conversation-controller.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ export class ConversationController {
659659

660660
// Show regenerate button if title generation failed, or loading indicator if pending
661661
if (conv.titleGenerationStatus === 'pending') {
662-
const loadingEl = actions.createEl('span', { cls: 'qoderian-action-btn qoderian-action-loading' });
662+
const loadingEl = actions.createSpan({ cls: 'qoderian-action-btn qoderian-action-loading' });
663663
setIcon(loadingEl, 'loader-2');
664664
loadingEl.setAttribute('aria-label', 'Generating title...');
665665
} else if (conv.titleGenerationStatus === 'failed') {
@@ -874,9 +874,7 @@ export class ConversationController {
874874
const titleEl = item.querySelector('.qoderian-history-item-title') as HTMLElement;
875875
if (!titleEl) return;
876876

877-
const input = (item.ownerDocument ?? window.document).createElement('input');
878-
input.type = 'text';
879-
input.className = 'qoderian-rename-input';
877+
const input = item.createEl('input', { cls: 'qoderian-rename-input', type: 'text' });
880878
input.value = currentTitle;
881879

882880
titleEl.replaceWith(input);

src/features/chat/rendering/message-renderer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -660,7 +660,7 @@ export class MessageRenderer {
660660
if (pre.parentElement?.classList.contains('qoderian-code-wrapper')) return;
661661

662662
// Create wrapper
663-
const wrapper = createEl('div', { cls: 'qoderian-code-wrapper' });
663+
const wrapper = createDiv({ cls: 'qoderian-code-wrapper' });
664664
pre.parentElement?.insertBefore(wrapper, pre);
665665
wrapper.appendChild(pre);
666666

@@ -670,7 +670,7 @@ export class MessageRenderer {
670670
const match = code.className.match(/language-(\w+)/);
671671
if (match) {
672672
wrapper.classList.add('has-language');
673-
const label = createEl('span', {
673+
const label = createSpan({
674674
cls: 'qoderian-code-lang-label',
675675
text: match[1],
676676
});

src/features/chat/ui/image-context.ts

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -86,27 +86,19 @@ export class ImageContextManager {
8686

8787
this.dropOverlay = inputWrapper.createDiv({ cls: 'qoderian-drop-overlay' });
8888
const dropContent = this.dropOverlay.createDiv({ cls: 'qoderian-drop-content' });
89-
const ownerDocument = inputWrapper.ownerDocument ?? window.document;
90-
const svg = ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'svg');
91-
svg.setAttribute('viewBox', '0 0 24 24');
92-
svg.setAttribute('width', '32');
93-
svg.setAttribute('height', '32');
94-
svg.setAttribute('fill', 'none');
95-
svg.setAttribute('stroke', 'currentColor');
96-
svg.setAttribute('stroke-width', '2');
97-
const pathEl = ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'path');
98-
pathEl.setAttribute('d', 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4');
99-
const polyline = ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'polyline');
100-
polyline.setAttribute('points', '17 8 12 3 7 8');
101-
const line = ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'line');
102-
line.setAttribute('x1', '12');
103-
line.setAttribute('y1', '3');
104-
line.setAttribute('x2', '12');
105-
line.setAttribute('y2', '15');
106-
svg.appendChild(pathEl);
107-
svg.appendChild(polyline);
108-
svg.appendChild(line);
109-
dropContent.appendChild(svg);
89+
const svg = dropContent.createSvg('svg', {
90+
attr: {
91+
viewBox: '0 0 24 24',
92+
width: '32',
93+
height: '32',
94+
fill: 'none',
95+
stroke: 'currentColor',
96+
'stroke-width': '2',
97+
},
98+
});
99+
svg.createSvg('path', { attr: { d: 'M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4' } });
100+
svg.createSvg('polyline', { attr: { points: '17 8 12 3 7 8' } });
101+
svg.createSvg('line', { attr: { x1: '12', y1: '3', x2: '12', y2: '15' } });
110102
dropContent.createSpan({ text: 'Drop image here' });
111103

112104
const dropZone = inputWrapper;

src/features/chat/ui/input-toolbar.ts

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -649,31 +649,36 @@ export class ContextUsageMeter {
649649
const y2 = cy + radius * Math.sin(endRad);
650650

651651
const gaugeEl = this.container.createDiv({ cls: 'qoderian-context-meter-gauge' });
652-
const svg = gaugeEl.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'svg');
653-
svg.setAttribute('width', String(size));
654-
svg.setAttribute('height', String(size));
655-
svg.setAttribute('viewBox', `0 0 ${size} ${size}`);
652+
const svg = gaugeEl.createSvg('svg', {
653+
attr: {
654+
width: String(size),
655+
height: String(size),
656+
viewBox: `0 0 ${size} ${size}`,
657+
},
658+
});
656659

657660
const pathData = `M ${x1} ${y1} A ${radius} ${radius} 0 1 1 ${x2} ${y2}`;
658-
const backgroundPath = gaugeEl.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'path');
659-
backgroundPath.classList.add('qoderian-meter-bg');
660-
backgroundPath.setAttribute('d', pathData);
661-
backgroundPath.setAttribute('fill', 'none');
662-
backgroundPath.setAttribute('stroke-width', String(strokeWidth));
663-
backgroundPath.setAttribute('stroke-linecap', 'round');
664-
665-
const fillPath = gaugeEl.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'path');
666-
fillPath.classList.add('qoderian-meter-fill');
667-
fillPath.setAttribute('d', pathData);
668-
fillPath.setAttribute('fill', 'none');
669-
fillPath.setAttribute('stroke-width', String(strokeWidth));
670-
fillPath.setAttribute('stroke-linecap', 'round');
671-
fillPath.setAttribute('stroke-dasharray', String(this.circumference));
672-
fillPath.setAttribute('stroke-dashoffset', String(this.circumference));
673-
674-
svg.appendChild(backgroundPath);
675-
svg.appendChild(fillPath);
676-
gaugeEl.appendChild(svg);
661+
svg.createSvg('path', {
662+
cls: 'qoderian-meter-bg',
663+
attr: {
664+
d: pathData,
665+
fill: 'none',
666+
'stroke-width': String(strokeWidth),
667+
'stroke-linecap': 'round',
668+
},
669+
});
670+
671+
const fillPath = svg.createSvg('path', {
672+
cls: 'qoderian-meter-fill',
673+
attr: {
674+
d: pathData,
675+
fill: 'none',
676+
'stroke-width': String(strokeWidth),
677+
'stroke-linecap': 'round',
678+
'stroke-dasharray': String(this.circumference),
679+
'stroke-dashoffset': String(this.circumference),
680+
},
681+
});
677682
this.fillPath = fillPath;
678683

679684
this.percentEl = this.container.createSpan({ cls: 'qoderian-context-meter-percent' });

0 commit comments

Comments
 (0)