Skip to content

Instantly share code, notes, and snippets.

@Heziode
Created April 8, 2023 14:47
Show Gist options
  • Save Heziode/f37d9ddbef0c29a40bf138fc0fc4b058 to your computer and use it in GitHub Desktop.
Save Heziode/f37d9ddbef0c29a40bf138fc0fc4b058 to your computer and use it in GitHub Desktop.
Word and Character Count of multiple notes in Obsidian, using dataviewjs.
// Word Count Dashboard
// a dataviewjs snippet by @pseudometa, https://gist.github.com/chrisgrieser/ac16a80cdd9e8e0e84606cc24e35ad99
// version 1.10.2
// last update: 2022-01-25
//----------------------------------------------------
// Import configuration
//----------------------------------------------------
const source = dv.current();
const sourceFolder = source.sourceFolder;
const target = source.target;
const toCount = source.toCount;
const includeFootnotes = source.includeFootnotes;
const charactersIncludeSpaces = source.charactersIncludeSpaces;
const excludeComments = source.excludeComments;
const includeBibliographyEstimate = source.includeBibliographyEstimate;
const wordsPerCitation = source.wordsPerCitation;
const charsPerCitation = source.charsPerCitation;
const thousandSeperator = source.thousandSeperator;
const useThousandSeperator = source.useThousandSeperator;
const naChar = source.naChar;
const subsectionStartChar = source.subsectionStartChar;
const wordsPerPage = source.wordsPerPage;
const charsPerPage = source.charsPerPage;
const pathToIndexFile = source.pathToIndexFile;
const cumulativeShare = source.cumulativeShare;
const groupedCount = source.groupedCount;
const mostRecentIcon = source.mostRecentIcon;
let sourceTag = source.sourceTag;
let excludeTag = source.excludeTag;
// prepend hashtags for tags
if (sourceTag) if (!sourceTag.startsWith("#")) sourceTag = "#" + sourceTag;
if (excludeTag) if (!excludeTag.startsWith("#")) excludeTag = "#" + excludeTag;
//----------------------------------------------------
// Functions
//----------------------------------------------------
function getWordCount(text) {
// Regex from BetterWordCount Plugin
const spaceDelimitedChars = /A-Za-z\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16F1-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC/
.source;
const nonSpaceDelimitedWords = /[\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u4E00-\u9FD5]{1}/
.source;
const pattern = new RegExp([
"(?:[0-9]+(?:(?:,|\\.)[0-9]+)*|[\\-" + spaceDelimitedChars + "])+",
nonSpaceDelimitedWords
].join("|"), "g");
return (text.match(pattern) || []).length;
}
function getCharacterCount(text) {
if (charactersIncludeSpaces) return text.length;
return text.replaceAll(" ", "").length;
}
function insert1000sep (num) {
let numText = String(num);
if (!useThousandSeperator) return numText;
if (num >= 10000) numText = numText.slice(0, -3) + thousandSeperator + numText.slice (-3); // eslint-disable-line no-magic-numbers
return numText;
}
String.prototype.strong = function () {
if (this === " ") return " ";
return "**" + this + "**";
};
function removeMarkdown (text) {
let plaintext = text
.replace(/`\$?=[^`]+`/g, "") // inline dataview
.replace(/^---\n.*?\n---\n/s, "") // YAML Header
.replace(/!?\[(.+)\]\(.+\)/g, "$1") // URLs & Image Captions
.replace(/\*|_|\[\[|\]\]|\||==|~~|---|#|> |`/g, ""); // Markdown Syntax
if (excludeComments) {
plaintext = plaintext
.replace(/<!--.*?-->/sg, "")
.replace(/%%.*?%%/sg, "");
}
else {
plaintext = plaintext
.replace(/%%|<!--|-->/g, ""); // remove only comment syntax
}
return plaintext;
}
function removeFootnotes (text) {
return text
.replace(/^\[\^[A-Za-z0-9-]+\]:.*$/gm, "") // footnote at the end
.replace(/\[\^[A-Za-z0-9-]+\]/g, ""); // footnote reference inline
}
function countPandocCitations (text) {
const citations = text.match(/@[A-Za-z0-9-]+(?=[,;\] ])/gi);
if (!citations) return 0;
const uniqCitations = [...new Set(citations)]; // only unique citations
return uniqCitations.length;
}
function toPercentStr (share) {
return (share * 100).toFixed(0).toString() + " %";
}
//----------------------------------------------------
// Table Construction
//----------------------------------------------------
async function getTableContents () {
const output = [];
let completeText = "";
let total = 0;
let share = 0;
let sectionCounter = 0;
let subsectionCounter = 0;
let totalTasks = 0;
// get sections via folder or via tag
let sections;
if (sourceFolder) sections = dv.pages("\"" + sourceFolder + "\"");
else sections = dv.pages(sourceTag);
// exclude certain notes
numExcludeStatus = sections.filter(t => t.status === "exclude").length;
sections = sections.filter(t => t.status !== "exclude");
if (excludeTag !== "") {
numExcludedNotes = sections.filter(t => t.file.tags.includes(excludeTag)).length;
sections = sections.filter(t => !t.file.tags.includes(excludeTag));
}
// most recent note
sections = sections.sort (s => s.file.mtime, "desc");
const mostRecentNote = sections[0].file.name;
// SORT sections
if (pathToIndexFile) {
const draftName = sourceFolder.split("/").pop();
const longformOrder =
dv.page(pathToIndexFile) // do not wrap in ", as with db.pages
.drafts
.filter(d => d.name === draftName)
.scenes;
sections = sections.sort(
s => s.file.name,
"desc",
(a, b) => longformOrder.indexOf(b) - longformOrder.indexOf(a)
);
} else {
sections = sections.sort(s => s.file.name);
}
//-------------------------------------------------
// SECTIONS LOOP
//-------------------------------------------------
for (const section of sections) {
// read page content
let content = await dv.io.load(section.file.path); // eslint-disable-line no-await-in-loop
// count markdown tasks
// need to be counted before cleanup
let tasks = content.match(/- \[ ] /g);
let taskNum = 0;
let taskStr = "";
if (tasks) {
taskNum = tasks.length;
taskStr = taskNum.toString();
}
// clean up
content = removeMarkdown (content);
if (!includeFootnotes) content = removeFootnotes (content);
content = content
.replace(/(^\s*)|(\s*$)/g, "") // remove the start and end spaces of the given string
.replace(/ {2,}/g, " "); // reduce multiple spaces to a single space
// Table Values: Count & Share
let wcCount = 0;
if (toCount === "words") wcCount = getWordCount(content);
if (toCount === "chars") wcCount = getCharacterCount(content);
if (cumulativeShare) share += (wcCount / target);
else share = (wcCount / target);
// Status
let status = section.status;
if (!status) status = " ";
// Section numbering
const isSubsection = section.file.name.startsWith(subsectionStartChar);
let sectionNumbering;
let sectionLink;
if (isSubsection) {
subsectionCounter++;
sectionNumbering = "<small>" + sectionCounter.toString() + "." + subsectionCounter.toString() + "</small>";
sectionLink =
"<small>[["
+ section.file.path
+ "|"
+ section.file.name.slice(1)
+ "]]</small>";
} else {
subsectionCounter = 0;
sectionCounter++;
sectionNumbering = sectionCounter.toString().strong();
sectionLink = "__" + section.file.link + "__";
}
// Most Recent Note
if (section.file.name === mostRecentNote) sectionLink += "&nbsp;&nbsp;&nbsp;" + mostRecentIcon;
// push table values
output.push([
sectionNumbering,
sectionLink,
wcCount,
share,
taskStr,
status
]);
// add to totals & bibliography calculation
totalTasks += taskNum;
total += wcCount;
if (includeBibliographyEstimate) completeText += content;
}
// Add Subsections counts to the sections
//-------------------------------------------------
if (groupedCount) {
let upperSectionID = -1;
for (var i = 0; i < output.length; i++) {
let isSubsection = output[i][0].includes(".");
let firstSectionFound = (upperSectionID !== -1);
if (!firstSectionFound && isSubsection) continue;
if (isSubsection) {
output[upperSectionID][2] += output[i][2]; // add count
if (!cumulativeShare) output[upperSectionID][3] += output[i][3]; // add share
}
if (!isSubsection) upperSectionID = i;
}
output.map(row => {
row[2] = insert1000sep(row[2]);
row[3] = toPercentStr(row[3]);
let isSubsection = row[0].includes(".");
if (isSubsection) {
row[2] = "<small>" + row[2] + "</small>";
if (!cumulativeShare) row[3] = "<small>" + row[3] + "</small>";
} else {
row[2] = "<u>" + row[2] + "</u>" ;
if (!cumulativeShare) row[3] = "<u>" + row[3] + "</u>";
}
return row;
});
}
//-------------------------------------------------
// OVERALL
//-------------------------------------------------
// Bibliography Estimate
if (includeBibliographyEstimate) {
const citationCount = countPandocCitations(completeText);
let wcCount = 0;
if (toCount === "words") wcCount = citationCount * wordsPerCitation;
if (toCount === "chars") wcCount = citationCount * charsPerCitation;
if (!charactersIncludeSpaces && toCount === "chars") wcCount = citationCount * (charsPerCitation - 20); // eslint-disable-line no-magic-numbers
if (cumulativeShare === "true") share += (wcCount / target);
else share = (wcCount / target);
output.push([
"",
"Bibliography (" + citationCount + " citations)",
"~" + insert1000sep(wcCount),
toPercentStr(share),
naChar,
naChar
]);
total += wcCount;
}
// Totals calculation
const totalShare = total / target;
let totalTitle = "Total";
if (wordsPerPage && toCount === "words") {
const totalPages = (total / wordsPerPage).toFixed(1);
totalTitle += "&nbsp;&nbsp;&nbsp;(~" + totalPages + " Pages)";
}
if (charsPerPage && toCount === "chars") {
const totalPages = (total / charsPerPage).toFixed(1);
totalTitle += "&nbsp;&nbsp;&nbsp;(~" + totalPages + " Pages)";
}
output.push([
"",
totalTitle.strong(),
insert1000sep(total).strong(),
toPercentStr(totalShare).strong(),
totalTasks.toString().strong(),
naChar.strong()
]);
// Target & Progress Bar
const progressBar =
"&nbsp;&nbsp;&nbsp;&nbsp;"
+ " <progress max=\"100\" value=\""
+ (totalShare * 100).toFixed().toString()
+ "\"> </progress>";
output.push([
"",
"Target".strong() + progressBar,
insert1000sep(target).strong(),
naChar.strong(),
naChar.strong(),
naChar.strong()
]);
return output;
}
//----------------------------------------------------
// Main
//----------------------------------------------------
// Print Table
let numExcludedNotes = 0;
let numExcludeStatus = 0;
let countedEntity = "Words";
if (toCount === "chars") countedEntity = "Chars";
let typeOfShare = "Share";
if (cumulativeShare === "true") countedEntity = "Target";
const tcontent = await getTableContents();
dv.table(["⟡", "Section", countedEntity, typeOfShare, "Tasks" ,"Status"], tcontent);
// Append Settings Info
let settingFt = "Footnotes excluded. ";
let settingExcludeTag = "";
let settingExcludeStatus = "";
let settingBibliography = "";
let settingCharSpaces = "Character Count includes Spaces. ";
let settingComments = "Comments included. ";
let settingPages = "";
if (includeFootnotes) settingFt = "Footnotes included. ";
if (!includeBibliographyEstimate) settingBibliography = "Bibliography excluded. ";
if (!charactersIncludeSpaces) settingCharSpaces = "Character Count without Spaces. ";
if (toCount === "words") settingCharSpaces = "";
if (excludeComments) settingComments = "Comments excluded. ";
if (wordsPerPage && toCount === "words") settingPages = "Assuming " + wordsPerPage.toString() + " words per page. ";
if (wordsPerPage && toCount === "chars") settingPages = "Assuming " + charsPerPage.toString() + " characters per page. ";
if (numExcludeStatus) {
let plural = "s";
if (numExcludeStatus === 1) plural = "";
const excludedQuery = "\"status: exclude\" path:(" + sourceFolder + ")";
settingExcludeStatus =
"[" + numExcludeStatus.toString() + " Section" + plural + "]"
+ "(obsidian://search?query=" + encodeURIComponent(excludedQuery) + ")"
+ " with the status \"exclude\" omitted. ";
}
if (numExcludedNotes) {
let plural = "s";
if (numExcludedNotes === 1) plural = "";
const excludedQuery = "tag:" + excludeTag + " path:(" + sourceFolder + ")";
settingExcludeTag =
"[" + numExcludedNotes.toString() + " Section" + plural + "]"
+ "(obsidian://search?query=" + encodeURIComponent(excludedQuery) + ")"
+ " tagged with " + excludeTag
+ " omitted. ";
}
dv.span(
"<small>"
+ "Settings: ".strong()
+ settingExcludeStatus
+ settingExcludeTag
+ settingFt
+ settingBibliography
+ settingComments
+ settingCharSpaces
+ settingPages
+ "</small>"
);

Wordcount Dashboard for Obsidian Dataview

image

Setup

  1. Install dataview
  2. Install the CSS file as CSS snippet.
  3. Create a note with the markdown note template.
  4. Insert the dataviewjs-script into the dataviewjs-codeblock
  5. Enter the configuration values in the note template. (The surrounding %% %% ensure that they are treated as comments, so the configuration will not be displayed in Preview Mode.)
  6. The status column will be populated with the value of the YAML-key status of every document, i.e., you have to use the add the following YAML-Header to every note.
  7. When also using the Longform Plugin, you can name the index file in your settings and the Dashboard will automatically change order based on the order of scenes in your Draft.

Wordcount_Dashboard

---
status: 
---

Known Issues & Troubleshooting

  • It seems that this dahsboard fails when amount of words / notes becomes too high. As far as I can tell, this is due to limitations by dataview/Obsidian, and one could only be tackled by a dedicated plugin for Word Counts. If you really want multi-note word counts, please request a plugin like that in the forum!
  • When dataview reports some error, try to use the default configuration with just the sourceFolder changed – that should work, and then try step-by-step to find out whether a certain configuration causes the dashboard to break.

Troubleshooting & Feature Requests

I am very sorry, but I unfortunately cannot really provide much support or implement feature requests. As much as I'd love to help out, the limitations of being an overly complex script running on top of dataview makes this dashboard quite brittle, and the fact that this isn't really a proper plugin make any sort of debugging extremely time-intensive (and writing a PhD and maintaining multiple plugins/themes already, my time is limited). If I do have the time, I'll maybe turn this into a proper plugin, but that would require quite some time, since it would require a lot of coding skills I do not have yet (being only a hobby coder.)

If you do want to have a nice word count dashboard in Obsidian, please make a request in the forum and/or make a feature request at one of the already existing plugins to integrate this dashboard (e.g. the longform plugin). Or, if you have coding experience yourself, feel free to take this code, customize it, and make a plugin of your own!

License

MIT License 2022

/* used to properly align the numbers of the dataviewjs wordcount snippet
https://gist.github.com/chrisgrieser/ac16a80cdd9e8e0e84606cc24e35ad99 */
.wordcountTable table.dataview.table-view-table td:first-child,
.wordcountTable table.dataview.table-view-table th:first-child {
text-align: center;
padding: 4px 7px;
border-left: none;
}
.wordcountTable table.dataview.table-view-table td:first-child {
color: var(--text-muted) !important;
}
.wordcountTable table.dataview.table-view-table td:nth-child(3),
.wordcountTable table.dataview.table-view-table td:nth-child(4) {
text-align: end;
}
.wordcountTable table.dataview.table-view-table th:nth-child(3),
.wordcountTable table.dataview.table-view-table td:nth-child(3),
.wordcountTable table.dataview.table-view-table th:nth-child(4),
.wordcountTable table.dataview.table-view-table td:nth-child(4),
.wordcountTable table.dataview.table-view-table th:nth-child(5),
.wordcountTable table.dataview.table-view-table td:nth-child(5) {
padding-right: 7px;
padding-left: 7px;
}
.wordcountTable table.dataview.table-view-table td:nth-child(2) {
text-align: start;
}
.wordcountTable table.dataview.table-view-table td:nth-child(5),
.wordcountTable table.dataview.table-view-table td:last-child {
text-align: center;
}
.wordcountTable .markdown-preview-section {
max-width: 100% !important;
}
.wordcountTable table.dataview.table-view-table th {
font-size: 1.1em;
text-align: center;
}
.wordcountTable table.dataview.table-view-table {
font-size: 0.9em;
}
.wordcountTable table.dataview.table-view-table a.internal-link {
text-decoration: none;
}
.wordcountTable progress {
margin-bottom: 3px;
}
/* target NA field */
.wordcountTable table.dataview.table-view-table tr:last-child td:nth-child(4) {
text-align: center;
}
/* Supercharged Links */
.data-link-icon[data-link-cssclass*="wordcount" i]::BEFORE { content: "🔢 " }
---
cssclass: wordcountTable
---
%%
__Notes to display__
*Gets either notes in a folder or notes with a certain tag. Leave one of them empty.*
sourceFolder:: Writing/Interdependence & Innovation/Drafts/Submission
sourceTag::
__Notes to exclude__
*Leave empty to disable. Notes with the yaml-key `status` and value `exclude` for that key are also excluded.)*
excludeTag:: #exclude
__Counting Settings__
*"chars" or "words"*
toCount:: chars
target:: 70000
*words or characters per page, depending on setting above. Set to zero to ignore.*
wordsPerPage:: 350
charsPerPage:: 2000
includeFootnotes:: true
charactersIncludeSpaces:: true
excludeComments:: true
cumulativeShare:: false
groupedCount:: true
__Bibliography Estimate for Pandoc Citations__
includeBibliographyEstimate:: true
wordsPerCitation:: 22
charsPerCitation:: 155
__Longform Plugin__
*Leave empty to sort alphabetically. Enter the path to the index file of a longform project to order sections by their order in the longform plugin. (The `sourceFolder` setting further above has to be a Longform Drafts folder. )*
pathToIndexFile::
*Begin a filename with this character and it will be treated as subsection*
subsectionStartChar:: _
__Purely visual__
useThousandSeperator:: true
thousandSeperator:: .
naChar:: —
mostRecentIcon:: 🕙
%%
```dataviewjs
<!-- put the code from above in a codeblock like this-->
```
@jhilker98
Copy link

jhilker98 commented Nov 4, 2023

No worries, thanks!

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