Add selection mode and tag position settings

Support single-line or paragraph selection via a setting, and allow
the #ticktick tag to be appended or prepended. Defaults to single-line
+ append to fix list formatting issues.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
muxinli 2026-03-11 18:41:17 -05:00
parent 96f437edaf
commit 0d650629fe
2 changed files with 66 additions and 11 deletions

43
main.ts
View file

@ -12,6 +12,11 @@ function generateRandomString(length: number): string {
return text;
}
// Helper function to retrieve the current line where the cursor is located
function getCurrentLine(editor: Editor, line: number): { text: string, line: number } {
return { text: editor.getLine(line), line };
}
// Helper function to retrieve the paragraph (consecutive lines) where the cursor is located
function getParagraph(editor: Editor, currentLine: number): { text: string, start: number, end: number } {
let start = currentLine;
@ -78,34 +83,52 @@ export default class TickTickPlugin extends Plugin {
await this.loadSettings();
this.addSettingTab(new TickTickSettingTab(this.app, this));
// Command: Create TickTick task from a paragraph
// Command: Create TickTick task
this.addCommand({
id: 'create-ticktick-task',
name: 'Create TickTick task from paragraph',
name: 'Create TickTick task',
editorCallback: async (editor: Editor, view: MarkdownView) => {
const cursor = editor.getCursor();
if (!view.file) {
new Notice("No file found for the current view!");
return;
}
const { text: paragraphText, start, end } = getParagraph(editor, cursor.line);
if (!paragraphText) {
new Notice("No paragraph text found!");
// Get text based on selection mode setting
let taskText: string;
let rangeStart: number;
let rangeEnd: number;
if (this.settings.selectionMode === 'paragraph') {
const { text, start, end } = getParagraph(editor, cursor.line);
taskText = text;
rangeStart = start;
rangeEnd = end;
} else {
const { text, line } = getCurrentLine(editor, cursor.line);
taskText = text;
rangeStart = line;
rangeEnd = line;
}
if (!taskText.trim()) {
new Notice("No text found on the current line!");
return;
}
// Generate unique block anchor
const blockId = generateRandomString(8);
// Prepend "#ticktick" to the paragraph and append the block anchor
const updatedParagraph = `#ticktick ${paragraphText} ^${blockId}`;
editor.replaceRange(updatedParagraph, { line: start, ch: 0 }, { line: end, ch: editor.getLine(end).length });
// Apply tag based on tag position setting
const updatedText = this.settings.tagPosition === 'prepend'
? `#ticktick ${taskText} ^${blockId}`
: `${taskText} #ticktick ^${blockId}`;
editor.replaceRange(updatedText, { line: rangeStart, ch: 0 }, { line: rangeEnd, ch: editor.getLine(rangeEnd).length });
// Construct Advanced URI for the block
const vaultName = this.app.vault.getName();
const filePath = view.file.path;
const advancedUri = `obsidian://advanced-uri?vault=${encodeURIComponent(vaultName)}&filepath=${encodeURIComponent(filePath)}&block=${encodeURIComponent(blockId)}`;
const taskDescription = `${paragraphText}\n\n[Open in Obsidian](${advancedUri})`;
const taskTitle = paragraphText.length > 50 ? paragraphText.substring(0, 50) + "..." : paragraphText;
const taskDescription = `${taskText}\n\n[Open in Obsidian](${advancedUri})`;
const taskTitle = taskText.length > 50 ? taskText.substring(0, 50) + "..." : taskText;
await this.ensureFreshToken();

View file

@ -10,13 +10,17 @@ export interface TickTickSettings {
redirectUri?: string; // New field for redirect URI
tempCodeVerifier?: string;
tempState?: string;
selectionMode: 'line' | 'paragraph';
tagPosition: 'append' | 'prepend';
}
export const DEFAULT_SETTINGS: TickTickSettings = {
accessToken: '',
clientId: '',
clientSecret: '',
redirectUri: 'https://ticktick-quick-add-obsidian-6yawfmvnj-mooshs-projects-0635287d.vercel.app'
redirectUri: 'https://ticktick-quick-add-obsidian-6yawfmvnj-mooshs-projects-0635287d.vercel.app',
selectionMode: 'line',
tagPosition: 'append'
};
export class TickTickSettingTab extends PluginSettingTab {
@ -71,6 +75,34 @@ export class TickTickSettingTab extends PluginSettingTab {
})
);
new Setting(containerEl)
.setName('Selection mode')
.setDesc('Choose whether the command captures only the current line or the entire paragraph.')
.addDropdown(dropdown =>
dropdown
.addOption('line', 'Current line')
.addOption('paragraph', 'Entire paragraph')
.setValue(this.plugin.settings.selectionMode)
.onChange(async (value: string) => {
this.plugin.settings.selectionMode = value as 'line' | 'paragraph';
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName('Tag position')
.setDesc('Choose whether the #ticktick tag is added to the beginning or end of the text.')
.addDropdown(dropdown =>
dropdown
.addOption('append', 'Append (end)')
.addOption('prepend', 'Prepend (beginning)')
.setValue(this.plugin.settings.tagPosition)
.onChange(async (value: string) => {
this.plugin.settings.tagPosition = value as 'append' | 'prepend';
await this.plugin.saveSettings();
})
);
new Setting(containerEl)
.setName('Access token')
.setDesc('Your current access token (read-only).')