This template enhances the conceptLinker system to automatically find and link poll objects in discussions.
{{#script}}
```js
// Enhanced poll discovery and linking system
async function findPollObjects() {
const polls = [];
try {
// Check if polls directory exists
const pollsDir = 'polls';
if (await app.vault.adapter.exists(pollsDir)) {
const pollFiles = await app.vault.adapter.list(pollsDir);
for (const file of pollFiles.files) {
if (file.endsWith('.md') && !file.endsWith('polls-index.md')) {
try {
const content = await app.vault.adapter.read(file);
const poll = parsePollFromContent(content, file);
if (poll) {
polls.push(poll);
}
} catch (error) {
console.warn(`Could not read poll file ${file}:`, error);
}
}
}
}
// Also search for polls in current directory
const currentFile = app.workspace.getActiveFile();
if (currentFile?.parent) {
const currentDir = currentFile.parent.path;
const localPollsDir = `${currentDir}/polls`;
if (await app.vault.adapter.exists(localPollsDir)) {
const localPollFiles = await app.vault.adapter.list(localPollsDir);
for (const file of localPollFiles.files) {
if (file.endsWith('.md') && !file.endsWith('polls-index.md')) {
try {
const content = await app.vault.adapter.read(file);
const poll = parsePollFromContent(content, file);
if (poll) {
polls.push(poll);
}
} catch (error) {
console.warn(`Could not read local poll file ${file}:`, error);
}
}
}
}
}
} catch (error) {
console.error('Error finding poll objects:', error);
}
return polls;
}
function parsePollFromContent(content, filePath) {
try {
// Extract frontmatter
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
if (!frontmatterMatch) return null;
const frontmatter = frontmatterMatch[1];
const pollIdMatch = frontmatter.match(/pollId:\s*(.+)/);
const titleMatch = frontmatter.match(/title:\s*(.+)/);
const typeMatch = frontmatter.match(/type:\s*(.+)/);
if (!pollIdMatch || typeMatch?.[1] !== 'poll') return null;
const pollId = pollIdMatch[1].trim();
const title = titleMatch?.[1]?.trim() || pollId;
// Extract description from content
const bodyContent = content.replace(/^---\n[\s\S]*?\n---/, '').trim();
const descriptionMatch = bodyContent.match(/# [^\n]+\n\n([^\n]+)/);
const description = descriptionMatch?.[1] || '';
return {
id: pollId,
title: title,
description: description,
filePath: filePath,
linkText: `[[${pollId}|${title}]]`
};
} catch (error) {
console.warn('Error parsing poll content:', error);
return null;
}
}
async function findRelevantPolls(text, polls) {
const relevantPolls = [];
const words = text.toLowerCase().split(/\s+/);
for (const poll of polls) {
const pollWords = (poll.title + ' ' + poll.description).toLowerCase().split(/\s+/);
// Calculate relevance score
let score = 0;
for (const word of words) {
if (word.length > 3) { // Skip short words
for (const pollWord of pollWords) {
if (pollWord.includes(word) || word.includes(pollWord)) {
score++;
}
}
}
}
// Check for specific poll-related keywords
const pollKeywords = ['vote', 'poll', 'survey', 'opinion', 'decide', 'choice', 'select'];
for (const keyword of pollKeywords) {
if (text.toLowerCase().includes(keyword)) {
score += 2;
}
}
if (score > 0) {
relevantPolls.push({
...poll,
relevanceScore: score
});
}
}
// Sort by relevance score
return relevantPolls.sort((a, b) => b.relevanceScore - a.relevanceScore);
}
async function enhanceTextWithPollLinks(text) {
const polls = await findPollObjects();
if (polls.length === 0) {
return {
enhancedText: text,
foundPolls: [],
message: "No poll objects found. Create polls using the pollCreator template."
};
}
const relevantPolls = await findRelevantPolls(text, polls);
if (relevantPolls.length === 0) {
return {
enhancedText: text,
foundPolls: polls,
message: `Found ${polls.length} poll(s) but none are relevant to this discussion.`
};
}
// Add poll links section to the text
const pollLinksSection = `
## 📊 Related Polls
${relevantPolls.map(poll =>
`- ${poll.linkText} - ${poll.description}`
).join('\n')}
---
*Auto-linked polls based on discussion content*`;
return {
enhancedText: text + pollLinksSection,
foundPolls: polls,
relevantPolls: relevantPolls,
message: `Enhanced discussion with ${relevantPolls.length} relevant poll link(s).`
};
}
// Main execution
async function processPollLinking() {
const selection = `{{tg_selection}}`.trim();
if (!selection) {
const polls = await findPollObjects();
return `# Poll Linker
## Available Poll Objects
${polls.length > 0 ?
polls.map(poll => `- ${poll.linkText} - ${poll.description}`).join('\n') :
'No poll objects found. Create some using the pollCreator template.'
}
## Usage
Select text from a discussion and run this template to automatically find and link relevant polls.
## Status
- **Total Polls Found**: ${polls.length}
- **Poll Discovery**: ${polls.length > 0 ? '✅ Working' : '❌ No objects found'}
- **Linking System**: ✅ Active`;
}
const result = await enhanceTextWithPollLinks(selection);
return `# Poll Linking Results
${result.message}
## Enhanced Text
${result.enhancedText}
## Discovery Summary
- **Total Polls Available**: ${result.foundPolls.length}
- **Relevant Polls Found**: ${result.relevantPolls?.length || 0}
- **Status**: ${result.foundPolls.length > 0 ? '✅ Objects found and linking working' : '❌ No objects found - create polls first'}
${result.relevantPolls?.length > 0 ? `
## Linked Polls Details
${result.relevantPolls.map(poll =>
`### ${poll.title}
- **ID**: \`${poll.id}\`
- **Relevance Score**: ${poll.relevanceScore}
- **Link**: ${poll.linkText}
- **Description**: ${poll.description}`
).join('\n\n')}` : ''}`;
}
return await processPollLinking();
{{/script}} ```
{{get "script"}}