For the past few months, I’ve been working on a plugin called ‘Commentator’, which aims to recreate Word’s/Google Docs’ suggestion and comment modi within Obsidian, using the CriticMarkup syntax.
This feature has been requested in below thread, and by several people in the Discord server:
Features
Currently, the plugin supports the following features:
A WYSIWYG suggestion mode that tracks text being added/deleted/replaced
Preview all suggestions being accepted/rejected within the editor
In-document comment rendering within the right side-bar
Vault wide comments & suggestions view with search and filters for location and type
With plans to add the following in the future:
Improved collaborative workflows for shared vaults (comments linked to author, …)
Providing a framework for adding metadata to suggestions and comments
Comment mode for quickly annotating your notes
Generating automatic diffs with previous versions of your notes
Discussion
Please leave feedback for the plugin either in the Discord server (under the Plugin Advanced > Commentator thread), or in the issues page. I am still in the process of figuring some workflows out, so I would love to hear your ideas!
That is stunning!! I don’t need the plugin itself, but you can bet I’ll be going through your code trying to figure out how you did some of that. Well done, it looks amazing.
Amazing! Since the topic came up in the forum and on Discord I was eagerly waiting for talented guys to develop this type of solution. Hats off to you!
You can download the plugin using Brat. Once installed, you can use commands like Mark as Addition to apply the CriticMarkup to the text, enable the suggestion mode and start typing (which will automatically mark inserted text as additions/…), or open the custom view via the Commentator: Open CriticMarkup view command, which lists all the suggestions/comments throughout the entire vault.
Always make sure to keep backup’s of your vault, that’s the most important thing (when using Obsidian in general).
From my general testing, everything should work normally – I haven’t encountered any issues with text being lost accidentally, not in the latest versions atleast. In general, you’ll also be able to undo any edit operation if something goes wrong.
But yeah, having backups of your vault is the most important thing.
Thanks for the suggestion! I’m definitely planning to implement this type of workflow into the plugin in some way. Not quite sure yet if I’ll implement it myself or offer some kind of integration with the plugin(s) that accomplish this.
What I just thought about: How will the plugins functions affect working on and dealing with the final text?
Say, I write a chapter for a publication. I write away and while doing so, I leave gaps or put in things to be done later, commenting on them being in need to be added or improved (additional research, sources, images, whatever).
Will there be a chance to create tasks from such comments, ideally linking to the place of the passage to be improved?
As the text progresses, these things will be gradually worked on so the comments become obsolete.
Will there be a possibility to tick the boxes off?
Will it be possible to keep them in an “archived” or “done” section for later reviewing? This would be very helpful if people want to review the genesis of the text lateron.
When the text is done, I only want the finished version to be published.
Will there be an export function?
One thing I did not say in my first post:
I really dreamed of such a plugin for a LONG time using Obsidian. This type of functionality is very important for anyone developing thought - both fictional and factual.
This plugin is really going to help Obsidian be WAY MORE attractive to writers.
I’m not entirely sure what you mean by the final text; you mean in terms of removing all the suggestions and comments from the note?
That’s a very good question. I’ll break down my current thoughts in two parts:
1. Create tasks from comments — This mainly depends on what kind of functionality you expect from these tasks.
Comments are inherently linked to the place where you added them within your note, and you could easily append links within these comments to other parts of the note that should be edited.
Furthermore, I’m currently in the process of planning out how custom syntax/metadata for comments and suggestions should be implemented. For example, I could make it so that a comment could look like: {>>type="task"<>Your comment<<}, and that you’ll be able to filter the plugin’s custom view to only show comments that have type “task”.
But yeah, that is quite limited. I’m interested to hear what you would want these tasks to do. Something more akin to obsidian-tasks (see also 2.), or something simpler.
2. Having an overview of comments/tasks — This could be implemented via the custom view, which already has many of the required systems in place (filtering comments & opening comment to the correct file), though I can imagine that you would want a Dataview-esque list of uncompleted tasks you can just embed straight into your nodes.
One idea I have for this, is that there could be some bridge/integration between Dataview/Datacore and the Commentator plugin, where you’ll be able to query the Commentator database of all comments/suggestions using the Datacore plugin as a backend:
```dataview
LIST
FROM #uncompleted
INCLUDE commentator.comment
WHERE comment.status = 0
``'
(List all unfinished comments from notes containing tag #uncompleted)
Please don’t take that as a promise that this will be implemented though, I have no idea at this moment how feasible this would be.
This could easily be done with the custom syntax. I’ll post the full specs of the CriticMarkup extension once I’ve finished my thoughts a bit.
Do note that even if people mark them as “archived”, they would still exist as text within the note until they’re fully deleted (though obviously hidden away by the plugin).
What do you mean by ‘the text is done’? And further: by publish, do you mean ‘Obsidian Publish’?
I imagine you mean that you don’t want any of the suggestions/comments to appear on the publish website?
Sadly, I don’t think there is currently a way for plugins to apply custom rendering on publish websites (though I remember it being on the roadmap at some point), so I’m not sure if there’ll be any way for me to explicitly hide the markup.
As for exporting: for PDFs, I do plan on removing any syntax and styling when rendering the PDF (haven’t gotten around to that yet).
And I’ll probably also add a Export as regular markdown file that strips all of the markup from the note.
Are there any other export options you would like me to include?
Please consider focusing on the main job of Commentator and following the DOTADIW / KISS / YAGNI principle – I don’t need any additional features apart from the CriticMarkup specs and can imagine that others feel the same.
If you are thinking of expanding the responsibilities of your plugin, please make them optional – maybe by implementing a sub-plugin system?
Absolutely. The intention was always to make the custom syntax opt-in only. I will make sure that the base syntax works first-and-foremost. I’ll also try to always give the option to opt-out for any features that you would rather not use, which is easily possible thanks to the rather modular nature of the plugin.
As for the extension on the CriticMarkup specification/syntax itself, I completely understand where you are coming from. Sadly, it really is not possible for me to offer comment replies, authorship of comments, marking suggestions as completed, …, without expanding the syntax. I hope that having the extensions be opt-in is a good-enough compromise.
Oh I didn’t really clarify this in my original message, but I do not at all intend to recreate the functionality of the tasks plugin. My main goal is to integrate with 3rd party plugins as much as is humanly possible. And if that doesn’t work out, I’ll only be implementing a very rudimentary rendition of the feature (i.e. without all the nice additional features that Tasks/… offers).
However, I do personally think that it makes most sense to keep everything contained within the same plugin – splitting up the code into separate plugins will bring a lot of techical complexity and unnecessary overhead with it, which I would like to avoid.
Apologies for the wall of text and the scattered thoughts, but I just wanted to note down my personal ‘philosophy’ on the project. Please let me know if you disagree with any of these points!
I did not mean Obsidian Publish but any other exporting function. Sorry to be unclear here.
The main thing is: Being able to get a “clean” version of the text at its respective stage (final or temporary, for instance to have someone else look at it).
This is exactly what I mean.
This can also be a nice way to create a “clean cut” at some point: I like versioning my work. For example, document versions 1.1 through 1,9 could be within the same document. 2.0 could be exported as a clean markdown without any commentary. Then this would be used to work on a more refined version of the text.
Users could still, however, go back to version 1.9 and have a look at what thoughts certain decisions were based on.
The versioning described here is an example workflow. It makes no sense to build some function like this into the plugin, I just wanted to illustrate a scenario where keeping both the “work versions” and the “clean cut” makes sense. I would surely use the plugin in exactly this way all the time.
What I thought about with tasks would not be too elaborate:
Marking something in my note “Commentary in academia from Plato to PKM” with a comment “Research x on topic y and fill in references as footnote”
Here, an direct option would be great to create a task.
This task I do not need inside the document, as far I know, Critic is not providing a solution for this. But it could be done easily by creating an external document. In the case of my example, this could be named “Commentary in academia from Plato to PKM - tasks” and reside in the same folder.
Links could lead from the comments title in the text to the task and vice versa.
The tasks itself would just be the title of the comment inside the text with a checkbox formatting. If one wishes to add further things like dates or prioritize, this can be done by hand, no need to create this in the plugin.
A small update for the forum: from tomorrow onwards, I will start with the implementation of the reply and metadata features. This will probably take a significant amount of time, as there are several systems that need to be rewritten from scratch, or heavily adapted.
In the meantime, in order to ensure that these extensions of the CriticMarkup syntax stay relevant for a long time and – most importantly – to ensure future compatibility with other applications, I’ve opened up a proposal on the CriticMarkup GitHub page for formally including these changes into the specification.
You can find a link to the proposal here:
The proposal would make the CriticMarkup standard much more versatile and makes it possible to implement annotation systems similar to those found in rich text editors.
Please do share your thoughts and opinions on the GitHub page!
After months of developments, I’m glad to announce that the metadata and replies extensions are now available with release 0.2.0!
The full checklist is listed on GitHub, but major additions/changes include:
Suggestions and ranges can now contain metadata, currently only authorship and timestamp information can be included, but more types are on the way. (OPT-IN)
Comments directly adjacent to suggestions and ranges are now considered as replies to that range.
The Comment Gutter in your notes can now be resized and folded away.
Having an Issue since update 1.7.4, have tried reinstalling it as well.
here the log when I try to activate it:
Plugin failure: commentator TypeError: Cannot destructure property 'tooltip' of 'this.states[F]' as it is undefined. at HF.attachButtons (plugin:commentator:11:114319) at HF.setRendering (plugin:commentator:11:113282) at new HF (plugin:commentator:11:113162) at mt (plugin:commentator:11:115231) at NQ.onload (plugin:commentator:39:3906167)
`Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'detachButtons')
at NQ.onunload (plugin:commentator:39:3907741)
at e.unload (app.js:1:1230613)
at e.<anonymous> (app.js:1:2382993)
at app.js:1:237228
at Object.next (app.js:1:237333)
at app.js:1:236249
at new Promise (<anonymous>)
at v (app.js:1:235994)
at e.unloadPlugin (app.js:1:2382880)
at e.<anonymous> (app.js:1:2386249)
at app.js:1:237228
at Object.next (app.js:1:237333)
at app.js:1:236249
at new Promise (<anonymous>)
at v (app.js:1:235994)
at e.disablePlugin (app.js:1:2386123)
at e.<anonymous> (app.js:1:2386910)
at app.js:1:237228
at Object.next (app.js:1:237333)
at app.js:1:236249
at new Promise (<anonymous>)
at v (app.js:1:235994)
at e.disablePluginAndSave (app.js:1:2386756)
at t.<anonymous> (app.js:1:3080276)
at app.js:1:237228
at Object.next (app.js:1:237333)
at app.js:1:236249
at new Promise (<anonymous>)
at v (app.js:1:235994)
at t.changeCallback (app.js:1:3080086)
at t.setValue (app.js:1:1405906)
at t.<anonymous> (app.js:1:3080239)
at app.js:1:237228
at Object.next (app.js:1:237333)
at a (app.js:1:236051)`