├── .gitignore
├── CapitalizeListItems.ftplugin
├── readme.md
├── package.json
├── main.js
└── spec.js
├── characterCount.ftplugin
├── package.json
└── main.js
├── ExampleKeyBinding.ftplugin
├── main.js
└── package.json
├── toggle tags.ftplugin
├── package.json
├── spec.js
└── main.js
├── EmacsKeyBindings.ftplugin
├── main.js
├── readme.md
└── package.json
├── ReverseText.ftplugin
├── main.js
├── package.json
└── spec.js
├── SortLines.ftplugin
├── main.js
├── package.json
└── spec.js
├── stopwatch.ftplugin
├── package.json
├── style.less
├── play.svg
├── pause.svg
└── main.js
├── RunScript.ftplugin
├── package.json
├── spec.js
└── main.js
├── SpeedUp.ftplugin
├── package.json
└── main.js
├── FilteringWordCount.ftplugin
├── package.json
└── main.js
├── MakeSentenceCase.ftplugin
├── package.json
├── main.js
└── spec.js
├── WikiLinks.ftplugin
├── package.json
├── main.js
└── spec.js
├── CreateListItems.ftplugin
├── package.json
├── spec.js
└── main.js
├── DateAndTime.ftplugin
├── package.json
├── main.js
├── spec.js
└── readme.md
└── ToggleEmptyLines.ftplugin
├── package.json
├── main.js
└── spec.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/CapitalizeListItems.ftplugin/readme.md:
--------------------------------------------------------------------------------
1 | # Capitalize Items in a List
2 |
3 | Capitlize each element within the list that is selected
4 |
5 | Author: FoldingText
--------------------------------------------------------------------------------
/characterCount.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Character Count",
3 | "version": "1.0.0",
4 | "description": "Show character count",
5 | "engines": {
6 | "foldingtext": ">=2.0.0"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/ExampleKeyBinding.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | //
2 | // Demo plugin showing how to add a keybinding
3 | //
4 | Extensions.addInit(function (editor) {
5 | editor.addKeyMap({
6 | 'Ctrl-A' : function (editor) {
7 | editor.replaceSelection('â');
8 | }
9 | });
10 | }, Extensions.PriorityLast);
11 |
--------------------------------------------------------------------------------
/toggle tags.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ToggleTags",
3 | "version": "1.0.0",
4 | "description": "Toggle @done and @today tags.",
5 | "homepage": "https://github.com/FoldingText/plugins/tree/FoldingText-Dev",
6 | "enabled": true,
7 | "engines": {
8 | "foldingtext": ">3.0.0",
9 | "taskpaper": ">3.0.0"
10 | }
11 | }
--------------------------------------------------------------------------------
/EmacsKeyBindings.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | Extensions.addKeyMap({
2 | name: 'croy emacs extensions',
3 | 'Home': 'moveToEndOfLine',
4 | 'Shift-Home': 'moveToEndOfLineAndModifySelection',
5 | 'Alt-F': 'moveWordRight',
6 | 'Alt-B': 'moveWordLeft',
7 | 'Alt-D': 'deleteWordForward',
8 | 'Alt-W': 'expandSelectionToWord',
9 | });
10 |
--------------------------------------------------------------------------------
/ReverseText.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | Extensions.addCommand({
2 | name: 'ReverseText',
3 | description: 'Reverse the selected text.',
4 | performCommand: (editor) => {
5 | var text = editor.selectedText(),
6 | reverseText = text.split('').reverse().join('');
7 | editor.replaceSelection(reverseText, 'around');
8 | }
9 | });
10 |
--------------------------------------------------------------------------------
/SortLines.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | Extensions.addCommand({
2 | name: 'sort lines',
3 | description: 'Sort the selected lines of text.',
4 | performCommand: function (editor) {
5 | var text = editor.selectedText(),
6 | sortedText = text.split('\n').sort().join('\n');
7 | editor.replaceSelection(sortedText, 'around');
8 | }
9 | });
10 |
--------------------------------------------------------------------------------
/EmacsKeyBindings.ftplugin/readme.md:
--------------------------------------------------------------------------------
1 | ### The following keys were added to standard emacs keybindings
2 |
3 | *Home* - Move cursor to end of the line
4 |
5 | *Shift-Home* - Move cursor to the end of the line and modify the selection
6 |
7 | *Alt-F* - Move cursor to the right one word
8 |
9 | *Alt-B* - Move cursor to the right one word
10 |
11 | *Alt-D* - Delete word forward
12 |
--------------------------------------------------------------------------------
/stopwatch.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Stopwatch Mode",
3 | "version": "1.0.0",
4 | "description": "Adds 'stopwatch' mode",
5 | "homepage": "https://github.com/FoldingText/plugins/tree/FoldingText-Dev",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "Utility"
11 | ],
12 | "packageId": "StopWatch",
13 | "engines": {
14 | "foldingtext": ">2.0.0"
15 | }
16 | }
--------------------------------------------------------------------------------
/RunScript.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Run Script",
3 | "version": "1.0.0",
4 | "description": "Run the selected text as a Javascript function.",
5 | "homepage": "https://github.com/FoldingText/plugins",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "utility",
11 | "sdk"
12 | ],
13 | "engines": {
14 | "foldingtext": ">3.0.0",
15 | "taskpaper": ">3.0.0"
16 | }
17 | }
--------------------------------------------------------------------------------
/SpeedUp.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Speed Up!",
3 | "version": "1.0.0",
4 | "description": "Write fast! If you pause for more then 5 seconds your document is cleared!!!",
5 | "homepage": "https://github.com/FoldingText/plugins/",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "Utility"
11 | ],
12 | "packageId" : "SpeedUp",
13 | "engines": {
14 | "foldingtext": ">3.0.0"
15 | }
16 | }
--------------------------------------------------------------------------------
/SortLines.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Sort Lines",
3 | "version": "1.0.0",
4 | "description": "Sort the selected lines.",
5 | "homepage": "https://github.com/FoldingText/plugins",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "utils",
11 | "formatting"
12 | ],
13 | "packageId": "SortLines",
14 | "engines": {
15 | "foldingtext": ">3.0.0",
16 | "taskpaper": ">3.0.0"
17 | }
18 | }
--------------------------------------------------------------------------------
/ReverseText.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Reverse Text",
3 | "version": "1.0.0",
4 | "description": "Adds command to reverse the selected text.",
5 | "homepage": "https://github.com/FoldingText/plugins/",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "formatting"
11 | ],
12 | "packageId": "ReverseText",
13 | "engines": {
14 | "foldingtext": ">3.0.0",
15 | "taskpaper": ">3.0.0"
16 | }
17 | }
--------------------------------------------------------------------------------
/FilteringWordCount.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Filtering Word Count",
3 | "version": "1.0.0",
4 | "description": "Alternative word count implementation that filters out blockquotes from total.",
5 | "homepage": "https://github.com/FoldingText/plugins/",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "display"
11 | ],
12 |
13 | "packageId": "FilteringWordCount",
14 | "engines": {
15 | "foldingtext": ">3.0.0"
16 | }
17 | }
--------------------------------------------------------------------------------
/MakeSentenceCase.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Capitalize List Items",
3 | "version": "1.0.0",
4 | "description": "Adds command to capitalize each selected list item.",
5 | "homepage": "https://github.com/FoldingText/plugins",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "formatting"
11 | ],
12 | "packageId" : "MakeSentenceCase",
13 | "engines": {
14 | "foldingtext": ">3.0.0",
15 | "taskpaper": ">3.0.0"
16 | }
17 | }
--------------------------------------------------------------------------------
/CapitalizeListItems.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Capitalize List Items",
3 | "version": "1.0.0",
4 | "description": "Capitalize each selected list item.",
5 | "homepage": "https://github.com/FoldingText/plugins",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "lists",
11 | "formatting"
12 | ],
13 | "packageId": "CapitalizeListItems",
14 | "engines": {
15 | "foldingtext": ">2.0.0",
16 | "taskpaper": ">3.0.0"
17 | }
18 | }
--------------------------------------------------------------------------------
/WikiLinks.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Wiki Links",
3 | "version": "1.0.0",
4 | "description": "Example plugin showing how to add new wiki link syntax to editor.",
5 | "homepage": "https://github.com/FoldingText/plugins/",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "keyboard",
11 | "emacs"
12 | ],
13 | "packageId": "WikiLinks",
14 | "engines": {
15 | "foldingtext": ">3.0.0",
16 | "taskpaper": ">3.0.0"
17 | }
18 | }
--------------------------------------------------------------------------------
/CreateListItems.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Create List Items",
3 | "version": "1.0.0",
4 | "description": "Create a list UnOrdered from selected list item.",
5 | "homepage": "https://github.com/FoldingText/plugins/",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "keywords": [
9 | "list",
10 | "formatting"
11 | ],
12 | "packageId": "CreateListItems",
13 | "enabled": true,
14 | "engines": {
15 | "foldingtext": ">3.0.0",
16 | "taskpaper": ">3.0.0"
17 | }
18 | }
--------------------------------------------------------------------------------
/DateAndTime.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Date and Time",
3 | "version": "1.0.0",
4 | "description": "Insert the current date or time at the cursor.",
5 | "homepage": "https://github.com/FoldingText/plugins/",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "date",
11 | "time",
12 | "formatting",
13 | ],
14 | "packageId": "DateAndTime",
15 | "engines": {
16 | "foldingtext": ">3.0.0",
17 | "taskpaper": ">3.0.0"
18 | }
19 | }
--------------------------------------------------------------------------------
/EmacsKeyBindings.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Emacs Key Bindings",
3 | "version": "1.0.0",
4 | "description": "Additions to the standard emacs keybindings",
5 | "homepage": "https://github.com/FoldingText/plugins",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "keyboard",
11 | "emacs"
12 | ],
13 | "packageId" : "EmacsKeybindings",
14 | "engines": {
15 | "foldingtext": ">3.0.0",
16 | "taskpaper": ">3.0.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/DateAndTime.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | Extensions.addCommand({
2 | name: 'date',
3 | description: 'Insert the current date',
4 | performCommand: function (editor) {
5 | editor.replaceSelection(new Date().toLocaleDateString(), 'around');
6 | }
7 | });
8 |
9 | Extensions.addCommand({
10 | name: 'time',
11 | description: 'Insert the current time',
12 | performCommand: function (editor) {
13 | editor.replaceSelection(new Date().toLocaleTimeString(), 'around');
14 | }
15 | });
16 |
17 |
--------------------------------------------------------------------------------
/ExampleKeyBinding.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Keybindings Example",
3 | "version": "1.0.0",
4 | "description": "Example plugin to show how to add custom keybinding.",
5 | "homepage": "https://github.com/FoldingText/plugins/",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": false,
9 | "keywords": [
10 | "keyboard",
11 | "example"
12 | ],
13 | "packageId": "ExampleKeyBinding",
14 | "engines": {
15 | "foldingtext": ">3.0.0",
16 | "taskpaper": ">3.0.0"
17 | }
18 | }
--------------------------------------------------------------------------------
/ToggleEmptyLines.ftplugin/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Toggle Empty Lines",
3 | "version": "1.0.0",
4 | "description": "Toggle between no empty lines, and every other line being empty.",
5 | "homepage": "https://github.com/FoldingText/plugins",
6 | "author": "FoldingText",
7 | "license": "MIT",
8 | "enabled": true,
9 | "keywords": [
10 | "Formatting",
11 | "Utility"
12 | ],
13 | "packageId": "ToggleEmptyLines",
14 | "engines": {
15 | "foldingtext": ">3.0.0",
16 | "taskpaper": ">3.0.0"
17 | }
18 | }
--------------------------------------------------------------------------------
/stopwatch.ftplugin/style.less:
--------------------------------------------------------------------------------
1 | .cm-stopwatch-renderwidget {
2 | text-align: right;
3 | .button {
4 | width: 32px;
5 | pointer-events:all;
6 | background: rgb(75, 200, 0);
7 | -webkit-mask: url(play.svg);
8 | -webkit-mask-size: 100% 100%;
9 | -webkit-mask-repeat: no-repeat;
10 | padding : 0.1rem 0.5rem;
11 | } &:hover {
12 | cursor: pointer;
13 | }
14 | } & .running {
15 | .button {
16 | width: 32px;
17 | background: rgb(226, 0, 0);
18 | -webkit-mask: url(pause.svg);
19 | -webkit-mask-size: 100% 100%;
20 | -webkit-mask-repeat: no-repeat;
21 | }
22 | }
--------------------------------------------------------------------------------
/SortLines.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Sort Lines', function () {
5 | var Editor = require('ft/editor/editor').Editor,
6 | editor;
7 |
8 | beforeEach(function () {
9 | editor = new Editor('');
10 | });
11 |
12 | afterEach(function () {
13 | editor.removeAndCleanupForCollection();
14 | });
15 |
16 | it('should sort selected text line', function () {
17 | editor.replaceSelection('c\na\nb', 'around');
18 | editor.performCommand('sort lines');
19 | expect(editor.textContent()).toEqual('a\nb\nc');
20 | });
21 | });
22 | });
--------------------------------------------------------------------------------
/ReverseText.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Reverse Text', function () {
5 | var Editor = require('ft/editor/editor').Editor,
6 | editor;
7 |
8 | beforeEach(function () {
9 | editor = new Editor('');
10 | });
11 |
12 | afterEach(function () {
13 | editor.removeAndCleanupForCollection();
14 | });
15 |
16 | it('should reverse selected text', function () {
17 | editor.replaceSelection('hello world!', 'around');
18 | editor.performCommand('reverse');
19 | expect(editor.textContent()).toEqual('!dlrow olleh');
20 | });
21 | });
22 | });
--------------------------------------------------------------------------------
/stopwatch.ftplugin/play.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/DateAndTime.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Date and time', function () {
5 | var Editor = require('ft/editor/editor').Editor,
6 | editor;
7 |
8 | beforeEach(function () {
9 | editor = new Editor('');
10 | });
11 |
12 | afterEach(function () {
13 | editor.removeAndCleanupForCollection();
14 | });
15 |
16 | it('should insert date', function () {
17 | editor.performCommand('date');
18 | expect(editor.textContent()).not.toEqual('');
19 | });
20 |
21 | it('should insert time', function () {
22 | editor.performCommand('time');
23 | expect(editor.textContent()).not.toEqual('');
24 | });
25 | });
26 | });
--------------------------------------------------------------------------------
/stopwatch.ftplugin/pause.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/CapitalizeListItems.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | //
2 | // This plugin is in response to http://support.foldingtext.com/discussions/suggestions/834-frq-transformations-make-sentence-case
3 | //
4 | Extensions.addCommand({
5 | name: 'capitalize lists',
6 | description: 'Capitalize each selected list item.',
7 | performCommand: function (editor) {
8 | var range = editor.selectedRange(),
9 | tree = editor.tree(),
10 | type, text;
11 |
12 | tree.beginUpdates();
13 | range.forEachNodeInRange(function (node) {
14 | type = node.type();
15 | if (type === 'ordered' || type === 'unordered' || type === 'todo' || type == 'task') {
16 | text = node.text();
17 | node.setText(text.charAt(0).toUpperCase() + text.slice(1));
18 | }
19 | });
20 | tree.endUpdates();
21 | }
22 | });
23 |
--------------------------------------------------------------------------------
/ToggleEmptyLines.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | Extensions.addCommand({
2 | name: 'toggle empty lines',
3 | description: 'Toggle between no empty lines and every other line empty.',
4 | performCommand: function (editor) {
5 | var tree = editor.tree(),
6 | emptyLines = tree.evaluateNodePath('//@type empty');
7 |
8 | tree.beginUpdates();
9 | if (emptyLines.length > 0) {
10 | tree.removeNodes(emptyLines);
11 | } else if (tree.nodeCount() > 1) {
12 | var each = tree.firstLineNode().nextLineNode();
13 | while (each) {
14 | tree.insertNodeBefore(tree.createNode(''), each);
15 | each = each.nextLineNode();
16 | }
17 | }
18 | tree.endUpdates();
19 | }
20 | });
21 |
--------------------------------------------------------------------------------
/RunScript.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Run Script', function () {
5 | var Editor = require('ft/editor/editor').Editor,
6 | editor;
7 |
8 | beforeEach(function () {
9 | editor = new Editor('');
10 | });
11 |
12 | afterEach(function () {
13 | editor.removeAndCleanupForCollection();
14 | });
15 |
16 | it('should run script', function () {
17 | editor.replaceSelection('1 + 2', 'around');
18 | expect(editor.performCommand('run script')).toEqual(3);
19 | });
20 |
21 | it('should run script function', function () {
22 | editor.replaceSelection('function(editor) { return editor.selectedText() }', 'around');
23 | expect(editor.performCommand('run script')).toEqual(editor.selectedText());
24 | });
25 | });
26 | });
--------------------------------------------------------------------------------
/RunScript.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | Extensions.addCommand({
2 | name: 'run script',
3 | description: 'Run the selected text as a javascript function.',
4 | performCommand: function (editor) {
5 | var script = editor.selectedText(),
6 | result;
7 |
8 | try {
9 | var wrappedScript = '(' + script + ')';
10 | result = eval(wrappedScript);
11 | if (typeof (result) == "function") {
12 | result = result(editor);
13 | }
14 | } catch (e) {
15 | result = e.toString();
16 | }
17 |
18 | var range = editor.selectedRange().rangeByCollapsing();
19 | editor.setSelectedRange(range);
20 | editor.replaceSelection(result + '', 'around');
21 |
22 | return result;
23 | }
24 | });
25 |
--------------------------------------------------------------------------------
/DateAndTime.ftplugin/readme.md:
--------------------------------------------------------------------------------
1 |
2 | Opening paragraph, with an ordered list of autumn leaves I found
3 |
4 | 1. A big leaf
5 | 1. Some small leaves:
6 | 1. Red (nested)
7 | 2. **Orange**
8 | 3. Yellow
9 | 1. A medium sized leaf that ~~maybe~~ was pancake shaped
10 |
11 | Unordered list of fruits:
12 |
13 | - Blueberries
14 | - Apples
15 | - Macintosh
16 | - Honey crisp
17 | - Cortland
18 | - Banana
19 |
20 | ### Fancy Header Title
21 |
22 | Here's what someone said:
23 |
24 | > I think blockquotes are cool
25 |
26 | Nesting **an *[emphasized link](https://apolloapp.io)* inside strong text**, neato!
27 |
28 | And then they mentiond code around 'NSAttributedString' that looked like this code block:
29 |
30 | ```swift
31 | func yeah() -> NSAttributedString {
32 | // TODO: Write code
33 | }
34 | ```
35 |
36 | Tables are even supported but (but need more than NSAttributedString' for support :p)
37 |
--------------------------------------------------------------------------------
/MakeSentenceCase.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | //
2 | // This plugin is in response to http://support.foldingtext.com/discussions/suggestions/834-frq-transformations-make-sentence-case
3 | //
4 | Extensions.addCommand({
5 | name: 'capitalize lists',
6 | description: 'Capitalize each selected list item.',
7 | performCommand: (editor) => {
8 | var range = editor.selectedRange(),
9 | tree = editor.tree(),
10 | type, text;
11 |
12 | tree.beginUpdates();
13 | range.forEachNodeInRange(function (node) {
14 | type = node.type();
15 | if (type === 'ordered' || type === 'unordered' || type === 'todo' || type === 'task') {
16 | text = node.text();
17 | if (text.length > 0) {
18 | node.setText(text.charAt(0).toUpperCase() + text.slice(1));
19 | }
20 | }
21 | });
22 | tree.endUpdates();
23 | }
24 | });
25 |
--------------------------------------------------------------------------------
/toggle tags.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Toggle Tags', function () {
5 | var MarkdownTaxonomy = require('ft/taxonomy/markdowntaxonomy').MarkdownTaxonomy,
6 | Taxonomies = require('ft/core/taxonomies'),
7 | Editor = require('ft/editor/editor').Editor,
8 | taxonomy = Taxonomies.taxonomy({
9 | foldingtext: true,
10 | multimarkdown: true,
11 | gitmarkdown: true,
12 | criticMarkup: true
13 | }, 'markdown'),
14 | editor;
15 |
16 | beforeEach(function () {
17 | editor = new Editor('', taxonomy);
18 | });
19 |
20 | afterEach(function () {
21 | editor.removeAndCleanupForCollection();
22 | });
23 |
24 | it('should toggle tags', function () {
25 | editor.setTextContent('hello');
26 | editor.performCommand('toggleToday');
27 | expect(editor.textContent()).toEqual('hello @today');
28 | editor.performCommand('toggleToday');
29 | expect(editor.textContent()).toEqual('hello');
30 | });
31 | });
32 | });
--------------------------------------------------------------------------------
/WikiLinks.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | //
2 | // This plugin is in response to
3 | //
4 | var wikiLinkRE = /\[\[(.*?)\]\]/g;
5 |
6 | Extensions.add('com.foldingtext.taxonomy.classifier', {
7 | classify: function (text, state, previousState) {
8 | var escapedText = text.escapedText(),
9 | match;
10 |
11 | if (escapedText.indexOf(']]') === -1) {
12 | return;
13 | }
14 |
15 | while ((match = wikiLinkRE.exec(escapedText))) {
16 | var linkText = match[0],
17 | linktarget = 'nv://' + encodeURI(match[1]);
18 |
19 | text.addAttributeInRange('keyword', '[[', match.index, 2);
20 | text.addAttributeInRange('wikilink', linkText, match.index, linkText.length);
21 | text.addAttributeInRange('linktarget', linktarget, match.index + 2, linkText.length - 4);
22 | text.addAttributeInRange('keyword', ']]', match.index + linkText.length - 2, 2);
23 | }
24 | },
25 | attributesToClear: ['wikilink']
26 | });
27 |
--------------------------------------------------------------------------------
/CreateListItems.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Capitalize List Items', function () {
5 | var MarkdownTaxonomy = require('ft/taxonomy/markdowntaxonomy').MarkdownTaxonomy,
6 | Taxonomies = require('ft/core/taxonomies'),
7 | Editor = require('ft/editor/editor').Editor,
8 | taxonomy = Taxonomies.taxonomy({
9 | foldingtext: true,
10 | multimarkdown: true,
11 | gitmarkdown: true,
12 | criticMarkup: true
13 | }, 'markdown'),
14 | editor;
15 |
16 | beforeEach(function () {
17 | editor = new Editor('', taxonomy);
18 | });
19 |
20 | afterEach(function () {
21 | editor.removeAndCleanupForCollection();
22 | });
23 |
24 | it('should capitlize each list item', function () {
25 | editor.setTextContent('line\n\n- one\n- two');
26 | editor.tree().ensureClassified();
27 | editor.performCommand('selectAll');
28 | editor.performCommand('capitalize lists');
29 | expect(editor.textContent()).toEqual('line\n\n- One\n- Two');
30 | });
31 | });
32 | });
--------------------------------------------------------------------------------
/CapitalizeListItems.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Capitalize List Items', function () {
5 | var MarkdownTaxonomy = require('ft/taxonomy/markdowntaxonomy').MarkdownTaxonomy,
6 | Taxonomies = require('ft/core/taxonomies'),
7 | Editor = require('ft/editor/editor').Editor,
8 | taxonomy = Taxonomies.taxonomy({
9 | foldingtext: true,
10 | multimarkdown: true,
11 | gitmarkdown: true,
12 | criticMarkup: true
13 | }, 'markdown'),
14 | editor;
15 |
16 | beforeEach(function () {
17 | editor = new Editor('', taxonomy);
18 | });
19 |
20 | afterEach(function () {
21 | editor.removeAndCleanupForCollection();
22 | });
23 |
24 | it('should capitlize each list item', function () {
25 | editor.setTextContent('line\n\n- one\n- two');
26 | editor.tree().ensureClassified();
27 | editor.performCommand('selectAll');
28 | editor.performCommand('capitalize lists');
29 | expect(editor.textContent()).toEqual('line\n\n- One\n- Two');
30 | });
31 | });
32 | });
--------------------------------------------------------------------------------
/MakeSentenceCase.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Capitalize List Items', function () {
5 | var MarkdownTaxonomy = require('ft/taxonomy/markdowntaxonomy').MarkdownTaxonomy,
6 | Taxonomies = require('ft/core/taxonomies'),
7 | Editor = require('ft/editor/editor').Editor,
8 | taxonomy = Taxonomies.taxonomy({
9 | foldingtext: true,
10 | multimarkdown: true,
11 | gitmarkdown: true,
12 | criticMarkup: true
13 | }, 'markdown'),
14 | editor;
15 |
16 | beforeEach(function () {
17 | editor = new Editor('', taxonomy);
18 | });
19 |
20 | afterEach(function () {
21 | editor.removeAndCleanupForCollection();
22 | });
23 |
24 | it('should capitlize each list item', function () {
25 | editor.setTextContent('line\n\n- one\n- two');
26 | editor.tree().ensureClassified();
27 | editor.performCommand('selectAll');
28 | editor.performCommand('capitalize lists');
29 | expect(editor.textContent()).toEqual('line\n\n- One\n- Two');
30 | });
31 | });
32 | });
--------------------------------------------------------------------------------
/WikiLinks.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Wiki Links', function () {
5 | var MarkdownTaxonomy = require('ft/taxonomy/markdowntaxonomy').MarkdownTaxonomy,
6 | Taxonomies = require('ft/core/taxonomies'),
7 | Editor = require('ft/editor/editor').Editor,
8 | taxonomy = Taxonomies.taxonomy({
9 | foldingtext: true,
10 | multimarkdown: true,
11 | gitmarkdown: true,
12 | criticMarkup: true
13 | }, 'markdown'),
14 | editor;
15 |
16 | beforeEach(function () {
17 | editor = new Editor('', taxonomy);
18 | });
19 |
20 | afterEach(function () {
21 | editor.removeAndCleanupForCollection();
22 | });
23 |
24 | it('should find wiki links tags', function () {
25 | editor.setTextContent('hello [[world]]');
26 | editor.tree().ensureClassified();
27 | expect(editor.tree().firstLineNode().lineAttributedString().toString()).toEqual('(hello /text)([[/keyword, text, wikilink)(world/linktarget, text, wikilink)(]]/keyword, text, wikilink)');
28 | });
29 | });
30 | });
--------------------------------------------------------------------------------
/ToggleEmptyLines.ftplugin/spec.js:
--------------------------------------------------------------------------------
1 | define(function (require) {
2 | 'use strict';
3 |
4 | describe('Toggle Empty Lines', function () {
5 | var MarkdownTaxonomy = require('ft/taxonomy/markdowntaxonomy').MarkdownTaxonomy,
6 | Taxonomies = require('ft/core/taxonomies'),
7 | Editor = require('ft/editor/editor').Editor,
8 | taxonomy = Taxonomies.taxonomy({
9 | foldingtext: true,
10 | multimarkdown: true,
11 | gitmarkdown: true,
12 | criticMarkup: true
13 | }, 'markdown'),
14 | editor;
15 |
16 | beforeEach(function () {
17 | editor = new Editor('', taxonomy);
18 | });
19 |
20 | afterEach(function () {
21 | editor.removeAndCleanupForCollection();
22 | });
23 |
24 | it('should toggle empty lines', function () {
25 | editor.replaceSelection('a\nb\nc', 'around');
26 | editor.performCommand('toggle empty lines');
27 | expect(editor.textContent()).toEqual('a\n\nb\n\nc');
28 | editor.performCommand('toggle empty lines');
29 | expect(editor.textContent()).toEqual('a\nb\nc');
30 | });
31 | });
32 | });
--------------------------------------------------------------------------------
/SpeedUp.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | //
2 | // http://support.foldingtext.com/t/plugin-for-write-or-it-will-be-erased-mode/520
3 | //
4 | var isSpeedUp,
5 | timeoutID,
6 | ignore;
7 |
8 | Extensions.addTreeChanged(function (editor, e) {
9 | if (!editor.option('speedUp')) {
10 | return;
11 | }
12 |
13 | if (timeoutID) {
14 | clearTimeout(timeoutID);
15 | }
16 |
17 | if (!ignore) {
18 | timeoutID = setTimeout(function () {
19 | if (!editor.option('speedUp')) {
20 | return;
21 | }
22 | ignore = true;
23 | editor.setTextContent('SPEED UP!\n- To get your work back UNDO!\n- To stop this crazyness Edit > Run Command > End Speed Up!');
24 | ignore = false;
25 | }, 5000);
26 | }
27 | });
28 |
29 | Extensions.addCommand({
30 | name: 'begin speed up',
31 | description: 'Begin "Speed Up!" session',
32 | performCommand: function (editor) {
33 | editor.setOption('speedUp', true);
34 | }
35 | });
36 |
37 | Extensions.addCommand({
38 | name: 'end speed up',
39 | description: 'End "Speed Up!" session',
40 | performCommand: function (editor) {
41 | editor.setOption('speedUp', false);
42 | }
43 | });
44 |
--------------------------------------------------------------------------------
/toggle tags.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | Extensions.addCommand({
2 | name: 'toggleDone',
3 | keymap: 'Cmd-D',
4 | description: 'Toggle @done tag for selected lines.',
5 | performCommand: (editor) => {
6 | editor.toggleTag('done', new Date().toISOString().substr(0, 10));
7 | }
8 | });
9 |
10 | Extensions.addCommand({
11 | name: 'toggleToday',
12 | keymap: 'Cmd-T',
13 | description: 'Toggle @today tag for selected lines.',
14 | performCommand: (editor) => {
15 | editor.toggleTag('today');
16 | }
17 | });
18 |
19 | Extensions.addCommand({
20 | name: 'toggleError',
21 | keymap: 'Shift-Cmd-E',
22 | description: 'Toggle @error tag for selected lines.',
23 | performCommand: (editor) => {
24 | editor.toggleTag('error');
25 | }
26 | });
27 |
28 | Extensions.addCommand({
29 | name: 'toggleMonthly',
30 | keymap: 'Shift-Cmd-M',
31 | description: 'Toggle @monthly tag for selected lines.',
32 | performCommand: (editor) => {
33 | editor.toggleTag('monthly');
34 | }
35 | });
36 |
37 | Extensions.addCommand({
38 | name: 'toggleCCMB',
39 | keymap: 'Ctrl-C',
40 | description: 'Toggle @ccmb tag for selected lines.',
41 | performCommand: (editor) => {
42 | editor.toggleTag('ccmb');
43 | }
44 | });
45 |
46 | Extensions.addCommand({
47 | name: 'toggleUSMC',
48 | keymap: 'Shift-Cmd-U',
49 | description: 'Toggle @usmc tag for selected lines.',
50 | performCommand: (editor) => {
51 | editor.toggleTag('usmc');
52 | }
53 | });
54 |
55 | Extensions.addCommand({
56 | name: 'newday',
57 | description: 'Insert the current date and make it a day formatted as needed',
58 | keymap: 'Shift-Cmd-N',
59 | performCommand: (editor) => {
60 | var today = new Date().toLocaleDateString(),
61 | str = "# **" + today + "** @day";
62 | editor.replaceSelection(str, 'end');
63 | }
64 | });
65 |
66 | Extensions.addKeyMap({
67 | 'Shift-Cmd-T': 'setTheme',
68 | });
69 |
70 |
--------------------------------------------------------------------------------
/characterCount.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | define(function (require, exports, module) {
2 | 'use strict';
3 |
4 | require('ft/util/parallel');
5 |
6 | var Extensions = require('ft/core/extensions').Extensions,
7 | element;
8 |
9 | function formatNumber(number) {
10 | return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',');
11 | }
12 |
13 | function updateDisplay(editor) {
14 | if (!element) {
15 | element = document.createElement('div');
16 | document.body.insertBefore(element, document.body.firstChild);
17 | }
18 |
19 | var selectedRange = editor.selectedRange(),
20 | newInnerHTML;
21 |
22 | if (selectedRange.isCollapsed()) {
23 | element.className = 'characterCount';
24 | newInnerHTML = formatNumber(editor.tree().textLength()) + ' Characters
';
25 | } else {
26 | element.className = 'characterCount characterCountSelected';
27 | newInnerHTML = formatNumber(selectedRange.length()) + ' Characters
';
28 | }
29 |
30 | if (newInnerHTML !== element.innerHTML) {
31 | element.innerHTML = newInnerHTML;
32 | }
33 | }
34 |
35 | Extensions.addInit(function (editor) {
36 | updateDisplay(editor);
37 | });
38 |
39 | Extensions.addTreeChanged(function (editor, e) {
40 | updateDisplay(editor);
41 | });
42 |
43 | Extensions.addSelectionDidChange(function (editor) {
44 | updateDisplay(editor);
45 | });
46 |
47 | /*jshint multistr:true */
48 | Extensions.add('com.foldingtext.editor.styles',
49 | '.characterCount {\
50 | pointer-events: none;\
51 | position: fixed;\
52 | top: 0.5rem;\
53 | right: 1.5rem;\
54 | color: @secondaryTextColor;\
55 | z-index: 100;\
56 | background-color: fadeout(@paperColor, 20%);\
57 | padding: 5px;\
58 | border-radius: 3px;\
59 | }\
60 | .characterCountSelected {\
61 | color: @secondaryTextColor;\
62 | }'
63 | );
64 | /*jshint multistr:false */
65 |
66 | });
67 |
--------------------------------------------------------------------------------
/CreateListItems.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | //
2 | // This plugin is in response to http://support.foldingtext.com/discussions/suggestions/834-frq-transformations-make-sentence-case
3 | //
4 | Extensions.addCommand({
5 | name: "create unordered list",
6 | keymap: "Shift-Cmd-O",
7 | description: "Create an Unordered list of selected items.",
8 | performCommand: function (editor) {
9 | var range = editor.selectedRange(),
10 | tree = editor.tree(),
11 | type,
12 | text;
13 |
14 | tree.beginUpdates();
15 | range.forEachNodeInRange(function (node) {
16 | type = node.type();
17 | if (type !== "ordered" && type !== "unordered" && type !== "todo") {
18 | text = node.text();
19 | node.setText("- " + text.charAt(0).toUpperCase() + text.slice(1));
20 | }
21 | });
22 | tree.endUpdates();
23 | },
24 | });
25 |
26 | Extensions.addCommand({
27 | name: "create ordered list",
28 | description: "Create an Ordered list of selected items.",
29 | performCommand: function (editor) {
30 | var range = editor.selectedRange(),
31 | tree = editor.tree(),
32 | type,
33 | text,
34 | index = 1;
35 |
36 | tree.beginUpdates();
37 | range.forEachNodeInRange(function (node) {
38 | type = node.type();
39 | if (type !== "ordered" && type !== "unordered" && type !== "task") {
40 | text = node.text();
41 | node.setText(
42 | index + ". " + text.charAt(0).toUpperCase() + text.slice(1)
43 | );
44 | index++;
45 | }
46 | });
47 | tree.endUpdates();
48 | },
49 | });
50 |
51 | Extensions.addCommand({
52 | name: "undo list",
53 | description: "Undo an list of selected items.",
54 | keymap: "Shift-Cmd-P",
55 | performCommand: function (editor) {
56 | var range = editor.selectedRange(),
57 | tree = editor.tree(),
58 | type,
59 | text;
60 |
61 | tree.beginUpdates();
62 | range.forEachNodeInRange(function (node) {
63 | type = node.type();
64 | if (type === "ordered" || type === "unordered" || type === "task") {
65 | node.setType("body");
66 | }
67 | });
68 | tree.endUpdates();
69 | },
70 | });
71 |
72 | // Extensions.addInit(function (editor) {
73 | // editor.addKeyMap({
74 | // 'Shift-Cmd-O': 'create unordered list',
75 | // 'Shift-Cmd-P': 'undo list',
76 | // });
77 |
--------------------------------------------------------------------------------
/FilteringWordCount.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Alternative word count approach that tracks counts per node. This makes it possible
3 | * to filter certain node types out of the count, and to exclude trailing tags and other
4 | * syntax from the count.
5 | */
6 | var nodeIDsToLastCount = {},
7 | totalWordCount = 0,
8 | element;
9 |
10 | function updateDisplay(editor) {
11 | if (!element) {
12 | element = document.createElement('div');
13 | element.className = 'filteringWordCount';
14 | document.body.appendChild(element);
15 | }
16 |
17 | var newInnerHTML = totalWordCount + ' Words
';
18 | if (newInnerHTML !== element.innerHTML) {
19 | element.innerHTML = newInnerHTML;
20 | }
21 | }
22 |
23 | function updateAndReturnWordCountForNode(node) {
24 | var text;
25 | if (node.type() !== 'blockquote') {
26 | text = node.text();
27 | }
28 |
29 | var match = text ? text.match(/\S+/g) : null,
30 | newWordCount = match ? match.length : 0;
31 | nodeIDsToLastCount[node.id] = newWordCount;
32 | return newWordCount;
33 | }
34 |
35 | Extensions.addInit(function (editor) {
36 | var each = editor.tree().firstLineNode();
37 | while (each) {
38 | totalWordCount += updateAndReturnWordCountForNode(each);
39 | each = each.nextLineNode();
40 | }
41 | });
42 |
43 | Extensions.addTreeChanged(function (editor, e) {
44 | var deltas = e.deltas,
45 | deletasLength = deltas.length;
46 | for (var i = 0; i < deletasLength; i++) {
47 | var eachDelta = deltas[i],
48 | updatedNode = eachDelta.updatedNode,
49 | removedNodes = eachDelta.removedNodes,
50 | insertedNodes = eachDelta.insertedNodes;
51 |
52 | if (updatedNode) {
53 | totalWordCount -= nodeIDsToLastCount[updatedNode.id];
54 | totalWordCount += updateAndReturnWordCountForNode(updatedNode);
55 | }
56 |
57 | for (var j = 0; j < removedNodes.length; j++) {
58 | totalWordCount -= nodeIDsToLastCount[removedNodes[j].id];
59 | delete nodeIDsToLastCount[removedNodes[j].id];
60 | }
61 |
62 | for (var k = 0; k < insertedNodes.length; k++) {
63 | totalWordCount += updateAndReturnWordCountForNode(insertedNodes[k]);
64 | }
65 | }
66 |
67 | updateDisplay(editor);
68 | });
69 |
70 | /*jshint multistr:true */
71 | Extensions.add('com.foldingtext.editor.styles',
72 | '.filteringWordCount {\
73 | pointer-events: none;\
74 | position: fixed;\
75 | bottom: 0.5rem;\
76 | left: 0.5rem;\
77 | color: @secondaryTextColor;\
78 | }'
79 | );
80 | /*jshint multistr:false */
81 |
--------------------------------------------------------------------------------
/stopwatch.ftplugin/main.js:
--------------------------------------------------------------------------------
1 | define(function (require, exports, module) {
2 | 'use strict';
3 |
4 | var AmountHelper = require('ft/taxonomy/helpers/amounthelper'),
5 | Extensions = require('ft/core/extensions').Extensions,
6 | NodeSet = require('ft/core/nodeset').NodeSet,
7 | DateUtils = require('ft/util/date'),
8 | currentDate = new Date(),
9 | stopwatchs = new NodeSet();
10 |
11 | Extensions.addMode({
12 | name: 'stopwatch'
13 | });
14 |
15 | function start(editor, node) {
16 | node.setPropertyNodeValue('Start', currentDate.format('mmm d, yyyy h:MM:ss TT'));
17 | }
18 |
19 | function stop(editor, node) {
20 | var tree = editor.tree(),
21 | startDate = getStartDate(node),
22 | startPropertyNode = node.propertyNode('start'),
23 | duration = formatDuration((currentDate.valueOf() - startDate.valueOf()) / 1000);
24 |
25 | tree.beginUpdates();
26 | node.insertChildBefore(tree.createNode('- ' + duration), startPropertyNode);
27 | startPropertyNode.removeFromParent();
28 | tree.endUpdates();
29 | }
30 |
31 | function getStartDate(node) {
32 | var startPropertyNode = node.propertyNode('start');
33 | if (startPropertyNode) {
34 | var value = startPropertyNode.tags().value;
35 | if (value) {
36 | return new Date(value);
37 | }
38 | }
39 | return undefined;
40 | }
41 |
42 | function formatDuration(duration, shortFormat) {
43 | var hours = Math.floor(duration / 3600),
44 | minutes = Math.floor((duration - (hours * 3600)) / 60),
45 | seconds = Math.ceil(duration - (hours * 3600) - (minutes * 60)),
46 | result = [];
47 |
48 | if (hours) {
49 | if (shortFormat) {
50 | result.push(hours + 'h');
51 | } else {
52 | result.push(hours + ' hours');
53 | }
54 | }
55 | if (minutes) {
56 | if (shortFormat) {
57 | result.push(minutes + 'm');
58 | } else {
59 | result.push(minutes + ' minutes');
60 | }
61 | }
62 | if (seconds) {
63 | if (shortFormat) {
64 | result.push(seconds + 's');
65 | } else {
66 | result.push(seconds + ' seconds');
67 | }
68 | }
69 |
70 | return result.join(' ');
71 | }
72 |
73 | Extensions.addRenderNode(function (editor, node, nodeRenderer) {
74 | if (node.mode() === 'stopwatch') {
75 | var widget = document.createElement('div'),
76 | button = document.createElement('span'),
77 | label = document.createElement('span'),
78 | startDate = getStartDate(node),
79 | duration = 0;
80 |
81 | widget.className = 'cm-' + 'stopwatch' + '-renderwidget';
82 | button.className = 'button';
83 | label.className = 'label';
84 |
85 | widget.appendChild(label);
86 | widget.appendChild(button);
87 |
88 | if (startDate) {
89 | widget.className += ' running';
90 | duration = (currentDate.valueOf() - startDate.valueOf()) / 1000;
91 | } else {
92 | node.children().forEach(function (each) {
93 | if (each.tags().duration) {
94 | duration += each.tags().duration;
95 | }
96 | });
97 | }
98 |
99 | if (duration) {
100 | label.textContent = formatDuration(duration, true) + '\xA0';
101 | }
102 |
103 | button.addEventListener('mousedown', function (e) {
104 | e.preventDefault();
105 | });
106 |
107 | button.addEventListener('mouseup', function (e) {
108 | e.preventDefault();
109 | editor.tree().ensureClassified();
110 | if (getStartDate(node)) {
111 | stop(editor, node);
112 | } else {
113 | start(editor, node);
114 | }
115 | });
116 |
117 | nodeRenderer.renderLineWidget(widget, {
118 | overlay : true,
119 | positionWidget : function (widgetWidth, widgetHeight) {
120 | var line = node.lineNumber(),
121 | leadingSpace = node.line().match(/\s*/)[0],
122 | coords = editor.cursorCoords({ line : line, ch : leadingSpace.length}, 'div');
123 | return {
124 | left: Math.round(coords.left - (widgetWidth + editor.defaultSpaceWidth())) + 'px'
125 | };
126 | }
127 | });
128 | }
129 | });
130 |
131 | Extensions.addTreeChanged(function (editor, e) {
132 | var deltas = e.deltas;
133 | for (var i = 0; i < deltas.length; i++) {
134 | var insertedNodes = deltas[i].insertedNodes,
135 | removedNodes = deltas[i].removedNodes,
136 | updatedNode = deltas[i].updatedNode,
137 | parent,
138 | each,
139 | j;
140 |
141 | length = removedNodes.length;
142 | for (j = 0; j < length; j++) {
143 | each = removedNodes[j];
144 | var previousParent = e.previousParent(each);
145 | if (previousParent && previousParent.mode() === 'stopwatch') {
146 | editor.setNeedsRender(previousParent);
147 | }
148 | }
149 |
150 | length = insertedNodes.length;
151 | for (j = 0; j < length; j++) {
152 | each = insertedNodes[j];
153 | if (each.mode() === 'stopwatch') {
154 | stopwatchs.addNode(each);
155 | } else {
156 | parent = each.parent;
157 | if (parent && parent.mode() === 'stopwatch') {
158 | editor.setNeedsRender(parent);
159 | }
160 | }
161 | }
162 |
163 | if (updatedNode) {
164 | if (updatedNode.mode() === 'stopwatch') {
165 | stopwatchs.addNode(updatedNode);
166 | } else {
167 | parent = updatedNode.parent;
168 | if (parent && parent.mode() === 'stopwatch') {
169 | editor.setNeedsRender(parent);
170 | }
171 | }
172 | }
173 | }
174 | });
175 |
176 | Extensions.add('com.foldingtext.taxonomy.classifier', {
177 | classify: function (text, state, previousState) {
178 | if (state.type === 'unordered') {
179 | var modeStack = state.modeStack;
180 | if (modeStack) {
181 | var modeRecord = modeStack.lastObject();
182 | if (!modeRecord || modeRecord.mode !== 'stopwatch') {
183 | return;
184 | }
185 | } else {
186 | return;
187 | }
188 |
189 | var duration = AmountHelper.parseDuration(text, state, previousState);
190 | if (duration) {
191 | state.tags.duration = duration;
192 | }
193 | }
194 | },
195 | attributesToClear: [].concat(AmountHelper.attributesToClear)
196 | });
197 |
198 | Extensions.add('com.foldingtext.editor.clockTick', function (editor, date) {
199 | currentDate = date;
200 | stopwatchs.forEachNodeInSet(function (each) {
201 | if (!each.isTracked || each.mode() !== 'stopwatch') {
202 | stopwatchs.removeNode(each);
203 | } else {
204 | editor.setNeedsRender(each);
205 | }
206 | });
207 | });
208 | });
--------------------------------------------------------------------------------