I wanna autogenerate block-ids without searching for a block

Autogeneration is rather vague…
I am using this script to add an auto-generated blockID to a paragraph/line by running the script myself (so it’s more like semi-auto):

import * as obsidian from 'obsidian';

const blockIdCreator = async (app: obsidian.App): Promise<void> => {
    const editor = app.workspace.activeLeaf?.view?.editor;
    const currentFile = app.workspace.getActiveFile();
    
    if (!editor || !currentFile) return;
    
    let selection = editor.getSelection();
    const hasSelection = selection.length > 0;
    console.log("Has selection:", hasSelection);
    
    // If no selection, get the current line at cursor position
    if (!hasSelection) {
        const cursor = editor.getCursor();
        const line = editor.getLine(cursor.line);
        selection = line;
        console.log("Using current line:", selection);
    }

    // Get the entire file content to check for existing block IDs
    const fileContent = await app.vault.read(currentFile);
    const selectionIndex = fileContent.indexOf(selection);
    
    if (selectionIndex === -1) {
        console.log("Selection not found in file content.");
        return;
    }
    
    // Check if there's a block ID right after the selection in the file
    const textAfterSelection = fileContent.substring(selectionIndex + selection.length);
    const nextLineBlockIdMatch = textAfterSelection.match(/^\s*\n\^([a-zA-Z0-9-]+)/);
    const inlineBlockIdMatch = textAfterSelection.match(/^\s\^([a-zA-Z0-9-]+)/);
    
    // If an existing block ID is found, use it
    if (nextLineBlockIdMatch || inlineBlockIdMatch) {
        const existingBlockId = (nextLineBlockIdMatch || inlineBlockIdMatch)[1];
        console.log("Existing block ID found:", existingBlockId);
        
        const clipboardText = `![[${currentFile.basename}#^${existingBlockId}]]`;
        await navigator.clipboard.writeText(clipboardText);
        new obsidian.Notice(`Link ${clipboardText} has been added to the clipboard`);
        return;
    }

    // Regex to match Zotero links
    const zoteroRegex = /items\/([A-Z0-9]{6,10}).*?annotation=([A-Z0-9]{6,10})/g;
    // Check for inline block ID
    const blockIdInlineRegex = /\s\^([a-zA-Z0-9-]+)(?:\s|$)/;
    
    // Check for inline block ID in the selection
    const selectionInlineBlockId = selection.match(blockIdInlineRegex);
    if (selectionInlineBlockId) {
        console.log("Selection already has inline block ID:", selectionInlineBlockId[1]);
        const clipboardText = `![[${currentFile.basename}#^${selectionInlineBlockId[1]}]]`;
        await navigator.clipboard.writeText(clipboardText);
        new obsidian.Notice(`Link ${clipboardText} has been added to the clipboard`);
        return;
    }

    const allMatches = [...selection.matchAll(zoteroRegex)];

    if (allMatches.length > 0) {
        let createdBlockIds = [];
        // Split by paragraphs while preserving line breaks
        const paragraphs = selection.split(/\n{2,}/);
        
        const updatedParagraphs = paragraphs.map(paragraph => {
            // Check if this paragraph already has an inline block ID
            const existingBlockId = paragraph.match(blockIdInlineRegex);
            if (existingBlockId) {
                console.log("Paragraph already has inline block ID:", existingBlockId[1]);
                createdBlockIds.push(existingBlockId[1]);
                return paragraph; // Keep paragraph unchanged
            }
            
            // No existing block ID found, process for Zotero links
            zoteroRegex.lastIndex = 0;
            const match = zoteroRegex.exec(paragraph);
            if (match) {
                const combinedId = `${match[1]}-${match[2]}`;
                createdBlockIds.push(combinedId);
                
                // Add the block ID to the end of the paragraph
                return `${paragraph.trim()} ^${combinedId}`;
            }
            
            return paragraph;
        });

        // Replace the selection or the current line
        if (hasSelection) {
            editor.replaceSelection(updatedParagraphs.join('\n\n'));
        } else {
            const cursor = editor.getCursor();
            editor.setLine(cursor.line, updatedParagraphs[0]);
        }

        if (createdBlockIds.length === 1 && !currentFile.basename.startsWith('@')) {
            const clipboardText = `![[${currentFile.basename}#^${createdBlockIds[0]}]]`;
            await navigator.clipboard.writeText(clipboardText);
            new obsidian.Notice(`Link ${clipboardText} has been added to the clipboard`);
        } else if (createdBlockIds.length > 1) {
            new obsidian.Notice('Multiple block IDs created. No link added to the clipboard.');
        }
    } else {
        // Handle regular text without Zotero links
        // Remove trailing whitespace
        selection = selection.replace(/\s+$/, '');
        
        // Generate random block ID
        const randomBlockId = Array(6).fill(0)
            .map(() => 'abcdefghijklmnopqrstuvwxyz0123456789'
            .charAt(Math.floor(Math.random() * 36))).join('');
        
        // Add the block ID to the text
        const newText = `${selection} ^${randomBlockId}`;
        
        // Replace the selection or the current line
        if (hasSelection) {
            editor.replaceSelection(newText);
        } else {
            const cursor = editor.getCursor();
            editor.setLine(cursor.line, newText);
        }
        
        const clipboardText = `![[${currentFile.basename}#^${randomBlockId}]]`;
        await navigator.clipboard.writeText(clipboardText);
        new obsidian.Notice(`Link ${clipboardText} has been added to the clipboard`);
    }
};

export class BlockIdCreatorPlugin extends obsidian.Plugin {
    async onload() {
        this.addCommand({
            id: 'block-id-creator',
            name: 'Block ID Creator',
            callback: () => blockIdCreator(this.app)
        });
    }
}

export async function invoke(app: obsidian.App): Promise<void> {
    return blockIdCreator(app);
}

Select line/paragraph and run the script. You can just put the cursor on the line without selecting anything and it will still work.
If the line contains a Zotero annotation link, the blockID will be made up of the item ID, otherwise a random ID will be generated. If the blockID was already created (on the same line or the next line), it copies it to the clipboard.

  • Multiple blockID’s are only created when the lines contain Zotero item ID’s. Then the clipboard will not be populated with multiple links.

Save code as Create-BlockID.ts or something (doesn’t matter actually but it must end with .ts and name it so you find the script by the name you set when it comes to assigning hotkeys).

You’ll need the CodeScript Toolkit plugin that will automatically load the .ts file, you just need to add in the settings, which folder it will look for, as I showed in this post with screenshots.