Introduction
Hi everyone,
I'm Abdallah Ahmed, a freshman CS student from Egypt. I will be developing a BibTeX Plugin for Joplin to help people who use the application for research purposes.
The development lifecycle of the plugin will be carefully monitored here alongside other discussions about the implementation process.
Project goals (Deliverables)
According to the spec provided by Mr. @Laurent22,
Adding support for BibTex references should be possible via the upcoming plugin API. It would require hooking into the config screen, note editor, and note viewer.
Three main tasks need to be done in the plugin, namely:
- Add a way in the config screen that allows the user to import a local BibTeX file.
- Create a new command that displays a pop-up dialog enabling the user to insert a reference in the current place in the note.
- Enhancing the markdown parser so that it can distinguish references from the note content and renders them in a specified format.
In addition to the above tasks, other crucial aspects must be integrated into the implementation process:
- User-friendly UI.
- Unit tests and Continuous Integration (Using Travis CI).
- Documentation for developers and users alike.
- Bi-weekly reports (or blog posts) containing a log of everything that has been done and what's next.
Implementation
The implementation relies heavily on Joplin's plugin API to do all sorts of things: showing dialogs, accessing settings, and modifying content. Below are the exact modifications that will be carried out by the plugin:
Config Screen
As required by the spec, the plugin should have a settings section in the config screen to allow the user to set the .bib file path. This can be added dynamically by calling the following methods whenever the plugin starts:
// To add a new section in the settings page
await joplin.settings().registerSection();
// To add a new key/value settings field
await joplin.settings().registerSettings();
Also, the section should have a meaningful name (like 'citation') and an expressive user-friendly icon.
Upon setting the file path of the citation source, the data of the file should be loaded into memory and then parsed by the Parser class, whose only purpose is to validate and parse .bib files. After validation and parsing, the Parser should return an Array of Reference objects. References returned by the parser should then be stored in the DataStore, which is responsible for storing citation data and providing it when needed. The Parser class must also report errors to the data store when encountering them (like when there is a parsing error or the file path is invalid). Regarding the implementation of the Parser class, there are various pre-built options out there (such as BibTeX-JS, BibTeX.js, Citation.js); A from-scratch implementation is also feasible. Moreover, the Parser should just act as a thin wrapper that hides most of the implementation details and the underlying libraries used.
Note Editor
The modifications applied to the Note Editor will involve registering a new addBibTexReference command by utilizing the Commands API as follows:
await joplin.commands.register({
name: 'addBibTexReference',
label: 'Add BibTex Reference',
iconName: 'ICON',
execute: () => {}
});
This command will be executed by either one of the following methods:
- Main menu item - using MenuItem Views API
- Toolbar Button - using ToolbarButtons Views API
When the command is invoked, a popup dialog will be displayed allowing the user to search through locally stored references and insert whichever one into the note content. This behavior can be implemented with the aid of Dialogs Views API as follows:
await joplin.views.dialogs.create("dialog_id");
To provide the search feature, a SearchUtility class will be built so that it can request citation data from the DataStore and filter the results based on the search query.
Note Viewer
The last bit of work will be directed towards the Note Viewer as the plugin is required to register a markdown-it content script that will parse the note content and render the references in a distinguishable style. Besides, the full content of the references must automatically appear at the bottom of the note viewer.
The following diagram describes the whole process in a high-level fashion:
File Watchers
There is a possibility the .bib file changes during the running time of the plugin. To account for this, there ought to be a file watcher in place that listens for changes and reports them to the Parser class to start the parsing process again. Available options are:
- Built-in Node.js modules
- node-watch
- chokidar (Recommended)
Testing
Writing tests is a crucial part of the software development lifecycle. Most software products should have some kind of automated testing process whose mission is to ensure the delivery of correct functionality, the BibTeX plugin is no Exception. Most components in the plugin will be accompanied by test cases to assert the component is properly working. Unit tests, for example, will be applied to pure isolated components that don't have many side effects (like Parser class). On the other hand, components that depend mainly on side effects will have lower chances of being unit-tested; they will probably be tested using integration or manual testing (like UI components).
Documentation
Like testing, documentation is an important part of any software product. The plan for documentation includes an API reference for every component so that future developers will have an easier time maintaining the existing codebase. As for users, if the situation demands it, there will be a step-by-step guide (or tutorial) explaining the usage of the plugin.
UI/UX
UI/UX is equally important as the other sections of the project. Before the coding work commences, a suitable amount of time should be assigned to the design of UI/UX. There are several software products out there that are used for UI design and prototyping, such as:
The following Figma sketch demonstrates the basic appearance of the pop-up dialog: