Skip to content

Instantly share code, notes, and snippets.

@pedramamini
Created June 18, 2025 18:13
Show Gist options
  • Save pedramamini/969ad042d8aa774e5c2ecb69bce1bfe1 to your computer and use it in GitHub Desktop.
Save pedramamini/969ad042d8aa774e5c2ecb69bce1bfe1 to your computer and use it in GitHub Desktop.
// This is the legend code. Add this after your existing table code.

// Add custom CSS for the legend
const legendCSS = `
<style>
    .legend-container {
        text-align: right;
        margin-top: 10px;
        font-size: 0.9em;
        color: #888;
    }
    .legend-item {
        margin-left: 10px;
    }
    .legend-code {
        font-family: monospace;
        background-color: #444;
        padding: 1px 3px;
        border-radius: 3px;
        color: #fff;
    }
</style>
`;

// Render the custom CSS for the legend
dv.container.innerHTML += legendCSS;

// Create and render the legend
const legendHTML = `
<div class="legend-container">
    <span class="legend-item"><span class="legend-code">H</span>ighlights</span>
    <span class="legend-item">Action <span class="legend-code">I</span>tems</span>
    <span class="legend-item"><span class="legend-code">A</span>ctions</span>
    <span class="legend-item">(<span class="legend-code">V</span>alue <span class="legend-code">P</span>er <span class="legend-code">M</span>inute)</span>
</div>
`;

dv.container.innerHTML += legendHTML;

async function main() {
  const folderPath = "Content Farm/Web";

  // Filter out inbox and archive entries
  let pages = dv.pages(`"${folderPath}"`).filter(p => {
    if (p.file.name === "📇 Web Inbox") return false;
    const filePath = p.file.path || p.file.folder;
    return filePath && !filePath.includes("Archive");
  });

  // Highlight checker
  function hasHighlights(content) {
    if (typeof content === "string") return content.includes("==");
    if (typeof content === "object") return JSON.stringify(content).includes("==");
    return false;
  }

  // Extract VPM from "# rate_value" JSON or fallback
  function extractVPM(content) {
    const blockRegex = /#\s*rate_value\s*\n+({[\s\S]*?})/m;
    const blockMatch = content.match(blockRegex);
    if (blockMatch) {
      try {
        const obj = JSON.parse(blockMatch[1]);
        if (obj.vpm !== undefined) return String(obj.vpm);
      } catch (error) {
        console.log("Failed to parse JSON from # rate_value block:", error);
      }
    }

    const vpmRegex = /"vpm"\s*:\s*"?([\d.]+)"?/;
    const vpmMatch = content.match(vpmRegex);
    return vpmMatch ? vpmMatch[1] : "";
  }

  let tableData = [];

  // Load each page's content
  for (let page of pages) {
    const content = await dv.io.load(page.file.path);

    const hasTasks = page.file.tasks && page.file.tasks.length > 0;
    const hasOpenTasks = hasTasks && page.file.tasks.some(task => !task.completed);
    const hasConsumedChecked = page.file.tasks?.some(
      task => task.text.toLowerCase().includes("consumed") && task.completed
    );

    if (!hasOpenTasks || hasConsumedChecked) continue;

    const highlightsPresent = hasHighlights(content);
    const hasActionItemTag = page.file.tags?.includes("#action-item");
    const hasActionTag = page.file.tags?.includes("#action");

    const vpmValue = extractVPM(content);

    tableData.push({
      link: page.file.link,
      words: Math.round(page.file.size / 6),
      flags: [
        highlightsPresent ? "H" : "",
        hasActionItemTag ? "I" : "",
        hasActionTag ? "A" : ""
      ].filter(Boolean).join(" "),
      vpm: vpmValue
    });
  }

  // Sort by filename descending
  tableData.sort((a, b) => {
    const nameA = a.link.path.split("/").pop() || "";
    const nameB = b.link.path.split("/").pop() || "";
    return nameB.localeCompare(nameA);
  });

  // Style rows and flags
  const customCSS = `
    <style>
      .dataview.table-view-table tr:nth-child(even) {
        background-color: #333;
        color: white;
      }
      .flag-code {
        font-family: monospace;
        background-color: #444;
        padding: 2px 4px;
        border-radius: 3px;
        color: white;
      }
    </style>
  `;
  dv.container.innerHTML += customCSS;

  // Render the table (without Creation Date)
  dv.table(
    ["Page", "~ Word Count", "Flags", "VPM"],
    tableData.map(row => [
      row.link,
      row.words,
      row.flags ? `<span class="flag-code">${row.flags}</span>` : "",
      row.vpm
    ])
  );
}

main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment