From 7686be7b14cdb3bb6e02ab7bd5a5204a8318942f Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Fri, 23 Oct 2020 17:23:17 +0200 Subject: [PATCH 001/124] Fix state tiddlers for action-create-tiddlers examples (#4897) --- .../tw5.com/tiddlers/ActionCreateTiddlerWidget Example 1.tid | 4 ++-- .../tw5.com/tiddlers/ActionCreateTiddlerWidget Example 2.tid | 4 ++-- .../tw5.com/tiddlers/ActionCreateTiddlerWidget Example 3.tid | 4 ++-- .../tw5.com/tiddlers/ActionCreateTiddlerWidget Example 4.tid | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 1.tid b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 1.tid index 5e4e84432..d5560be3b 100644 --- a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 1.tid +++ b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 1.tid @@ -1,5 +1,5 @@ created: 20200131142401129 -modified: 20200131152023958 +modified: 20201020112608874 tags: ActionCreateTiddlerWidget title: ActionCreateTiddlerWidget Example 1 type: text/vnd.tiddlywiki @@ -21,6 +21,6 @@ Create Tiddler ``` <$button actions=<> > -<$action-setfield $tiddler="$:/state/tab/sidebar-1206596165" text="$:/core/ui/SideBar/Recent"/> +<$action-setfield $tiddler="$:/state/tab/sidebar--595412856" text="$:/core/ui/SideBar/Recent"/> Create Tiddler - Clicking this button, will also open the Right sidebar: Recent tab diff --git a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 2.tid b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 2.tid index 089ab4763..876e5fbba 100644 --- a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 2.tid +++ b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 2.tid @@ -1,5 +1,5 @@ created: 20200131144828713 -modified: 20200131152102232 +modified: 20201020112601032 tags: ActionCreateTiddlerWidget title: ActionCreateTiddlerWidget Example 2 type: text/vnd.tiddlywiki @@ -23,6 +23,6 @@ Create Tiddler ``` <$button actions=<> > -<$action-setfield $tiddler="$:/state/tab/sidebar-1206596165" text="$:/core/ui/SideBar/Recent"/> +<$action-setfield $tiddler="$:/state/tab/sidebar--595412856" text="$:/core/ui/SideBar/Recent"/> Create Tiddler - Clicking this button, will also open the Right sidebar: Recent tab diff --git a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 3.tid b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 3.tid index 325499fc0..54524108a 100644 --- a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 3.tid +++ b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 3.tid @@ -1,5 +1,5 @@ created: 20200131145355658 -modified: 20200131152045990 +modified: 20201020112553050 tags: ActionCreateTiddlerWidget title: ActionCreateTiddlerWidget Example 3 type: text/vnd.tiddlywiki @@ -23,6 +23,6 @@ Create Tiddler ``` <$button actions=<> > -<$action-setfield $tiddler="$:/state/tab/sidebar-1206596165" text="$:/core/ui/SideBar/Recent"/> +<$action-setfield $tiddler="$:/state/tab/sidebar--595412856" text="$:/core/ui/SideBar/Recent"/> Create Tiddler - Clicking this button, will also open the Right sidebar: Recent tab diff --git a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 4.tid b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 4.tid index b116ee5e7..b1eb7275f 100644 --- a/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 4.tid +++ b/editions/tw5.com/tiddlers/ActionCreateTiddlerWidget Example 4.tid @@ -1,5 +1,5 @@ created: 20200131150229551 -modified: 20200131152051626 +modified: 20201020112544146 tags: ActionCreateTiddlerWidget title: ActionCreateTiddlerWidget Example 4 type: text/vnd.tiddlywiki @@ -23,6 +23,6 @@ Create Tiddler ``` <$button actions=<> > -<$action-setfield $tiddler="$:/state/tab/sidebar-1206596165" text="$:/core/ui/SideBar/Recent"/> +<$action-setfield $tiddler="$:/state/tab/sidebar--595412856" text="$:/core/ui/SideBar/Recent"/> Create Tiddler - Clicking this button, will also open the Right sidebar: Recent tab From 15338e60e894064600889ecd0d12d892def6f7f0 Mon Sep 17 00:00:00 2001 From: Mario Pietsch Date: Sun, 25 Oct 2020 23:03:35 +0100 Subject: [PATCH 002/124] Get "New Release Banner" from TW5-com edition (#4912) * Fix state tiddlers for action-create-tiddlers examples * Get "New Release Banner" from TW5-com edition --- .../de-AT/tiddlers/bilder/New_Release_Banner.png.tid | 6 ------ editions/de-AT/tiddlers/external/tiddlywiki.files | 12 ++++++++++++ .../intro/HelloThumbnail_-_Latest_Version.tid | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) delete mode 100644 editions/de-AT/tiddlers/bilder/New_Release_Banner.png.tid create mode 100644 editions/de-AT/tiddlers/external/tiddlywiki.files diff --git a/editions/de-AT/tiddlers/bilder/New_Release_Banner.png.tid b/editions/de-AT/tiddlers/bilder/New_Release_Banner.png.tid deleted file mode 100644 index 02a927c13..000000000 --- a/editions/de-AT/tiddlers/bilder/New_Release_Banner.png.tid +++ /dev/null @@ -1,6 +0,0 @@ -created: 20150513150058938 -tags: picture -title: New Release Banner.png -type: image/png - -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 \ No newline at end of file diff --git a/editions/de-AT/tiddlers/external/tiddlywiki.files b/editions/de-AT/tiddlers/external/tiddlywiki.files new file mode 100644 index 000000000..0c59b7bc5 --- /dev/null +++ b/editions/de-AT/tiddlers/external/tiddlywiki.files @@ -0,0 +1,12 @@ +{ + "tiddlers": [ + { + "file": "../../../tw5.com/tiddlers/images/New Release Banner.png", + "fields": { + "type": "image/jpg", + "title": "New Release Banner", + "tags": "picture" + } + } + ] +} diff --git a/editions/de-AT/tiddlers/intro/HelloThumbnail_-_Latest_Version.tid b/editions/de-AT/tiddlers/intro/HelloThumbnail_-_Latest_Version.tid index e453a44db..ecc127e67 100644 --- a/editions/de-AT/tiddlers/intro/HelloThumbnail_-_Latest_Version.tid +++ b/editions/de-AT/tiddlers/intro/HelloThumbnail_-_Latest_Version.tid @@ -1,7 +1,7 @@ caption: Was ist neu in <> color: #fff created: 20150513145829381 -image: New Release Banner.png +image: New Release Banner link: Releases modified: 20150518143526750 tags: HelloThumbnail From 9eec6ff915a5ad4b961be68867b68a1afad5196c Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" Date: Tue, 27 Oct 2020 12:32:06 +0000 Subject: [PATCH 003/124] Update path-prefix docs Addressing @OblivionSY's comment https://github.com/Jermolene/TiddlyWiki5/issues/4898#issuecomment-717207456 --- .../webserver/WebServer Parameter_ path-prefix.tid | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/editions/tw5.com/tiddlers/webserver/WebServer Parameter_ path-prefix.tid b/editions/tw5.com/tiddlers/webserver/WebServer Parameter_ path-prefix.tid index 365407a65..4a0b4dc86 100644 --- a/editions/tw5.com/tiddlers/webserver/WebServer Parameter_ path-prefix.tid +++ b/editions/tw5.com/tiddlers/webserver/WebServer Parameter_ path-prefix.tid @@ -1,6 +1,6 @@ caption: path-prefix created: 20180630180514893 -modified: 20200311171847360 +modified: 20201027122943281 tags: [[WebServer Parameters]] title: WebServer Parameter: path-prefix type: text/vnd.tiddlywiki @@ -13,4 +13,7 @@ This example causes the server to serve from http://127.0.0.1/MyApp instead of t tiddlywiki mywikifolder --listen "path-prefix=/MyApp" ``` -Note that further steps are required to configure the client-side components to use the prefix. See [[Using a custom path prefix with the client-server edition]]. \ No newline at end of file +Notes: + +* Further steps are required to configure the client-side components to use the prefix. See [[Using a custom path prefix with the client-server edition]] +* If no path prefix is required then the `path-prefix` parameter should be omitted or set to the empty string, and not to `\` as might be expected From 49142080115b8aeb03a9fe2c7700155f4088264a Mon Sep 17 00:00:00 2001 From: twMat Date: Thu, 29 Oct 2020 13:57:11 +0100 Subject: [PATCH 004/124] Update Configuring startup tiddlers.tid (#4009) --- .../tiddlers/customising/Configuring startup tiddlers.tid | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/customising/Configuring startup tiddlers.tid b/editions/tw5.com/tiddlers/customising/Configuring startup tiddlers.tid index c1697f55e..752415fd9 100644 --- a/editions/tw5.com/tiddlers/customising/Configuring startup tiddlers.tid +++ b/editions/tw5.com/tiddlers/customising/Configuring startup tiddlers.tid @@ -22,4 +22,6 @@ You can also use [[filter expressions|Filter Expression]] to open more than one will open all tiddlers tagged as <>. -You can also use this technique to [[preserve open tiddlers at startup|Preserving open tiddlers at startup]] \ No newline at end of file +You can also use this technique to [[preserve open tiddlers at startup|Preserving open tiddlers at startup]] + +See also [[StartupActions]] for controlling more advanced startup behaviours. From c0b021f509f514285ccd556167c844076202b488 Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Sun, 1 Nov 2020 18:03:59 +0700 Subject: [PATCH 005/124] Typo fix (#4951) --- editions/tw5.com/tiddlers/filters/compare Operator.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/filters/compare Operator.tid b/editions/tw5.com/tiddlers/filters/compare Operator.tid index a882914ae..95bdce2a9 100644 --- a/editions/tw5.com/tiddlers/filters/compare Operator.tid +++ b/editions/tw5.com/tiddlers/filters/compare Operator.tid @@ -30,7 +30,7 @@ The ''type'' can be: The ''mode'' can be: * "eq" - equal to -* "ne" - not equal ot +* "ne" - not equal to * "gteq" - greater than or equal to * "gt" - greater than * "lteq" - less than or equal to From feefc4cceb2448c9f96adc4da4985b3fc9d1aeab Mon Sep 17 00:00:00 2001 From: Miha Lunar Date: Fri, 6 Nov 2020 18:51:53 +0100 Subject: [PATCH 006/124] Signing the CLA (#4976) --- licenses/cla-individual.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/licenses/cla-individual.md b/licenses/cla-individual.md index abddae206..d83484a3a 100644 --- a/licenses/cla-individual.md +++ b/licenses/cla-individual.md @@ -411,3 +411,5 @@ Kamal Habash, @Kamal-Habash, 2020/08/28 Florian Kohrt, @fkohrt, 2020/09/10 Gerald Liu, @gera2ld, 2020/09/25 + +Miha Lunar, @SmilyOrg, 2020/11/04 From d8d88c67e3a3a5fe9146b36a153a474a11c5068d Mon Sep 17 00:00:00 2001 From: Robin Munn Date: Mon, 16 Nov 2020 23:50:32 +0700 Subject: [PATCH 007/124] Fix minor mistake in ButtonWidget docs (#5050) The ButtonWidget documentation refers to a "state" attribute, but this should probably be "set". The name "state" appears to be an artifact from when the setTitle, setField, and setIndex attributes were added to the widget; at one time they were called stateTitle and so on, and then they were renamed to setTitle instead, but not every instance of "state" was found and renamed to "set". This is one such instance, now fixed. --- editions/tw5.com/tiddlers/widgets/ButtonWidget.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid b/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid index 21a0a48a1..1f0a0d2b5 100644 --- a/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ButtonWidget.tid @@ -29,7 +29,7 @@ The content of the `<$button>` widget is displayed within the button. |message |The name of the [[widget message|Messages]] to send when the button is clicked | |param |The optional parameter to the message | |set |A TextReference to which a new value will be assigned | -|setTitle |A title to which a new value will be assigned, ''without'' TextReference. Gets preferred over <<.attr state>> | +|setTitle |A title to which a new value will be assigned, ''without'' TextReference. Gets preferred over <<.attr set>> | |setField |A ''field name'' to which the new value will be assigned, if the attribute <<.attr setTitle>> is present. Defaults to the ''text'' field | |setIndex |An ''index'' to which the new value will be assigned, if the attribute <<.attr setTitle>> is present | |setTo |The new value to assign to the TextReference identified in the `set` attribute or the text field / the field specified through <<.attr setField>> / the index specified through <<.attr setIndex>> of the title given through <<.attr setTitle>> | From 2b60ab1fdc930cb7165f5e8996888e80da86dfbe Mon Sep 17 00:00:00 2001 From: saqimtiaz Date: Tue, 17 Nov 2020 15:43:46 +0100 Subject: [PATCH 008/124] Doc updates for Modals (#5057) --- editions/tw5.com/tiddlers/features/Modals.tid | 6 ++++-- .../tiddlers/messages/WidgetMessage_ tm-modal.tid | 13 ++++++++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/editions/tw5.com/tiddlers/features/Modals.tid b/editions/tw5.com/tiddlers/features/Modals.tid index aa87ab68c..06b43a880 100644 --- a/editions/tw5.com/tiddlers/features/Modals.tid +++ b/editions/tw5.com/tiddlers/features/Modals.tid @@ -1,5 +1,5 @@ created: 20160107225427489 -modified: 20200312172056083 +modified: 20201117081054556 tags: Features title: Modals type: text/vnd.tiddlywiki @@ -10,9 +10,11 @@ The tiddler to be displayed can contain the following optional fields that are u |!Field |!Description | |footer|The footer text for the modal| -|subtitle|The subtitle text for a modal| +|subtitle|The subtitle text for a modal, displayed in a `h3` html tag| |class|An additional class to apply to the modal wrapper| +Note that the footer and subtitle fields are not limited to plain text, and wiki text features such as widgets and transclusions can be used as well. + Modals are displayed with the [[WidgetMessage: tm-modal]]. <$button message="tm-modal" param="SampleWizard">Open demo modal diff --git a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid index a1b90b688..b6db37eef 100644 --- a/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid +++ b/editions/tw5.com/tiddlers/messages/WidgetMessage_ tm-modal.tid @@ -1,22 +1,25 @@ +caption: tm-modal created: 20140811112133701 -modified: 20141107142803042 +modified: 20201117081247738 tags: Messages title: WidgetMessage: tm-modal type: text/vnd.tiddlywiki -caption: tm-modal |!Name |!Description | |param |Title of the tiddler to be displayed | -|paramObject |Hashmap of variables to be provided to the modal | +|paramObject |Hashmap of variables to be provided to the modal, contains all extra parameters passed to the widget sending the message. | |rootwindow |<<.from-version 5.1.18>> ''yes'' or ''true'' will always display a modal in the wiki-root-window | The "currentTiddler" variable is set to the title of the modal tiddler, but can be overridden by specifying a different value in `paramObject`. The modal message is usually generated with the ButtonWidget. The modal message is handled by the TiddlyWiki core. +[[Fields within the tiddler|Modals]] being displayed in the modal can be used to customize its appearance. + ! Example Here is an example of displaying a modal and passing parameters to it: +(Note how all parameters to `action-sendmessage` other than `$param` and `$message` are available as variables within the modal.) <$macrocall $name='wikitext-example-without-html' src='Your name: <$edit-text tiddler="$:/temp/yourName" tag="input" default="Your name"/> @@ -29,5 +32,9 @@ Your message: Click me! '/> + <<.tip """<$macrocall $name=".from-version" version="5.1.18"/> if triggered from within a ''new window'', the above examples will be displayed within that window. The <$macrocall $name=".attr" _="rootwindow"/> attribute can be set to ''yes'' or ''true'' to inherit this behavior and to display the Modal within the ''root'' window""">> +<<.tip """<$macrocall $name=".from-version" version="5.1.23"/> Links to tiddlers within a modal will open in the same story as the widget that sent the `tm-modal` message. You can override this by specifying values for the variables `tv-story-list` and `tv-history-list` when sending the `tm-modal` message. + +""">> \ No newline at end of file From 3b75297168d411bb9e0ed117ece5cab16eba6a9f Mon Sep 17 00:00:00 2001 From: Mohammad Rahmani <830394+kookma@users.noreply.github.com> Date: Tue, 17 Nov 2020 18:15:32 +0330 Subject: [PATCH 009/124] Correct for new GitHub default branch (#5055) * Correct for new GitHub default branch This PR corrects the default branch of GitHub from master to main. This is ne GitHub repository configuration from Oct 1st, 2020 * Update Saving to a Git service.tid GitLab still uses `master` as default branch. * Add Kookma plugins as resources Some of Kookma resources including TW-Scripts, Commander, Trashbin, Todolist has been added. * Revert "Add Kookma plugins as resources" This reverts commit 199fce3a08f8e21c776c7e37734b0d36753bb3e8. --- editions/tw5.com/tiddlers/saving/Saving to a Git service.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid b/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid index b6bb269db..ab4186f6c 100644 --- a/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid +++ b/editions/tw5.com/tiddlers/saving/Saving to a Git service.tid @@ -17,7 +17,7 @@ Saving to a Git service is configured in the [[$:/ControlPanel]] in the ''Git Se * ''Username'' - (mandatory) the username for the Git service account used for saving changes * ''Password'' - (mandatory) the password, OAUTH token or personal access token for the specified account. Note that GitHub permits [[several different mechanisms|https://developer.github.com/v3/#authentication]] for authentication * ''Repository'' - (mandatory) the name of the Git repository. Both the owner name and the repository name must be specified. For example `Jermolene/TiddlyWiki5` -* ''Branch'' - (optional) the name of the branch to be used within the Git repository. Defaults to `master` +* ''Branch'' - (optional) the name of the branch to be used within the Git repository. Defaults to `main` (~GitHub) or `master` (~GitLab)" * ''Path'' - (optional) the path to the target file. Defaults to `/` * ''Filename'' - (mandatory) the filename of the target file From 8cd13e2f89ab85b47794a4f6198fbb1418775704 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" Date: Tue, 17 Nov 2020 14:47:15 +0000 Subject: [PATCH 010/124] Change default branch for GitHub saver to "main" To match GitHub's new default See also #5055 for the accompanying docs change --- core/modules/savers/github.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/savers/github.js b/core/modules/savers/github.js index 7585db34e..2d59f45ff 100644 --- a/core/modules/savers/github.js +++ b/core/modules/savers/github.js @@ -26,7 +26,7 @@ GitHubSaver.prototype.save = function(text,method,callback) { repo = this.wiki.getTiddlerText("$:/GitHub/Repo"), path = this.wiki.getTiddlerText("$:/GitHub/Path",""), filename = this.wiki.getTiddlerText("$:/GitHub/Filename"), - branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "master", + branch = this.wiki.getTiddlerText("$:/GitHub/Branch") || "main", endpoint = this.wiki.getTiddlerText("$:/GitHub/ServerURL") || "https://api.github.com", headers = { "Accept": "application/vnd.github.v3+json", From 684f13fbcbb73ce3c56b0ad83a91330f4677a213 Mon Sep 17 00:00:00 2001 From: Bram Chen Date: Tue, 17 Nov 2020 22:47:31 +0800 Subject: [PATCH 011/124] Add chinese translations for `ConfirmAction` (#5056) --- languages/zh-Hans/Misc.multids | 1 + languages/zh-Hant/Misc.multids | 1 + 2 files changed, 2 insertions(+) diff --git a/languages/zh-Hans/Misc.multids b/languages/zh-Hans/Misc.multids index 9349c1157..8d94c60e9 100644 --- a/languages/zh-Hans/Misc.multids +++ b/languages/zh-Hans/Misc.multids @@ -10,6 +10,7 @@ ConfirmCancelTiddler: 您确定要放弃对条目 "<$text text=<>/>" 的 ConfirmDeleteTiddler: 您确定要删除条目 "<$text text=<<title>>/>"? ConfirmOverwriteTiddler: 您确定要复写条目 "<$text text=<<title>>/>"? ConfirmEditShadowTiddler: 您即将要编辑默认条目,任何更改将会复盖默认的系统,使未来的升级不寻常。您确定要编辑 "<$text text=<<title>>/>"? +ConfirmAction: 是否要继续? Count: 计数 DefaultNewTiddlerTitle: 新条目 Diffs/CountMessage: <<diff-count>> 个差异 diff --git a/languages/zh-Hant/Misc.multids b/languages/zh-Hant/Misc.multids index e4c739830..008ded4fc 100644 --- a/languages/zh-Hant/Misc.multids +++ b/languages/zh-Hant/Misc.multids @@ -10,6 +10,7 @@ ConfirmCancelTiddler: 您確定要放棄對條目 "<$text text=<<title>>/>" 的 ConfirmDeleteTiddler: 您確定要刪除條目 "<$text text=<<title>>/>"? ConfirmOverwriteTiddler: 您確定要覆寫條目 "<$text text=<<title>>/>"? ConfirmEditShadowTiddler: 您即將要編輯預設條目,任何更改將會覆蓋預設的系統,使未來的升級不尋常。您確定要編輯 "<$text text=<<title>>/>"? +ConfirmAction: 是否要繼續? Count: 計數 DefaultNewTiddlerTitle: 新條目 Diffs/CountMessage: <<diff-count>> 個差異 From eae3da0e9de40e00eefa3589a6a4a9534d314c2c Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Tue, 17 Nov 2020 20:05:32 +0100 Subject: [PATCH 012/124] Make sidebarsegments/search-results-count work with all search tabs (#5062) --- core/ui/SideBarSegments/search.tid | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/core/ui/SideBarSegments/search.tid b/core/ui/SideBarSegments/search.tid index ac96fa63b..4e7e6eb72 100644 --- a/core/ui/SideBarSegments/search.tid +++ b/core/ui/SideBarSegments/search.tid @@ -8,11 +8,13 @@ tags: $:/tags/SideBarSegment <$button popup=<<qualify "$:/state/popup/search-dropdown">> class="tc-btn-invisible"> {{$:/core/images/down-arrow}} <$list filter="[{$(searchTiddler)$}minlength{$:/config/Search/MinLength}limit[1]]" variable="listItem"> -<$set name="searchTerm" value={{{ [<searchTiddler>get[text]] }}}> -<$set name="resultCount" value="""<$count filter="[!is[system]search<searchTerm>]"/>"""> +<$vars userInput={{{ [<searchTiddler>get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}> +<$vars primaryListFilter={{{ [<configTiddler>get[first-search-filter]] }}} secondaryListFilter={{{ [<configTiddler>get[second-search-filter]] }}}> +<$set name="resultCount" value="""<$count filter="[subfilter<primaryListFilter>] =[subfilter<secondaryListFilter>]"/>"""> {{$:/language/Search/Matches}} </$set> -</$set> +</$vars> +</$vars> </$list> </$button> \end From 6d5ea90bfd33a87d520f3b7a17acad019abb235d Mon Sep 17 00:00:00 2001 From: Mohammad Rahmani <830394+kookma@users.noreply.github.com> Date: Tue, 17 Nov 2020 22:37:32 +0330 Subject: [PATCH 013/124] Add resources by Mohammad (#5061) * Correct for new GitHub default branch This PR corrects the default branch of GitHub from master to main. This is ne GitHub repository configuration from Oct 1st, 2020 * Update Saving to a Git service.tid GitLab still uses `master` as default branch. * Add Kookma plugins as resources Some of Kookma resources including TW-Scripts, Commander, Trashbin, Todolist has been added. * Revert "Add Kookma plugins as resources" This reverts commit 199fce3a08f8e21c776c7e37734b0d36753bb3e8. * Adding Resources by Mohammad This PR adds resources created by Mohammad mostly in GitHub --- .../resources/Favorites by Mohammad.tid | 20 +++++++++++ .../GitHub Saver Tutorial by Mohammad.tid | 25 ++++++++++++++ .../Kookma Plugin Library by Mohammad.tid | 17 ++++++++++ .../resources/Refnotes by Mohammad.tid | 24 +++++++++++++ .../RegExp in Tiddlywiki by Mohammad.tid | 21 ++++++++++++ .../resources/Searchwikis by Mohammad.tid | 23 +++++++++++++ .../resources/Semantic Colors by Mohammad.tid | 24 +++++++++++++ .../resources/Shiraz by Mohammad.tid | 34 +++++++++++++++++++ .../resources/Slider by Mohammad.tid | 20 +++++++++++ .../resources/TW-Scripts by Mohammad.tid | 24 +++++++++++++ .../Tiddler Commander by Mohammad.tid | 27 +++++++++++++++ .../resources/Tiddlyshow by Mohammad.tid | 18 ++++++++++ .../resources/Timelines by Mohammad.tid | 16 +++++++++ .../resources/Todolist by Mohammad.tid | 16 +++++++++ .../resources/Trashbin by Mohammad.tid | 16 +++++++++ .../resources/Utility by Mohammad.tid | 15 ++++++++ 16 files changed, 340 insertions(+) create mode 100644 editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid create mode 100644 editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid diff --git a/editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid new file mode 100644 index 000000000..4715cbc3f --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid @@ -0,0 +1,20 @@ +created: 20201117155737569 +creator: Mohammad +modified: 20201117155943559 +modifier: Mohammad +tags: Resources Plugings +title: Favorites by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Favorites/ + +Favorites plugin is a set of tool for creating favorites (bookmarks) in Tiddlywiki. Each favorite item is a shortcut to a tiddler. + +{{!!url}} + +A favorite item also called a bookmark is a shortcut, you are creating for quick access to it. You can access that bookmark at any time and view that as many times as you want without having to search and find it again. + +The Favorites plugin contains three modes + +* flat mode: one favorite list, no folder +* structured mode: use folder, search tool, export and delete tool +* frozen list: read only, simple table of content style diff --git a/editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid new file mode 100644 index 000000000..0db8ff926 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid @@ -0,0 +1,25 @@ +created: 20201117163027900 +creator: Mohammad +modified: 20201117163855463 +modifier: Mohammad +tags: Resources +title: GitHub Saver Tutorial by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW5-GitHub-Saver/ + +GitHub Saver is a step by step tutorial shows how to integrate Tiddlywiki 5 and GitHub Pages to create websites hosted on https://github.com/. + +{{!!url}} + +This instruction is based on Tiddlywiki single html file model, while it can use subfolder for extra materials like images, audios, videos, pdfs,... in separate folders. + +!! Other tutorials + +;Tiddlywiki, Travis-CI and GitHub Pages +:https://kookma.github.io/Tiddlywiki-Travis-CI/ +:This wiki shows how to set up websites hosted on [[GitHub Pages|https://pages.github.com/]] using [[Travis-CI|https://travis-ci.org]] and [[Tiddlywiki 5|https://tiddlywiki.com]] on Node.js. + + +;Tiddlywiki and GitHub Pages +:https://kookma.github.io/Tiddlywiki-and-GitHub-Pages/ +:This instruction is based on local edit, save and push to GitHub. It does NOT use the new GitHub Saver mechanism (requires TW 5.1.20+) which lets edit and save directly from Tiddlywiki! \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid new file mode 100644 index 000000000..27ae0a35e --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid @@ -0,0 +1,17 @@ +created: 20201117160603290 +creator: Mohammad +modified: 20201117160819308 +modifier: Mohammad +tags: Resources Plugings +title: Kookma Plugin Library by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-PluginLibrary/ + +This library contains most useful plugins developed under the name [[Kookma|https://github.com/kookma]] for Tiddlywiki 5. + +{{!!url}} + + +It has two parts + +The plugin library introduces a very simple mechanism like Tiddlywiki Official Plugin Library to let select among the published plugins and install any number of them you like. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid new file mode 100644 index 000000000..2dfb6e964 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid @@ -0,0 +1,24 @@ +created: 20201117161853918 +creator: Mohammad +modified: 20201117162122822 +modifier: Mohammad +tags: Resources Plugings +title: Refnotes by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/Refnotes/ + +Refnotes plugin is a set of macros and stylesheets for creating abbreviations, footnotes and citations. It also makes tables of footnotes, abbreviations (glossaery) and references (bibliography table). + +{{!!url}} + +Refnotes contains codes and elements to + +;Create and insert +:Abbreviation +:Footnote +:Reference + +;Create tables of +:Abbreviations or glossary +:Footnotes and endnote +:References (bibliography) using different output style \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid new file mode 100644 index 000000000..4bd091698 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid @@ -0,0 +1,21 @@ +created: 20201117164024930 +creator: Mohammad +modified: 20201117164308641 +modifier: Mohammad +tags: Resources +title: RegExp in Tiddlywiki by Mohammad +type: text/vnd.tiddlywiki +url: http://tw-regexp.tiddlyspot.com/ + +~RegExp in Tiddlywiki contains practical use cases of reular expression in Tiddlywiki. + +{{!!url}} + +The regular expression is a way to describe complex search patterns using sequences of characters . + +~RegExp in Tiddlywiki has four main parts + +* Using regular expression to match a pattern in tiddler title +* Using regular expression to match a pattern in tiddler fields excluding tiddler text (body) +* Using regular expression to match a pattern in tiddler body (text field) +* Using regular expression for validation like username, password, etc. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid new file mode 100644 index 000000000..77ced56fb --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid @@ -0,0 +1,23 @@ +created: 20201117160302426 +creator: Mohammad +modified: 20201117160443306 +modifier: Mohammad +tags: Resources Plugings +title: Searchwikis by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Searchwikis/ + +Searchwikis plugin uses index (dataTiddler) to search multiple external Tiddlywikis. + +{{!!url}} + + +It has two parts + +# An indexer, to build an index of all tiddlers in an external wiki +# A search tool to search indexes and display a link to a tiddler found in an external wiki + +Then one master wiki can hosts many index tiddlers and lets to search several external wikis through index tiddlers. + +Searchwikis enable to have a central wiki and search all other wikis from one place. + diff --git a/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid new file mode 100644 index 000000000..34963f263 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid @@ -0,0 +1,24 @@ +created: 20201117162254751 +creator: Mohammad +modified: 20201117162601326 +modifier: Mohammad +tags: Resources +title: Semantic Colors by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Semantic-Colors/ + +Semantic colors are set of CSS to apply colorful theme to individual tiddlers for categorization purpose. + +{{!!url}} + +Tiddlywiki "semantic colors" has two objectives: + +# How it is simply possible to apply theme to an individual tiddler +# Use semantic colors for categorization + +;Some use cases +:Learning materials (each topic, category can have dedicated semantic color, like learning a foreign language) +:Slideshow (section divider, each part can have a semantic color) +:Books and tutorials ( different semantic colors can be applied to chapters, specific subjects, like example tiddlers) +:Visual tags (instead of looking for tag bar and see to what category this subject (tiddler) belongs, you can identify it by its semantic color) + diff --git a/editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid new file mode 100644 index 000000000..3c31679f5 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid @@ -0,0 +1,34 @@ +created: 20201116204317018 +creator: Mohammad +modified: 20201116210618803 +modifier: Mohammad +tags: Resources Plugings +title: Shiraz by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Shiraz/ + +Shiraz plugin is a very small in size and framework to create stylish contents in Tiddlywiki. + +{{!!url}} + +Shiraz plugin contains extended markups, macros, styles, and many customization to empty Tiddlywiki and can be used as a ''starter kit''. + +Some of Shiraz features are: + +* Customized elements like, alerts, cards, panels, badges +* Dynamic tables +* Sortable tables +* Display on demand, slider, and details +* Images, basic image macros, slidein, and overlay images, polaroid and pretty images +* Table customization tools +* Sticky footer +* Multi columns tiddler +* Multi column story river +* List search +* Badge status +* Notebook style +* Test utilities +* Stylish buttons + + +Adding Shiraz plugin to any Tiddlywiki, convert it to a full production tool. Shiraz uses modified CSS classes from [[Bootstrap|https://getbootstrap.com/]]. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid new file mode 100644 index 000000000..b8b14cddb --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid @@ -0,0 +1,20 @@ +created: 20201117162655614 +creator: Mohammad +modified: 20201117162926714 +modifier: Mohammad +tags: Resources Plugings +title: Slider by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/slider/ + +Slider is a plugin to create an ordered set of tiddlers also called Trail. + +{{!!url}} + +A trail can be used to create a sequence of selected contents like step by step tutorial, guided help, lessons and similar. + +The slider plugin user interface contains three sections + +* A sidebar tab called Trails to manage trails +* A dashboard for each trail (where trail structure is managed) +* Tiddlers in a trail, also called slides diff --git a/editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid new file mode 100644 index 000000000..f319938f7 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid @@ -0,0 +1,24 @@ +created: 20180830194141190 +creator: Mohammad +modified: 20201116203625120 +modifier: Mohammad +tags: Resources +title: TW-Scripts by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Scripts/ + +TW-Scripts is one of the most comprehensive collections of solutions for Tiddlywiki 5. + +{{!!url}} + +TW-Scripts includes: + +* Collected solutions to questions in [[Tiddlywiki Google groups|https://groups.google.com/group/TiddlyWiki]] +* Learn through examples +* Templates, stylesheets +* Wikitext, macros, and snippets +* Tips and tricks +* Search tools  + + + diff --git a/editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid new file mode 100644 index 000000000..959290950 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid @@ -0,0 +1,27 @@ +created: 20201116203717105 +creator: Mohammad +modified: 20201116204652385 +modifier: Mohammad +tags: Resources Plugings +title: Tiddler Commander by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Commander/ + +Tiddler Commander plugin, in short ''Commander'' is a unique tool for batch operations on tiddlers. + +{{!!url}} + +Commander has many features including: + +* Bulk tiddler creation/deletion +* Selective operation +* Combo search to filter and select tiddlers +* Title operation: add, remove prefixes and suffixes, also remove cahras form begining and end of title (on renaming tiddlers, [[relink|https://flibbles.github.io/tw5-relink/]] can be used to update title in other tiddlers) +* Tag operation: add, remove, replace +* Field operation: add, remove, rename, and set field value +* ~SnR, search and replace in all fields including text, tags, //title//, and common fields +* Inspect, to review and inspect tiddlers in one place, scroll among them and edit all fields (including common fields), tags, text (title is an exception!) +* Log, create logs of all operations +* Search, //save and load// any combination of filter search + + diff --git a/editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid new file mode 100644 index 000000000..67d6b22ad --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid @@ -0,0 +1,18 @@ +created: 20201117160944367 +creator: Mohammad +modified: 20201117162735263 +modifier: Mohammad +tags: Resources Plugings +title: Tiddlyshow by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/Tiddlyshow/ + +Tiddlyshow is a small application of Tiddlywiki for presentation and slideshow. It can also be used as a plugin. + +{{!!url}} + +Tiddlyshow contains the following features + +* Tools for preparing slides +* Shortcut keys for navigation (forward and backward) +* Themes to colorify and customize the slideshow diff --git a/editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid new file mode 100644 index 000000000..ccc15be78 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid @@ -0,0 +1,16 @@ +created: 20201117161434779 +creator: Mohammad +modified: 20201117161728094 +modifier: Mohammad +tags: Resources Plugings +title: Timelines by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Timelines/ + +Timelines plugin is for creating vertical and horizontal timeline and sequences. + +{{!!url}} + +The content or description and data of events are stored in individual tiddlers. + +Timelines contain two timeline macros and two sequence macros. A sequence macro shows event contents in sequence not necessarily in chronological order. The order can be determined by tag or list field or other methods. diff --git a/editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid new file mode 100644 index 000000000..7144521ee --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid @@ -0,0 +1,16 @@ +created: 20201116210711381 +creator: Mohammad +modified: 20201116212041642 +modifier: Mohammad +tags: Resources Plugings +title: Todolist by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Todolist/ + +Todolist is a small pure wikitext plugin, contain all tools to work with todo list. + +{{!!url}} + +With Todolist, easily organize and prioritize your tasks and projects so you’ll always know exactly what to work on next. + +Todolist creates custom UI and lets you to add new items, set priority, done/undone items, archive, delete. Using Todolist plugin it is possible to create several todo lists in one Tiddlywiki. diff --git a/editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid new file mode 100644 index 000000000..76af19e07 --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid @@ -0,0 +1,16 @@ +created: 20201117155328920 +creator: Mohammad +modified: 20201117155604253 +modifier: Mohammad +tags: Resources Plugings +title: Trashbin by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Trashbin/ + +The concept behind Trashbin plugin is to have a simple mechanism to move deleted tiddlers to Trashbin and be able to restore them later if required. + +{{!!url}} + +The trash (also known as the Recycle Bin in Microsoft Windows) is a temporary storage for tiddlers that have been deleted in a Tiddlywiki by the user, but not yet permanently erased. + +Typically, a trash bin is presented as a special storage, allowing the user to browse deleted (removed) tiddlers, undelete those that were deleted by mistake, or delete them permanently (either one by one, or by the "Empty Trash" function). diff --git a/editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid new file mode 100644 index 000000000..97ab74b0f --- /dev/null +++ b/editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid @@ -0,0 +1,15 @@ +created: 20201117160011169 +creator: Mohammad +modified: 20201117160235750 +modifier: Mohammad +tags: Resources Plugings +title: Utility by Mohammad +type: text/vnd.tiddlywiki +url: https://kookma.github.io/TW-Utility/ + +The utility plugin objective is to provide set of tools for developers and authors. + +{{!!url}} + + +These tools include simple transclusions, show raw contents of tiddlers, author tools, wikitext macros, show fields in view mode, etc. From b95f9e6000bffb563e06d644d76a34abd87f131a Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Tue, 17 Nov 2020 20:08:14 +0100 Subject: [PATCH 014/124] Partial fix for issue #4721 (#5060) * Update new-tiddler.tid * Update new-journal.tid * Update new-image.tid --- core/ui/Actions/new-image.tid | 5 +++-- core/ui/Actions/new-journal.tid | 7 ++++--- core/ui/Actions/new-tiddler.tid | 5 ++++- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/core/ui/Actions/new-image.tid b/core/ui/Actions/new-image.tid index d27d5c8c1..fc7316235 100644 --- a/core/ui/Actions/new-image.tid +++ b/core/ui/Actions/new-image.tid @@ -5,6 +5,7 @@ description: create a new image tiddler \define get-type() image/$(imageType)$ \end -<$vars imageType={{$:/config/NewImageType}}> -<$action-sendmessage $message="tm-new-tiddler" type=<<get-type>> tags={{$:/config/NewTiddler/Tags}}/> +\define get-tags() $(textFieldTags)$ $(tagsFieldTags)$ +<$vars imageType={{$:/config/NewImageType}} textFieldTags={{$:/config/NewJournal/Tags}} tagsFieldTags={{$:/config/NewJournal/Tags!!tags}}> +<$action-sendmessage $message="tm-new-tiddler" type=<<get-type>> tags=<<get-tags>>/> </$vars> diff --git a/core/ui/Actions/new-journal.tid b/core/ui/Actions/new-journal.tid index 4c5082f78..b5d1fe09f 100644 --- a/core/ui/Actions/new-journal.tid +++ b/core/ui/Actions/new-journal.tid @@ -2,13 +2,14 @@ title: $:/core/ui/Actions/new-journal tags: $:/tags/Actions description: create a new journal tiddler -<$vars journalTitleTemplate={{$:/config/NewJournal/Title}} journalTags={{$:/config/NewJournal/Tags}} journalText={{$:/config/NewJournal/Text}}> +\define get-tags() $(textFieldTags)$ $(tagsFieldTags)$ +<$vars journalTitleTemplate={{$:/config/NewJournal/Title}} textFieldTags={{$:/config/NewJournal/Tags}} tagsFieldTags={{$:/config/NewJournal/Tags!!tags}} journalText={{$:/config/NewJournal/Text}}> <$wikify name="journalTitle" text="""<$macrocall $name="now" format=<<journalTitleTemplate>>/>"""> <$reveal type="nomatch" state=<<journalTitle>> text=""> -<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<journalTags>> text={{{ [<journalTitle>get[]] }}}/> +<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<get-tags>> text={{{ [<journalTitle>get[]] }}}/> </$reveal> <$reveal type="match" state=<<journalTitle>> text=""> -<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<journalTags>> text=<<journalText>>/> +<$action-sendmessage $message="tm-new-tiddler" title=<<journalTitle>> tags=<<get-tags>> text=<<journalText>>/> </$reveal> </$wikify> </$vars> diff --git a/core/ui/Actions/new-tiddler.tid b/core/ui/Actions/new-tiddler.tid index 4a6eeac7b..c919a109e 100644 --- a/core/ui/Actions/new-tiddler.tid +++ b/core/ui/Actions/new-tiddler.tid @@ -2,4 +2,7 @@ title: $:/core/ui/Actions/new-tiddler tags: $:/tags/Actions description: create a new empty tiddler -<$action-sendmessage $message="tm-new-tiddler" tags={{$:/config/NewTiddler/Tags}}/> +\define get-tags() $(textFieldTags)$ $(tagsFieldTags)$ +<$vars textFieldTags={{$:/config/NewTiddler/Tags}} tagsFieldTags={{$:/config/NewTiddler/Tags!!tags}}> +<$action-sendmessage $message="tm-new-tiddler" tags=<<get-tags>>/> +</$vars> From 527638d5e60114653385ed39dc55c736a67e58d2 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Tue, 17 Nov 2020 20:12:41 +0100 Subject: [PATCH 015/124] Improved status messages in ImportListing to remove redundant and irrelevant messages (#5059) --- core/language/en-GB/Import.multids | 16 ++++++++-------- core/modules/upgraders/plugins.js | 2 +- core/modules/widgets/navigator.js | 1 + core/ui/ImportListing.tid | 10 +++++++--- 4 files changed, 17 insertions(+), 12 deletions(-) diff --git a/core/language/en-GB/Import.multids b/core/language/en-GB/Import.multids index cc2c6c143..3b3308ad5 100644 --- a/core/language/en-GB/Import.multids +++ b/core/language/en-GB/Import.multids @@ -18,11 +18,11 @@ Listing/Rename/Prompt: Rename to: Listing/Rename/ConfirmRename: Rename tiddler Listing/Rename/CancelRename: Cancel Listing/Rename/OverwriteWarning: A tiddler with this title already exists. -Upgrader/Plugins/Suppressed/Incompatible: Blocked incompatible or obsolete plugin -Upgrader/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>> being older than existing <<existing>>) -Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>> -Upgrader/State/Suppressed: Blocked temporary state tiddler -Upgrader/System/Suppressed: Blocked system tiddler -Upgrader/System/Warning: Core module tiddler -Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable -Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/> +Upgrader/Plugins/Suppressed/Incompatible: Blocked incompatible or obsolete plugin. +Upgrader/Plugins/Suppressed/Version: Blocked plugin (due to incoming <<incoming>> not being newer than existing <<existing>>). +Upgrader/Plugins/Upgraded: Upgraded plugin from <<incoming>> to <<upgraded>>. +Upgrader/State/Suppressed: Blocked temporary state tiddler. +Upgrader/System/Suppressed: Blocked system tiddler. +Upgrader/System/Warning: Core module tiddler. +Upgrader/System/Alert: You are about to import a tiddler that will overwrite a core module tiddler. This is not recommended as it may make the system unstable. +Upgrader/ThemeTweaks/Created: Migrated theme tweak from <$text text=<<from>>/>. diff --git a/core/modules/upgraders/plugins.js b/core/modules/upgraders/plugins.js index 83c762897..a7dd02982 100644 --- a/core/modules/upgraders/plugins.js +++ b/core/modules/upgraders/plugins.js @@ -57,7 +57,7 @@ exports.upgrade = function(wiki,titles,tiddlers) { // Reject the incoming plugin by blanking all its fields if($tw.utils.checkVersions(existingTiddler.fields.version,incomingTiddler.version)) { tiddlers[title] = Object.create(null); - messages[title] = requiresReload + $tw.language.getString("Import/Upgrader/Plugins/Suppressed/Version",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}}); + messages[title] = $tw.language.getString("Import/Upgrader/Plugins/Suppressed/Version",{variables: {incoming: incomingTiddler.version, existing: existingTiddler.fields.version}}); return; } } diff --git a/core/modules/widgets/navigator.js b/core/modules/widgets/navigator.js index 189765396..c44a24afb 100755 --- a/core/modules/widgets/navigator.js +++ b/core/modules/widgets/navigator.js @@ -529,6 +529,7 @@ NavigatorWidget.prototype.handleImportTiddlersEvent = function(event) { $tw.utils.each(importData.tiddlers,function(tiddler,title) { if($tw.utils.count(tiddler) === 0) { newFields["selection-" + title] = "unchecked"; + newFields["suppressed-" + title] = "yes"; } }); // Save the $:/Import tiddler diff --git a/core/ui/ImportListing.tid b/core/ui/ImportListing.tid index a2c371807..e3705abab 100644 --- a/core/ui/ImportListing.tid +++ b/core/ui/ImportListing.tid @@ -7,13 +7,17 @@ title: $:/core/ui/ImportListing \define payloadTitleFilter() [<currentTiddler>get<renameField>minlength[1]else<payloadTiddler>] \define overWriteWarning() +<$list filter="[<currentTiddler>!has<suppressedField>]"> <$text text={{{[subfilter<payloadTitleFilter>!is[tiddler]then[]] ~[<lingo-base>addsuffix[Listing/Rename/OverwriteWarning]get[text]]}}}/> +</$list> \end \define selectionField() selection-$(payloadTiddler)$ \define renameField() rename-$(payloadTiddler)$ +\define suppressedField() suppressed-$(payloadTiddler)$ + \define newImportTitleTiddler() $:/temp/NewImportTitle-$(payloadTiddler)$ \define previewPopupState() $(currentTiddler)$!!popup-$(payloadTiddler)$ @@ -44,15 +48,15 @@ title: $:/core/ui/ImportListing <$list filter="[all[current]plugintiddlers[]sort[title]]" variable="payloadTiddler"> <tr> <td> -<$checkbox field=<<selectionField>> checked="checked" unchecked="unchecked" default="checked"/> +<$checkbox field=<<selectionField>> checked="checked" unchecked="unchecked" default="checked" disabled={{{[<currentTiddler>has<suppressedField>then[yes]else[no]]}}}/> </td> <td> <$reveal type="nomatch" state=<<renameFieldState>> text="yes" tag="div"> <$reveal type="nomatch" state=<<previewPopupState>> text="yes" tag="div" class="tc-flex"> -<$button class="tc-btn-invisible tc-btn-dropdown tc-flex-grow-1 tc-word-break" set=<<previewPopupState>> setTo="yes"> +<$button class="tc-btn-invisible tc-btn-dropdown tc-flex-grow-1 tc-word-break" set=<<previewPopupState>> setTo="yes" disabled={{{[<currentTiddler>has<suppressedField>then[yes]else[no]]}}}> <span class="tc-small-gap-right">{{$:/core/images/right-arrow}}</span><$text text={{{[subfilter<payloadTitleFilter>]}}}/> </$button> -<$button class="tc-btn-invisible" set=<<renameFieldState>> setTo="yes" tooltip={{{[<lingo-base>addsuffix[Listing/Rename/Tooltip]get[text]]}}}>{{$:/core/images/edit-button}}</$button> +<$list filter="[<currentTiddler>!has<suppressedField>]"><$button class="tc-btn-invisible" set=<<renameFieldState>> setTo="yes" tooltip={{{[<lingo-base>addsuffix[Listing/Rename/Tooltip]get[text]]}}}>{{$:/core/images/edit-button}}</$button></$list> </$reveal> <$reveal type="match" state=<<previewPopupState>> text="yes" tag="div"> <$button class="tc-btn-invisible tc-btn-dropdown" set=<<previewPopupState>> setTo="no"> From d181b9651895943521832908a2fee6ab80aa2d71 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 18 Nov 2020 12:05:06 +0000 Subject: [PATCH 016/124] Wikitext parser: Refactor a poorly written utility function --- core/modules/parsers/wikiparser/wikiparser.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/core/modules/parsers/wikiparser/wikiparser.js b/core/modules/parsers/wikiparser/wikiparser.js index 673176038..dbeed9de2 100644 --- a/core/modules/parsers/wikiparser/wikiparser.js +++ b/core/modules/parsers/wikiparser/wikiparser.js @@ -386,22 +386,18 @@ Amend the rules used by this instance of the parser WikiParser.prototype.amendRules = function(type,names) { names = names || []; // Define the filter function - var keepFilter; + var target; if(type === "only") { - keepFilter = function(name) { - return names.indexOf(name) !== -1; - }; + target = true; } else if(type === "except") { - keepFilter = function(name) { - return names.indexOf(name) === -1; - }; + target = false; } else { return; } // Define a function to process each of our rule arrays var processRuleArray = function(ruleArray) { for(var t=ruleArray.length-1; t>=0; t--) { - if(!keepFilter(ruleArray[t].rule.name)) { + if((names.indexOf(ruleArray[t].rule.name) === -1) === target) { ruleArray.splice(t,1); } } From 061b75741ba33ffda2472fdb3d0d7b2e13b1bd3a Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 18 Nov 2020 13:14:19 +0000 Subject: [PATCH 017/124] Fix GitHub Actions Copied from 4ecd885a0c990967df96cbb98b3b7bd6593c1415 which fixes #4885 --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ac889fe9..f377b3921 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,9 +39,9 @@ jobs: - name: "Set dynamic environment variables" run: | TW5_BUILD_BRANCH=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }') - echo ::set-env name=TW5_BUILD_BRANCH::${TW5_BUILD_BRANCH} - echo ::set-env name=TW5_BUILD_VERSION::$(./bin/get-plugin-library-version-number) - echo ::set-env name=TW5_BUILD_DETAILS::Prerelease built from branch \'$TW5_BUILD_BRANCH\' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z') + echo "TW5_BUILD_BRANCH=${TW5_BUILD_BRANCH}" >> $GITHUB_ENV + echo "TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)" >> $GITHUB_ENV + echo "TW5_BUILD_DETAILS=Prerelease built from branch '$TW5_BUILD_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')" >> $GITHUB_ENV - run: "./bin/build-site.sh" - run: "./bin/ci-push.sh" env: @@ -65,9 +65,9 @@ jobs: - name: "Set dynamic environment variables" run: | TW5_BUILD_BRANCH=$(echo $GITHUB_REF | awk 'BEGIN { FS = "/" } ; { print $3 }') - echo ::set-env name=TW5_BUILD_BRANCH::${TW5_BUILD_BRANCH} - echo ::set-env name=TW5_BUILD_VERSION::$(./bin/get-plugin-library-version-number) - echo ::set-env name=TW5_BUILD_DETAILS::Built from branch \'$TW5_BUILD_BRANCH\' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z') + echo "TW5_BUILD_BRANCH=${TW5_BUILD_BRANCH}" >> $GITHUB_ENV + echo "TW5_BUILD_VERSION=$(./bin/get-plugin-library-version-number)" >> $GITHUB_ENV + echo "TW5_BUILD_DETAILS=Built from branch '$TW5_BUILD_BRANCH' at commit $(git rev-parse HEAD) of $(git remote get-url origin) at $(date +'%F %T %Z')" >> $GITHUB_ENV - run: "./bin/build-site.sh" - run: "./bin/ci-push.sh" env: From 6f8dca956bd894ef52f66c6f280e9ed7a7e7e20d Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Wed, 18 Nov 2020 16:50:40 +0100 Subject: [PATCH 018/124] Colour code ImportListing rows (#5067) --- core/ui/ImportListing.tid | 2 +- themes/tiddlywiki/vanilla/base.tid | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/core/ui/ImportListing.tid b/core/ui/ImportListing.tid index e3705abab..04ccd9a79 100644 --- a/core/ui/ImportListing.tid +++ b/core/ui/ImportListing.tid @@ -46,7 +46,7 @@ title: $:/core/ui/ImportListing </th> </tr> <$list filter="[all[current]plugintiddlers[]sort[title]]" variable="payloadTiddler"> -<tr> +<tr class={{{[<currentTiddler>has<suppressedField>then[tc-row-disabled]] ~[subfilter<payloadTitleFilter>is[tiddler]then[tc-row-warning]] }}}> <td> <$checkbox field=<<selectionField>> checked="checked" unchecked="unchecked" default="checked" disabled={{{[<currentTiddler>has<suppressedField>then[yes]else[no]]}}}/> </td> diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index eb57435f8..dc9b99f08 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -2086,6 +2086,15 @@ html body.tc-body.tc-single-tiddler-window { width: 30%; } +.tc-import-table .tc-row-disabled { + background: <<colour very-muted-foreground>>10; + opacity: 0.8; +} + +.tc-import-table .tc-row-warning { + background: <<colour diff-delete-background>>50; +} + /* ** Alerts */ From 1a8c6fdc4bd33caf256c707dbe88defd134ab6ff Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Wed, 18 Nov 2020 16:56:38 +0100 Subject: [PATCH 019/124] Docs: Added example of how to remove stop words (#5066) * Added example of how to remove stop words * Moved filter operator example tiddlers to correct folder --- .../examples/How to remove stop words.tid | 28 +++++++++++++++++++ .../search-replace Operator (Examples).tid | 7 +++-- .../examples/sortsub Operator (Examples).tid | 4 ++- .../toggle Operator (Examples).tid | 0 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 editions/tw5.com/tiddlers/filters/examples/How to remove stop words.tid rename editions/tw5.com/tiddlers/filters/{ => examples}/search-replace Operator (Examples).tid (91%) rename editions/tw5.com/tiddlers/filters/{ => examples}/toggle Operator (Examples).tid (100%) diff --git a/editions/tw5.com/tiddlers/filters/examples/How to remove stop words.tid b/editions/tw5.com/tiddlers/filters/examples/How to remove stop words.tid new file mode 100644 index 000000000..a228e4404 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/How to remove stop words.tid @@ -0,0 +1,28 @@ +created: 20201118094513209 +modified: 20201118103414384 +tags: [[Operator Examples]] [[search-replace Operator]] [[sortsub Operator]] +title: How to remove stop words +type: text/vnd.tiddlywiki + +\define book-list() +[[A Tale of Two Cities]] +[[The Dice Man]] +[[A New Kind of Science]] +[[The Recursive Universe]] +[[Great Expectations]] +[[Animal Farm]] +\end + +\define compare-without-stopwords() +[<currentTiddler>search-replace:i:regexp[^The |A ],[]] +\end + +You can use the [[search-replace Operator]] in combination with the [[sortsub Operator]] to ignore stop words like "A" and "The" at the beginning of titles when sorting. (Note for example that "A Tale of Two Cities" sorts under "T" rather than "A") +<<.operator-example 6 "[enlist<book-list>sortsub<compare-without-stopwords>]">> + +You can also customise the listing so that "A Tale of Two Cities" is listed as "Tale of Two Cities, A" but still links to the correct tiddler. +<<wikitext-example-without-html """<ul> +<$list filter="[enlist<book-list>sortsub<compare-without-stopwords>]"> +<li><$link><$text text={{{[<currentTiddler>search-replace:i:regexp[(^The |A )(.*)],[$2, $1]]}}}/></$link></li> +</$list> +</ul>""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/search-replace Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/search-replace Operator (Examples).tid similarity index 91% rename from editions/tw5.com/tiddlers/filters/search-replace Operator (Examples).tid rename to editions/tw5.com/tiddlers/filters/examples/search-replace Operator (Examples).tid index 79c9b60b6..5bcb57509 100644 --- a/editions/tw5.com/tiddlers/filters/search-replace Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/search-replace Operator (Examples).tid @@ -1,5 +1,5 @@ created: 20201107112846692 -modified: 20201107113536230 +modified: 20201118103305351 tags: [[Operator Examples]] [[search-replace Operator]] title: search-replace Operator (Examples) type: text/vnd.tiddlywiki @@ -20,6 +20,7 @@ Replace all matches of a string irrespective of case: <<.operator-example 3 """[[Hello There]search-replace:gi[H],[]]""">> You can also use regular expression capture groups in the replacement string: - `\define names() (\w+)\s(\w+)` -<<.operator-example 4 """[[John Smith]search-replace::regexp<names>,[$2,$1]]""" >> \ No newline at end of file +<<.operator-example 4 """[[John Smith]search-replace::regexp<names>,[$2,$1]]""" >> + +{{How to remove stop words}} diff --git a/editions/tw5.com/tiddlers/filters/examples/sortsub Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/sortsub Operator (Examples).tid index 475413155..ea91205d9 100644 --- a/editions/tw5.com/tiddlers/filters/examples/sortsub Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/sortsub Operator (Examples).tid @@ -1,5 +1,5 @@ created: 20200425110427700 -modified: 20200425110427700 +modified: 20201118103327392 tags: [[sortsub Operator]] [[Operator Examples]] title: sortsub Operator (Examples) type: text/vnd.tiddlywiki @@ -29,4 +29,6 @@ These examples make use of the following variables: <<.operator-example 4 "[!sortsub:number<compare-by-text-length>limit[10]]">> <<.operator-example 5 "[tag[Field Operators]sortsub:date<compare-by-newest-of-modified-and-created-dates>]">> +{{How to remove stop words}} + </$vars> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/toggle Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/toggle Operator (Examples).tid similarity index 100% rename from editions/tw5.com/tiddlers/filters/toggle Operator (Examples).tid rename to editions/tw5.com/tiddlers/filters/examples/toggle Operator (Examples).tid From f61906501d89f9ce2bbc77bb3badba2cd5a81a34 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 18 Nov 2020 16:31:28 +0000 Subject: [PATCH 020/124] Fix issue with Arabic translation See discussion https://groups.google.com/d/msgid/tiddlywikidev/bb2f558e-5daa-4f18-8dca-73abc61d4dbfn%40googlegroups.com @Kamal-Habash the .multids file does not allow line breaks in items. Does my fix look right? --- languages/ar-PS/ControlPanel.multids | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/languages/ar-PS/ControlPanel.multids b/languages/ar-PS/ControlPanel.multids index df17cecc4..61ca9e045 100644 --- a/languages/ar-PS/ControlPanel.multids +++ b/languages/ar-PS/ControlPanel.multids @@ -1,6 +1,5 @@ title: $:/language/ControlPanel/ -<$button set="$: DefaultTiddlers" setTo="[list[$:/StoryList]]"> Advanced/Caption: متقدم Advanced/Hint: معلومات داخلية عن هذا الوكي Appearance/Caption: مظهر خارجي @@ -9,10 +8,7 @@ Appearance/Hint: طرق لتخصيص مظهر وكي خاص بك. Basics/AnimDuration/Prompt: مدة الرسوم المتحركة Basics/AutoFocus/Prompt: موقع مؤشر الماوس الإفتراضي للتدلرز الجددة Basics/Caption: أساسيات -Basics/DefaultTiddlers/BottomHint: إستخدم [[أقواس مربعة مزدوجة]] للعناوين مع مسافات. أو بإمكانك إختيار -<$button set="$:/DefaultTiddlers" setTo="[list[$:/StoryList]]"> -الإحتفاظ بترتيب القصة -</$button> +Basics/DefaultTiddlers/BottomHint: إستخدم [[أقواس مربعة مزدوجة]] للعناوين مع مسافات. أو بإمكانك إختيار<$button set="$:/DefaultTiddlers" setTo="[list[$:/StoryList]]">الإحتفاظ بترتيب القصة</$button> Basics/DefaultTiddlers/Prompt: تدلرز مفترضة Basics/DefaultTiddlers/TopHint: أي تدلرز ستظهر عند التشغيل Basics/Language/Prompt: مرحبا! اللغة الحالية: From 37f4421ed1c7d7957d622c1fa600ac8135068471 Mon Sep 17 00:00:00 2001 From: Bram Chen <bram.chen@gmail.com> Date: Thu, 19 Nov 2020 00:39:45 +0800 Subject: [PATCH 021/124] Improve chinese status messages in ImportListing (#5064) --- languages/zh-Hans/Import.multids | 14 +++++++------- languages/zh-Hant/Import.multids | 14 +++++++------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/languages/zh-Hans/Import.multids b/languages/zh-Hans/Import.multids index 247c2e68c..a1320b5c4 100644 --- a/languages/zh-Hans/Import.multids +++ b/languages/zh-Hans/Import.multids @@ -18,11 +18,11 @@ Listing/Rename/Tooltip: 导入前重新命名条目 Listing/Rename/ConfirmRename: 重新命名条目 Listing/Rename/CancelRename: 取消 Listing/Rename/OverwriteWarning: 具有此标题的条目已存在。 -Upgrader/Plugins/Suppressed/Incompatible: 封锁的不兼容或过时插件 -Upgrader/Plugins/Suppressed/Version: 封锁的插件 (由于传入的 <<incoming>> 较现有版本 <<existing>> 旧) -Upgrader/Plugins/Upgraded: 升级插件,从 <<incoming>> 到 <<upgraded>> -Upgrader/State/Suppressed: 封锁的暂存状态条目 -Upgrader/System/Suppressed: 封锁的系统条目 -Upgrader/System/Warning: 核心模块条目 +Upgrader/Plugins/Suppressed/Incompatible: 封锁的不兼容或过时插件。 +Upgrader/Plugins/Suppressed/Version: 封锁的插件 (由于传入的 <<incoming>> 不比现有版本 <<existing>> 新)。 +Upgrader/Plugins/Upgraded: 升级插件,从 <<incoming>> 到 <<upgraded>>。 +Upgrader/State/Suppressed: 封锁的暂存状态条目。 +Upgrader/System/Suppressed: 封锁的系统条目。 +Upgrader/System/Warning: 核心模块条目。 Upgrader/System/Alert: 您即将导入一个条目会覆盖一个核心模块条目。不建议这样做,因为可能会使系统不稳定。 -Upgrader/ThemeTweaks/Created: 从 <$text text=<<from>>/> 迁移布景主题 +Upgrader/ThemeTweaks/Created: 从 <$text text=<<from>>/> 迁移布景主题。 diff --git a/languages/zh-Hant/Import.multids b/languages/zh-Hant/Import.multids index 4c6b5d3d5..d87935929 100644 --- a/languages/zh-Hant/Import.multids +++ b/languages/zh-Hant/Import.multids @@ -18,11 +18,11 @@ Listing/Rename/Tooltip: 導入前重新命名條目 Listing/Rename/ConfirmRename: 重新命名條目 Listing/Rename/CancelRename: 取消 Listing/Rename/OverwriteWarning: 具有此標題的條目已存在。 -Upgrader/Plugins/Suppressed/Incompatible: 封鎖的不相容或過時插件 -Upgrader/Plugins/Suppressed/Version: 封鎖的插件 (由於傳入的 <<incoming>> 較現有版本 <<existing>> 舊) -Upgrader/Plugins/Upgraded: 升級插件,從 <<incoming>> 到 <<upgraded>> -Upgrader/State/Suppressed: 封鎖的暫存狀態條目 -Upgrader/System/Suppressed: 封鎖的系統條目 -Upgrader/System/Warning: 核心模組條目 +Upgrader/Plugins/Suppressed/Incompatible: 封鎖的不相容或過時插件。 +Upgrader/Plugins/Suppressed/Version: 封鎖的插件 (由於傳入的 <<incoming>> 不比現有版本 <<existing>> 新)。 +Upgrader/Plugins/Upgraded: 升級插件,從 <<incoming>> 到 <<upgraded>>。 +Upgrader/State/Suppressed: 封鎖的暫存狀態條目。 +Upgrader/System/Suppressed: 封鎖的系統條目。 +Upgrader/System/Warning: 核心模組條目。 Upgrader/System/Alert: 您即將導入一個條目會覆蓋一個核心模組條目。不建議這樣做,因為可能會使系統不穩定。 -Upgrader/ThemeTweaks/Created: 從 <$text text=<<from>>/> 遷移佈景主題 +Upgrader/ThemeTweaks/Created: 從 <$text text=<<from>>/> 遷移佈景主題。 From 0be778fc27f03fd42bcd7c8d1f434925e02ae349 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 18 Nov 2020 16:56:01 +0000 Subject: [PATCH 022/124] Update Dutch translation Thanks @gernert --- languages/nl-NL/ControlPanel.multids | 5 +++++ languages/nl-NL/EditTemplate.multids | 2 ++ languages/nl-NL/Import.multids | 6 ++++++ languages/nl-NL/Misc.multids | 12 ++++++++++++ 4 files changed, 25 insertions(+) diff --git a/languages/nl-NL/ControlPanel.multids b/languages/nl-NL/ControlPanel.multids index 6c25eb77d..82b2ba946 100644 --- a/languages/nl-NL/ControlPanel.multids +++ b/languages/nl-NL/ControlPanel.multids @@ -88,6 +88,7 @@ Plugins/Reinstall/Caption: herinstalleer Plugins/Theme/Prompt: Thema's Plugins/Themes/Caption: Thema's Plugins/Themes/Hint: Thema plugins +Plugins/Updates/Hint: Beschikbare updates voor geïnstalleerde plugins Saving/Caption: Opslaan Saving/DownloadSaver/AutoSave/Description: Sta automatisch opslaan toe voor de opslagmodule Saving/DownloadSaver/AutoSave/Hint: Sla automatisch op voor de opslagmodule @@ -108,7 +109,9 @@ Saving/GitService/Branch: Doeltak (branch) voor opslaan Saving/GitService/CommitMessage: Opgeslagen door TiddlyWiki Saving/GitService/Description: Deze instellingen worden alleen gebruikt bij opslaan naar <<service-name>> Saving/GitService/Filename: Bestandsnaam van doelbestand (b.v. `index.html`) +Saving/GitService/Gitea/Caption: Gitea opslagmodule Saving/GitService/Gitea/Password: Persoonlijk toegangs-token voor API (via Gitea’s web interface: `Settings | Applications | Generate New Token`) +Saving/GitService/GitHub/Caption: ~GitHub opslagmodule Saving/GitService/GitHub/Password: Wachtwoord, OAUTH token, of persoonlijk toegangs-token (zie [[GitHub help-pagina|https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line]] voor details) Saving/GitService/GitLab/Caption: ~GitLab opslagmodule Saving/GitService/GitLab/Password: Persoonlijk toegangs-token voor API (zie [[GitLab help-pagina|https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html]] voor details) @@ -120,6 +123,8 @@ Saving/Hint: Instellingen voor opslaan van de gehele TiddlyWiki als één bestan Saving/TiddlySpot/Advanced/Heading: Geavanceerde instellingen Saving/TiddlySpot/BackupDir: Backup folder Saving/TiddlySpot/Backups: Backups +Saving/TiddlySpot/Caption: ~TiddlySpot opslagmodule +Saving/TiddlySpot/ControlPanel: ~TiddlySpot bedieningspaneel Saving/TiddlySpot/Description: Deze instellingen worden alleen gebruikt bij http://tiddlyspot.com of een vergelijkbare server Saving/TiddlySpot/Filename: Upload bestandsnaam Saving/TiddlySpot/Heading: ~TiddlySpot diff --git a/languages/nl-NL/EditTemplate.multids b/languages/nl-NL/EditTemplate.multids index d8cb1126f..3cf78980a 100644 --- a/languages/nl-NL/EditTemplate.multids +++ b/languages/nl-NL/EditTemplate.multids @@ -18,6 +18,8 @@ Shadow/Warning: Dit is een schaduwtiddler. Elke verandering overschrijft de stan Tags/Add/Button: + Tags/Add/Button/Hint: voeg label toe Tags/Add/Placeholder: labelnaam +Tags/ClearInput/Caption: verwijde ingave +Tags/ClearInput/Hint: Verwijder labelingave Tags/Dropdown/Caption: labellijst Tags/Dropdown/Hint: Toon labellijst Title/BadCharacterWarning: Waarschuwing: vermijd elk karakter van <<bad-chars>> in tiddler titels diff --git a/languages/nl-NL/Import.multids b/languages/nl-NL/Import.multids index f08222ad7..32004f3ce 100644 --- a/languages/nl-NL/Import.multids +++ b/languages/nl-NL/Import.multids @@ -10,6 +10,12 @@ Listing/Preview/DiffFields: Verschil (Velden) Listing/Preview/Fields: Velden Listing/Preview/Text: Tekst Listing/Preview/TextRaw: Tekst (Ruw) +Listing/Rename/CancelRename: Annuleer +Listing/Rename/ConfirmRename: Hernoem tiddler +Listing/Rename/OverwriteWarning: Een tiddler met deze naam bestaat al + +Listing/Rename/Prompt: Hernoem tot: +Listing/Rename/Tooltip: Hernoem tiddler voor import Listing/Select/Caption: Selecteer Listing/Status/Caption: Status Listing/Title/Caption: Titel diff --git a/languages/nl-NL/Misc.multids b/languages/nl-NL/Misc.multids index 16ad5d126..958817def 100644 --- a/languages/nl-NL/Misc.multids +++ b/languages/nl-NL/Misc.multids @@ -5,6 +5,7 @@ BinaryWarning/Prompt: Deze tiddler bevat binaire data ClassicWarning/Hint: Deze tiddler is in TiddlyWiki Classic wiki tekstformaat geschreven dat niet geheel compatibel is met TiddlyWiki versie 5. Zie https://tiddlywiki.com/static/Upgrading.html voor meer details. ClassicWarning/Upgrade/Caption: upgrade CloseAll/Button: sluit alle +ConfirmAction: Wil je doorgaan? ConfirmCancelTiddler: Wil je gemaakte wijzigingen aan de tiddler "<$text text=<<title>>/>" annuleren? ConfirmDeleteTiddler: Wil je de tiddler "<$text text=<<title>>/>" verwijderen? ConfirmEditShadowTiddler: Je staat op het punt een schaduwtiddler te wijzigen. Toekomstige automatische veranderingen (upgrades) zijn dan niet mogelijk. Wil je "<$text text=<<title>>/>" wijzigen? @@ -24,7 +25,9 @@ Encryption/Username: Gebruikersnaam Error/Caption: Fout Error/EditConflict: Bestand gewijzigd op server Error/Filter: Filterfout +Error/FilterRunPrefix: Filterfout: Onbekend voorvoegsel voor filter 'run' Error/FilterSyntax: Syntaxfout in filter expressie +Error/FormatFilterOperator: Filterfout: Onbekend achtervoegsel voor de 'format' filter operator Error/IsFilterOperator: Filterfout: Onbekende operand voor het 'is' filter Error/LoadingPluginLibrary: Fout bij laden van de pluginbibliotheek Error/NetworkErrorAlert: `<h2>''Network fout''</h2>De verbinding met de server lijkt verbroken. Mogelijk een probleem met de netwerkverbinding. Herstel de netwerkverbinding voordat verder wordt gegaan.<br><br>''Niet opgeslagen veranderingen worden gesynchroniseerd als de verbinding hersteld is''.` @@ -60,6 +63,15 @@ OfficialPluginLibrary: Officiële ~TiddlyWiki pluginbibliotheek OfficialPluginLibrary/Hint: De officiële ~TiddlyWiki pluginbibliotheek op tiddlywiki.com. Plugins, thema's en taalpaketten worden door het core team onderhouden. PluginReloadWarning: Sla op {{$:/core/ui/Buttons/save-wiki}} en ververs {{$:/core/ui/Buttons/refresh}} om wijzigingen aan plugins door te voeren RecentChanges/DateFormat: DD MMM YYYY +Shortcuts/Input/Accept/Hint: Accepteer het geselecteerde item +Shortcuts/Input/AcceptVariant/Hint: Accepteer het geselecteerde item (variant) +Shortcuts/Input/AdvancedSearch/Hint: Open geavanceerd zoeken vanuit het zoekveld in het zijpaneel +Shortcuts/Input/Cancel/Hint: Wis het input veld +Shortcuts/Input/Down/Hint: Selecteer het volgende item +Shortcuts/Input/Tab-Left/Hint: Selecteer de voorgaande tab +Shortcuts/Input/Tab-Right/Hint: Selecteer de volgende tab +Shortcuts/Input/Up/Hint: Selecteer het voorgaande item +Shortcuts/SidebarLayout/Hint: Verander de layout van het zijpaneel SystemTiddler/Tooltip: Dit is een systeem tiddler SystemTiddlers/Include/Prompt: Inclusief systeem tiddlers TagManager/Colour/Heading: Kleur From da66323dc572a2e4b4b628314ef408e68483a54c Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 18 Nov 2020 19:02:40 +0100 Subject: [PATCH 023/124] Remove 2em of whitespace from EditTemplate when there are no visible fields (#5063) * Remove 2em of whitespace from EditTemplate when there are no visible fields * Update base.tid * Update fields.tid * Update fields.tid * Update base.tid --- core/ui/EditTemplate/fields.tid | 2 +- themes/tiddlywiki/vanilla/base.tid | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/core/ui/EditTemplate/fields.tid b/core/ui/EditTemplate/fields.tid index 84f0baa68..7afaf8ac1 100644 --- a/core/ui/EditTemplate/fields.tid +++ b/core/ui/EditTemplate/fields.tid @@ -57,7 +57,7 @@ $value={{{ [<newFieldValueTiddler>get[text]] }}}/> \whitespace trim <div class="tc-edit-fields"> -<table class="tc-edit-fields"> +<table class={{{ [all[current]fields[]] :filter[lookup[$:/config/EditTemplateFields/Visibility/]!match[hide]] +[count[]!match[0]] +[then[tc-edit-fields]] ~[[tc-edit-fields tc-edit-fields-small]] }}}> <tbody> <$list filter="[all[current]fields[]] +[sort[title]]" variable="currentField" storyview="pop"> <$list filter=<<config-filter>> variable="temp"> diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index dc9b99f08..89811d577 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -1420,6 +1420,10 @@ html body.tc-body.tc-single-tiddler-window { width: 100%; } +.tc-edit-fields.tc-edit-fields-small { + margin-top: 0; + margin-bottom: 0; +} .tc-edit-fields table, .tc-edit-fields tr, .tc-edit-fields td { border: none; From a81b7fc9f4b7da42597c7ebfb1718b7bdfdac032 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 18 Nov 2020 18:21:38 +0000 Subject: [PATCH 024/124] Remove extraneous modifier/creator fields Fixes #5068 --- .../tiddlers/community/resources/Favorites by Mohammad.tid | 2 -- .../community/resources/GitHub Saver Tutorial by Mohammad.tid | 2 -- .../community/resources/Kookma Plugin Library by Mohammad.tid | 2 -- .../tiddlers/community/resources/Refnotes by Mohammad.tid | 2 -- .../community/resources/RegExp in Tiddlywiki by Mohammad.tid | 2 -- .../tiddlers/community/resources/Searchwikis by Mohammad.tid | 2 -- .../community/resources/Semantic Colors by Mohammad.tid | 2 -- .../tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid | 2 -- .../tw5.com/tiddlers/community/resources/Slider by Mohammad.tid | 2 -- .../tiddlers/community/resources/TW-Scripts by Mohammad.tid | 2 -- .../community/resources/Tiddler Commander by Mohammad.tid | 2 -- .../tiddlers/community/resources/Tiddlyshow by Mohammad.tid | 2 -- .../tiddlers/community/resources/Timelines by Mohammad.tid | 2 -- .../tiddlers/community/resources/Todolist by Mohammad.tid | 2 -- .../tiddlers/community/resources/Trashbin by Mohammad.tid | 2 -- .../tiddlers/community/resources/Utility by Mohammad.tid | 2 -- 16 files changed, 32 deletions(-) diff --git a/editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid index 4715cbc3f..17d6532b4 100644 --- a/editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Favorites by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117155737569 -creator: Mohammad modified: 20201117155943559 -modifier: Mohammad tags: Resources Plugings title: Favorites by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid index 0db8ff926..07534dd5c 100644 --- a/editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/GitHub Saver Tutorial by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117163027900 -creator: Mohammad modified: 20201117163855463 -modifier: Mohammad tags: Resources title: GitHub Saver Tutorial by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid index 27ae0a35e..69cfc8181 100644 --- a/editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Kookma Plugin Library by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117160603290 -creator: Mohammad modified: 20201117160819308 -modifier: Mohammad tags: Resources Plugings title: Kookma Plugin Library by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid index 2dfb6e964..3f400bc19 100644 --- a/editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Refnotes by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117161853918 -creator: Mohammad modified: 20201117162122822 -modifier: Mohammad tags: Resources Plugings title: Refnotes by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid index 4bd091698..8d962586e 100644 --- a/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/RegExp in Tiddlywiki by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117164024930 -creator: Mohammad modified: 20201117164308641 -modifier: Mohammad tags: Resources title: RegExp in Tiddlywiki by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid index 77ced56fb..3f7cbc729 100644 --- a/editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Searchwikis by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117160302426 -creator: Mohammad modified: 20201117160443306 -modifier: Mohammad tags: Resources Plugings title: Searchwikis by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid index 34963f263..834348b94 100644 --- a/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Semantic Colors by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117162254751 -creator: Mohammad modified: 20201117162601326 -modifier: Mohammad tags: Resources title: Semantic Colors by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid index 3c31679f5..38d743552 100644 --- a/editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Shiraz by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201116204317018 -creator: Mohammad modified: 20201116210618803 -modifier: Mohammad tags: Resources Plugings title: Shiraz by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid index b8b14cddb..8373e86c8 100644 --- a/editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Slider by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117162655614 -creator: Mohammad modified: 20201117162926714 -modifier: Mohammad tags: Resources Plugings title: Slider by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid index f319938f7..d269023b6 100644 --- a/editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/TW-Scripts by Mohammad.tid @@ -1,7 +1,5 @@ created: 20180830194141190 -creator: Mohammad modified: 20201116203625120 -modifier: Mohammad tags: Resources title: TW-Scripts by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid index 959290950..d2c873745 100644 --- a/editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Tiddler Commander by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201116203717105 -creator: Mohammad modified: 20201116204652385 -modifier: Mohammad tags: Resources Plugings title: Tiddler Commander by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid index 67d6b22ad..50a639ac8 100644 --- a/editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Tiddlyshow by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117160944367 -creator: Mohammad modified: 20201117162735263 -modifier: Mohammad tags: Resources Plugings title: Tiddlyshow by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid index ccc15be78..d1e6fa7cc 100644 --- a/editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Timelines by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117161434779 -creator: Mohammad modified: 20201117161728094 -modifier: Mohammad tags: Resources Plugings title: Timelines by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid index 7144521ee..5dcb15b75 100644 --- a/editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Todolist by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201116210711381 -creator: Mohammad modified: 20201116212041642 -modifier: Mohammad tags: Resources Plugings title: Todolist by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid index 76af19e07..c8e442ae9 100644 --- a/editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Trashbin by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117155328920 -creator: Mohammad modified: 20201117155604253 -modifier: Mohammad tags: Resources Plugings title: Trashbin by Mohammad type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid b/editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid index 97ab74b0f..38da64a30 100644 --- a/editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid +++ b/editions/tw5.com/tiddlers/community/resources/Utility by Mohammad.tid @@ -1,7 +1,5 @@ created: 20201117160011169 -creator: Mohammad modified: 20201117160235750 -modifier: Mohammad tags: Resources Plugings title: Utility by Mohammad type: text/vnd.tiddlywiki From e2bea854b64c1347efeee78a3e8a6b54e68ca961 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Thu, 19 Nov 2020 16:59:02 +0100 Subject: [PATCH 025/124] System tiddler syncing (#4987) * First pass at a fix for system tiddler sync issues * Add new filter syncFromServer * Undo previous attempt at a fix * Added a flag to control sync of system tiddlers from server --- .../server/routes/get-tiddlers-json.js | 3 +++ core/modules/syncer.js | 19 ++++++++++++------- core/wiki/config/SyncFilter.tid | 2 +- .../config/SyncSystemTiddlersFromServer.tid | 3 +++ 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 core/wiki/config/SyncSystemTiddlersFromServer.tid diff --git a/core/modules/server/routes/get-tiddlers-json.js b/core/modules/server/routes/get-tiddlers-json.js index 2c730e066..203900346 100644 --- a/core/modules/server/routes/get-tiddlers-json.js +++ b/core/modules/server/routes/get-tiddlers-json.js @@ -28,6 +28,9 @@ exports.handler = function(request,response,state) { return; } } + if(state.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "no") { + filter += "+[!is[system]]"; + } var excludeFields = (state.queryParameters.exclude || "text").split(","), titles = state.wiki.filterTiddlers(filter); response.writeHead(200, {"Content-Type": "application/json"}); diff --git a/core/modules/syncer.js b/core/modules/syncer.js index 1ad9c3474..d5eae1f48 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -305,7 +305,8 @@ Syncer.prototype.syncFromServer = function() { self.pollTimerId = null; self.syncFromServer.call(self); },self.pollTimerInterval); - }; + }, + syncSystemFromServer = (self.wiki.getTiddlerText("$:/config/SyncSystemTiddlersFromServer") === "yes" ? true : false); if(this.syncadaptor && this.syncadaptor.getUpdatedTiddlers) { this.logger.log("Retrieving updated tiddler list"); cancelNextSync(); @@ -320,9 +321,11 @@ Syncer.prototype.syncFromServer = function() { self.titlesToBeLoaded[title] = true; }); $tw.utils.each(updates.deletions,function(title) { - delete self.tiddlerInfo[title]; - self.logger.log("Deleting tiddler missing from server:",title); - self.wiki.deleteTiddler(title); + if(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) { + delete self.tiddlerInfo[title]; + self.logger.log("Deleting tiddler missing from server:",title); + self.wiki.deleteTiddler(title); + } }); if(updates.modifications.length > 0 || updates.deletions.length > 0) { self.processTaskQueue(); @@ -365,9 +368,11 @@ Syncer.prototype.syncFromServer = function() { } // Delete any tiddlers that were previously reported but missing this time $tw.utils.each(previousTitles,function(title) { - delete self.tiddlerInfo[title]; - self.logger.log("Deleting tiddler missing from server:",title); - self.wiki.deleteTiddler(title); + if(syncSystemFromServer || !self.wiki.isSystemTiddler(title)) { + delete self.tiddlerInfo[title]; + self.logger.log("Deleting tiddler missing from server:",title); + self.wiki.deleteTiddler(title); + } }); self.processTaskQueue(); }); diff --git a/core/wiki/config/SyncFilter.tid b/core/wiki/config/SyncFilter.tid index 41d71537c..06b3f192f 100644 --- a/core/wiki/config/SyncFilter.tid +++ b/core/wiki/config/SyncFilter.tid @@ -1,3 +1,3 @@ title: $:/config/SyncFilter -[is[tiddler]] -[[$:/core]] -[prefix[$:/StoryList]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/isEncrypted]] -[prefix[$:/status/]] -[prefix[$:/state/]] -[prefix[$:/temp/]] +[is[tiddler]] -[[$:/core]] -[[$:/library/sjcl.js]] -[prefix[$:/boot/]] -[prefix[$:/HistoryList]] -[status[pending]plugin-type[import]] -[[$:/isEncrypted]] -[prefix[$:/status/]] -[prefix[$:/state/]] -[prefix[$:/temp/]] diff --git a/core/wiki/config/SyncSystemTiddlersFromServer.tid b/core/wiki/config/SyncSystemTiddlersFromServer.tid new file mode 100644 index 000000000..32fcb7a46 --- /dev/null +++ b/core/wiki/config/SyncSystemTiddlersFromServer.tid @@ -0,0 +1,3 @@ +title: $:/config/SyncSystemTiddlersFromServer + +no \ No newline at end of file From f591a78f370b05822b418acc48ab45b5b53af3ab Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Thu, 19 Nov 2020 17:32:43 +0100 Subject: [PATCH 026/124] Fix small typo in syncer-actions-refresh.tid (#5075) --- plugins/tiddlywiki/tiddlyweb/syncer-actions-refresh.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/tiddlyweb/syncer-actions-refresh.tid b/plugins/tiddlywiki/tiddlyweb/syncer-actions-refresh.tid index eeb0ddba2..46f8a95db 100644 --- a/plugins/tiddlywiki/tiddlyweb/syncer-actions-refresh.tid +++ b/plugins/tiddlywiki/tiddlyweb/syncer-actions-refresh.tid @@ -4,6 +4,6 @@ tags: $:/tags/SyncerDropdown <$reveal state="$:/status/IsLoggedIn" type="match" text="yes"> <$button tooltip="Get latest changes from the server" aria-label="Refresh from server" class="tc-btn-invisible"> <$action-sendmessage $message="tm-server-refresh"/> -{{$:/core/images/refresh-button}} <span clas]s="tc-btn-text"><$text text="Get latest changes from the server"/></span> +{{$:/core/images/refresh-button}} <span class="tc-btn-text"><$text text="Get latest changes from the server"/></span> </$button> </$reveal> From fd14e9461037edc9ba63551bf8d576c06ac4b9f0 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Thu, 19 Nov 2020 17:37:36 +0100 Subject: [PATCH 027/124] Add whitespace trims to EditToolbar Buttons (#5076) * Add whitespace trim to EditToolbar cancel Button * Add whitespace trim to EditToolbar delete Button * Add whitespace trim to EditToolbar save Button --- core/ui/EditToolbar/cancel.tid | 1 + core/ui/EditToolbar/delete.tid | 1 + core/ui/EditToolbar/save.tid | 1 + 3 files changed, 3 insertions(+) diff --git a/core/ui/EditToolbar/cancel.tid b/core/ui/EditToolbar/cancel.tid index 341ae9d0b..fe21c2e99 100644 --- a/core/ui/EditToolbar/cancel.tid +++ b/core/ui/EditToolbar/cancel.tid @@ -3,6 +3,7 @@ tags: $:/tags/EditToolbar caption: {{$:/core/images/cancel-button}} {{$:/language/Buttons/Cancel/Caption}} description: {{$:/language/Buttons/Cancel/Hint}} +\whitespace trim <$button actions=<<cancel-delete-tiddler-actions "cancel">> tooltip={{$:/language/Buttons/Cancel/Hint}} aria-label={{$:/language/Buttons/Cancel/Caption}} class=<<tv-config-toolbar-class>>> <$list filter="[<tv-config-toolbar-icons>match[yes]]"> {{$:/core/images/cancel-button}} diff --git a/core/ui/EditToolbar/delete.tid b/core/ui/EditToolbar/delete.tid index 67e68c68b..fcaed4b48 100644 --- a/core/ui/EditToolbar/delete.tid +++ b/core/ui/EditToolbar/delete.tid @@ -3,6 +3,7 @@ tags: $:/tags/EditToolbar $:/tags/ViewToolbar caption: {{$:/core/images/delete-button}} {{$:/language/Buttons/Delete/Caption}} description: {{$:/language/Buttons/Delete/Hint}} +\whitespace trim <$button actions=<<cancel-delete-tiddler-actions "delete">> tooltip={{$:/language/Buttons/Delete/Hint}} aria-label={{$:/language/Buttons/Delete/Caption}} class=<<tv-config-toolbar-class>>> <$list filter="[<tv-config-toolbar-icons>match[yes]]"> {{$:/core/images/delete-button}} diff --git a/core/ui/EditToolbar/save.tid b/core/ui/EditToolbar/save.tid index cd69d7686..c539009ee 100644 --- a/core/ui/EditToolbar/save.tid +++ b/core/ui/EditToolbar/save.tid @@ -4,6 +4,7 @@ caption: {{$:/core/images/done-button}} {{$:/language/Buttons/Save/Caption}} description: {{$:/language/Buttons/Save/Hint}} \define save-tiddler-button() +\whitespace trim <$fieldmangler><$button tooltip={{$:/language/Buttons/Save/Hint}} aria-label={{$:/language/Buttons/Save/Caption}} class=<<tv-config-toolbar-class>>> <<save-tiddler-actions>> <$list filter="[<tv-config-toolbar-icons>match[yes]]"> From 89541edcff6672a70020c67cdbe5a38c2ef125d7 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Fri, 20 Nov 2020 15:00:20 +0100 Subject: [PATCH 028/124] Added mathematics filter operators power and log (#5080) --- core/modules/filters/math.js | 14 ++++++++++++++ .../filters/examples/log Operator (Examples).tid | 14 ++++++++++++++ .../examples/power Operator (Examples).tid | 8 ++++++++ .../tw5.com/tiddlers/filters/log Operator.tid | 15 +++++++++++++++ .../tw5.com/tiddlers/filters/power Operator.tid | 15 +++++++++++++++ 5 files changed, 66 insertions(+) create mode 100644 editions/tw5.com/tiddlers/filters/examples/log Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/examples/power Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/log Operator.tid create mode 100644 editions/tw5.com/tiddlers/filters/power Operator.tid diff --git a/core/modules/filters/math.js b/core/modules/filters/math.js index ac2b40117..f52a8c678 100644 --- a/core/modules/filters/math.js +++ b/core/modules/filters/math.js @@ -91,6 +91,20 @@ exports.exponential = makeNumericBinaryOperator( function(a,b) {return Number.prototype.toExponential.call(a,Math.min(Math.max(b,0),100));} ); +exports.power = makeNumericBinaryOperator( + function(a,b) {return Math.pow(a,b);} +); + +exports.log = makeNumericBinaryOperator( + function(a,b) { + if(b) { + return Math.log(a)/Math.log(b); + } else { + return Math.log(a); + } + } +); + exports.sum = makeNumericReducingOperator( function(accumulator,value) {return accumulator + value}, 0 // Initial value diff --git a/editions/tw5.com/tiddlers/filters/examples/log Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/log Operator (Examples).tid new file mode 100644 index 000000000..371952170 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/log Operator (Examples).tid @@ -0,0 +1,14 @@ +created: 20201120041503515 +modified: 20201120042024813 +tags: [[Operator Examples]] [[log Operator]] +title: log Operator (Examples) +type: text/vnd.tiddlywiki + +Logarithm of `8` with base `2`: +<<.operator-example 1 "[[8]log[2]]">> + +Logarithm of `100` with base `10`: +<<.operator-example 2 "[[100]log[10]]">> + +Natural logarithm of 10 (base `e`), equivalent to `ln(10)` in mathematics: +<<.operator-example 2 "[[10]log[]]">> diff --git a/editions/tw5.com/tiddlers/filters/examples/power Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/power Operator (Examples).tid new file mode 100644 index 000000000..e2bfdb0f5 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/power Operator (Examples).tid @@ -0,0 +1,8 @@ +created: 20201120040913073 +modified: 20201120041513726 +tags: [[Operator Examples]] [[power Operator]] +title: power Operator (Examples) +type: text/vnd.tiddlywiki + +<<.operator-example 1 "[[3]power[3]]">> +<<.operator-example 2 "9 +[power[2]]">> diff --git a/editions/tw5.com/tiddlers/filters/log Operator.tid b/editions/tw5.com/tiddlers/filters/log Operator.tid new file mode 100644 index 000000000..bfca18853 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/log Operator.tid @@ -0,0 +1,15 @@ +caption: log +created: 20201120041113537 +modified: 20201120041443518 +op-input: a [[selection of titles|Title Selection]] +op-output: the logarithm of each input title as numbers, with base <<.place N>> if specified otherwise base `e` +op-parameter: a number +op-parameter-name: N +op-purpose: treating each input title as a number, return its logarithm with base equal to the numeric value of the operand if specified, otherwise base `e` +tags: [[Filter Operators]] [[Mathematics Operators]] [[Binary Mathematics Operators]] +title: log Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.1.23">> + +<<.operator-examples "log">> diff --git a/editions/tw5.com/tiddlers/filters/power Operator.tid b/editions/tw5.com/tiddlers/filters/power Operator.tid new file mode 100644 index 000000000..d4afb67ce --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/power Operator.tid @@ -0,0 +1,15 @@ +caption: power +created: 20201120040720190 +modified: 20201120040852980 +op-input: a [[selection of titles|Title Selection]] +op-output: the input as numbers, but with each one raised to the power of <<.place N>> +op-parameter: a number +op-parameter-name: N +op-purpose: treating each input title as a number, raise it to the power of the numeric value of the operand +tags: [[Filter Operators]] [[Mathematics Operators]] [[Binary Mathematics Operators]] +title: power Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.1.23">> + +<<.operator-examples "power">> From 1339c23b3ab90da37e9e91c4ae042198046b86d1 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Fri, 20 Nov 2020 15:00:56 +0100 Subject: [PATCH 029/124] Adjustments for narrow screens (#5079) --- themes/tiddlywiki/vanilla/base.tid | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 89811d577..28a9b3d4a 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -757,6 +757,14 @@ button.tc-btn-invisible.tc-remove-tag-button { right: 29px; } +@media (max-width: <<sidebarbreakpoint-minus-one>>) { + + .tc-topbar-right { + right: 10px; + } + +} + .tc-topbar button { padding: 8px; } @@ -969,6 +977,14 @@ button.tc-btn-invisible.tc-remove-tag-button { border-bottom: 1px solid <<colour tiddler-info-tab-background>>; } +@media (max-width: <<sidebarbreakpoint-minus-one>>) { + + .tc-tiddler-info { + padding: 14px 14px 14px 14px; + } + +} + .tc-view-field-table { width: 100%; } @@ -986,6 +1002,7 @@ button.tc-btn-invisible.tc-remove-tag-button { @media (max-width: <<sidebarbreakpoint-minus-one>>) { .tc-tiddler-frame { padding: 14px 14px 14px 14px; + margin-bottom: .5em; } .tc-tiddler-info { From 483fd941f57a81bfb86ff7f92a62ff2186cd8ff3 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Fri, 20 Nov 2020 15:08:18 +0100 Subject: [PATCH 030/124] Extend action-log and subclass it as log widget (#5078) * Extended action-log and subclassed it as log widget * Do not rename LogWidget class * Removed unneeded variable declaration --- core/modules/widgets/action-log.js | 47 ++++++++++++++++++++++++++++-- core/modules/widgets/log.js | 30 +++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 core/modules/widgets/log.js diff --git a/core/modules/widgets/action-log.js b/core/modules/widgets/action-log.js index e3027a8e9..216eb1167 100644 --- a/core/modules/widgets/action-log.js +++ b/core/modules/widgets/action-log.js @@ -28,23 +28,66 @@ Render this widget into the DOM */ LogWidget.prototype.render = function(parent,nextSibling) { this.computeAttributes(); + this.execute(); }; +LogWidget.prototype.execute = function(){ + this.message = this.getAttribute("$$message","debug"); + this.logAll = this.getAttribute("$$all","no") === "yes" ? true : false; + this.filter = this.getAttribute("$$filter"); +} + /* Refresh the widget by ensuring our attributes are up to date */ LogWidget.prototype.refresh = function(changedTiddlers) { - return this.refreshChildren(changedTiddlers); + this.refreshSelf(); + return true; }; /* Invoke the action associated with this widget */ LogWidget.prototype.invokeAction = function(triggeringWidget,event) { - $tw.utils.logTable(this.attributes,["attribute name","value"]); + this.log(); return true; // Action was invoked }; +LogWidget.prototype.log = function() { + var data = {}, + dataCount, + allVars = {}, + filteredVars; + + $tw.utils.each(this.attributes,function(attribute,name) { + if(name.substring(0,2) !== "$$") { + data[name] = attribute; + } + }); + + for(var v in this.variables) { + allVars[v] = this.getVariable(v,{defaultValue:""}); + } + if(this.filter) { + filteredVars = this.wiki.compileFilter(this.filter).call(this.wiki,this.wiki.makeTiddlerIterator(allVars)); + $tw.utils.each(filteredVars,function(name) { + data[name] = allVars[name]; + }); + } + dataCount = $tw.utils.count(data); + + console.group(this.message); + if(dataCount > 0) { + $tw.utils.logTable(data,["name","value"]); + } + if(this.logAll || !dataCount) { + console.groupCollapsed("All variables"); + $tw.utils.logTable(allVars,["name","value"]); + console.groupEnd(); + } + console.groupEnd(); +} + exports["action-log"] = LogWidget; })(); diff --git a/core/modules/widgets/log.js b/core/modules/widgets/log.js new file mode 100644 index 000000000..2615547ad --- /dev/null +++ b/core/modules/widgets/log.js @@ -0,0 +1,30 @@ +/*\ +title: $:/core/modules/widgets/log.js +type: application/javascript +module-type: widget-subclass + +Widget to log debug messages + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +exports.baseClass = "action-log"; + +exports.name = "log"; + +exports.constructor = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +} + +exports.prototype = {}; + +exports.prototype.render = function(event) { + Object.getPrototypeOf(Object.getPrototypeOf(this)).render.call(this,event); + Object.getPrototypeOf(Object.getPrototypeOf(this)).log.call(this); +} + +})(); \ No newline at end of file From 59455061695d7c5c45961e0ce470a5e16c58b2c8 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Fri, 20 Nov 2020 19:21:30 +0100 Subject: [PATCH 031/124] Revert line-height of 3em on tiddler-edit-title (#5083) --- themes/tiddlywiki/vanilla/base.tid | 4 ---- 1 file changed, 4 deletions(-) diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 28a9b3d4a..2b3d427f1 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -1191,10 +1191,6 @@ canvas.tc-edit-bitmapeditor { overflow: hidden; /* https://github.com/Jermolene/TiddlyWiki5/issues/282 */ } -.tc-tiddler-title.tc-tiddler-edit-title { - line-height: 3em; -} - html body.tc-body.tc-single-tiddler-window { margin: 1em; background: <<colour tiddler-background>>; From 4f07539164921b9d41c374642015e9dfee737755 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Fri, 20 Nov 2020 19:37:23 +0100 Subject: [PATCH 032/124] Cycle operator improvements plus docs (#5069) * Tweak cycle operator to support step size parameter and add docs for toggle and cycle * Mention that title list should have no duplicates --- core/modules/filters/x-listops.js | 20 +++++++++------- .../tiddlers/filters/cycle Operator.tid | 24 +++++++++++++++++++ .../examples/cycle Operator (Examples).tid | 21 ++++++++++++++++ .../examples/toggle Operator (Examples).tid | 3 ++- .../tiddlers/filters/toggle Operator.tid | 9 ++++--- 5 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 editions/tw5.com/tiddlers/filters/cycle Operator.tid create mode 100644 editions/tw5.com/tiddlers/filters/examples/cycle Operator (Examples).tid diff --git a/core/modules/filters/x-listops.js b/core/modules/filters/x-listops.js index 5b3a9aba1..eeda70c4a 100644 --- a/core/modules/filters/x-listops.js +++ b/core/modules/filters/x-listops.js @@ -188,19 +188,21 @@ Extended filter operators to manipulate the current list. return set; }; - var cycleValueInArray = function(results,operands) { + var cycleValueInArray = function(results,operands,stepSize) { var resultsIndex, + step = stepSize || 1, i = 0, + opLength = operands.length, nextOperandIndex; - for(i; i < operands.length; i++) { + for(i; i < opLength; i++) { resultsIndex = results.indexOf(operands[i]); if(resultsIndex !== -1) { break; } } if(resultsIndex !== -1) { - i++; - nextOperandIndex = (i === operands.length ? 0 : i); + i = i + step; + nextOperandIndex = (i < opLength ? i : i - opLength); if(operands.length > 1) { results.splice(resultsIndex,1,operands[nextOperandIndex]); } else { @@ -221,11 +223,13 @@ Extended filter operators to manipulate the current list. exports.cycle = function(source,operator) { var results = prepare_results(source), - operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]); - if(operator.suffix === "reverse") { + operands = (operator.operand.length ? $tw.utils.parseStringArray(operator.operand, "true") : [""]), + step = $tw.utils.getInt(operator.operands[1]||"",1); + if(step < 0) { operands.reverse(); - } - return cycleValueInArray(results,operands); + step = Math.abs(step); + } + return cycleValueInArray(results,operands,step); } })(); \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/cycle Operator.tid b/editions/tw5.com/tiddlers/filters/cycle Operator.tid new file mode 100644 index 000000000..dfccac54b --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/cycle Operator.tid @@ -0,0 +1,24 @@ +caption: cycle +created: 20201118172906835 +modified: 20201118192136472 +op-input: a list of items +op-output: the input list with the titles specified in the parameter toggled in a cyclical manner +op-parameter: the <<.op cycle>> operator accepts 1 or 2 parameters, see below for details +op-purpose: toggle in the input, the titles specified in the first operand in a cyclical manner +tags: [[Filter Operators]] [[Listops Operators]] [[Order Operators]] +title: cycle Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.1.23">> + +The <<.op cycle>> operator requires at least one parameter. + +``` +[toggle[<titles>],[step-size]] +``` +* ''titles'' : a title list to toggle in the input list cyclically. If no title from the parameter is present in the input, the first title is added. If a title from the parameter is present in the input, it is replaced with the next title from the parameter. Note that all titles specified in this parameter should be unique. +* ''step-size'': (optional). Defaults to 1. Specifies the number of steps in the parameter list to move each time. Can be a negative number. + +<$macrocall $name=".tip" _="While the <<.op cycle>> operator interprets its first parameter as a list of titles to cycle through, the [[toggle Operator]] accepts an unlimited number of distinct parameters and offers similar functionality."/> + +<<.operator-examples "cycle">> diff --git a/editions/tw5.com/tiddlers/filters/examples/cycle Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/cycle Operator (Examples).tid new file mode 100644 index 000000000..0ff1d0336 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/cycle Operator (Examples).tid @@ -0,0 +1,21 @@ +created: 20201118174250896 +modified: 20201118175415868 +tags: [[Operator Examples]] [[cycle Operator]] +title: cycle Operator (Examples) +type: text/vnd.tiddlywiki + +Cycle through a list of values to add as a tag: + +``` +<$action-listops $tiddler="target" $tags="+[cycle[todo soon now maybe done ]]" /> +``` + +Cycle through a list of values to add as a tag, in reverse order: + +``` +<$action-listops $tiddler="target" $tags="+[cycle[todo soon now maybe done ],[-1]]" /> +``` + +<<.using-days-of-week>> +<<.operator-example 1 """[list[Days of the Week]first[]] +[cycle{Days of the Week!!list}]""">> +<<.operator-example 1 """[list[Days of the Week]first[]] +[cycle{Days of the Week!!list},[2]]""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/examples/toggle Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/toggle Operator (Examples).tid index 95e3d56a8..7fa986b7e 100644 --- a/editions/tw5.com/tiddlers/filters/examples/toggle Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/toggle Operator (Examples).tid @@ -1,5 +1,6 @@ created: 20201107154352695 -modified: 20201109104951727 +modified: 20201118174726982 +tags: [[Operator Examples]] [[toggle Operator]] title: toggle Operator (Examples) type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/filters/toggle Operator.tid b/editions/tw5.com/tiddlers/filters/toggle Operator.tid index 2c2738134..13e971990 100644 --- a/editions/tw5.com/tiddlers/filters/toggle Operator.tid +++ b/editions/tw5.com/tiddlers/filters/toggle Operator.tid @@ -1,9 +1,9 @@ caption: toggle created: 20201107153758990 -modified: 20201109104654310 +modified: 20201118192155504 op-input: a list of items op-output: the input list with the title specified in the parameter toggled -op-parameter: the <<.op toggle>> operator accepts 1 or 2 parameters, see below for details +op-parameter: the <<.op toggle>> operator accepts 1 or more parameters, see below for details op-purpose: toggle the title specified in the operand in the input tags: [[Filter Operators]] [[Listops Operators]] [[Order Operators]] title: toggle Operator @@ -11,7 +11,7 @@ type: text/vnd.tiddlywiki <<.from-version "5.1.23">> -The <<.op toggle>> operator requires at least one parameter and can accept a second optional parameter: +The <<.op toggle>> operator requires at least one parameter and can accept additional optional parameters. With a second optional parameter it can be used to toggle between a pair of titles: ``` [toggle[<title1>],[<title2>]] @@ -19,5 +19,8 @@ The <<.op toggle>> operator requires at least one parameter and can accept a sec * ''title1'' : a title to toggle in the input list. If it is already present, it is removed. Otherwise, it is added. * ''title2'': (optional). When the second parameter is provided, the operator toggles between the two values in the input list. If neither is present, the first parameter takes precedence is added to the list. +With more than two parameters, the <<.op toggle>> behaves similar to the [[cycle|cycle Operator]] and can be used to cycle through a list of values. Note that all operands should be unique. + +<$macrocall $name=".tip" _="While the <<.op cycle>> operator interprets its first parameter as a list of titles to cycle through and offers similar functionality, the <<.op toggle>> operator accepts an unlimited number of distinct parameters."/> <<.operator-examples "toggle">> From c97003238be4cc4183a0e5201c57ce9ce9c9771e Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Fri, 20 Nov 2020 19:37:48 +0100 Subject: [PATCH 033/124] Doc updates for ActionLog and Log widgets (#5081) --- .../definitions/Web Developer Tools.tid | 7 +++ .../tiddlers/widgets/ActionLogWidget.tid | 26 +++++++++-- .../tw5.com/tiddlers/widgets/LogWidget.tid | 45 +++++++++++++++++++ 3 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 editions/tw5.com/tiddlers/definitions/Web Developer Tools.tid create mode 100644 editions/tw5.com/tiddlers/widgets/LogWidget.tid diff --git a/editions/tw5.com/tiddlers/definitions/Web Developer Tools.tid b/editions/tw5.com/tiddlers/definitions/Web Developer Tools.tid new file mode 100644 index 000000000..c02f4c277 --- /dev/null +++ b/editions/tw5.com/tiddlers/definitions/Web Developer Tools.tid @@ -0,0 +1,7 @@ +created: 20201120153119665 +modified: 20201120154646100 +tags: Definitions +title: Web Developer Tools +type: text/vnd.tiddlywiki + +Most browsers provide ''Web Developer Tools'' that include a JavaScript console. In Chrome and Firefox it can be opened via the ''Tools'' menu, or by pressing <kbd>Ctrl + Shift + J</kbd> (<kbd>Cmd + Shift + J</kbd> on a Mac). \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/ActionLogWidget.tid b/editions/tw5.com/tiddlers/widgets/ActionLogWidget.tid index b8440f31b..2fa75cfad 100644 --- a/editions/tw5.com/tiddlers/widgets/ActionLogWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/ActionLogWidget.tid @@ -1,21 +1,29 @@ caption: action-log created: 20201114113318785 -modified: 20201114125859948 -tags: Widgets ActionWidgets +modified: 20201120155202652 +tags: Widgets ActionWidgets [[Debugging Widgets]] title: ActionLogWidget type: text/vnd.tiddlywiki ! Introduction -<<.from-version "5.1.23">> The ''action-log'' widget is an [[action widget|ActionWidgets]] that can be used to output debugging information to the JavaScript console supported by most browsers. This can be useful because otherwise it is difficult to observe what is going on within a sequence of actions. +<<.from-version "5.1.23">> The ''action-log'' widget is an [[action widget|ActionWidgets]] that can be used to output debugging information to the [[JavaScript console|Web Developer Tools]] supported by most browsers. This can be useful because otherwise it is difficult to observe what is going on within a sequence of actions. ActionWidgets are used within triggering widgets such as the ButtonWidget. +<<.tip """ For debugging outside of actions see [[LogWidget]]""">> + ! Content and Attributes The ''action-log'' widget is invisible. Any content within it is ignored. When the actions are invoked, the names and values of all attributes are logged to the JavaScript console. +In addition there are optional attributes that can be used: + +|!Optional Attribute |!Description | +|$$filter|All variables matching this filter will also be logged. | +|$$message |A message to display as the title of the information logged. Useful when several `action-log` widgets are used in sequence. | +|$$all |Set to "yes" to log all variables in a collapsed table. Note that if there is nothing specified to log, all variables are always logged instead.| <<.tip """A handy tip if an action widget is not behaving as expected is to temporarily change it to an `<$action-log>` widget so that the attributes can be observed.""">> @@ -28,3 +36,15 @@ Here is an example of logging two variables: <$action-log myVar=<<myVar>> otherVar=<<otherVar>>/> ``` +To log all variables: + +``` +<$action-log /> +``` + + +To log two variables as well as all core variables (which start with `tv-`): + +``` +<$action-log myVar=<<myVar>> other={{!!status}} $$filter="[prefix[tv-]]"/> +``` diff --git a/editions/tw5.com/tiddlers/widgets/LogWidget.tid b/editions/tw5.com/tiddlers/widgets/LogWidget.tid new file mode 100644 index 000000000..71cb01b03 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/LogWidget.tid @@ -0,0 +1,45 @@ +created: 20201120152706842 +modified: 20201120154927696 +tags: Widgets [[Debugging Widgets]] +title: LogWidget +type: text/vnd.tiddlywiki + +! Introduction + +<<.from-version "5.1.23">> The ''log'' widget can be used to output debugging information to the [[JavaScript console|Web Developer Tools]] supported by most browsers. + +<<.tip """ For use with ActionWidgets see [[ActionLogWidget]] which uses identical parameters""">> + +! Content and Attributes + +The ''log'' widget is invisible. Any content within it is ignored. Note that the widget will log to the console both when it is first rendered and also every time it refreshes. + +When the widget is rendered, the names and values of all attributes are logged to the JavaScript console. +In addition there are optional attributes that can be used: + +|!Optional Attribute |!Description | +|$$filter|All variables matching this filter will also be logged. | +|$$message |A message to display as the title of the information logged. Useful when several `log` widgets are used in sequence. | +|$$all |Set to "yes" to log all variables in a collapsed table. Note that if there is nothing specified to log, all variables are always logged instead.| + + +! Example + +Here is an example of logging two variables: + +``` +<$log myVar=<<myVar>> otherVar=<<otherVar>>/> +``` + +To log all variables: + +``` +<$log /> +``` + + +To log two variables as well as all core variables (which start with `tv-`): + +``` +<$log myVar=<<myVar>> other={{!!status}} $$filter="[prefix[tv-]]"/> +``` From a0f145197cb91dd5e77b33741578678b4621a70f Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Fri, 20 Nov 2020 22:34:43 +0100 Subject: [PATCH 034/124] Correct error in operator documentation (#5084) --- editions/tw5.com/tiddlers/filters/cycle Operator.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/filters/cycle Operator.tid b/editions/tw5.com/tiddlers/filters/cycle Operator.tid index dfccac54b..f54316f29 100644 --- a/editions/tw5.com/tiddlers/filters/cycle Operator.tid +++ b/editions/tw5.com/tiddlers/filters/cycle Operator.tid @@ -14,7 +14,7 @@ type: text/vnd.tiddlywiki The <<.op cycle>> operator requires at least one parameter. ``` -[toggle[<titles>],[step-size]] +[cycle[<titles>],[step-size]] ``` * ''titles'' : a title list to toggle in the input list cyclically. If no title from the parameter is present in the input, the first title is added. If a title from the parameter is present in the input, it is replaced with the next title from the parameter. Note that all titles specified in this parameter should be unique. * ''step-size'': (optional). Defaults to 1. Specifies the number of steps in the parameter list to move each time. Can be a negative number. From d2f87d6200149876a31aa784f38b4e4bfb7a7dbe Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Sat, 21 Nov 2020 18:19:52 +0100 Subject: [PATCH 035/124] Reveal widget allow re-positioning (#5087) * Jeremy's original version of the event widget * Renamed to eventcatcher, added modifier key support and mouse button support as variables * Reveal widget: update popup position when state tiddler updates --- core/modules/widgets/reveal.js | 11 +++++++++++ editions/tw5.com/tiddlers/widgets/RevealWidget.tid | 5 +++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/core/modules/widgets/reveal.js b/core/modules/widgets/reveal.js index ebbf490b2..e6334dff2 100755 --- a/core/modules/widgets/reveal.js +++ b/core/modules/widgets/reveal.js @@ -70,6 +70,10 @@ RevealWidget.prototype.positionPopup = function(domNode) { left = this.popup.left + this.popup.width; top = this.popup.top + this.popup.height - domNode.offsetHeight; break; + case "belowright": + left = this.popup.left + this.popup.width; + top = this.popup.top + this.popup.height; + break; case "right": left = this.popup.left + this.popup.width; top = this.popup.top; @@ -78,6 +82,10 @@ RevealWidget.prototype.positionPopup = function(domNode) { left = this.popup.left + this.popup.width - domNode.offsetWidth; top = this.popup.top + this.popup.height; break; + case "aboveleft": + left = this.popup.left - domNode.offsetWidth; + top = this.popup.top - domNode.offsetHeight; + break; default: // Below left = this.popup.left; top = this.popup.top + this.popup.height; @@ -109,6 +117,7 @@ RevealWidget.prototype.execute = function() { this.retain = this.getAttribute("retain","no"); this.openAnimation = this.animate === "no" ? undefined : "open"; this.closeAnimation = this.animate === "no" ? undefined : "close"; + this.updatePopupPosition = this.getAttribute("updatePopupPosition","no") === "yes"; // Compute the title of the state tiddler and read it this.stateTiddlerTitle = this.state; this.stateTitle = this.getAttribute("stateTitle"); @@ -212,6 +221,8 @@ RevealWidget.prototype.refresh = function(changedTiddlers) { this.refreshSelf(); return true; } + } else if(this.type === "popup" && this.updatePopupPosition && (changedTiddlers[this.state] || changedTiddlers[this.stateTitle])) { + this.positionPopup(this.domNodes[0]); } return this.refreshChildren(changedTiddlers); } diff --git a/editions/tw5.com/tiddlers/widgets/RevealWidget.tid b/editions/tw5.com/tiddlers/widgets/RevealWidget.tid index 4716648a3..7ff3747d3 100644 --- a/editions/tw5.com/tiddlers/widgets/RevealWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/RevealWidget.tid @@ -1,7 +1,7 @@ caption: reveal created: 20131024141900000 jeremy: tiddlywiki -modified: 20190910150520583 +modified: 20201121100908827 tags: Widgets title: RevealWidget type: text/vnd.tiddlywiki @@ -33,11 +33,12 @@ The content of the `<$reveal>` widget is displayed according to the rules given |text |The text to match when the type is ''match'', ''nomatch'', ''lt'', ''gt'', ''lteq'' or ''gteq'' | |class |An optional CSS class name to be assigned to the HTML element<br/>» Set to `tc-popup-keep` to make a popup "sticky", so it won't close when you click inside of it| |style |An optional CSS style attribute to be assigned to the HTML element | -|position |The position used for the popup when the type is ''popup''. Can be ''left'', ''above'', ''aboveright'', ''right'', ''belowleft'' or ''below'' | +|position |The position used for the popup when the type is ''popup''. Can be ''left'', ''above'', ''aboveleft'', ''aboveright'', ''right'', ''belowleft'', ''belowright'' or ''below'' | |positionAllowNegative |Set to "yes" to prevent computed popup positions from being clamped to be above zero | |default |Default value to use when the state tiddler is missing | |animate |Set to "yes" to animate opening and closure (defaults to "no"; requires "retain" to be set to "yes") | |retain |Set to "yes" to force the content to be retained even when hidden (defaults to "no") | +|updatePopupPosition|<<.from-version "5.1.23">>Set to "yes" to update the popup position when the state tiddler is updated (defaults to "no")| <<.tip """<$macrocall $name=".from-version" version="5.1.18"/> <$macrocall $name=".attr" _="stateTitle"/>, <$macrocall $name=".attr" _="stateField"/> and <$macrocall $name=".attr" _="stateIndex"/> attributes allow specifying Tiddler states ''directly'', without interpreting them as [[TextReferences|TextReference]]. This is useful for edge-cases where titles may contain characters that are used to denote Tiddler fields or indices (`!!`, `##`)""">> From 51ca14861e12e7bd2363a75e403857774b3560dc Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Sun, 22 Nov 2020 21:43:36 +0100 Subject: [PATCH 036/124] Fixed bug with default value in lookup operator (#5088) * Fixed bug with default value in lookup operator * Fixed test for lookup operator with default --- core/modules/filters/lookup.js | 2 +- editions/test/tiddlers/tests/test-filters.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/modules/filters/lookup.js b/core/modules/filters/lookup.js index 3ab7f42e6..49c8e205a 100644 --- a/core/modules/filters/lookup.js +++ b/core/modules/filters/lookup.js @@ -22,7 +22,7 @@ Export our filter function exports.lookup = function(source,operator,options) { var results = []; source(function(tiddler,title) { - results.push(options.wiki.getTiddlerText(operator.operand + title) || options.wiki.getTiddlerText(operator.operand + operator.suffix)); + results.push(options.wiki.getTiddlerText(operator.operand + title) || operator.suffix); }); return results; }; diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index dedfd5179..6649af4e3 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -207,7 +207,7 @@ function runTests(wiki) { it("should handle the lookup operator", function() { expect(wiki.filterTiddlers("Six Seventh 8 +[lookup[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,,Tidd"); - expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,Tidd,Tidd"); + expect(wiki.filterTiddlers("Six Seventh 8 +[lookup:8[Tiddler]]").join(",")).toBe("Missing inaction from TiddlerOne,8,Tidd"); }); it("should retrieve shadow tiddlers", function() { From fa63ac5d1ee3306d2572c94e38f23f5bc59adfaf Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Sun, 22 Nov 2020 21:47:12 +0100 Subject: [PATCH 037/124] Add: Eventcatcher widget (#5086) * Jeremy's original version of the event widget * Renamed to eventcatcher, added modifier key support and mouse button support as variables * Allow updating classname without re-rendering entire widget * Handle tag attribute in refresh handler * Improve handling for mouse button variable * Fix typo in refresh handler * Added variables for position of selected node and position of event relative to selected node and catcher node --- core/modules/widgets/eventcatcher.js | 146 +++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 core/modules/widgets/eventcatcher.js diff --git a/core/modules/widgets/eventcatcher.js b/core/modules/widgets/eventcatcher.js new file mode 100644 index 000000000..c0d691f5e --- /dev/null +++ b/core/modules/widgets/eventcatcher.js @@ -0,0 +1,146 @@ +/*\ +title: $:/core/modules/widgets/eventcatcher.js +type: application/javascript +module-type: widget + +Event handler widget + +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +var Widget = require("$:/core/modules/widgets/widget.js").widget; + +var EventWidget = function(parseTreeNode,options) { + this.initialise(parseTreeNode,options); +}; + +/* +Inherit from the base widget class +*/ +EventWidget.prototype = new Widget(); + +/* +Render this widget into the DOM +*/ +EventWidget.prototype.render = function(parent,nextSibling) { + var self = this; + // Remember parent + this.parentDomNode = parent; + // Compute attributes and execute state + this.computeAttributes(); + this.execute(); + // Create element + var tag = this.parseTreeNode.isBlock ? "div" : "span"; + if(this.elementTag && $tw.config.htmlUnsafeElements.indexOf(this.elementTag) === -1) { + tag = this.elementTag; + } + var domNode = this.document.createElement(tag); + this.domNode = domNode; + // Assign classes + this.assignDomNodeClasses(); + // Add our event handler + domNode.addEventListener(this.type,function(event) { + var selector = self.getAttribute("selector"), + actions = self.getAttribute("actions"), + selectedNode = event.target, + selectedNodeRect, + catcherNodeRect, + variables = {}; + if(selector) { + // Search ancestors for a node that matches the selector + while(!selectedNode.matches(selector) && selectedNode !== domNode) { + selectedNode = selectedNode.parentNode; + } + // If we found one, copy the attributes as variables, otherwise exit + if(selectedNode.matches(selector)) { + $tw.utils.each(selectedNode.attributes,function(attribute) { + variables["dom-" + attribute.name] = attribute.value; + }); + //Add a variable with a popup coordinate string for the selected node + variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")"; + + //Add variables for offset of selected node + variables["tv-selectednode-posx"] = selectedNode.offsetLeft; + variables["tv-selectednode-posy"] = selectedNode.offsetTop; + variables["tv-selectednode-width"] = selectedNode.offsetWidth; + variables["tv-selectednode-height"] = selectedNode.offsetHeight; + + //Add variables for event X and Y position relative to selected node + selectedNodeRect = selectedNode.getBoundingClientRect(); + variables["event-fromselected-posx"] = event.clientX - selectedNodeRect.left; + variables["event-fromselected-posy"] = event.clientY - selectedNodeRect.top; + + //Add variables for event X and Y position relative to event catcher node + catcherNodeRect = self.domNode.getBoundingClientRect(); + variables["event-fromcatcher-posx"] = event.clientX - catcherNodeRect.left; + variables["event-fromcatcher-posy"] = event.clientY - catcherNodeRect.top; + } else { + return false; + } + } + // Execute our actions with the variables + if(actions) { + // Add a variable for the modifier key + variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event); + // Add a variable for the mouse button + if("button" in event) { + if(event.button === 0) { + variables["event-mousebutton"] = "left"; + } else if(event.button === 1) { + variables["event-mousebutton"] = "middle"; + } else if(event.button === 2) { + variables["event-mousebutton"] = "right"; + } + } + self.invokeActionString(actions,self,event,variables); + event.preventDefault(); + event.stopPropagation(); + return true; + } + return false; + },false); + // Insert element + parent.insertBefore(domNode,nextSibling); + this.renderChildren(domNode,null); + this.domNodes.push(domNode); +}; + +/* +Compute the internal state of the widget +*/ +EventWidget.prototype.execute = function() { + var self = this; + // Get attributes that require a refresh on change + this.type = this.getAttribute("type"); + this.elementTag = this.getAttribute("tag"); + // Make child widgets + this.makeChildWidgets(); +}; + +EventWidget.prototype.assignDomNodeClasses = function() { + var classes = this.getAttribute("class","").split(" "); + classes.push("tc-eventcatcher"); + this.domNode.className = classes.join(" "); +}; + +/* +Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering +*/ +EventWidget.prototype.refresh = function(changedTiddlers) { + var changedAttributes = this.computeAttributes(); + if(changedAttributes.type || changedAttributes["tag"]) { + this.refreshSelf(); + return true; + } else if(changedAttributes["class"]) { + this.assignDomNodeClasses(); + } + return this.refreshChildren(changedTiddlers); +}; + +exports.eventcatcher = EventWidget; + +})(); \ No newline at end of file From 530b4308e325cd6b08e0ed1f594a0eda9e7cc255 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sun, 22 Nov 2020 22:12:19 +0100 Subject: [PATCH 038/124] Make type input field min-width the highest character length of selectable types (#5090) * Make type input field min-width the highest character length of selectable types * Update base.tid * Update base.tid --- themes/tiddlywiki/vanilla/base.tid | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 2b3d427f1..bc74494bd 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -47,6 +47,20 @@ $else$ </$reveal> \end +\define set-type-selector-min-width() +<$set name="typeLength" value={{{ [all[shadows+tiddlers]prefix[$:/language/Docs/Types/]get[name]length[]maxall[]] }}}> + + .tc-type-selector-dropdown-wrapper { + min-width: calc(<<typeLength>>ch + 4em); + } + + .tc-type-selector-dropdown-wrapper input.tc-edit-typeeditor { + min-width: <<typeLength>>ch; + } + +</$set> +\end + \rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock /* @@ -1371,6 +1385,8 @@ html body.tc-body.tc-single-tiddler-window { display: inline-block; } +<<set-type-selector-min-width>> + .tc-edit-tags { border: 1px solid <<colour tiddler-editor-border>>; padding: 4px 8px 4px 8px; From 3c195b05cb1dca2eec5e6b8c059f08f4119c9bb1 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Sun, 22 Nov 2020 22:13:24 +0100 Subject: [PATCH 039/124] Button and Droppable widgets: improve refresh handling for classes (#5091) * Button and Droppable widgets: improve refesh handling for classes * Added comment regarding handling of class attribute --- core/modules/widgets/button.js | 46 ++++++++++++++++++------------- core/modules/widgets/droppable.js | 23 ++++++++++------ 2 files changed, 42 insertions(+), 27 deletions(-) diff --git a/core/modules/widgets/button.js b/core/modules/widgets/button.js index 0294ac0ba..3ece52371 100644 --- a/core/modules/widgets/button.js +++ b/core/modules/widgets/button.js @@ -27,33 +27,22 @@ ButtonWidget.prototype = new Widget(); Render this widget into the DOM */ ButtonWidget.prototype.render = function(parent,nextSibling) { - var self = this; + var self = this, + tag = "button", + domNode; // Remember parent this.parentDomNode = parent; // Compute attributes and execute state this.computeAttributes(); this.execute(); // Create element - var tag = "button"; if(this.buttonTag && $tw.config.htmlUnsafeElements.indexOf(this.buttonTag) === -1) { tag = this.buttonTag; } - var domNode = this.document.createElement(tag); + domNode = this.document.createElement(tag); + this.domNode = domNode; // Assign classes - var classes = this["class"].split(" ") || [], - isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp(); - if(this.selectedClass) { - if((this.set || this.setTitle) && this.setTo && this.isSelected()) { - $tw.utils.pushTop(classes,this.selectedClass.split(" ")); - } - if(isPoppedUp) { - $tw.utils.pushTop(classes,this.selectedClass.split(" ")); - } - } - if(isPoppedUp) { - $tw.utils.pushTop(classes,"tc-popup-handle"); - } - domNode.className = classes.join(" "); + this.assignDomNodeClasses(); // Assign other attributes if(this.style) { domNode.setAttribute("style",this.style); @@ -200,10 +189,10 @@ ButtonWidget.prototype.execute = function() { this.setTo = this.getAttribute("setTo"); this.popup = this.getAttribute("popup"); this.hover = this.getAttribute("hover"); - this["class"] = this.getAttribute("class",""); this["aria-label"] = this.getAttribute("aria-label"); this.tooltip = this.getAttribute("tooltip"); this.style = this.getAttribute("style"); + // Class attribute is handled in assignDomNodeClasses() this.selectedClass = this.getAttribute("selectedClass"); this.defaultSetValue = this.getAttribute("default",""); this.buttonTag = this.getAttribute("tag"); @@ -219,14 +208,33 @@ ButtonWidget.prototype.execute = function() { this.makeChildWidgets(); }; +ButtonWidget.prototype.assignDomNodeClasses = function() { + var classes = this.getAttribute("class","").split(" "), + isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp(); + if(this.selectedClass) { + if((this.set || this.setTitle) && this.setTo && this.isSelected()) { + $tw.utils.pushTop(classes,this.selectedClass.split(" ")); + } + if(isPoppedUp) { + $tw.utils.pushTop(classes,this.selectedClass.split(" ")); + } + } + if(isPoppedUp) { + $tw.utils.pushTop(classes,"tc-popup-handle"); + } + this.domNode.className = classes.join(" "); +} + /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ ButtonWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes["class"] || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled) { + if(changedAttributes.actions || changedAttributes.to || changedAttributes.message || changedAttributes.param || changedAttributes.set || changedAttributes.setTo || changedAttributes.popup || changedAttributes.hover || changedAttributes.selectedClass || changedAttributes.style || changedAttributes.dragFilter || changedAttributes.dragTiddler || (this.set && changedTiddlers[this.set]) || (this.popup && changedTiddlers[this.popup]) || (this.popupTitle && changedTiddlers[this.popupTitle]) || changedAttributes.setTitle || changedAttributes.setField || changedAttributes.setIndex || changedAttributes.popupTitle || changedAttributes.disabled) { this.refreshSelf(); return true; + } else if(changedAttributes["class"]) { + this.assignDomNodeClasses(); } return this.refreshChildren(changedTiddlers); }; diff --git a/core/modules/widgets/droppable.js b/core/modules/widgets/droppable.js index e6678527b..87a130f39 100644 --- a/core/modules/widgets/droppable.js +++ b/core/modules/widgets/droppable.js @@ -27,21 +27,21 @@ DroppableWidget.prototype = new Widget(); Render this widget into the DOM */ DroppableWidget.prototype.render = function(parent,nextSibling) { - var self = this; + var self = this, + tag = this.parseTreeNode.isBlock ? "div" : "span", + domNode; // Remember parent this.parentDomNode = parent; // Compute attributes and execute state this.computeAttributes(); this.execute(); - var tag = this.parseTreeNode.isBlock ? "div" : "span"; if(this.droppableTag && $tw.config.htmlUnsafeElements.indexOf(this.droppableTag) === -1) { tag = this.droppableTag; } // Create element and assign classes - var domNode = this.document.createElement(tag), - classes = (this.droppableClass || "").split(" "); - classes.push("tc-droppable"); - domNode.className = classes.join(" "); + domNode = this.document.createElement(tag); + this.domNode = domNode; + this.assignDomNodeClasses(); // Add event handlers if(this.droppableEnable) { $tw.utils.addEventListeners(domNode,[ @@ -144,20 +144,27 @@ DroppableWidget.prototype.execute = function() { this.droppableActions = this.getAttribute("actions"); this.droppableEffect = this.getAttribute("effect","copy"); this.droppableTag = this.getAttribute("tag"); - this.droppableClass = this.getAttribute("class"); this.droppableEnable = (this.getAttribute("enable") || "yes") === "yes"; // Make child widgets this.makeChildWidgets(); }; +DroppableWidget.prototype.assignDomNodeClasses = function() { + var classes = this.getAttribute("class","").split(" "); + classes.push("tc-droppable"); + this.domNode.className = classes.join(" "); +}; + /* Selectively refreshes the widget if needed. Returns true if the widget or any of its children needed re-rendering */ DroppableWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes["class"] || changedAttributes.tag || changedAttributes.enable) { + if(changedAttributes.tag || changedAttributes.enable) { this.refreshSelf(); return true; + } else if(changedAttributes["class"]) { + this.assignDomNodeClasses(); } return this.refreshChildren(changedTiddlers); }; From 8c4d67ba2bd6810cc5f6ce3963da205b951ba635 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sun, 22 Nov 2020 22:18:34 +0100 Subject: [PATCH 040/124] Add light "DesertSand" palette - a desert-sandy palette (#5092) * Add light "DesertSand" palette - a desert-sandy palette * Update DesertSand.tid * Update DesertSand.tid --- core/palettes/DesertSand.tid | 140 +++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 core/palettes/DesertSand.tid diff --git a/core/palettes/DesertSand.tid b/core/palettes/DesertSand.tid new file mode 100644 index 000000000..1f07e4d55 --- /dev/null +++ b/core/palettes/DesertSand.tid @@ -0,0 +1,140 @@ +title: $:/palettes/DesertSand +tags: $:/tags/Palette +name: Desert Sand +description: A desert sand palette +type: application/x-tiddler-dictionary + +alert-background: #ffe476 +alert-border: #b99e2f +alert-highlight: #881122 +alert-muted-foreground: #b99e2f +background: #E9E0C7 +blockquote-bar: <<colour muted-foreground>> +button-background: #BAB29C +button-foreground: <<colour foreground>> +button-border: transparent +code-background: #F3EDDF +code-border: #C3BAA1 +code-foreground: #ab3250 +diff-delete-background: #bd8b8b +diff-delete-foreground: <<colour foreground>> +diff-equal-background: +diff-equal-foreground: <<colour foreground>> +diff-insert-background: #91c093 +diff-insert-foreground: <<colour foreground>> +diff-invisible-background: +diff-invisible-foreground: <<colour muted-foreground>> +dirty-indicator: #ad3434 +download-background: #6ca16c +download-foreground: <<colour background>> +dragger-background: <<colour foreground>> +dragger-foreground: <<colour background>> +dropdown-background: <<colour background>> +dropdown-border: <<colour muted-foreground>> +dropdown-tab-background-selected: #E9E0C7 +dropdown-tab-background: #BAB29C +dropzone-background: rgba(0,200,0,0.7) +external-link-background-hover: inherit +external-link-background-visited: inherit +external-link-background: inherit +external-link-foreground-hover: inherit +external-link-foreground-visited: #313163 +external-link-foreground: #555592 +foreground: #2D2A23 +menubar-background: #CDC2A6 +menubar-foreground: #5A5446 +message-background: #ECE5CF +message-border: #D6CBAA +message-foreground: #5f6e7d +modal-backdrop: <<colour foreground>> +modal-background: <<colour background>> +modal-border: #8A8885 +modal-footer-background: #CDC2A6 +modal-footer-border: #9D998E +modal-header-border: #9D998E +muted-foreground: #9D998E +notification-background: #F0E9D7 +notification-border: #939189 +page-background: #e0d3af +pre-background: #D6CBAA +pre-border: #CDC2A6 +primary: #5B6F55 +selection-background: <<colour foreground>> +selection-foreground: <<colour background>> +select-tag-background: #F0E9D7 +select-tag-foreground: #2D2A23 +sidebar-button-foreground: <<colour foreground>> +sidebar-controls-foreground-hover: #2D2A23 +sidebar-controls-foreground: #867F69 +sidebar-foreground-shadow: transparent +sidebar-foreground: #867F69 +sidebar-muted-foreground-hover: #706A58 +sidebar-muted-foreground: #B3A98C +sidebar-tab-background-selected: #C3BAA1 +sidebar-tab-background: #A6A193 +sidebar-tab-border-selected: #C3BAA1 +sidebar-tab-border: #C3BAA1 +sidebar-tab-divider: #CDC2A6 +sidebar-tab-foreground-selected: +sidebar-tab-foreground: #2D2A23 +sidebar-tiddler-link-foreground-hover: #433F35 +sidebar-tiddler-link-foreground: #706A58 +site-title-foreground: <<colour tiddler-title-foreground>> +static-alert-foreground: #A6A193 +tab-background-selected: #E9E0C7 +tab-background: #A6A193 +tab-border-selected: #C3BAA1 +tab-border: #C3BAA1 +tab-divider: #CDC2A6 +tab-foreground-selected: <<colour tab-foreground>> +tab-foreground: #2D2A23 +table-border: #9D998E +table-footer-background: #8A8885 +table-header-background: #B0AA98 +tag-background: #706A58 +tag-foreground: #E3D7B7 +tiddler-background: <<colour background>> +tiddler-border: <<colour background>> +tiddler-controls-foreground-hover: #9D947B +tiddler-controls-foreground-selected: #706A58 +tiddler-controls-foreground: #C3BAA1 +tiddler-editor-background: #C3BAA1 +tiddler-editor-border-image: #A6A193 +tiddler-editor-border: #A6A193 +tiddler-editor-fields-even: #D6CBAA +tiddler-editor-fields-odd: #C3BAA1 +tiddler-info-background: #E3D7B7 +tiddler-info-border: #BAB29C +tiddler-info-tab-background: #E9E0C7 +tiddler-link-background: <<colour background>> +tiddler-link-foreground: <<colour primary>> +tiddler-subtitle-foreground: #867F69 +tiddler-title-foreground: #374464 +toolbar-new-button: +toolbar-options-button: +toolbar-save-button: +toolbar-info-button: +toolbar-edit-button: +toolbar-close-button: +toolbar-delete-button: +toolbar-cancel-button: +toolbar-done-button: +untagged-background: #8A8885 +very-muted-foreground: #CDC2A6 +wikilist-background: <<colour page-background>> +wikilist-item: #CDC2A6 +wikilist-info: #161512 +wikilist-title: #433F35 +wikilist-title-svg: <<colour wikilist-title>> +wikilist-url: #706A58 +wikilist-button-open: #7db66a +wikilist-button-open-hover: #56a556 +wikilist-button-reveal: #5a6c9e +wikilist-button-reveal-hover: #454591 +wikilist-button-remove: #bc5972 +wikilist-button-remove-hover: #814040 +wikilist-toolbar-background: #CDC2A6 +wikilist-toolbar-foreground: #2D2A23 +wikilist-droplink-dragover: rgba(255,192,192,0.5) +wikilist-button-background: #A6A193 +wikilist-button-foreground: #161512 From 60850ee69b38c0216e684ed43dc8bfb0bbfb82e9 Mon Sep 17 00:00:00 2001 From: Mario Pietsch <pmariojo@gmail.com> Date: Mon, 23 Nov 2020 17:24:37 +0100 Subject: [PATCH 041/124] Update German Language (#5096) * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * Don't override browser selection colours by default Reverts some of #4590 * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * add a new-line before the log text to increase readability of the test output * make eslint, jslint happy * it shouldn't be there * fremove this file from my PRs * Update German Language * some typos Co-authored-by: jeremy@jermolene.com <jeremy@jermolene.com> --- languages/de-DE/ControlPanel.multids | 7 +++++++ languages/de-DE/CoreReadMe.tid | 2 +- languages/de-DE/EditTemplate.multids | 2 ++ languages/de-DE/Help/help.tid | 2 +- languages/de-DE/Help/import.tid | 2 +- languages/de-DE/Help/rendertiddlers.tid | 4 ++-- languages/de-DE/Import.multids | 19 ++++++++++++------- languages/de-DE/Misc.multids | 14 +++++++++++++- languages/de-DE/NewJournalTags.tid | 3 ++- 9 files changed, 41 insertions(+), 14 deletions(-) diff --git a/languages/de-DE/ControlPanel.multids b/languages/de-DE/ControlPanel.multids index 205372f86..f7c9f46f4 100644 --- a/languages/de-DE/ControlPanel.multids +++ b/languages/de-DE/ControlPanel.multids @@ -70,6 +70,7 @@ Plugins/Caption: Plugins Plugins/Disable/Caption: deaktivieren Plugins/Disable/Hint: Deaktivieren Sie dieses Plugin beim nächsten Laden der Seite. Plugins/Disabled/Status: (deaktiviert) +Plugins/Downgrade/Caption: herabstufen Plugins/Empty/Hint: keine Plugins/Enable/Caption: aktivieren Plugins/Enable/Hint: Aktivieren Sie dieses Plugin beim nächsten Laden der Seite. @@ -87,6 +88,11 @@ Plugins/Plugins/Hint: Erweiterungen Plugins/Reinstall/Caption: erneut installieren Plugins/Themes/Caption: Themes Plugins/Themes/Hint: Theme Erweiterungen +Plugins/Update/Caption: aktualisieren +Plugins/Updates/Caption: Aktualisieren +Plugins/Updates/Hint: Verfügbare Erweiterungen zu bereits installierten "Plugins" +Plugins/Updates/UpdateAll/Caption: Aktualisiere <<update-count>> "Plugins" +Plugins/SubPluginPrompt: Mit <<count>> "sub-plugins" verfügbar Saving/Caption: Speichern Saving/DownloadSaver/AutoSave/Description: Erlaube automatisches Speichern für den "Download Saver" Saving/DownloadSaver/AutoSave/Hint: Erlaube automatisches Speichern für den "Download Saver" @@ -111,6 +117,7 @@ Saving/GitService/Gitea/Caption: Gitea Saver Saving/GitService/Gitea/Password: Persönlicher "Zugriffs-Token" (siehe: Gitea’s web Seite: `Settings | Applications | Generate New Token`) Saving/TiddlySpot/Advanced/Heading: Erweiterte Einstellungen Saving/TiddlySpot/BackupDir: Verzeichnis für das "Backup" +Saving/TiddlySpot/ControlPanel: ~TiddlySpot Control Panel Saving/TiddlySpot/Backups: "Backups" Saving/TiddlySpot/Caption: Speichern auf ~TiddlySpot Saving/TiddlySpot/Description: Diese Einstellungen sind nur für http://tiddlyspot.com und kompatible Server aktiv! diff --git a/languages/de-DE/CoreReadMe.tid b/languages/de-DE/CoreReadMe.tid index 7cee41961..2e5b6ab2c 100644 --- a/languages/de-DE/CoreReadMe.tid +++ b/languages/de-DE/CoreReadMe.tid @@ -4,5 +4,5 @@ Dieses Plugin enthält die TiddlyWiki Basis Komponenten, bestehend aus: * JavaScript Code Module. * Piktogramme (icons). -* Vorlagen, die benötigt werden um die TiddlyWiki Oberfläche zu erstellen. +* Vorlagen, die benötigt werden um die ~TiddlyWiki Oberfläche zu erstellen. * British English (''en-GB'') übersetzbare Texte, die von der TW Basis Software verwendet werden. diff --git a/languages/de-DE/EditTemplate.multids b/languages/de-DE/EditTemplate.multids index 17c4f8936..6fafba055 100644 --- a/languages/de-DE/EditTemplate.multids +++ b/languages/de-DE/EditTemplate.multids @@ -19,6 +19,8 @@ Shadow/OverriddenWarning: Dies ist ein veränderter Tiddler. Um zur Standardvers Tags/Add/Button: ok Tags/Add/Button/Hint: Erzeuge einen neuen Tag Tags/Add/Placeholder: Neuer Tag +Tags/ClearInput/Caption: lösche Eingabefeld +Tags/ClearInput/Hint: Lösche Tag Eingabefeld Tags/Dropdown/Caption: Tag Liste Tags/Dropdown/Hint: Tag Liste anzeigen Title/BadCharacterWarning: Warnung: Folgende Zeichen im Titel können zu Problemen führen: <<bad-chars>> diff --git a/languages/de-DE/Help/help.tid b/languages/de-DE/Help/help.tid index 9d76aced5..44b1e0ca6 100644 --- a/languages/de-DE/Help/help.tid +++ b/languages/de-DE/Help/help.tid @@ -1,7 +1,7 @@ title: $:/language/Help/help description: Anzeige der Hilfe für die TiddlyWiki Befehle. -Anzeige der Hilfe für die TiddlyWiki Befehle. +Anzeige der Hilfe für die ~TiddlyWiki Befehle. Beispiel: diff --git a/languages/de-DE/Help/import.tid b/languages/de-DE/Help/import.tid index 606882826..cdf8d81fb 100644 --- a/languages/de-DE/Help/import.tid +++ b/languages/de-DE/Help/import.tid @@ -3,7 +3,7 @@ description: Importiert mehrere Tiddler aus einer Datei Dieser Befehl importiert / extrahiert Tiddler aus folgenden Dateien: -* TiddlyWiki `*.html` +* ~TiddlyWiki `*.html` * `*.tiddler` * `*.tid` * `*.json` diff --git a/languages/de-DE/Help/rendertiddlers.tid b/languages/de-DE/Help/rendertiddlers.tid index 3c7449bd8..7f3ef4d83 100644 --- a/languages/de-DE/Help/rendertiddlers.tid +++ b/languages/de-DE/Help/rendertiddlers.tid @@ -9,13 +9,13 @@ description: Gefilterte Ausgabe von Tiddlern, in einem spezifizierten Format. Gefilterte Ausgabe mehrerer Tiddler, in ein angegebenes Dateiformat (standard: `text/html`) mit spezifischer Erweiterung (Standard: `.html`). ``` ---rendertiddlers <filter> <template> <pathname> [<type>] [<extension>] ["noclean"] +--rendertiddlers '<filter>' <template> <pathname> [<type>] [<extension>] ["noclean"] ``` Beispiel: ``` ---rendertiddlers [!is[system]] $:/core/templates/static.tiddler.html ./static text/plain +--rendertiddlers '[!is[system]]' $:/core/templates/static.tiddler.html ./static text/plain ``` Standardmäßig ist das `output` Verzeichnis ein Unterverzeichnis im `edition` Verzeichnis. Der `--output` Befehl kann verwendet werden, um ein anderes Verzeichnis auszuwählen. diff --git a/languages/de-DE/Import.multids b/languages/de-DE/Import.multids index be3987cc7..e94d255c1 100644 --- a/languages/de-DE/Import.multids +++ b/languages/de-DE/Import.multids @@ -13,11 +13,16 @@ Listing/Preview/TextRaw: Text - roh Listing/Preview/Fields: Felder Listing/Preview/Diff: Diff - Text Listing/Preview/DiffFields: Diff - Felder -Upgrader/Plugins/Suppressed/Incompatible: Unterdrückte, inkompatible oder veraltete "plugins" +Listing/Rename/Tooltip: Tiddler vorm Importieren umbenennen +Listing/Rename/Prompt: Umbenennen in: +Listing/Rename/ConfirmRename : Tiddler umbenennen +Listing/Rename/CancelRename : Abbrechen +Listing/Rename/OverwriteWarning: Ein Tiddler mit diesem Titel existiert bereits. +Upgrader/Plugins/Suppressed/Incompatible: Unterdrückte, inkompatible oder veraltete "plugins". Upgrader/Plugins/Suppressed/Version: Einige "plugins" weden unterdrückt! Importierte plugins: <<incoming>> sind älter als existierende: <<existing>>. -Upgrader/Plugins/Upgraded: Aktualisieren der plugins von: <<incoming>> nach: <<upgraded>> -Upgrader/State/Suppressed: Unterdrückte temporäre Status Tiddler -Upgrader/System/Suppressed: Unterdrückte "System Tiddler" -Upgrader/System/Warning: "Core Modul Tiddler" -Upgrader/System/Alert: Sie sind dabei einen Tiddler zu importieren, der einen "Core Tiddler" überschreibt. Diese Aktion wird nicht empfohlen! Das System kann instabil werden -Upgrader/ThemeTweaks/Created: Migrieren der "theme tweaks" von: <$text text=<<from>>/> +Upgrader/Plugins/Upgraded: Aktualisieren der plugins von: <<incoming>> nach: <<upgraded>>. +Upgrader/State/Suppressed: Unterdrückte temporäre Status Tiddler. +Upgrader/System/Suppressed: Unterdrückte "System Tiddler". +Upgrader/System/Warning: "Core Modul Tiddler". +Upgrader/System/Alert: Sie sind dabei einen Tiddler zu importieren, der einen "Core Tiddler" überschreibt. Diese Aktion wird nicht empfohlen! Das System kann instabil werden. +Upgrader/ThemeTweaks/Created: Migrieren der "theme tweaks" von: <$text text=<<from>>/>. diff --git a/languages/de-DE/Misc.multids b/languages/de-DE/Misc.multids index eb8962857..936a1fc0b 100644 --- a/languages/de-DE/Misc.multids +++ b/languages/de-DE/Misc.multids @@ -10,6 +10,7 @@ ConfirmCancelTiddler: Wollen Sie die Änderungen im Tiddler: "<$text text=<<titl ConfirmDeleteTiddler: Wollen Sie den Tiddler: "<$text text=<<title>>/>" löschen? ConfirmOverwriteTiddler: Tiddler: "<$text text=<<title>>/>" existiert! OK überschreibt den tiddler! ConfirmEditShadowTiddler: Sie sind dabei, einen Schatten-Tiddler zu verändern. Zukünftige, automatische Anpassungen werden dadurch unterdrückt. Sie können Ihre Änderungen rückgängig machen, indem Sie diesen Tiddler wieder löschen. Wollen Sie den Tiddler: "<$text text=<<title>>/>" ändern? +ConfirmAction: Möchten Sie weitermachen? Count: Anzahl DefaultNewTiddlerTitle: Neuer Tiddler Diffs/CountMessage: <<diff-count>> Unterschied(e) @@ -26,7 +27,9 @@ Error/Caption: Fehler Error/EditConflict: Datei auf Server verändert Error/Filter: Filter Fehler Error/FilterSyntax: Syntax Fehler im Filter-Ausdruck +Error/FilterRunPrefix: Filter Fehler: Unbekanntes Prefix für Filter lauf Error/IsFilterOperator: Filter Fehler: Unbekannter Operand für den 'is' Filter Operator +Error/FormatFilterOperator: Filter Fehler: Unbekannter Operand für den 'format' Filter Operator Error/LoadingPluginLibrary: Fehler beim Laden der "plugin library" Error/NetworkErrorAlert: `<h2>''Netzwerk Fehler''</h2>Es scheint, die Verbindung zum Server ist ausgefallen. Das weist auf Probleme mit der Netzwerkverbindung hin. Bitte versuchen Sie die Verbingung wider herzustellen, bevor Sie weitermachen.<br><br>''Nicht gespeicherte Änderungen werden automatich synchronisiert, sobald die Verbindung wider hergestellt ist. Error/RecursiveTransclusion: Recursive Transclusion: Fehler im "transclude widget" @@ -62,6 +65,15 @@ OfficialPluginLibrary: Offizielles ~TiddlyWiki Plugin-Verzeichnis OfficialPluginLibrary/Hint: Offizielles ~TiddlyWiki Plugin-Verzeichnis auf tiddlywiki.com. Plugin, Themes und Sprach Dateien werden vom "core team" gewartet. PluginReloadWarning: Das Wiki muss gespeichert {{$:/core/ui/Buttons/save-wiki}} und neu gladen {{$:/core/ui/Buttons/refresh}} werden, damit die ~JavaScript Plugins ausgeführt werden. RecentChanges/DateFormat: YYYY MMM DD +Shortcuts/Input/AdvancedSearch/Hint: Öffne den ~AdvancedSearch Tiddler vom "Suchmenü" aus +Shortcuts/Input/Accept/Hint: Wähle das selektierte Element +Shortcuts/Input/AcceptVariant/Hint: Wähle das selektierte Element (Variante) +Shortcuts/Input/Cancel/Hint: Lösche das Eingabefeld +Shortcuts/Input/Down/Hint: Gehe zum nächsten Element +Shortcuts/Input/Up/Hint: Gehe zum vorherigen Element +Shortcuts/Input/Tab-Left/Hint: Gehe zum vorherigen Tab +Shortcuts/Input/Tab-Right/Hint: Gehe zum nächsten Tab +Shortcuts/SidebarLayout/Hint: Das Layout des rechten Menüs ändern SystemTiddler/Tooltip: Das ist ein System-Tiddler SystemTiddlers/Include/Prompt: System-Tiddler einschließen TagManager/Colour/Heading: Farbe @@ -71,5 +83,5 @@ TagManager/Icons/None: Keine TagManager/Info/Heading: Info TagManager/Tag/Heading: Tag Tiddler/DateFormat: DDth MMM YYYY um 0hh:0mm -UnsavedChangesWarning: TiddlyWiki wurde geändert, aber noch nicht gespeichert! +UnsavedChangesWarning: ~TiddlyWiki wurde geändert, aber noch nicht gespeichert! Yes: Ja diff --git a/languages/de-DE/NewJournalTags.tid b/languages/de-DE/NewJournalTags.tid index 0534cba33..eec29622f 100644 --- a/languages/de-DE/NewJournalTags.tid +++ b/languages/de-DE/NewJournalTags.tid @@ -1,2 +1,3 @@ title: $:/config/NewJournal/Tags -tags: Journal + +Journal \ No newline at end of file From 72b32946aa1ad25e93123bc6f1c2c1aa959b95d9 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 17:59:48 +0100 Subject: [PATCH 042/124] Small adjustments for DesertSand palette (#5098) * Small adjustments for DesertSand palette * Update DesertSand.tid --- core/palettes/DesertSand.tid | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/palettes/DesertSand.tid b/core/palettes/DesertSand.tid index 1f07e4d55..ba0581095 100644 --- a/core/palettes/DesertSand.tid +++ b/core/palettes/DesertSand.tid @@ -59,8 +59,8 @@ page-background: #e0d3af pre-background: #D6CBAA pre-border: #CDC2A6 primary: #5B6F55 -selection-background: <<colour foreground>> -selection-foreground: <<colour background>> +selection-background: #9D947B +selection-foreground: <<colour foreground>> select-tag-background: #F0E9D7 select-tag-foreground: #2D2A23 sidebar-button-foreground: <<colour foreground>> @@ -70,7 +70,7 @@ sidebar-foreground-shadow: transparent sidebar-foreground: #867F69 sidebar-muted-foreground-hover: #706A58 sidebar-muted-foreground: #B3A98C -sidebar-tab-background-selected: #C3BAA1 +sidebar-tab-background-selected: #e0d3af sidebar-tab-background: #A6A193 sidebar-tab-border-selected: #C3BAA1 sidebar-tab-border: #C3BAA1 @@ -98,7 +98,7 @@ tiddler-border: <<colour background>> tiddler-controls-foreground-hover: #9D947B tiddler-controls-foreground-selected: #706A58 tiddler-controls-foreground: #C3BAA1 -tiddler-editor-background: #C3BAA1 +tiddler-editor-background: #E9E0C7 tiddler-editor-border-image: #A6A193 tiddler-editor-border: #A6A193 tiddler-editor-fields-even: #D6CBAA From aa6f152d35f0e71e32db1d3052bbb435100c942f Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Mon, 23 Nov 2020 18:06:24 +0100 Subject: [PATCH 043/124] Add Switcher modal (#5089) * Alternative switcher using a parameter via tm-show-switcher * Add CSS class for centered modals * Changed keyboardshortcut and removed transition CSS * Resolved wording issues --- core/language/en-GB/Misc.multids | 7 +++++++ core/modules/startup/rootwidget.js | 3 +++ core/ui/KeyboardShortcuts/switcher.tid | 5 +++++ core/ui/LayoutSwitcher.tid | 16 ++++++++++++++++ core/ui/PageTemplate.tid | 2 ++ core/ui/SwitcherModal.tid | 11 +++++++++++ core/wiki/config/ShortcutInfo.multids | 1 + core/wiki/config/SwitcherTargets.multids | 6 ++++++ core/wiki/config/shortcuts/shortcuts.multids | 1 + themes/tiddlywiki/vanilla/base.tid | 11 +++++++++++ 10 files changed, 63 insertions(+) create mode 100644 core/ui/KeyboardShortcuts/switcher.tid create mode 100644 core/ui/LayoutSwitcher.tid create mode 100644 core/ui/SwitcherModal.tid create mode 100644 core/wiki/config/SwitcherTargets.multids diff --git a/core/language/en-GB/Misc.multids b/core/language/en-GB/Misc.multids index a6655709d..81c5758cc 100644 --- a/core/language/en-GB/Misc.multids +++ b/core/language/en-GB/Misc.multids @@ -40,6 +40,7 @@ Error/XMLHttpRequest: XMLHttpRequest error code InternalJavaScriptError/Title: Internal JavaScript Error InternalJavaScriptError/Hint: Well, this is embarrassing. It is recommended that you restart TiddlyWiki by refreshing your browser InvalidFieldName: Illegal characters in field name "<$text text=<<fieldName>>/>". Fields can only contain lowercase letters, digits and the characters underscore (`_`), hyphen (`-`) and period (`.`) +LayoutSwitcher/Description: Open the layout switcher LazyLoadingWarning: <p>Trying to load external content from ''<$text text={{!!_canonical_uri}}/>''</p><p>If this message doesn't disappear, either the tiddler content type doesn't match the type of the external content, or you may be using a browser that doesn't support external content for wikis loaded as standalone files. See https://tiddlywiki.com/#ExternalText</p> LoginToTiddlySpace: Login to TiddlySpace Manager/Controls/FilterByTag/None: (none) @@ -63,6 +64,8 @@ MissingTiddler/Hint: Missing tiddler "<$text text=<<currentTiddler>>/>" -- click No: No OfficialPluginLibrary: Official ~TiddlyWiki Plugin Library OfficialPluginLibrary/Hint: The official ~TiddlyWiki plugin library at tiddlywiki.com. Plugins, themes and language packs are maintained by the core team. +PageTemplate/Description: the default ~TiddlyWiki layout +PageTemplate/Name: Default ~PageTemplate PluginReloadWarning: Please save {{$:/core/ui/Buttons/save-wiki}} and reload {{$:/core/ui/Buttons/refresh}} to allow changes to ~JavaScript plugins to take effect RecentChanges/DateFormat: DDth MMM YYYY Shortcuts/Input/AdvancedSearch/Hint: Open the ~AdvancedSearch panel from within the sidebar search field @@ -74,6 +77,10 @@ Shortcuts/Input/Tab-Left/Hint: Select the previous Tab Shortcuts/Input/Tab-Right/Hint: Select the next Tab Shortcuts/Input/Up/Hint: Select the previous item Shortcuts/SidebarLayout/Hint: Change the sidebar layout +Switcher/Subtitle/theme: Switch Theme +Switcher/Subtitle/layout: Switch Layout +Switcher/Subtitle/language: Switch Language +Switcher/Subtitle/palette: Switch Palette SystemTiddler/Tooltip: This is a system tiddler SystemTiddlers/Include/Prompt: Include system tiddlers TagManager/Colour/Heading: Colour diff --git a/core/modules/startup/rootwidget.js b/core/modules/startup/rootwidget.js index d02748b28..353c25958 100644 --- a/core/modules/startup/rootwidget.js +++ b/core/modules/startup/rootwidget.js @@ -25,6 +25,9 @@ exports.startup = function() { $tw.rootWidget.addEventListener("tm-modal",function(event) { $tw.modal.display(event.param,{variables: event.paramObject, event: event}); }); + $tw.rootWidget.addEventListener("tm-show-switcher",function(event) { + $tw.modal.display("$:/core/ui/SwitcherModal",{variables: event.paramObject, event: event}); + }); // Install the notification mechanism $tw.notifier = new $tw.utils.Notifier($tw.wiki); $tw.rootWidget.addEventListener("tm-notify",function(event) { diff --git a/core/ui/KeyboardShortcuts/switcher.tid b/core/ui/KeyboardShortcuts/switcher.tid new file mode 100644 index 000000000..06dbae69d --- /dev/null +++ b/core/ui/KeyboardShortcuts/switcher.tid @@ -0,0 +1,5 @@ +title: $:/core/ui/KeyboardShortcuts/switcher +tags: $:/tags/KeyboardShortcut +key: ((layout-switcher)) + +<$action-sendmessage $message="tm-show-switcher" switch="layout"/> \ No newline at end of file diff --git a/core/ui/LayoutSwitcher.tid b/core/ui/LayoutSwitcher.tid new file mode 100644 index 000000000..688375110 --- /dev/null +++ b/core/ui/LayoutSwitcher.tid @@ -0,0 +1,16 @@ +title: $:/snippets/LayoutSwitcher +tags: $:/tags/ControlPanel/Appearance + +<$linkcatcher to="$:/layout"> +<div class="tc-chooser"> +<$list filter="[all[tiddlers+shadows]tag[$:/tags/Layout]] [[$:/core/ui/PageTemplate]] +[sort[name]]"> +<$list filter="[{$:/layout}!has[text]]" variable="ignore" emptyMessage=""" +<$set name="cls" filter="[all[current]field:title{$:/layout}]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item"><div class=<<cls>>><$link to={{!!title}}>''<$transclude field="name"/>'' - <$transclude field="description"/></$link></div> +</$set> +"""> +<$set name="cls" filter="[all[current]field:title[$:/core/ui/PageTemplate]]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item"><div class=<<cls>>><$link to={{!!title}}>''<$transclude field="name"/>'' - <$transclude field="description"/></$link></div> +</$set> +</$list> +</$list> +</div> +</$linkcatcher> \ No newline at end of file diff --git a/core/ui/PageTemplate.tid b/core/ui/PageTemplate.tid index abb23a104..a432cc76a 100644 --- a/core/ui/PageTemplate.tid +++ b/core/ui/PageTemplate.tid @@ -1,4 +1,6 @@ title: $:/core/ui/PageTemplate +name: {{$:/language/PageTemplate/Name}} +description: {{$:/language/PageTemplate/Description}} \whitespace trim \define containerClasses() diff --git a/core/ui/SwitcherModal.tid b/core/ui/SwitcherModal.tid new file mode 100644 index 000000000..3477f5778 --- /dev/null +++ b/core/ui/SwitcherModal.tid @@ -0,0 +1,11 @@ +title: $:/core/ui/SwitcherModal +subtitle: <$text text={{{[<switch>lookup[$:/language/Switcher/Subtitle/]]}}}/> +class: tc-modal-centered + +<$tiddler tiddler={{{[<switch>lookup[$:/config/SwitcherTargets/]]}}}> + + +<$transclude/> + + +</$tiddler> \ No newline at end of file diff --git a/core/wiki/config/ShortcutInfo.multids b/core/wiki/config/ShortcutInfo.multids index 8e26f9ad8..1f903dcad 100644 --- a/core/wiki/config/ShortcutInfo.multids +++ b/core/wiki/config/ShortcutInfo.multids @@ -22,6 +22,7 @@ input-tab-left: {{$:/language/Shortcuts/Input/Tab-Left/Hint}} input-tab-right: {{$:/language/Shortcuts/Input/Tab-Right/Hint}} input-up: {{$:/language/Shortcuts/Input/Up/Hint}} italic: {{$:/language/Buttons/Italic/Hint}} +layout-switcher: {{$:/language/LayoutSwitcher/Description}} link: {{$:/language/Buttons/Link/Hint}} linkify: {{$:/language/Buttons/Linkify/Hint}} list-bullet: {{$:/language/Buttons/ListBullet/Hint}} diff --git a/core/wiki/config/SwitcherTargets.multids b/core/wiki/config/SwitcherTargets.multids new file mode 100644 index 000000000..22583c872 --- /dev/null +++ b/core/wiki/config/SwitcherTargets.multids @@ -0,0 +1,6 @@ +title: $:/config/SwitcherTargets/ + +layout: $:/snippets/LayoutSwitcher +language: $:/snippets/languageswitcher +palette: $:/core/ui/ControlPanel/Palette +theme: $:/core/ui/ControlPanel/Theme \ No newline at end of file diff --git a/core/wiki/config/shortcuts/shortcuts.multids b/core/wiki/config/shortcuts/shortcuts.multids index 78cefee4a..2a312cfa0 100644 --- a/core/wiki/config/shortcuts/shortcuts.multids +++ b/core/wiki/config/shortcuts/shortcuts.multids @@ -21,6 +21,7 @@ input-down: Down input-tab-left: alt-Left input-tab-right: alt-Right input-up: Up +layout-switcher: ctrl-shift-L link: ctrl-L linkify: alt-shift-L list-bullet: ctrl-shift-L diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index bc74494bd..940b486fe 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -1840,6 +1840,17 @@ html body.tc-body.tc-single-tiddler-window { border-top: 1px solid <<colour modal-footer-border>>; } + +/* +** Centered modals +*/ +.tc-modal-centered .tc-modal { + width: auto; + top: 50%; + left: 50%; + transform: translate(-50%, -50%) !important; +} + /* ** Notifications */ From cb62c8c96dd5cfa9ef6af2dad11470665d4525c6 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Mon, 23 Nov 2020 18:07:41 +0100 Subject: [PATCH 044/124] Docs for eventcatcher (#5097) --- .../tiddlers/variables/modifier Variable.tid | 4 +- .../tiddlers/widgets/EventCatcherWidget.tid | 78 +++++++++++++++++++ 2 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid diff --git a/editions/tw5.com/tiddlers/variables/modifier Variable.tid b/editions/tw5.com/tiddlers/variables/modifier Variable.tid index d5db7d702..835b3e7cb 100644 --- a/editions/tw5.com/tiddlers/variables/modifier Variable.tid +++ b/editions/tw5.com/tiddlers/variables/modifier Variable.tid @@ -1,8 +1,10 @@ +created: 20201123120203415 +modified: 20201123120211360 tags: Variables [[Core Variables]] title: modifier Variable type: text/vnd.tiddlywiki -Within the ''action'' string of the DroppableWidget, the ''action'' string of the ButtonWidget and the ''action'' string of the LinkCatcherWidget, the <<.def modifier>> [[variable|Variables]] contains the modifier key(s) held during the drag-process. +Within the ''action'' string of the DroppableWidget, the ''action'' string of the ButtonWidget and the ''action'' string of the LinkCatcherWidget and the EventCatcherWidget, the <<.def modifier>> [[variable|Variables]] contains the modifier key(s) held during the drag-process. The possible keys are ''meta'', ''ctrl'', ''shift'', ''alt'', ''meta'' and ''ctrl'', ''meta'' and ''shift'', ''meta'' and ''alt'', ''ctrl'' and ''shift'', ''alt'' and ''shift'', ''ctrl'' and ''alt'', ''ctrl'' and ''alt'' and ''shift'', ''meta'' and ''alt'' and ''shift'', ''meta'' and ''ctrl'' and ''shift'', ''meta'' and ''ctrl'' and ''alt'', ''meta'' and ''ctrl'' and ''alt'' and ''shift'' The variable contains a string that identifies the keys: diff --git a/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid b/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid new file mode 100644 index 000000000..dc8e6b0e3 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid @@ -0,0 +1,78 @@ +created: 20201123113532200 +modified: 20201123143104394 +tags: Widgets +title: EventCatcherWidget +type: text/vnd.tiddlywiki + +! Introduction + +The event catcher widget traps JavaScript events dispatched within its child content, and allows invoking a series of ActionWidgets in response to the events. + +In order for the events to be trapped they must: + +* be of the type specified as a parameter to the event catcher widget. +* arise within a DOM node matching the selector specified as a parameter to the widget. + +Use of the event catcher widget is useful when using large numbers of other trigger widgets such as the ButtonWidget is causing performance problems. The workflow it enables is akin to what is referred to as "event delegation" in JavaScript parlance. + +//This is an advanced widget intended to be used by those familiar with HTML, CSS and JavaScript.// + +! Content and Attributes + +The content of the `<$eventcatcher>` widget is displayed normally. + +|!Attribute |!Description | +|type |The JavaScript event type to be trapped, for example "click", or "dblclick" | +|selector |A CSS selector. Only events originating inside a DOM node with this selector will be trapped. | +|actions |Action strings to be invoked when a matching event is trapped | +|class |An optional CSS class name to be assigned to the HTML element | +|tag |Optional. The html element the widget creates to capture the events, defaults to:<br>» `span` when parsed in inline-mode<br>» `div` when parsed in block-mode | + +! Variables + +The following variables are made available to the actions: + +|!Variables |!Description | +|`dom-*` |All DOM attributes of the node matching the given selector are made available as variables, with the prefix `dom-` | +|`modifier` |The [[modifier Variable]] contains the Modifier Key held during the event (can be "normal", "ctrl", "shift", "alt" or combinations thereof) | +|`event-mousebutton`|The mouse button (if any) used to trigger the event (can be "left", "right" or "middle"). Note that not all event types support the mousebutton property | +|`tv-popup-coords`|A co-ordinate string that can be used with the ActionPopupWidget to trigger a popup at the DOM node matching the selector where the event originated | +|`tv-selectednode-posx`|`x` offset position of the selected DOM node | +|`tv-selectednode-posy`|`y` offset position of the selected DOM node | +|`tv-selectednode-width`|`offsetWidth` of the selected DOM node | +|`tv-selectednode-height`|`offsetHeight` of the selected DOM node | +|`event-fromselected-posx`|`x` position of the event relative to the selected DOM node | +|`event-fromselected-posy`|`y` position of the event relative to the selected DOM node | +|`event-fromcatcher-posx`|`x` position of the event relative to the event catcher DOM node | +|`event-fromcatcher-posy`|`y` position of the event relative to the event catcher DOM node | + +! Example + +This example uses the ActionLogWidget and will log the `data-item-id` attribute of the clicked DOM node to the browser's JavaScript [[console|Web Developer Tools]] + +``` +\define myactions() +<$action-log item=<<dom-data-item-id>>/> +\end + +<$eventcatcher type="click" selector=".item" actions=<<myactions>> tag="div"> + +<div class="item" data-item-id="item1"> +Click events here will be trapped +</div> + +<div class="item" data-item-id="item2"> +And here too +</div> + +<div data-item-id="item3"> +Not here +</div> + +<div class="item" data-item-id="item4"> +And here +</div> + +</$eventcatcher>""" +``` + From 3d93790573fca8c41f65c6f1517007d4cb9d7549 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 19:06:46 +0100 Subject: [PATCH 045/124] Fix StaticRiver exporter width of static tiddlers (#5099) * Add tc-static-story-river class to StaticRiver exporter * Update base.tid --- core/templates/exporters/StaticRiver.tid | 2 +- themes/tiddlywiki/vanilla/base.tid | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/core/templates/exporters/StaticRiver.tid b/core/templates/exporters/StaticRiver.tid index 48e62b1f2..4583bc1ce 100644 --- a/core/templates/exporters/StaticRiver.tid +++ b/core/templates/exporters/StaticRiver.tid @@ -26,7 +26,7 @@ extension: .html </head> <body class="tc-body"> {{$:/StaticBanner||$:/core/templates/html-tiddler}} -<section class="tc-story-river"> +<section class="tc-story-river tc-static-story-river"> {{$:/core/templates/exporters/StaticRiver/Content||$:/core/templates/html-tiddler}} </section> </body> diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 940b486fe..92d9858c5 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -937,6 +937,11 @@ button.tc-btn-invisible.tc-remove-tag-button { ">> + .tc-story-river.tc-static-story-river { + margin-right: 0; + padding-right: 42px; + } + } @media print { From c9a77c5877c3325e1ab31d47554dc4e9fda6e55d Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 19:41:38 +0100 Subject: [PATCH 046/124] Create MacOSDark.tid (#5100) --- core/palettes/MacOSDark.tid | 113 ++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 core/palettes/MacOSDark.tid diff --git a/core/palettes/MacOSDark.tid b/core/palettes/MacOSDark.tid new file mode 100644 index 000000000..3d8caeb9d --- /dev/null +++ b/core/palettes/MacOSDark.tid @@ -0,0 +1,113 @@ +title: $:/palettes/MacOSDark +tags: $:/tags/palette +description: A MacOS inspired dark palette + +alert-background: <<colour background>> +alert-border: <<colour very-muted-foreground>> +alert-highlight: <<colour very-muted-foreground>> +alert-muted-foreground: <<colour muted-foreground>> +background: #282828 +blockquote-bar: <<colour page-background>> +button-background: #3F638B +button-foreground: inherit +button-border: transparent +code-background: <<colour pre-background>> +code-border: <<colour pre-border>> +code-foreground: rgba(255, 255, 255, 0.54) +dirty-indicator: #FF453A +download-background: <<colour primary>> +download-foreground: <<colour foreground>> +dragger-background: <<colour foreground>> +dragger-foreground: <<colour background>> +dropdown-background: #464646 +dropdown-border: <<colour dropdown-background>> +dropdown-tab-background-selected: #3F638B +dropdown-tab-background: #323232 +dropzone-background: <<colour tag-background>> +external-link-background-hover: transparent +external-link-background-visited: transparent +external-link-background: transparent +external-link-foreground-hover: +external-link-foreground-visited: #BF5AF2 +external-link-foreground: #32D74B +foreground: #FFFFFF +message-background: <<colour background>> +message-border: <<colour very-muted-foreground>> +message-foreground: rgba(255, 255, 255, 0.54) +modal-backdrop: <<colour page-background>> +modal-background: <<colour background>> +modal-border: <<colour very-muted-foreground>> +modal-footer-background: <<colour background>> +modal-footer-border: <<colour background>> +modal-header-border: <<colour very-muted-foreground>> +muted-foreground: rgba(255, 255, 255, 0.54) +notification-background: <<colour dropdown-background>> +notification-border: <<colour dropdown-background>> +page-background: #323232 +pre-background: #464646 +pre-border: transparent +primary: #0A84FF +select-tag-background: <<colour background>> +select-tag-foreground: <<colour foreground>> +sidebar-button-foreground: <<colour foreground>> +sidebar-controls-foreground-hover: #FF9F0A +sidebar-controls-foreground: #464646 +sidebar-foreground-shadow: transparent +sidebar-foreground: rgba(255, 255, 255, 0.54) +sidebar-muted-foreground-hover: rgba(255, 255, 255, 0.54) +sidebar-muted-foreground: rgba(255, 255, 255, 0.38) +sidebar-tab-background-selected: #3F638B +sidebar-tab-background: <<colour background>> +sidebar-tab-border-selected: <<colour background>> +sidebar-tab-border: <<colour background>> +sidebar-tab-divider: <<colour background>> +sidebar-tab-foreground-selected: rgba(255, 255, 255, 0.87) +sidebar-tab-foreground: rgba(255, 255, 255, 0.54) +sidebar-tiddler-link-foreground-hover: rgba(255, 255, 255, 0.7) +sidebar-tiddler-link-foreground: rgba(255, 255, 255, 0.54) +site-title-foreground: #ffffff +static-alert-foreground: #B4B4B4 +tab-background-selected: #3F638B +tab-background: <<colour page-background>> +tab-border-selected: <<colour page-background>> +tab-border: <<colour page-background>> +tab-divider: <<colour page-background>> +tab-foreground-selected: rgba(255, 255, 255, 0.87) +tab-foreground: rgba(255, 255, 255, 0.54) +table-border: #464646 +table-footer-background: <<colour tiddler-editor-fields-odd>> +table-header-background: <<colour tiddler-editor-fields-even>> +tag-background: #48484A +tag-foreground: #323232 +tiddler-background: <<colour background>> +tiddler-border: transparent +tiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>> +tiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>> +tiddler-controls-foreground: <<colour sidebar-controls-foreground>> +tiddler-editor-background: transparent +tiddler-editor-border-image: +tiddler-editor-border: rgba(255, 255, 255, 0.08) +tiddler-editor-fields-even: rgba(255, 255, 255, 0.1) +tiddler-editor-fields-odd: rgba(255, 255, 255, 0.04) +tiddler-info-background: #1E1E1E +tiddler-info-border: #1E1E1E +tiddler-info-tab-background: #3F638B +tiddler-link-background: <<colour background>> +tiddler-link-foreground: <<colour primary>> +tiddler-subtitle-foreground: <<colour muted-foreground>> +tiddler-title-foreground: #FFFFFF +toolbar-new-button: +toolbar-options-button: +toolbar-save-button: +toolbar-info-button: +toolbar-edit-button: +toolbar-close-button: +toolbar-delete-button: +toolbar-cancel-button: +toolbar-done-button: +untagged-background: <<colour very-muted-foreground>> +very-muted-foreground: rgba(255, 255, 255, 0.12) +selection-background: #3F638B +selection-foreground: #ffffff +menubar-background: #464646 +menubar-foreground: #ffffff From 519962b4a93dba9f16f7a9950a86d7996416e550 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 20:14:07 +0100 Subject: [PATCH 047/124] Update and rename MacOSDark.tid to CupertinoDark.tid (#5101) * Update and rename MacOSDark.tid to CupertinoDark.tid * Update CupertinoDark.tid * Update CupertinoDark.tid * Update CupertinoDark.tid --- core/palettes/{MacOSDark.tid => CupertinoDark.tid} | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename core/palettes/{MacOSDark.tid => CupertinoDark.tid} (96%) diff --git a/core/palettes/MacOSDark.tid b/core/palettes/CupertinoDark.tid similarity index 96% rename from core/palettes/MacOSDark.tid rename to core/palettes/CupertinoDark.tid index 3d8caeb9d..295e3bc04 100644 --- a/core/palettes/MacOSDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -1,6 +1,8 @@ -title: $:/palettes/MacOSDark -tags: $:/tags/palette -description: A MacOS inspired dark palette +title: $:/palettes/CupertinoDark +tags: $:/tags/Palette +name: Cupertino Dark +description: A macOS inspired dark palette +type: application/x-tiddler-dictionary alert-background: <<colour background>> alert-border: <<colour very-muted-foreground>> From af72fdf24579396c4fdf213632f1d509298bf7c9 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 20:15:04 +0100 Subject: [PATCH 048/124] Add caption to ControlPanel LayoutSwitcher (#5103) * Update LayoutSwitcher.tid * Update ControlPanel.multids --- core/language/en-GB/ControlPanel.multids | 1 + core/ui/LayoutSwitcher.tid | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/language/en-GB/ControlPanel.multids b/core/language/en-GB/ControlPanel.multids index c75aa5679..852197083 100644 --- a/core/language/en-GB/ControlPanel.multids +++ b/core/language/en-GB/ControlPanel.multids @@ -44,6 +44,7 @@ KeyboardShortcuts/Platform/Linux: Linux platform only KeyboardShortcuts/Platform/NonLinux: Non-Linux platforms only KeyboardShortcuts/Platform/Windows: Windows platform only KeyboardShortcuts/Platform/NonWindows: Non-Windows platforms only +LayoutSwitcher/Caption: Layout LoadedModules/Caption: Loaded Modules LoadedModules/Hint: These are the currently loaded tiddler modules linked to their source tiddlers. Any italicised modules lack a source tiddler, typically because they were setup during the boot process. Palette/Caption: Palette diff --git a/core/ui/LayoutSwitcher.tid b/core/ui/LayoutSwitcher.tid index 688375110..11c0c01a0 100644 --- a/core/ui/LayoutSwitcher.tid +++ b/core/ui/LayoutSwitcher.tid @@ -1,5 +1,6 @@ title: $:/snippets/LayoutSwitcher tags: $:/tags/ControlPanel/Appearance +caption: {{$:/language/ControlPanel/LayoutSwitcher/Caption}} <$linkcatcher to="$:/layout"> <div class="tc-chooser"> @@ -13,4 +14,4 @@ tags: $:/tags/ControlPanel/Appearance </$list> </$list> </div> -</$linkcatcher> \ No newline at end of file +</$linkcatcher> From e0f4d82214aed29d02c547f0474b24d7f9bf8d77 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 20:32:51 +0100 Subject: [PATCH 049/124] Update CupertinoDark.tid (#5105) --- core/palettes/CupertinoDark.tid | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index 295e3bc04..504e627d3 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -4,9 +4,9 @@ name: Cupertino Dark description: A macOS inspired dark palette type: application/x-tiddler-dictionary -alert-background: <<colour background>> -alert-border: <<colour very-muted-foreground>> -alert-highlight: <<colour very-muted-foreground>> +alert-background: #FF453A +alert-border: #FF453A +alert-highlight: #FFD60A alert-muted-foreground: <<colour muted-foreground>> background: #282828 blockquote-bar: <<colour page-background>> @@ -25,7 +25,7 @@ dropdown-background: #464646 dropdown-border: <<colour dropdown-background>> dropdown-tab-background-selected: #3F638B dropdown-tab-background: #323232 -dropzone-background: <<colour tag-background>> +dropzone-background: #30D158 external-link-background-hover: transparent external-link-background-visited: transparent external-link-background: transparent From 77971ff7201a9669c671d45232fdcc863a666e9e Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 20:41:51 +0100 Subject: [PATCH 050/124] Lighter sidebar-controls-foreground for Cupertino Dark Palette (#5106) --- core/palettes/CupertinoDark.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index 504e627d3..438292d97 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -53,7 +53,7 @@ select-tag-background: <<colour background>> select-tag-foreground: <<colour foreground>> sidebar-button-foreground: <<colour foreground>> sidebar-controls-foreground-hover: #FF9F0A -sidebar-controls-foreground: #464646 +sidebar-controls-foreground: #8E8E93 sidebar-foreground-shadow: transparent sidebar-foreground: rgba(255, 255, 255, 0.54) sidebar-muted-foreground-hover: rgba(255, 255, 255, 0.54) From 50a3c5526fbf9dfbd476428eac7b61b6647e1f2c Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 23 Nov 2020 21:09:53 +0100 Subject: [PATCH 051/124] Update CupertinoDark.tid (#5107) --- core/palettes/CupertinoDark.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index 438292d97..12db75000 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -85,7 +85,7 @@ tiddler-background: <<colour background>> tiddler-border: transparent tiddler-controls-foreground-hover: <<colour sidebar-controls-foreground-hover>> tiddler-controls-foreground-selected: <<colour sidebar-controls-foreground-hover>> -tiddler-controls-foreground: <<colour sidebar-controls-foreground>> +tiddler-controls-foreground: #48484A tiddler-editor-background: transparent tiddler-editor-border-image: tiddler-editor-border: rgba(255, 255, 255, 0.08) From 7327a3fb92fa2ae17d7264c66ab0409d43b18fdc Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Tue, 24 Nov 2020 18:57:39 +0000 Subject: [PATCH 052/124] Fixed: Shadow tiddlers don't refresh when their plugin is deleted/modified --- core/modules/startup/plugins.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core/modules/startup/plugins.js b/core/modules/startup/plugins.js index 907579dbe..cad61b104 100644 --- a/core/modules/startup/plugins.js +++ b/core/modules/startup/plugins.js @@ -24,6 +24,7 @@ var PREFIX_CONFIG_REGISTER_PLUGIN_TYPE = "$:/config/RegisterPluginType/"; exports.startup = function() { $tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "no"}); $tw.wiki.addEventListener("change",function(changes) { + // Work out which of the changed tiddlers are plugins that we need to reregister var changesToProcess = [], requireReloadDueToPluginChange = false; $tw.utils.each(Object.keys(changes),function(title) { @@ -38,6 +39,7 @@ exports.startup = function() { } } }); + // Issue warning if any of the tiddlers require a reload if(requireReloadDueToPluginChange) { $tw.wiki.addTiddler({title: TITLE_REQUIRE_RELOAD_DUE_TO_PLUGIN_CHANGE,text: "yes"}); } @@ -45,12 +47,35 @@ exports.startup = function() { if(changesToProcess.length > 0) { var changes = $tw.wiki.readPluginInfo(changesToProcess); if(changes.modifiedPlugins.length > 0 || changes.deletedPlugins.length > 0) { + var changedShadowTiddlers = {}; + // Collect the shadow tiddlers of any deleted plugins + $tw.utils.each(changes.deletedPlugins,function(pluginTitle) { + var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle); + if(pluginInfo) { + $tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) { + changedShadowTiddlers[title] = true; + }); + } + }); + // Collect the shadow tiddlers of any modified plugins + $tw.utils.each(changes.modifiedPlugins,function(pluginTitle) { + var pluginInfo = $tw.wiki.getPluginInfo(pluginTitle); + if(pluginInfo) { + $tw.utils.each(Object.keys(pluginInfo.tiddlers),function(title) { + changedShadowTiddlers[title] = false; + }); + } + }); // (Re-)register any modified plugins $tw.wiki.registerPluginTiddlers(null,changes.modifiedPlugins); // Unregister any deleted plugins $tw.wiki.unregisterPluginTiddlers(null,changes.deletedPlugins); // Unpack the shadow tiddlers $tw.wiki.unpackPluginTiddlers(); + // Queue change events for the changed shadow tiddlers + $tw.utils.each(Object.keys(changedShadowTiddlers),function(title) { + $tw.wiki.enqueueTiddlerEvent(title,changedShadowTiddlers[title]); + }); } } }); From c854e518faa2d2661b7b7278634b10607ab0a5f5 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Tue, 24 Nov 2020 19:01:33 +0000 Subject: [PATCH 053/124] Add support for $:/info/darkmode (and for dynamic info tiddlers) --- core/modules/info/platform.js | 9 +++- core/modules/startup/info.js | 44 +++++++++++-------- .../tiddlers/mechanisms/InfoMechanism.tid | 3 +- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/core/modules/info/platform.js b/core/modules/info/platform.js index 29ebdd594..a73a5e5df 100644 --- a/core/modules/info/platform.js +++ b/core/modules/info/platform.js @@ -12,7 +12,7 @@ Initialise basic platform $:/info/ tiddlers /*global $tw: false */ "use strict"; -exports.getInfoTiddlerFields = function() { +exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) { var mapBoolean = function(value) {return value ? "yes" : "no";}, infoTiddlerFields = []; // Basics @@ -36,6 +36,13 @@ exports.getInfoTiddlerFields = function() { // Screen size infoTiddlerFields.push({title: "$:/info/browser/screen/width", text: window.screen.width.toString()}); infoTiddlerFields.push({title: "$:/info/browser/screen/height", text: window.screen.height.toString()}); + // Dark mode through event listener on MediaQueryList + var mqList = window.matchMedia("(prefers-color-scheme: dark)"), + getDarkModeTiddler = function() {return {title: "$:/info/darkmode", text: mqList.matches ? "yes" : "no"};}; + infoTiddlerFields.push(getDarkModeTiddler()); + mqList.addEventListener("change", function(event) { + updateInfoTiddlersCallback([getDarkModeTiddler()]); + }); // Language infoTiddlerFields.push({title: "$:/info/browser/language", text: navigator.language || ""}); } diff --git a/core/modules/startup/info.js b/core/modules/startup/info.js index 7efaa5b0e..ed2305930 100644 --- a/core/modules/startup/info.js +++ b/core/modules/startup/info.js @@ -21,29 +21,37 @@ exports.synchronous = true; var TITLE_INFO_PLUGIN = "$:/temp/info-plugin"; exports.startup = function() { + // Function to bake the info plugin with new tiddlers + var updateInfoPlugin = function(tiddlerFieldsArray) { + // Get the existing tiddlers + var json = $tw.wiki.getTiddlerData(TITLE_INFO_PLUGIN,{tiddlers: {}}); + // Add the new ones + $tw.utils.each(tiddlerFieldsArray,function(fields) { + if(fields && fields.title) { + json.tiddlers[fields.title] = fields; + } + }); + // Bake the info tiddlers into a plugin. We use the non-standard plugin-type "info" because ordinary plugins are only registered asynchronously after being loaded dynamically + var fields = { + title: TITLE_INFO_PLUGIN, + type: "application/json", + "plugin-type": "info", + text: JSON.stringify(json,null,$tw.config.preferences.jsonSpaces) + }; + $tw.wiki.addTiddler(new $tw.Tiddler(fields)); + + }; // Collect up the info tiddlers - var infoTiddlerFields = {}; - // Give each info module a chance to fill in as many info tiddlers as they want + var tiddlerFieldsArray = []; + // Give each info module a chance to provide as many info tiddlers as they want as an array, and give them a callback for dynamically updating them $tw.modules.forEachModuleOfType("info",function(title,moduleExports) { if(moduleExports && moduleExports.getInfoTiddlerFields) { - var tiddlerFieldsArray = moduleExports.getInfoTiddlerFields(infoTiddlerFields); - $tw.utils.each(tiddlerFieldsArray,function(fields) { - if(fields) { - infoTiddlerFields[fields.title] = fields; - } - }); + Array.prototype.push.apply(tiddlerFieldsArray,moduleExports.getInfoTiddlerFields(updateInfoPlugin)); } }); - // Bake the info tiddlers into a plugin. We use the non-standard plugin-type "info" because ordinary plugins are only registered asynchronously after being loaded dynamically - var fields = { - title: TITLE_INFO_PLUGIN, - type: "application/json", - "plugin-type": "info", - text: JSON.stringify({tiddlers: infoTiddlerFields},null,$tw.config.preferences.jsonSpaces) - }; - $tw.wiki.addTiddler(new $tw.Tiddler(fields)); - $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]); - $tw.wiki.registerPluginTiddlers("info"); + updateInfoPlugin(tiddlerFieldsArray); + var changes = $tw.wiki.readPluginInfo([TITLE_INFO_PLUGIN]); + $tw.wiki.registerPluginTiddlers("info",[TITLE_INFO_PLUGIN]); $tw.wiki.unpackPluginTiddlers(); }; diff --git a/editions/tw5.com/tiddlers/mechanisms/InfoMechanism.tid b/editions/tw5.com/tiddlers/mechanisms/InfoMechanism.tid index 62d907076..c56bd47eb 100644 --- a/editions/tw5.com/tiddlers/mechanisms/InfoMechanism.tid +++ b/editions/tw5.com/tiddlers/mechanisms/InfoMechanism.tid @@ -1,5 +1,5 @@ created: 20140720164948099 -modified: 20200506110435897 +modified: 20201124185829706 tags: Mechanisms title: InfoMechanism type: text/vnd.tiddlywiki @@ -27,3 +27,4 @@ System tiddlers in the namespace `$:/info/` are used to expose information about |[[$:/info/url/port]] |<<.from-version "5.1.14">> Port portion of URL of wiki (eg, ''<<example port>>'') | |[[$:/info/url/protocol]] |<<.from-version "5.1.14">> Protocol portion of URL of wiki (eg, ''<<example protocol>>'') | |[[$:/info/url/search]] |<<.from-version "5.1.14">> Search portion of URL of wiki (eg, ''<<example search>>'') | +|[[$:/info/darkmode]] |<<.from-version "5.1.23">> Is dark mode enabled? ("yes" or "no") | From 5769cf9784cba842c1b8ff5f1481cc1b4db67f48 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Tue, 24 Nov 2020 22:15:37 +0100 Subject: [PATCH 054/124] Fix #5108 - vanilla/reset overrides system fonts (#5118) --- themes/tiddlywiki/vanilla/base.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 92d9858c5..2b2ce4ce9 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -90,7 +90,7 @@ html button { ** Basic element styles */ -html { +html, body { font-family: {{$:/themes/tiddlywiki/vanilla/settings/fontfamily}}; text-rendering: optimizeLegibility; /* Enables kerning and ligatures etc. */ -webkit-font-smoothing: antialiased; From a9d583b85e1dc660d4c6b75c45db4f95e776d373 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Tue, 24 Nov 2020 22:16:24 +0100 Subject: [PATCH 055/124] Update CupertinoDark.tid (#5117) --- core/palettes/CupertinoDark.tid | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index 12db75000..b4f8f12aa 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -11,7 +11,7 @@ alert-muted-foreground: <<colour muted-foreground>> background: #282828 blockquote-bar: <<colour page-background>> button-background: #3F638B -button-foreground: inherit +button-foreground: <<colour foreground>> button-border: transparent code-background: <<colour pre-background>> code-border: <<colour pre-border>> @@ -33,6 +33,8 @@ external-link-foreground-hover: external-link-foreground-visited: #BF5AF2 external-link-foreground: #32D74B foreground: #FFFFFF +menubar-background: #464646 +menubar-foreground: #ffffff message-background: <<colour background>> message-border: <<colour very-muted-foreground>> message-foreground: rgba(255, 255, 255, 0.54) @@ -42,7 +44,7 @@ modal-border: <<colour very-muted-foreground>> modal-footer-background: <<colour background>> modal-footer-border: <<colour background>> modal-header-border: <<colour very-muted-foreground>> -muted-foreground: rgba(255, 255, 255, 0.54) +muted-foreground: #464646 notification-background: <<colour dropdown-background>> notification-border: <<colour dropdown-background>> page-background: #323232 @@ -108,8 +110,22 @@ toolbar-delete-button: toolbar-cancel-button: toolbar-done-button: untagged-background: <<colour very-muted-foreground>> -very-muted-foreground: rgba(255, 255, 255, 0.12) +very-muted-foreground: #464646 selection-background: #3F638B selection-foreground: #ffffff -menubar-background: #464646 -menubar-foreground: #ffffff +wikilist-background: <<colour page-background>> +wikilist-button-background: <<colour button-background>> +wikilist-button-foreground: <<colour foreground>> +wikilist-button-open: #32D74B +wikilist-button-open-hover: #32D74B +wikilist-button-reveal: #0A84FF +wikilist-button-reveal-hover: #0A84FF +wikilist-button-remove: #FF453A +wikilist-button-remove-hover: #FF453A +wikilist-droplink-dragover: #32D74B +wikilist-item: <<colour background>> +wikilist-toolbar-background: <<colour background>> +wikilist-title: <<colour foreground>> +wikilist-title-svg: <<colour foreground>> +wikilist-toolbar-foreground: <<colour foreground>> +wikilist-url: <<colour muted-foreground>> From ce27492b968b7f7b698ab720f233ab55f3336826 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Tue, 24 Nov 2020 22:19:20 +0100 Subject: [PATCH 056/124] Refactor updating of classes for button widgets to avoid potential edge case failures (#5115) --- core/modules/widgets/button.js | 48 ++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/core/modules/widgets/button.js b/core/modules/widgets/button.js index 3ece52371..5b15c875f 100644 --- a/core/modules/widgets/button.js +++ b/core/modules/widgets/button.js @@ -42,7 +42,20 @@ ButtonWidget.prototype.render = function(parent,nextSibling) { domNode = this.document.createElement(tag); this.domNode = domNode; // Assign classes - this.assignDomNodeClasses(); + var classes = this["class"].split(" ") || [], + isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp(); + if(this.selectedClass) { + if((this.set || this.setTitle) && this.setTo && this.isSelected()) { + $tw.utils.pushTop(classes,this.selectedClass.split(" ")); + } + if(isPoppedUp) { + $tw.utils.pushTop(classes,this.selectedClass.split(" ")); + } + } + if(isPoppedUp) { + $tw.utils.pushTop(classes,"tc-popup-handle"); + } + domNode.className = classes.join(" "); // Assign other attributes if(this.style) { domNode.setAttribute("style",this.style); @@ -192,7 +205,7 @@ ButtonWidget.prototype.execute = function() { this["aria-label"] = this.getAttribute("aria-label"); this.tooltip = this.getAttribute("tooltip"); this.style = this.getAttribute("style"); - // Class attribute is handled in assignDomNodeClasses() + this["class"] = this.getAttribute("class",""); this.selectedClass = this.getAttribute("selectedClass"); this.defaultSetValue = this.getAttribute("default",""); this.buttonTag = this.getAttribute("tag"); @@ -208,21 +221,22 @@ ButtonWidget.prototype.execute = function() { this.makeChildWidgets(); }; -ButtonWidget.prototype.assignDomNodeClasses = function() { - var classes = this.getAttribute("class","").split(" "), - isPoppedUp = (this.popup || this.popupTitle) && this.isPoppedUp(); - if(this.selectedClass) { - if((this.set || this.setTitle) && this.setTo && this.isSelected()) { - $tw.utils.pushTop(classes,this.selectedClass.split(" ")); +ButtonWidget.prototype.updateDomNodeClasses = function() { + var domNodeClasses = this.domNode.className.split(" "), + oldClasses = this.class.split(" "), + newClasses; + this["class"] = this.getAttribute("class",""); + newClasses = this.class.split(" "); + //Remove classes assigned from the old value of class attribute + $tw.utils.each(oldClasses,function(oldClass){ + var i = domNodeClasses.indexOf(oldClass); + if(i !== -1) { + domNodeClasses.splice(i,1); } - if(isPoppedUp) { - $tw.utils.pushTop(classes,this.selectedClass.split(" ")); - } - } - if(isPoppedUp) { - $tw.utils.pushTop(classes,"tc-popup-handle"); - } - this.domNode.className = classes.join(" "); + }); + //Add new classes from updated class attribute. + $tw.utils.pushTop(domNodeClasses,newClasses); + this.domNode.className = domNodeClasses.join(" "); } /* @@ -234,7 +248,7 @@ ButtonWidget.prototype.refresh = function(changedTiddlers) { this.refreshSelf(); return true; } else if(changedAttributes["class"]) { - this.assignDomNodeClasses(); + this.updateDomNodeClasses(); } return this.refreshChildren(changedTiddlers); }; From 0e247c991db7dfc638c358c7d9824897066a51a5 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Tue, 24 Nov 2020 22:19:37 +0100 Subject: [PATCH 057/124] Update modifier variable docs (#5114) Listing the potential key combination in a single line is hard to read and also redundant when we have the same information in the table below. --- editions/tw5.com/tiddlers/variables/modifier Variable.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/variables/modifier Variable.tid b/editions/tw5.com/tiddlers/variables/modifier Variable.tid index 835b3e7cb..3d1322e7f 100644 --- a/editions/tw5.com/tiddlers/variables/modifier Variable.tid +++ b/editions/tw5.com/tiddlers/variables/modifier Variable.tid @@ -5,7 +5,7 @@ title: modifier Variable type: text/vnd.tiddlywiki Within the ''action'' string of the DroppableWidget, the ''action'' string of the ButtonWidget and the ''action'' string of the LinkCatcherWidget and the EventCatcherWidget, the <<.def modifier>> [[variable|Variables]] contains the modifier key(s) held during the drag-process. -The possible keys are ''meta'', ''ctrl'', ''shift'', ''alt'', ''meta'' and ''ctrl'', ''meta'' and ''shift'', ''meta'' and ''alt'', ''ctrl'' and ''shift'', ''alt'' and ''shift'', ''ctrl'' and ''alt'', ''ctrl'' and ''alt'' and ''shift'', ''meta'' and ''alt'' and ''shift'', ''meta'' and ''ctrl'' and ''shift'', ''meta'' and ''ctrl'' and ''alt'', ''meta'' and ''ctrl'' and ''alt'' and ''shift'' +Possible key combinations are listed in the table below. The variable contains a string that identifies the keys: From 4f88d79d8b0a8560c3e0da7e590687adb35bc6f6 Mon Sep 17 00:00:00 2001 From: Bram Chen <bram.chen@gmail.com> Date: Wed, 25 Nov 2020 05:27:24 +0800 Subject: [PATCH 058/124] Add chinese translations for Switchers (#5111) --- languages/zh-Hans/ControlPanel.multids | 1 + languages/zh-Hans/Misc.multids | 7 +++++++ languages/zh-Hant/ControlPanel.multids | 1 + languages/zh-Hant/Misc.multids | 7 +++++++ 4 files changed, 16 insertions(+) diff --git a/languages/zh-Hans/ControlPanel.multids b/languages/zh-Hans/ControlPanel.multids index e40c7b1b7..41b94baf1 100644 --- a/languages/zh-Hans/ControlPanel.multids +++ b/languages/zh-Hans/ControlPanel.multids @@ -44,6 +44,7 @@ KeyboardShortcuts/Platform/Linux: 仅 Linux 平台 KeyboardShortcuts/Platform/NonLinux: 仅非 Linux 平台 KeyboardShortcuts/Platform/Windows: 仅 Windows 平台 KeyboardShortcuts/Platform/NonWindows: 仅非 Windows 平台 +LayoutSwitcher/Caption: 布局 LoadedModules/Caption: 已加载的模块 LoadedModules/Hint: 这些是当前已加载的模块之源码条目。斜体的模块则无源码条目,通常是因为它们是在引导过程中设置。 Palette/Caption: 调色板 diff --git a/languages/zh-Hans/Misc.multids b/languages/zh-Hans/Misc.multids index 8d94c60e9..556e8b492 100644 --- a/languages/zh-Hans/Misc.multids +++ b/languages/zh-Hans/Misc.multids @@ -40,6 +40,7 @@ Error/XMLHttpRequest: XMLHttpRequest 错误代码 InternalJavaScriptError/Title: 内部的 JavaScript 错误 InternalJavaScriptError/Hint: 喔,真是令人尴尬。建议刷新您的浏览器,重新启动 TiddlyWiki InvalidFieldName: 字段名称 "<$text text=<<fieldName>>/>" 包含无效字符,字段名称只能包含小写字母、数字、底线 (`_`)、 连字号 (`-`) 和小数点 (`.`) +LayoutSwitcher/Description: 打开布局切换器 LazyLoadingWarning: <p>正在从 ''<$text text={{!!_canonical_uri}}/>'' 加载外部内容 ...</p><p>如果此信息未消失,可能是条目内容类型与外部内容的类型不匹配,或是您可能正在使用的浏览器,不支援单文件式维基的外部内容。请参阅 https://tiddlywiki.com/#ExternalText</p> LoginToTiddlySpace: 登录 TiddlySpace Manager/Controls/FilterByTag/None: (无) @@ -63,6 +64,8 @@ MissingTiddler/Hint: 佚失条目 "<$text text=<<currentTiddler>>/>" - 点击 {{ No: 否 OfficialPluginLibrary: ~TiddlyWiki 官方插件程式库 OfficialPluginLibrary/Hint: 此为在 tiddlywiki.com 的 ~TiddlyWiki 官方插件程式库。由核心团队维护的插件、主题和语言包。 +PageTemplate/Description: 默认的 ~Tiddlywiki 布局 +PageTemplate/Name: 默认的 ~PageTemplate PluginReloadWarning: 请保存 {{$:/core/ui/Buttons/save-wiki}} 并刷新页面 {{$:/core/ui/Buttons/refresh}} ,使 ~JavaScript 插件的更改生效 RecentChanges/DateFormat: YYYY年0MM月0DD日 Shortcuts/Input/Accept/Hint: 接受选取的项目 @@ -74,6 +77,10 @@ Shortcuts/Input/Tab-Left/Hint: 选择上一个页签 Shortcuts/Input/Tab-Right/Hint: 选择下一个页签 Shortcuts/Input/Up/Hint: 选择前一个项目 Shortcuts/SidebarLayout/Hint: 更改侧边栏布局 +Switcher/Subtitle/theme: 切换布景主题 +Switcher/Subtitle/layout: 切换布局 +Switcher/Subtitle/language: 切换语言 +Switcher/Subtitle/palette: 切换调色板 SystemTiddler/Tooltip: 此为系统条目 SystemTiddlers/Include/Prompt: 包括系统条目 TagManager/Colour/Heading: 颜色 diff --git a/languages/zh-Hant/ControlPanel.multids b/languages/zh-Hant/ControlPanel.multids index 988ae4c39..5fb35f427 100644 --- a/languages/zh-Hant/ControlPanel.multids +++ b/languages/zh-Hant/ControlPanel.multids @@ -44,6 +44,7 @@ KeyboardShortcuts/Platform/Linux: 僅 Linux 平臺 KeyboardShortcuts/Platform/NonLinux: 僅非 Linux 平臺 KeyboardShortcuts/Platform/Windows: 僅 Windows 平臺 KeyboardShortcuts/Platform/NonWindows: 僅非 Windows 平臺 +LayoutSwitcher/Caption: 版面 LoadedModules/Caption: 已載入的模組 LoadedModules/Hint: 這些是當前已載入的模組之源碼條目。斜體的模組則無源碼條目,通常是因為它們是在引導過程中設置。 Palette/Caption: 調色盤 diff --git a/languages/zh-Hant/Misc.multids b/languages/zh-Hant/Misc.multids index 008ded4fc..b9d036826 100644 --- a/languages/zh-Hant/Misc.multids +++ b/languages/zh-Hant/Misc.multids @@ -40,6 +40,7 @@ Error/XMLHttpRequest: XMLHttpRequest 錯誤代碼 InternalJavaScriptError/Title: 內部的 JavaScript 錯誤 InternalJavaScriptError/Hint: 喔,真是令人尷尬。建議刷新您的瀏覽器,重新啟動 TiddlyWiki InvalidFieldName: 欄位名稱 "<$text text=<<fieldName>>/>" 包含無效字元,欄位名稱只能包含小寫字母、數字、底線 (`_`)、 連接號 (`-`) 和小數點 (`.`) +LayoutSwitcher/Description: 開啟版面切換器 LazyLoadingWarning: <p>正在從 ''<$text text={{!!_canonical_uri}}/>'' 載入外部內容 ...</p><p>如果此訊息未消失,可能是條目內容類型與外部內容的類型不匹配,或是您可能正在使用的瀏覽器,不支援單檔式維基的外部內容。請參閱 https://tiddlywiki.com/#ExternalText</p> LoginToTiddlySpace: 登入 TiddlySpace Manager/Controls/FilterByTag/None: (無) @@ -63,6 +64,8 @@ MissingTiddler/Hint: 佚失條目 "<$text text=<<currentTiddler>>/>" - 點擊 {{ No: 否 OfficialPluginLibrary: ~TiddlyWiki 官方插件程式庫 OfficialPluginLibrary/Hint: 此為在 tiddlywiki.com 的 ~TiddlyWiki 官方插件程式庫。由核心團隊維護的插件、主題和語言包。 +PageTemplate/Description: 預設的 ~Tiddlywiki 佈局 +PageTemplate/Name: 預設的 ~PageTemplate PluginReloadWarning: 請儲存 {{$:/core/ui/Buttons/save-wiki}} 並刷新頁面 {{$:/core/ui/Buttons/refresh}} ,使 ~JavaScript 插件的更改生效 RecentChanges/DateFormat: YYYY年0MM月0DD日 Shortcuts/Input/Accept/Hint: 接受選取的項目 @@ -74,6 +77,10 @@ Shortcuts/Input/Tab-Left/Hint: 選擇上一個頁籤 Shortcuts/Input/Tab-Right/Hint: 選擇下一個頁籤 Shortcuts/Input/Up/Hint: 選擇前一個項目 Shortcuts/SidebarLayout/Hint: 更改側邊欄版面 +Switcher/Subtitle/theme: 切換佈景主題 +Switcher/Subtitle/layout: 切換版面 +Switcher/Subtitle/language: 切換語言 +Switcher/Subtitle/palette: 切換調色盤 SystemTiddler/Tooltip: 此為系統條目 SystemTiddlers/Include/Prompt: 包括系統條目 TagManager/Colour/Heading: 顏色 From 6c98bb706a15b353a92895529a69bece11f613ff Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Tue, 24 Nov 2020 22:38:18 +0100 Subject: [PATCH 059/124] Docs for switching layouts (#5109) --- editions/tw5.com/tiddlers/concepts/SystemTags.tid | 3 ++- .../customising/Alternative page layouts.tid | 15 +++++++++++++++ .../tiddlers/customising/Customise TiddlyWiki.tid | 9 +++++---- .../Page and tiddler layout customisation.tid | 9 ++++++--- .../systemtags/SystemTag_ $__tags_Layout.tid | 9 +++++++++ .../tiddlers/widgets/EventCatcherWidget.tid | 3 ++- 6 files changed, 39 insertions(+), 9 deletions(-) create mode 100644 editions/tw5.com/tiddlers/customising/Alternative page layouts.tid create mode 100644 editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_Layout.tid diff --git a/editions/tw5.com/tiddlers/concepts/SystemTags.tid b/editions/tw5.com/tiddlers/concepts/SystemTags.tid index d7f01cbf1..6b6d4a5a1 100644 --- a/editions/tw5.com/tiddlers/concepts/SystemTags.tid +++ b/editions/tw5.com/tiddlers/concepts/SystemTags.tid @@ -1,5 +1,6 @@ created: 20130822080600000 -modified: 20180927080631239 +list: [[SystemTag: $:/tags/AboveStory]] [[SystemTag: $:/tags/AdvancedSearch]] [[SystemTag: $:/tags/AdvancedSearch/FilterButton]] [[SystemTag: $:/tags/Alert]] [[SystemTag: $:/tags/BelowStory]] [[SystemTag: $:/tags/ControlPanel]] [[SystemTag: $:/tags/ControlPanel/Advanced]] [[SystemTag: $:/tags/ControlPanel/Appearance]] [[SystemTag: $:/tags/ControlPanel/Info]] [[SystemTag: $:/tags/ControlPanel/Saving]] [[SystemTag: $:/tags/ControlPanel/Settings]] [[SystemTag: $:/tags/ControlPanel/Toolbars]] [[SystemTag: $:/tags/EditorToolbar]] [[SystemTag: $:/tags/EditPreview]] [[SystemTag: $:/tags/EditTemplate]] [[SystemTag: $:/tags/EditToolbar]] [[SystemTag: $:/tags/Exporter]] [[SystemTag: $:/tags/Filter]] [[SystemTag: $:/tags/Image]] [[SystemTag: $:/tags/ImportPreview]] [[SystemTag: $:/tags/KeyboardShortcut]] [[SystemTag: $:/tags/Layout]] [[SystemTag: $:/tags/Macro]] [[SystemTag: $:/tags/Macro/View]] [[SystemTag: $:/tags/Manager/ItemMain]] [[SystemTag: $:/tags/Manager/ItemSidebar]] [[SystemTag: $:/tags/MoreSideBar]] [[SystemTag: $:/tags/MoreSideBar/Plugins]] [[SystemTag: $:/tags/PageControls]] [[SystemTag: $:/tags/PageTemplate]] [[SystemTag: $:/tags/Palette]] [[SystemTag: $:/tags/PluginLibrary]] [[SystemTag: $:/tags/RawMarkup]] [[SystemTag: $:/tags/RawMarkupWikified]] [[SystemTag: $:/tags/RawMarkupWikified/BottomBody]] [[SystemTag: $:/tags/RawMarkupWikified/TopBody]] [[SystemTag: $:/tags/RawMarkupWikified/TopHead]] [[SystemTag: $:/tags/RawStaticContent]] [[SystemTag: $:/tags/RemoteAssetInfo]] [[SystemTag: $:/tags/SearchResults]] [[SystemTag: $:/tags/ServerConnection]] [[SystemTag: $:/tags/SideBar]] [[SystemTag: $:/tags/SideBarSegment]] [[SystemTag: $:/tags/StartupAction]] [[SystemTag: $:/tags/StartupAction/Browser]] [[SystemTag: $:/tags/StartupAction/Node]] [[SystemTag: $:/tags/Stylesheet]] [[SystemTag: $:/tags/TagDropdown]] [[SystemTag: $:/tags/TextEditor/Snippet]] [[SystemTag: $:/tags/TiddlerInfo]] [[SystemTag: $:/tags/TiddlerInfo/Advanced]] [[SystemTag: $:/tags/TiddlerInfoSegment]] [[SystemTag: $:/tags/ToolbarButtonStyle]] [[SystemTag: $:/tags/TopLeftBar]] [[SystemTag: $:/tags/TopRightBar]] [[SystemTag: $:/tags/ViewTemplate]] [[SystemTag: $:/tags/ViewToolbar]] +modified: 20201123192434277 tags: Reference Concepts title: SystemTags type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/customising/Alternative page layouts.tid b/editions/tw5.com/tiddlers/customising/Alternative page layouts.tid new file mode 100644 index 000000000..554313b73 --- /dev/null +++ b/editions/tw5.com/tiddlers/customising/Alternative page layouts.tid @@ -0,0 +1,15 @@ +created: 20201123172925848 +modified: 20201123192845498 +tags: [[Customise TiddlyWiki]] +title: Alternative page layouts +type: text/vnd.tiddlywiki + +<<.from-version "5.1.23">> You can have multiple alternative page layouts and switch between them. To see a list of available layouts and switch between them, use the keyboard shortcut <kbd><<displayshortcuts ((layout-switcher))>></kbd>. + +! Creating an alternative page layout + +Creating an alternative layout goes beyond [[adding or removing features|Page and tiddler layout customisation]] from the default interface and allows you to create an entirely new layout from scratch. + +To create an alternative page layout and have the ability to switch to it, you need to create an alternative page template tiddler with the [[SystemTag: $:/tags/Layout]]. + +This alternative page template can either be a tweaked and modified version of the [[default page template|$:/core/ui/PageTemplate]], or something entirely different. The layout switching mechanism requires that your page template tiddler has the fields `name` and `description`, which are used in the listing in the switching user interface. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/customising/Customise TiddlyWiki.tid b/editions/tw5.com/tiddlers/customising/Customise TiddlyWiki.tid index 29820d5a9..3c1327366 100644 --- a/editions/tw5.com/tiddlers/customising/Customise TiddlyWiki.tid +++ b/editions/tw5.com/tiddlers/customising/Customise TiddlyWiki.tid @@ -1,8 +1,9 @@ -title: Customise TiddlyWiki +created: 20140904101600000 +list: [[Adding a table of contents to the sidebar]] [[Configuring startup tiddlers]] [[Configuring the default TiddlerInfo tab]] [[Creating a custom export format]] [[Creating a splash screen]] [[Customising search results]] [[Hidden Settings]] [[How to add a new tab to the sidebar]] [[How to apply custom styles]] [[How to create keyboard shortcuts]] [[How to turn off camel case linking]] [[How to widen tiddlers (aka storyriver)]] [[Making a custom journal button]] [[Page and tiddler layout customisation]] [[Alternative page layouts]] [[Preserving open tiddlers at startup]] [[Setting a favicon]] [[Setting a page background image]] [[Using Stylesheets]] +modified: 20201123173044437 tags: TableOfContents -created: 201409041016 -modified: 201409041016 -list: [[Initial customisation]] +title: Customise TiddlyWiki +type: text/vnd.tiddlywiki Information about customising TiddlyWiki diff --git a/editions/tw5.com/tiddlers/customising/Page and tiddler layout customisation.tid b/editions/tw5.com/tiddlers/customising/Page and tiddler layout customisation.tid index 7a233d396..a99687aac 100644 --- a/editions/tw5.com/tiddlers/customising/Page and tiddler layout customisation.tid +++ b/editions/tw5.com/tiddlers/customising/Page and tiddler layout customisation.tid @@ -1,7 +1,8 @@ -title: Page and tiddler layout customisation +created: 20141120125300000 +modified: 20201123173002935 tags: [[Customise TiddlyWiki]] -created: 201411201253 -modified: 201411201253 +title: Page and tiddler layout customisation +type: text/vnd.tiddlywiki One major feature of TiddlyWiki that many new users are unaware of is the degree to which TiddlyWiki can be customised, just by adding or removing SystemTags in key shadow tiddlers or in your own custom tiddlers. @@ -11,6 +12,8 @@ One major feature of TiddlyWiki that many new users are unaware of is the degree Once you know what you are doing, all of these things are actually pretty easy to do. +<<.from-version "5.1.23">> You can also create [[alternative page layouts|Alternative page layouts]] and switch between them. + ! Adding custom-made tiddlers to the user interface You can also create any tiddler you want and tag it with the appropriate SystemTag, and it will appear in that place. For example, if you create a tiddler 'Reminder to self', add the text 'This is a reminder' and tag it `$:/tags/EditTemplate`, the words 'This is a reminder' will appear inside every tiddler when you edit it. diff --git a/editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_Layout.tid b/editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_Layout.tid new file mode 100644 index 000000000..537ca1d91 --- /dev/null +++ b/editions/tw5.com/tiddlers/systemtags/SystemTag_ $__tags_Layout.tid @@ -0,0 +1,9 @@ +caption: $:/tags/Layout +created: 20201123191935978 +description: marks alternative page layouts +modified: 20201123192158739 +tags: SystemTags +title: SystemTag: $:/tags/Layout +type: text/vnd.tiddlywiki + +The [[system tag|SystemTags]] `$:/tags/Layout` marks [[alternative page layouts|Alternative page layouts]] that can be switched to. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid b/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid index dc8e6b0e3..28d2c9e9a 100644 --- a/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid @@ -1,11 +1,12 @@ created: 20201123113532200 -modified: 20201123143104394 +modified: 20201123172753436 tags: Widgets title: EventCatcherWidget type: text/vnd.tiddlywiki ! Introduction +<<.from-version "5.1.23">> The event catcher widget traps JavaScript events dispatched within its child content, and allows invoking a series of ActionWidgets in response to the events. In order for the events to be trapped they must: From 94ffb50e047c47e37b1992ca8a9cecf8d7bcf255 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 25 Nov 2020 12:33:39 +0000 Subject: [PATCH 060/124] Fix dark mode event handling Previous code worked but this matches the spec, and works on iOS --- core/modules/info/platform.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/info/platform.js b/core/modules/info/platform.js index a73a5e5df..b9c140956 100644 --- a/core/modules/info/platform.js +++ b/core/modules/info/platform.js @@ -40,7 +40,7 @@ exports.getInfoTiddlerFields = function(updateInfoTiddlersCallback) { var mqList = window.matchMedia("(prefers-color-scheme: dark)"), getDarkModeTiddler = function() {return {title: "$:/info/darkmode", text: mqList.matches ? "yes" : "no"};}; infoTiddlerFields.push(getDarkModeTiddler()); - mqList.addEventListener("change", function(event) { + mqList.addListener(function(event) { updateInfoTiddlersCallback([getDarkModeTiddler()]); }); // Language From 64ac29adca05b0daaaa34b0bee183858ffa3967c Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 25 Nov 2020 13:58:54 +0000 Subject: [PATCH 061/124] Fix typo preventing filter run prefix modules from being cached This had a significant impact on performance. --- core/modules/filters.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/filters.js b/core/modules/filters.js index 9a18eb2af..0beb86208 100644 --- a/core/modules/filters.js +++ b/core/modules/filters.js @@ -188,7 +188,7 @@ exports.getFilterOperators = function() { }; exports.getFilterRunPrefixes = function() { - if(!this.filterPrefixes) { + if(!this.filterRunPrefixes) { $tw.Wiki.prototype.filterRunPrefixes = {}; $tw.modules.applyMethods("filterrunprefix",this.filterRunPrefixes); } From e3bf1f43cfe78914525b2969b4aef2cde6671960 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 25 Nov 2020 14:07:01 +0000 Subject: [PATCH 062/124] Missed off previous commit 64ac29adc Thanks @saqimtiaz --- core/wiki/config/RegisterPluginTypes.multids | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/wiki/config/RegisterPluginTypes.multids b/core/wiki/config/RegisterPluginTypes.multids index f0e52acd5..0ea7e1a01 100644 --- a/core/wiki/config/RegisterPluginTypes.multids +++ b/core/wiki/config/RegisterPluginTypes.multids @@ -3,5 +3,5 @@ title: $:/config/RegisterPluginType/ plugin: yes theme: no language: no -info: no +info: yes import: no From 2267e31546271588b88e49c762f7d7482f678c0a Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Wed, 25 Nov 2020 15:54:28 +0000 Subject: [PATCH 063/124] Fix eventcatcher to ensure variable values are strings I was getting some inconsistencies with filter operators that expect strings. --- core/modules/widgets/eventcatcher.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/core/modules/widgets/eventcatcher.js b/core/modules/widgets/eventcatcher.js index c0d691f5e..1f3d96688 100644 --- a/core/modules/widgets/eventcatcher.js +++ b/core/modules/widgets/eventcatcher.js @@ -58,26 +58,26 @@ EventWidget.prototype.render = function(parent,nextSibling) { // If we found one, copy the attributes as variables, otherwise exit if(selectedNode.matches(selector)) { $tw.utils.each(selectedNode.attributes,function(attribute) { - variables["dom-" + attribute.name] = attribute.value; + variables["dom-" + attribute.name] = attribute.value.toString(); }); //Add a variable with a popup coordinate string for the selected node variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")"; //Add variables for offset of selected node - variables["tv-selectednode-posx"] = selectedNode.offsetLeft; - variables["tv-selectednode-posy"] = selectedNode.offsetTop; - variables["tv-selectednode-width"] = selectedNode.offsetWidth; - variables["tv-selectednode-height"] = selectedNode.offsetHeight; + variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString(); + variables["tv-selectednode-posy"] = selectedNode.offsetTop.toString(); + variables["tv-selectednode-width"] = selectedNode.offsetWidth.toString(); + variables["tv-selectednode-height"] = selectedNode.offsetHeight.toString(); //Add variables for event X and Y position relative to selected node selectedNodeRect = selectedNode.getBoundingClientRect(); - variables["event-fromselected-posx"] = event.clientX - selectedNodeRect.left; - variables["event-fromselected-posy"] = event.clientY - selectedNodeRect.top; + variables["event-fromselected-posx"] = (event.clientX - selectedNodeRect.left).toString(); + variables["event-fromselected-posy"] = (event.clientY - selectedNodeRect.top).toString(); //Add variables for event X and Y position relative to event catcher node catcherNodeRect = self.domNode.getBoundingClientRect(); - variables["event-fromcatcher-posx"] = event.clientX - catcherNodeRect.left; - variables["event-fromcatcher-posy"] = event.clientY - catcherNodeRect.top; + variables["event-fromcatcher-posx"] = (event.clientX - catcherNodeRect.left).toString(); + variables["event-fromcatcher-posy"] = (event.clientY - catcherNodeRect.top).toString(); } else { return false; } From 8320a55fef4b34be305568ae1dd930f5177a2f44 Mon Sep 17 00:00:00 2001 From: Mario Pietsch <pmariojo@gmail.com> Date: Wed, 25 Nov 2020 17:27:31 +0100 Subject: [PATCH 064/124] fix titlebar line-height for chrome (#5122) --- themes/tiddlywiki/vanilla/base.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 2b2ce4ce9..0807c37bd 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -1053,7 +1053,7 @@ button.tc-btn-invisible.tc-remove-tag-button { .tc-titlebar { font-weight: 300; font-size: 2.35em; - line-height: 1.3em; + line-height: 1.35em; color: <<colour tiddler-title-foreground>>; margin: 0; } From 9637a29e55d72c3533c3d92356fc9057974ce0e4 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Thu, 26 Nov 2020 12:41:24 +0000 Subject: [PATCH 065/124] Rename widget.executeStartupTiddlers() to invokeActionsByTag() This method was introduced earlier in v5.1.23 in 5cc1600072f5aa50c8ff5f5d2e748d81a7067420 It is not in fact restricted to startup tiddlers. --- core/modules/startup/render.js | 2 +- core/modules/startup/startup.js | 6 +++--- core/modules/widgets/widget.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/core/modules/startup/render.js b/core/modules/startup/render.js index 7ec6ec444..fa4d21003 100644 --- a/core/modules/startup/render.js +++ b/core/modules/startup/render.js @@ -107,7 +107,7 @@ exports.startup = function() { $tw.rootWidget.domNodes = [$tw.pageContainer]; $tw.rootWidget.children = [$tw.pageWidgetNode]; // Run any post-render startup actions - $tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction/PostRender"); + $tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/PostRender"); }; })(); diff --git a/core/modules/startup/startup.js b/core/modules/startup/startup.js index b7897a5ce..781852cea 100755 --- a/core/modules/startup/startup.js +++ b/core/modules/startup/startup.js @@ -64,12 +64,12 @@ exports.startup = function() { document: $tw.browser ? document : $tw.fakeDocument }); // Execute any startup actions - $tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction"); + $tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction"); if($tw.browser) { - $tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction/Browser"); + $tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Browser"); } if($tw.node) { - $tw.rootWidget.executeStartupTiddlers("$:/tags/StartupAction/Node"); + $tw.rootWidget.invokeActionsByTag("$:/tags/StartupAction/Node"); } // Kick off the language manager and switcher $tw.language = new $tw.Language(); diff --git a/core/modules/widgets/widget.js b/core/modules/widgets/widget.js index bd66438e2..22112a516 100755 --- a/core/modules/widgets/widget.js +++ b/core/modules/widgets/widget.js @@ -574,10 +574,10 @@ Widget.prototype.invokeActionString = function(actions,triggeringWidget,event,va /* Execute action tiddlers by tag */ -Widget.prototype.executeStartupTiddlers = function(tag) { +Widget.prototype.invokeActionsByTag = function(tag,event,variables) { var self = this; $tw.utils.each(self.wiki.filterTiddlers("[all[shadows+tiddlers]tag[" + tag + "]!has[draft.of]]"),function(title) { - self.invokeActionString(self.wiki.getTiddlerText(title),self); + self.invokeActionString(self.wiki.getTiddlerText(title),self,event,variables); }); }; From 2175be27b0ceac691f711d7c45994ce97aaa0267 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Fri, 27 Nov 2020 22:37:11 +0100 Subject: [PATCH 066/124] Ensure that we always fetch the latest sha bypassing cache. (#5126) Ensure that we always fetch the latest sha bypassing cache. --- core/modules/savers/github.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/modules/savers/github.js b/core/modules/savers/github.js index 2d59f45ff..2276a2346 100644 --- a/core/modules/savers/github.js +++ b/core/modules/savers/github.js @@ -31,7 +31,8 @@ GitHubSaver.prototype.save = function(text,method,callback) { headers = { "Accept": "application/vnd.github.v3+json", "Content-Type": "application/json;charset=UTF-8", - "Authorization": "Basic " + window.btoa(username + ":" + password) + "Authorization": "Basic " + window.btoa(username + ":" + password), + "If-None-Match": "" }; // Bail if we don't have everything we need if(!username || !password || !repo || !filename) { From 86a9f922bf8f424703d4fee6a730659cec08f240 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Fri, 27 Nov 2020 22:52:26 +0100 Subject: [PATCH 067/124] Update LayoutSwitcher.tid (#5125) --- core/ui/LayoutSwitcher.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/ui/LayoutSwitcher.tid b/core/ui/LayoutSwitcher.tid index 11c0c01a0..28bc19158 100644 --- a/core/ui/LayoutSwitcher.tid +++ b/core/ui/LayoutSwitcher.tid @@ -4,7 +4,7 @@ caption: {{$:/language/ControlPanel/LayoutSwitcher/Caption}} <$linkcatcher to="$:/layout"> <div class="tc-chooser"> -<$list filter="[all[tiddlers+shadows]tag[$:/tags/Layout]] [[$:/core/ui/PageTemplate]] +[sort[name]]"> +<$list filter="[all[tiddlers+shadows]tag[$:/tags/Layout]] [[$:/core/ui/PageTemplate]] +[!is[draft]sort[name]]"> <$list filter="[{$:/layout}!has[text]]" variable="ignore" emptyMessage=""" <$set name="cls" filter="[all[current]field:title{$:/layout}]" value="tc-chooser-item tc-chosen" emptyValue="tc-chooser-item"><div class=<<cls>>><$link to={{!!title}}>''<$transclude field="name"/>'' - <$transclude field="description"/></$link></div> </$set> From 8005c91e79cf1cbafe7aee64ff99398149d83c18 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 08:26:47 +0100 Subject: [PATCH 068/124] Correctly add EventListener 'click' for popup-handling in new windows (#5127) --- core/modules/startup/windows.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/core/modules/startup/windows.js b/core/modules/startup/windows.js index 16b8f0316..5c867f74d 100644 --- a/core/modules/startup/windows.js +++ b/core/modules/startup/windows.js @@ -84,11 +84,8 @@ exports.startup = function() { name: "keydown", handlerObject: $tw.keyboardManager, handlerMethod: "handleKeydownEvent" - },{ - name: "click", - handlerObject: $tw.popup, - handlerMethod: "handleEvent" }]); + srcWindow.document.documentElement.addEventListener("click",$tw.popup,true); srcWindow.haveInitialisedWindow = true; }); // Close open windows when unloading main window From 09d7a77f1b5ecf6b3519de13f960223b8ab8e864 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 15:07:12 +0100 Subject: [PATCH 069/124] Add default "tiddlywiki" styles to CodeMirror and Highlight.js (#5128) * Update styles.tid * Update styles.tid * Update theme.tid * Delete cm-theme-tiddlywiki.tid --- .../tiddlers/cm-theme-tiddlywiki.tid | 56 ------------- .../tiddlywiki/codemirror/config/theme.tid | 2 +- plugins/tiddlywiki/codemirror/styles.tid | 80 ++++++++++++++++++- plugins/tiddlywiki/highlight/styles.tid | 80 ++++++++++++++++++- 4 files changed, 159 insertions(+), 59 deletions(-) delete mode 100644 editions/codemirrordemo/tiddlers/cm-theme-tiddlywiki.tid diff --git a/editions/codemirrordemo/tiddlers/cm-theme-tiddlywiki.tid b/editions/codemirrordemo/tiddlers/cm-theme-tiddlywiki.tid deleted file mode 100644 index 501b20b9a..000000000 --- a/editions/codemirrordemo/tiddlers/cm-theme-tiddlywiki.tid +++ /dev/null @@ -1,56 +0,0 @@ -title: $:/themes/codemirror/tiddlywiki -tags: $:/tags/Stylesheet -module-type: codemirror-theme -name: tiddlywiki - -.cm-s-tiddlywiki { - font-size: 1em; - line-height: 1.5em; - letter-spacing: 0.3px; - word-spacing: 1px; - background: <<colour page-background>>; - color: <<colour foreground>>; -} -.cm-s-tiddlywiki .CodeMirror-lines { - padding: 8px 0; -} -.cm-s-tiddlywiki .CodeMirror-gutters { - background-color: <<colour page-background>>; - padding-right: 10px; - z-index: 3; - border: none; -} -.cm-s-tiddlywiki div.CodeMirror-cursor { - border-left: 3px solid <<colour very-muted-foreground>>; -} -.cm-s-tiddlywiki .CodeMirror-activeline-background { - background: <<colour tiddler-editor-fields-even>>; -} -.cm-s-tiddlywiki .CodeMirror-selected { - background: <<colour muted-foreground>>; -} -.cm-s-tiddlywiki .cm-comment { - font-style: italic; - color: <<colour muted-foreground>>; -} -.cm-s-tiddlywiki .CodeMirror-linenumber { - color: italic; -} - -.cm-s-tiddlywiki span.cm-atom, .cm-s-tiddlywiki span.cm-number, .cm-s-tiddlywiki span.cm-keyword, .cm-s-tiddlywiki span.cm-variable, .cm-s-tiddlywiki span.cm-attribute, .cm-s-tiddlywiki span.cm-quote, .cm-s-tiddlywiki-light span.cm-hr, .cm-s-tiddlywiki-light span.cm-link { color: #063289; } - -.cm-s-tiddlywiki span.cm-property { color: #b29762; } -.cm-s-tiddlywiki span.cm-punctuation, .cm-s-tiddlywiki span.cm-unit, .cm-s-tiddlywiki span.cm-negative { color: #063289; } -.cm-s-tiddlywiki span.cm-string, .cm-s-tiddlywiki span.cm-operator { color: #1659df; } -.cm-s-tiddlywiki span.cm-positive { color: #896724; } - -.cm-s-tiddlywiki span.cm-variable-2, .cm-s-tiddlywiki span.cm-variable-3, .cm-s-tiddlywiki span.cm-type, .cm-s-tiddlywiki span.cm-string-2, .cm-s-tiddlywiki span.cm-url { color: #896724; } -.cm-s-tiddlywiki span.cm-def, .cm-s-tiddlywiki span.cm-tag, .cm-s-tiddlywiki span.cm-builtin, .cm-s-tiddlywiki span.cm-qualifier, .cm-s-tiddlywiki span.cm-header, .cm-s-tiddlywiki span.cm-em { color: #2d2006; } -.cm-s-tiddlywiki span.cm-bracket, .cm-s-tiddlywiki span.cm-comment { color: #b6ad9a; } - -/* using #f00 red for errors, don't think any of the colorscheme variables will stand out enough, ... maybe by giving it a background-color ... */ -/* .cm-s-tiddlywiki span.cm-error { background: #896724; color: #728fcb; } */ -.cm-s-tiddlywiki span.cm-error, .cm-s-tiddlywiki span.cm-invalidchar { color: #f00; } - -.cm-s-tiddlywiki span.cm-header { font-weight: normal; } -.cm-s-tiddlywiki .CodeMirror-matchingbracket { text-decoration: underline; color: #faf8f5 !important; } diff --git a/plugins/tiddlywiki/codemirror/config/theme.tid b/plugins/tiddlywiki/codemirror/config/theme.tid index 66eb3fce0..e0e25ba37 100644 --- a/plugins/tiddlywiki/codemirror/config/theme.tid +++ b/plugins/tiddlywiki/codemirror/config/theme.tid @@ -1,3 +1,3 @@ title: $:/config/codemirror/theme type: string -text: default +text: tiddlywiki diff --git a/plugins/tiddlywiki/codemirror/styles.tid b/plugins/tiddlywiki/codemirror/styles.tid index 869521839..135584b2a 100755 --- a/plugins/tiddlywiki/codemirror/styles.tid +++ b/plugins/tiddlywiki/codemirror/styles.tid @@ -1,5 +1,7 @@ title: $:/plugins/tiddlywiki/codemirror/styles tags: [[$:/tags/Stylesheet]] +module-type: codemirror-theme +name: tiddlywiki /* Make the editor resize to fit its content */ @@ -13,5 +15,81 @@ tags: [[$:/tags/Stylesheet]] .CodeMirror-scroll { overflow-x: auto; - overflow-y: hidden; + overflow-y: hidden; +} + +.cm-s-tiddlywiki { + color-profile: sRGB; + rendering-intent: auto; +} + +.cm-s-tiddlywiki.CodeMirror, .cm-s-tiddlywiki .CodeMirror-gutters { background-color: <<colour tiddler-editor-background>>; color: <<colour foreground>>; } +.cm-s-tiddlywiki .CodeMirror-gutters {background: <<colour tiddler-editor-background>>; border-right: 0px;} +.cm-s-tiddlywiki .CodeMirror-linenumber {color: <<colour primary>>;} +.cm-s-tiddlywiki .CodeMirror-cursor { border-left: 2px solid <<colour foreground>>; } +.cm-s-tiddlywiki div.CodeMirror-selected { background: <<colour selection-background>>; } +.cm-s-tiddlywiki .CodeMirror-selectedtext, +.cm-s-tiddlywiki .CodeMirror-selected, +.cm-s-tiddlywiki .CodeMirror-line::selection, +.cm-s-tiddlywiki .CodeMirror-line > span::selection, +.cm-s-tiddlywiki .CodeMirror-line > span > span::selection, +.cm-s-tiddlywiki .CodeMirror-line::-moz-selection, +.cm-s-tiddlywiki .CodeMirror-line > span::-moz-selection, +.cm-s-tiddlywiki .CodeMirror-line > span > span::-moz-selection { background: <<colour selection-background>>; } +.cm-s-tiddlywiki span.cm-comment { color: <<colour muted-foreground>>; font-style:italic; font-weight:normal; } +.cm-s-tiddlywiki .CodeMirror-activeline-background, .cm-s-tiddlywiki .CodeMirror-activeline-gutter .CodeMirror-linenumber { background: <<colour background>>; } +.cm-s-tiddlywiki .CodeMirror-activeline .CodeMirror-linenumber.CodeMirror-gutter-elt { background: <<colour background>>; color: <<colour foreground>>; } +.cm-s-tiddlywiki .CodeMirror-matchingbracket { background: <<colour primary>>; color:<<colour foreground>> !important; } +.cm-s-tiddlywiki span.cm-matchhighlight { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} +.cm-s-tiddlywiki span.cm-searching { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} + + +.cm-s-tiddlywiki .CodeMirror-widget { + text-shadow: none; +} + +.cm-s-tiddlywiki .cm-header { color: #586e75; } +.cm-s-tiddlywiki .cm-quote { color: #93a1a1; } + +.cm-s-tiddlywiki .cm-keyword { color: #cb4b16; } +.cm-s-tiddlywiki .cm-atom { color: #d33682; } +.cm-s-tiddlywiki .cm-number { color: #d33682; } +.cm-s-tiddlywiki .cm-def { color: #2aa198; } + +.cm-s-tiddlywiki .cm-variable { color: #839496; } +.cm-s-tiddlywiki .cm-variable-2 { color: #b58900; } +.cm-s-tiddlywiki .cm-variable-3, .cm-s-tiddlywiki .cm-type { color: #6c71c4; } + +.cm-s-tiddlywiki .cm-property { color: #2aa198; } +.cm-s-tiddlywiki .cm-operator { color: #6c71c4; } + +.cm-s-tiddlywiki .cm-comment { color: #586e75; font-style:italic; } + +.cm-s-tiddlywiki .cm-string { color: #859900; } +.cm-s-tiddlywiki .cm-string-2 { color: #b58900; } + +.cm-s-tiddlywiki .cm-meta { color: #859900; } +.cm-s-tiddlywiki .cm-qualifier { color: #b58900; } +.cm-s-tiddlywiki .cm-builtin { color: #d33682; } +.cm-s-tiddlywiki .cm-bracket { color: #cb4b16; } +.cm-s-tiddlywiki .CodeMirror-matchingbracket { color: #859900; } +.cm-s-tiddlywiki .CodeMirror-nonmatchingbracket { color: #dc322f; } +.cm-s-tiddlywiki .cm-tag { color: #93a1a1; } +.cm-s-tiddlywiki .cm-attribute { color: #2aa198; } +.cm-s-tiddlywiki .cm-hr { + color: transparent; + border-top: 1px solid #586e75; + display: block; +} +.cm-s-tiddlywiki .cm-link { color: #93a1a1; cursor: pointer; } +.cm-s-tiddlywiki .cm-special { color: #6c71c4; } +.cm-s-tiddlywiki .cm-em { + color: #999; + text-decoration: underline; + text-decoration-style: dotted; +} +.cm-s-tiddlywiki .cm-error, +.cm-s-tiddlywiki .cm-invalidchar { + color: #586e75; + border-bottom: 1px dotted #dc322f; } diff --git a/plugins/tiddlywiki/highlight/styles.tid b/plugins/tiddlywiki/highlight/styles.tid index 1e55917ed..ac22a85b4 100644 --- a/plugins/tiddlywiki/highlight/styles.tid +++ b/plugins/tiddlywiki/highlight/styles.tid @@ -1,4 +1,82 @@ title: $:/plugins/tiddlywiki/highlight/styles tags: [[$:/tags/Stylesheet]] -.hljs{display:block;overflow-x:auto;padding:.5em;color:#333;background:#f8f8f8;-webkit-text-size-adjust:none}.hljs-comment,.diff .hljs-header,.hljs-javadoc{color:#998;font-style:italic}.hljs-keyword,.css .rule .hljs-keyword,.hljs-winutils,.nginx .hljs-title,.hljs-subst,.hljs-request,.hljs-status{color:#333;font-weight:bold}.hljs-number,.hljs-hexcolor,.ruby .hljs-constant{color:teal}.hljs-string,.hljs-tag .hljs-value,.hljs-phpdoc,.hljs-dartdoc,.tex .hljs-formula{color:#d14}.hljs-title,.hljs-id,.scss .hljs-preprocessor{color:#900;font-weight:bold}.hljs-list .hljs-keyword,.hljs-subst{font-weight:normal}.hljs-class .hljs-title,.hljs-type,.vhdl .hljs-literal,.tex .hljs-command{color:#458;font-weight:bold}.hljs-tag,.hljs-tag .hljs-title,.hljs-rule .hljs-property,.django .hljs-tag .hljs-keyword{color:navy;font-weight:normal}.hljs-attribute,.hljs-variable,.lisp .hljs-body,.hljs-name{color:teal}.hljs-regexp{color:#009926}.hljs-symbol,.ruby .hljs-symbol .hljs-string,.lisp .hljs-keyword,.clojure .hljs-keyword,.scheme .hljs-keyword,.tex .hljs-special,.hljs-prompt{color:#990073}.hljs-built_in{color:#0086b3}.hljs-preprocessor,.hljs-pragma,.hljs-pi,.hljs-doctype,.hljs-shebang,.hljs-cdata{color:#999;font-weight:bold}.hljs-deletion{background:#fdd}.hljs-addition{background:#dfd}.diff .hljs-change{background:#0086b3}.hljs-chunk{color:#aaa} \ No newline at end of file +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + background: <<colour tiddler-editor-background>>; + color: <<colour foreground>>; + -webkit-text-size-adjust:none +} + +.hljs-comment, +.hljs-quote { + color: #93a1a1; +} + +/* Solarized Green */ +.hljs-keyword, +.hljs-selector-tag, +.hljs-addition { + color: #859900; +} + +/* Solarized Cyan */ +.hljs-number, +.hljs-string, +.hljs-meta .hljs-meta-string, +.hljs-literal, +.hljs-doctag, +.hljs-regexp { + color: #2aa198; +} + +/* Solarized Blue */ +.hljs-title, +.hljs-section, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class { + color: #268bd2; +} + +/* Solarized Yellow */ +.hljs-attribute, +.hljs-attr, +.hljs-variable, +.hljs-template-variable, +.hljs-class .hljs-title, +.hljs-type { + color: #b58900; +} + +/* Solarized Orange */ +.hljs-symbol, +.hljs-bullet, +.hljs-subst, +.hljs-meta, +.hljs-meta .hljs-keyword, +.hljs-selector-attr, +.hljs-selector-pseudo, +.hljs-link { + color: #cb4b16; +} + +/* Solarized Red */ +.hljs-built_in, +.hljs-deletion { + color: #dc322f; +} + +.hljs-formula { + background: #eee8d5; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} From 7d2703bffb1365b7691af9c24480d524073fe595 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 15:07:46 +0100 Subject: [PATCH 070/124] Make tiddler-editor iframe same color as tiddler background (#5132) --- themes/tiddlywiki/vanilla/base.tid | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index 0807c37bd..e32a4b45e 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -1164,12 +1164,20 @@ button.tc-btn-invisible.tc-remove-tag-button { .tc-tiddler-frame iframe.tc-edit-texteditor { padding: 3px 3px 3px 3px; border: 1px solid <<colour tiddler-editor-border>>; - background-color: <<colour tiddler-editor-background>>; line-height: 1.3em; -webkit-appearance: none; font-family: {{$:/themes/tiddlywiki/vanilla/settings/editorfontfamily}}; } +.tc-tiddler-frame input.tc-edit-texteditor, +.tc-tiddler-frame textarea.tc-edit-texteditor { + background-color: <<colour tiddler-editor-background>>; +} + +.tc-tiddler-frame iframe.tc-edit-texteditor { + background-color: <<colour background>>; +} + .tc-tiddler-frame .tc-binary-warning { width: 100%; height: 5em; From c655ec5469f16c7c8d83615618ce87a633b136fc Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 15:08:16 +0100 Subject: [PATCH 071/124] Remove background-colors from framed engine (#5131) --- core/modules/editor/engines/framed.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/modules/editor/engines/framed.js b/core/modules/editor/engines/framed.js index 4d6113fae..08ff0ffd7 100644 --- a/core/modules/editor/engines/framed.js +++ b/core/modules/editor/engines/framed.js @@ -42,7 +42,6 @@ function FramedEngine(options) { this.iframeNode.style.border = "none"; this.iframeNode.style.padding = "0"; this.iframeNode.style.resize = "none"; - this.iframeNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background"); this.iframeDoc.body.style.margin = "0"; this.iframeDoc.body.style.padding = "0"; this.widget.domNodes.push(this.iframeNode); @@ -100,7 +99,6 @@ FramedEngine.prototype.copyStyles = function() { this.domNode.style.display = "block"; this.domNode.style.width = "100%"; this.domNode.style.margin = "0"; - this.domNode.style["background-color"] = this.widget.wiki.extractTiddlerDataItem(this.widget.wiki.getTiddlerText("$:/palette"),"tiddler-editor-background"); // In Chrome setting -webkit-text-fill-color overrides the placeholder text colour this.domNode.style["-webkit-text-fill-color"] = "currentcolor"; }; From 98e60758a9b3e934596fba98046c2277db3826bc Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Sat, 28 Nov 2020 17:32:42 +0000 Subject: [PATCH 072/124] Updated Release Note --- .../prerelease/tiddlers/Release 5.1.23.tid | 119 +++++++++++------- 1 file changed, 73 insertions(+), 46 deletions(-) diff --git a/editions/prerelease/tiddlers/Release 5.1.23.tid b/editions/prerelease/tiddlers/Release 5.1.23.tid index b50e2116a..9446aa892 100644 --- a/editions/prerelease/tiddlers/Release 5.1.23.tid +++ b/editions/prerelease/tiddlers/Release 5.1.23.tid @@ -1,6 +1,6 @@ caption: 5.1.23 -created: 20201018143621963 -modified: 20201018143621963 +created: 20201128173201204 +modified: 20201128173201204 tags: ReleaseNotes title: Release 5.1.23 type: text/vnd.tiddlywiki @@ -9,7 +9,7 @@ type: text/vnd.tiddlywiki ! Major Improvements -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4725]] support for navigating the search and new tag dropdowns via the keyboard. The [[keyboard-driven-input Macro]] can be used to add this capability to other dropdowns. +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4725]] support for navigating the search and new tag dropdowns via the keyboard. The [[keyboard-driven-input Macro]] can be used to add this capability to other dropdowns * [[New|https://github.com/Jermolene/TiddlyWiki5/commit/4a84ed0018df7fd67000404bb5ef8a7ca50509c1]] [[Consent Banner Plugin]] to help make websites compliant with cookie legislation by displaying a consent banner * [[Extended|https://github.com/Jermolene/TiddlyWiki5/commit/6a0ff7db1807f45b73061ced82f5a85f1a529bbf]] [[JSZip Plugin]] ability to dynamically create Zip files, giving TiddlyWiki the ability to build static sites within the browser * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/14a28b77796461c9167898793ab9851e029e0354]] new [[filter|filter Operator]] and [[reduce|reduce Operator]] operators for processing lists of items @@ -20,15 +20,25 @@ type: text/vnd.tiddlywiki * New Arabic (Palestine) translation * Improved Catalan translation * Improved Chinese translation +* Improved Dutch translation +* Improved French translation +* Improved German translation ! Performance Improvements * [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4659]] templates to use a single VarsWidget instead of several [[SetVariableWidgets|SetVariableWidget]], for improved performance and easier debugging -* [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4954]] ListWidget to not initialize parsers for blank `emptyMessage` attributes. -* [[Refactored|https://github.com/Jermolene/TiddlyWiki5/pull/4200]] `story.js` to remove dependency on `wiki.js` for story start up and navigator. +* [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4954]] ListWidget to not initialize parsers for blank `emptyMessage` attributes +* [[Refactored|https://github.com/Jermolene/TiddlyWiki5/pull/4200]] `story.js` to remove dependency on `wiki.js` for story start up and navigator ! Usability Improvements +* Several improvements to the import mechanism: +** [[Improved|https://github.com/Jermolene/TiddlyWiki5/commit/527638d5e60114653385ed39dc55c736a67e58d2]] status messages in the import listing +** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5067]] colour coding for import items that will overwrite existing tiddlers, and for other warnings +** [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/4937]] the Import UI to allow renaming tiddlers and to warn about tiddlers that already exist +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5037]] new ActionConfirm widget +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5092]] new "Desert Sand" palette +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5100]] new "Cupertino Dark" palette * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/8cf458d3b3f1e38c14a2819529e08dca4a7e297c]] "Solarized Dark" palette * [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4590]] (and [[here|https://github.com/Jermolene/TiddlyWiki5/commit/274a07b4fd2ca2d1b95c8ddf52fe055c44260d9b]]) the Vanilla theme to optionally use palette colours for the [[browser selection outline|https://developer.mozilla.org/en-US/docs/Web/CSS/::selection]] * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/1546a4a1895b93a47b79c9d37b94be039604443a]] warning message about using the online plugin library with the client-server configuration @@ -36,34 +46,44 @@ type: text/vnd.tiddlywiki * [[Changed|https://github.com/Jermolene/TiddlyWiki5/commit/9cd5415dfe54b47819920aa3cf6ac2d5e3a9188e]] favicon for the prerelease edition * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/484c9e986fc6f323e30460a88f134da3a4e8a89e]] the $:/PaletteManager to show "indirect" colours (ie, colours defined by another `<<colour>>` macro) * [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4791]] a 'tabIndex' property to the tiddler editor input area to make it easier to use the tab key to move between edit controls -* [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/4937]] the Import UI to allow renaming tiddlers and to warn about tiddlers that already exist. * Added keyboard support: -** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4909]] keyboard support for cycling through the tabs in $:/AdvancedSearch. -** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4921]] keyboard support for navigating the field name dropdown in the Edit Template. -** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4989]] keyboard support or navigating the `type` field input in the Edit Template. -** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4919]] keyboard support for using the ''insert wikilink'' toolbar dropdown in the Edit Template. -** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4927]] keyboard shortcut for saving the wiki. -** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4978]] keyboard shortcut for deleting a field in the Edit Template. +** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4909]] keyboard support for cycling through the tabs in $:/AdvancedSearch +** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4921]] keyboard support for navigating the field name dropdown in the Edit Template +** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4989]] keyboard support or navigating the `type` field input in the Edit Template +** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4919]] keyboard support for using the ''insert wikilink'' toolbar dropdown in the Edit Template +** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4927]] keyboard shortcut for saving the wiki +** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4978]] keyboard shortcut for deleting a field in the Edit Template * [[Removed|https://github.com/Jermolene/TiddlyWiki5/commit/22e25c05eb5e5cc5b670a362d1eead1d62dedbb9]] normalize.css's styling of search input fields and [[updated|https://github.com/Jermolene/TiddlyWiki5/commit/9003c810393d90ee20db083fda35b6469acc592a]] to a modern fork of normalize.css +* [[Removed|https://github.com/Jermolene/TiddlyWiki5/commit/bb6fee4e1c79a2b1cbf75cd0326ecb8fb1ccb86b]] unneeded editor toolbar buttons when editing SVG tiddlers +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5089]] global keyboard shortcut for switching layouts +* [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/5128]] the [[CodeMirror Plugin]] and the [[Hightlight Plugin]] to use palette colours ! Filter Improvements +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5080]] [[power Operator]] and [[log Operator]] * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/4966f6ab625c8ce2c9f0812a726ba928d68ea00b]] new [[slugify Operator]] and [[duplicateslugs Operator]] for generating human readable filenames/URLs * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/619c0752bd3c6e71d1fcdb74daa03cfe8257afe4]] new [[sortsub Operator]] for sorting by a user defined subfilter * [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4785]] new [[format Operator]] for formatting dates * [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/4811]] the [[trim Operator]] to optionally trim a given string instead of whitespace, and trim from front, back, or both sides of input tiddlers -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4991]] new [[draft Operator|is Operator]] to check if a tiddler is a draft of another tiddler. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4973]] new [[search-replace Operator]] to search and replace in strings. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4948]] new [[enlist-input Operator]] to parse its input titles as a title lists. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/14a28b77796461c9167898793ab9851e029e0354]] new [[reduce Operator]] to apply a subfilter to each input title in turn, accumulating a single value . -* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/14a28b77796461c9167898793ab9851e029e0354]] new [[filter Operator]] to apply a subfilter to each input title and return the titles that return a non-empty result from the subfilter. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4918]] new [[:filter filter run prefix|Filter Expression]] which is analagous to the new [[filter Operator]] but applies to a filter run. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4959]] new [[:intersection filter run prefix|Filter Expression]] to get the intersection of two filter runs. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4990]] new [[toggle Operator]] to toggle a title in a list. - +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4991]] new [[draft Operator|is Operator]] to check if a tiddler is a draft of another tiddler +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4973]] new [[search-replace Operator]] to search and replace in strings +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4948]] new [[enlist-input Operator]] to parse its input titles as a title lists +* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/14a28b77796461c9167898793ab9851e029e0354]] new [[reduce Operator]] to apply a subfilter to each input title in turn, accumulating a single value +* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/14a28b77796461c9167898793ab9851e029e0354]] new [[filter Operator]] to apply a subfilter to each input title and return the titles that return a non-empty result from the subfilter +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4918]] new [[:filter filter run prefix|Filter Expression]] which is analagous to the new [[filter Operator]] but applies to a filter run +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4959]] new [[:intersection filter run prefix|Filter Expression]] to get the intersection of two filter runs +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4990]] new [[toggle Operator]] to toggle a title in a list +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5021]] new [[cycle Operator]] ! Hackability Improvements +* [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/5091]] ButtonWidget and DroppableWidget so that changing the class attribute does not trigger a refresh. This makes it easier to use classes to trigger CSS animations +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5086]] EventCatcherWidget for low level event handling +* [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/5087]] the RevealWidget to optionally dynamically refresh popup positions when the state tiddler changes +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/5027]] modals to incorporate a NavigatorWidget so that links work as expected +* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/1b31c25ea77ee4dce86a9aac4375337423ebd3a6]] new LogWidget and ActionLogWidget to help debugging +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5014]] support for ''disabled'' attribute to EditWidget, EditTextWidget, CheckboxWidget, RadioWidget and RangeWidget +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5010]] support for ''disabled'' attribute to ButtonWidget * [[Extended|https://github.com/Jermolene/TiddlyWiki5/commit/5af76c5ea10db2b59cc20f963a836c6a9faa8b10]] the [[Table-of-Contents Macros]] to support custom link targets * [[Extended|https://github.com/Jermolene/TiddlyWiki5/commit/ae13a0fee118c50169b7835c950df1dade33788f]] the MacroCallWidget to be able to optionally render the raw text of the macro (previously the output was always wikified) * [[Adedd|https://github.com/Jermolene/TiddlyWiki5/pull/4777]] new Hyperdrive saver for use with Beaker Browser v1.0 @@ -82,26 +102,31 @@ type: text/vnd.tiddlywiki * [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4724]] original event to `tm-navigate` event * [[Extended|https://github.com/Jermolene/TiddlyWiki5/commit/651fb777abd11c88e58b4bdfbced01d6db508852]] the password prompt to enable it to be customised * [[Extended|https://github.com/Jermolene/TiddlyWiki5/commit/69c12618d963c711edd72a60427bd15ec4fa0e6e]] syncer to enable syncadaptors to customise the login prompt -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4979]] support for switching page templates. -* [[Extended|https://github.com/Jermolene/TiddlyWiki5/commit/a1b486436e9278078c524c6aa11f7f4de6cbc877]] the [[tabs Macro]] to support `actions` and `explicitState` attributes. -* [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4906]] (and [[here|https://github.com/Jermolene/TiddlyWiki5/pull/4907]]) filters used for syncing on node.js and saving the single file version to exclude multiple story lists and history lists based on their prefix, as well as multiple tiddlers that might be used for the import process. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/5cc1600072f5aa50c8ff5f5d2e748d81a7067420]] post-render startup actions. +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4979]] support for switching page templates +* [[Extended|https://github.com/Jermolene/TiddlyWiki5/commit/a1b486436e9278078c524c6aa11f7f4de6cbc877]] the [[tabs Macro]] to support `actions` and `explicitState` attributes +* [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4906]] (and [[here|https://github.com/Jermolene/TiddlyWiki5/pull/4907]]) filters used for syncing on node.js and saving the single file version to exclude multiple story lists and history lists based on their prefix, as well as multiple tiddlers that might be used for the import process +* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/5cc1600072f5aa50c8ff5f5d2e748d81a7067420]] post-render startup actions * [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/f7f55e8eff8b172d8fd04f095781efa2420b1be6]] support for username/password parameters for `tm-login` message -* [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/4914]] [[tiddlywiki.files Files]] specification with `isEditableFile` attribute allowing files to be saved back to their original location. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/4c6de2271124fc3a4b01e4324a0d5e401500cca2]] support for the content type `image/jpg`. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4908]] support for an override saver. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4923]] utility CSS classes to replace use of ` ` to introduce visual separation. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4952]] a keyboard shortcut to change the sidebar layout. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4983]] option to configure the tag used for TableOfContents in the menubar. -* [[Modified|https://github.com/Jermolene/TiddlyWiki5/pull/4971]] the KeyboardWidget to not trap keys if there are no actions to be invoked. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4975]] buttons to the Edit Template toolbar for the editor-height and the stamp tool for tiddlers of type `application/javascript`,`application/json` and `application/x-tiddler-dictionary`. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4915]] support for named filter run prefixes. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4964]] support for multiple operands for filter operators. -* [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4985]] all instance of the [[tabs Macro]] in the core to use the explicitState attribute. -* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5000]] support for the `meta` key as a modifier in actions. +* [[Extended|https://github.com/Jermolene/TiddlyWiki5/pull/4914]] [[tiddlywiki.files Files]] specification with `isEditableFile` attribute allowing files to be saved back to their original location +* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/4c6de2271124fc3a4b01e4324a0d5e401500cca2]] support for the content type `image/jpg` +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4908]] support for an override saver +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4923]] utility CSS classes to replace use of ` ` to introduce visual separation +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4952]] a keyboard shortcut to change the sidebar layout +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4983]] option to configure the tag used for TableOfContents in the menubar +* [[Modified|https://github.com/Jermolene/TiddlyWiki5/pull/4971]] the KeyboardWidget to not trap keys if there are no actions to be invoked +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4975]] buttons to the Edit Template toolbar for the editor-height and the stamp tool for tiddlers of type `application/javascript`,`application/json` and `application/x-tiddler-dictionary` +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4915]] support for named filter run prefixes +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4964]] support for multiple operands for filter operators +* [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4985]] all instance of the [[tabs Macro]] in the core to use the explicitState attribute +* [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/5000]] support for the `meta` key as a modifier in actions +* [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/c854e518faa2d2661b7b7278634b10607ab0a5f5]] support for $:/info/darkmode to the InfoMechanism, reflecting the browser dark mode vs. light mode setting ! Bug Fixes +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/5126]] "409 conflict" errors with the ~GitHub saver when saving within 60 seconds of the last save +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/5088]] incorrect behaviour of default values with [[lookup Operator]] +* [[Restored|https://github.com/Jermolene/TiddlyWiki5/pull/4987]] behaviour of system tiddler syncing with the client server configuration. By default, changes to system tiddlers are not synced from the server to the client, restoring the behaviour from v5.1.21 and earlier. Bidirectional syncing of system tiddlers can be enabled with the configuration tiddler $:/config/SyncSystemTiddlersFromServer +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/cc3462999b80461fe30b8f4b4f272ccfbbb78b35]] content type of imported `.tid` files that do not have a `type` field * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4632]] hover effect for search dropdown items * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4584]] restored missing parameter to `saveTiddler()` method of syncadaptors * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/678e25f510786fbc38f505f8b594f57f39e33a04]] MakeLibraryCommand to skip non-directories @@ -130,12 +155,14 @@ type: text/vnd.tiddlywiki * [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4751]] a `plugin-priority` field to the TiddlyWeb plugin so that language plugins can override its language strings * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4853]] bug whereby joining an empty list would not return an empty list * [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/59f233cd46616646fa8889f65aa9cc7d704d8c9a]] bug exporting tiddlers with double quoted titles -* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/issues/4900]] bug with syncing plugin tiddlers. -* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/4877891980f077c6c31e99cc6a9eb45b5d1230e1]] bug with the position of the tiddler title when there is no icon in use. -* [[Disabled|https://github.com/Jermolene/TiddlyWiki5/commit/3153c588ecddfdc97cc8289720d36b1fb15ef236]] autosave in the upgrade wizard. -* [[Disabled|https://github.com/Jermolene/TiddlyWiki5/pull/4938]] saving of `$:/temp` tiddlers in single file wikis. -* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4839]] a bug with the `sortan` filter operator when used with date fields. -* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4947]] a bug for location hashes that contain a `#` character. +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/issues/4900]] bug with syncing plugin tiddlers +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/4877891980f077c6c31e99cc6a9eb45b5d1230e1]] bug with the position of the tiddler title when there is no icon in use +* [[Disabled|https://github.com/Jermolene/TiddlyWiki5/commit/3153c588ecddfdc97cc8289720d36b1fb15ef236]] autosave in the upgrade wizard +* [[Disabled|https://github.com/Jermolene/TiddlyWiki5/pull/4938]] saving of `$:/temp` tiddlers in single file wikis +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4839]] a bug with the `sortan` filter operator when used with date fields +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4947]] a bug for location hashes that contain a `#` character +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/5055]] default branch to ''main'' for saving to ~GitHub +* [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/7327a3fb92fa2ae17d7264c66ab0409d43b18fdc]] shadow tiddlers not refreshing when their plugin is deleted or modified ! Plugin Improvements @@ -153,7 +180,7 @@ type: text/vnd.tiddlywiki ** [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4680]] encoding of Markdown image files ** [[Fixed|https://github.com/Jermolene/TiddlyWiki5/commit/e01b354f7d9e137cb355f7090f5e68661a4ead41]] issue with whitespace and linebreaks ** [[Added|https://github.com/Jermolene/TiddlyWiki5/pull/4862]] ''tc-tiddlylink-external'' class to external links -** [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4771]] to add `rel="noopener noreferrer"` to external links. +** [[Fixed|https://github.com/Jermolene/TiddlyWiki5/pull/4771]] to add `rel="noopener noreferrer"` to external links * [[Amazon Web Services Plugin]] ** [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/0338f0fee23d176a94de9009492d2e43a916fbfa]] a new ''aws-encodeuricomponent'' filter that also encodes single quotes * ~BibTeX Plugin @@ -161,9 +188,9 @@ type: text/vnd.tiddlywiki * Menubar Plugin ** [[Updated|https://github.com/Jermolene/TiddlyWiki5/pull/4974]] so the top margin of the side bar adjusts to the height of the menu * Dynannotate Plugin -** [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/4394b8e723f78b3d2562a95155aeb91a3d6bbd5f]] examples of usage in the View Template. +** [[Added|https://github.com/Jermolene/TiddlyWiki5/commit/4394b8e723f78b3d2562a95155aeb91a3d6bbd5f]] examples of usage in the View Template * External Attachments Plugin -** [[Fixed|https://github.com/Jermolene/TiddlyWiki5/issues/4549]] a bug with relative paths in the External Attachments plugin. +** [[Fixed|https://github.com/Jermolene/TiddlyWiki5/issues/4549]] a bug with relative paths in the External Attachments plugin ! Contributors From 62a2a0e5796e6ceef9e985186cb88a023233b189 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 22:13:18 +0100 Subject: [PATCH 073/124] Fix typo in vanilla/base (#5135) --- themes/tiddlywiki/vanilla/base.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/themes/tiddlywiki/vanilla/base.tid b/themes/tiddlywiki/vanilla/base.tid index e32a4b45e..2010b45e6 100644 --- a/themes/tiddlywiki/vanilla/base.tid +++ b/themes/tiddlywiki/vanilla/base.tid @@ -1175,7 +1175,7 @@ button.tc-btn-invisible.tc-remove-tag-button { } .tc-tiddler-frame iframe.tc-edit-texteditor { - background-color: <<colour background>>; + background-color: <<colour tiddler-background>>; } .tc-tiddler-frame .tc-binary-warning { From 28724138d11c6db25e1cd14e6a24d609228c726b Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 22:21:53 +0100 Subject: [PATCH 074/124] Small update for better readability for CupertinoDark palette (#5134) --- core/palettes/CupertinoDark.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index b4f8f12aa..44ad38e8b 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -21,7 +21,7 @@ download-background: <<colour primary>> download-foreground: <<colour foreground>> dragger-background: <<colour foreground>> dragger-foreground: <<colour background>> -dropdown-background: #464646 +dropdown-background: <<colour tiddler-info-background>> dropdown-border: <<colour dropdown-background>> dropdown-tab-background-selected: #3F638B dropdown-tab-background: #323232 From b3cbd7d7338925e57ede258a5a5bc9017794b79f Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 22:22:32 +0100 Subject: [PATCH 075/124] Add TiddlySpot-ReadOnly Message-Box to Tiddlyspot Saving Panel (#5133) * Add message box to TiddlySpot Saving panel * add readonly message --- core/language/en-GB/ControlPanel.multids | 1 + core/ui/ControlPanel/Saving/TiddlySpot.tid | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/core/language/en-GB/ControlPanel.multids b/core/language/en-GB/ControlPanel.multids index 852197083..50f77b40f 100644 --- a/core/language/en-GB/ControlPanel.multids +++ b/core/language/en-GB/ControlPanel.multids @@ -126,6 +126,7 @@ Saving/TiddlySpot/Filename: Upload Filename Saving/TiddlySpot/Heading: ~TiddlySpot Saving/TiddlySpot/Hint: //The server URL defaults to `http://<wikiname>.tiddlyspot.com/store.cgi` and can be changed to use a custom server address, e.g. `http://example.com/store.php`.// Saving/TiddlySpot/Password: Password +Saving/TiddlySpot/ReadOnly: ~TiddlySpot service may currently be available as read only. Please see http://tiddlyspot.com/ for details Saving/TiddlySpot/ServerURL: Server URL Saving/TiddlySpot/UploadDir: Upload Directory Saving/TiddlySpot/UserName: Wiki Name diff --git a/core/ui/ControlPanel/Saving/TiddlySpot.tid b/core/ui/ControlPanel/Saving/TiddlySpot.tid index 2497b300e..dad217251 100644 --- a/core/ui/ControlPanel/Saving/TiddlySpot.tid +++ b/core/ui/ControlPanel/Saving/TiddlySpot.tid @@ -20,6 +20,12 @@ http://$(userName)$.tiddlyspot.com/$path$/ </$reveal> \end +<div class="tc-message-box"> + +<<lingo ReadOnly>> + +</div> + <<lingo Description>> |<<lingo UserName>> |<$edit-text tiddler="$:/UploadName" default="" tag="input"/> | @@ -34,4 +40,4 @@ http://$(userName)$.tiddlyspot.com/$path$/ |<<lingo UploadDir>> |<$edit-text tiddler="$:/UploadDir" default="." tag="input"/> | |<<lingo BackupDir>> |<$edit-text tiddler="$:/UploadBackupDir" default="." tag="input"/> | -<<lingo TiddlySpot/Hint>> \ No newline at end of file +<<lingo TiddlySpot/Hint>> From eb7f59a8555fe73af250d56914c2d07b2c0f7205 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 28 Nov 2020 22:24:01 +0100 Subject: [PATCH 076/124] Make "tc-dirty" update also on external windows (#5129) * Update windows.js * Update saver-handler.js * Update saver-handler.js --- core/modules/saver-handler.js | 4 ++++ core/modules/startup/windows.js | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/modules/saver-handler.js b/core/modules/saver-handler.js index a4b7f4a4e..e2ac21361 100644 --- a/core/modules/saver-handler.js +++ b/core/modules/saver-handler.js @@ -197,8 +197,12 @@ SaverHandler.prototype.isDirty = function() { Update the document body with the class "tc-dirty" if the wiki has unsaved/unsynced changes */ SaverHandler.prototype.updateDirtyStatus = function() { + var self = this; if($tw.browser) { $tw.utils.toggleClass(document.body,"tc-dirty",this.isDirty()); + $tw.utils.each($tw.windows,function(win) { + $tw.utils.toggleClass(win.document.body,"tc-dirty",self.isDirty()); + }); } }; diff --git a/core/modules/startup/windows.js b/core/modules/startup/windows.js index 5c867f74d..75786d026 100644 --- a/core/modules/startup/windows.js +++ b/core/modules/startup/windows.js @@ -19,7 +19,7 @@ exports.after = ["startup"]; exports.synchronous = true; // Global to keep track of open windows (hashmap by title) -var windows = {}; +$tw.windows = {}; exports.startup = function() { // Handle open window message @@ -44,7 +44,7 @@ exports.startup = function() { catch(e) { return; } - windows[title] = srcWindow; + $tw.windows[title] = srcWindow; // Check for reopening the same window if(srcWindow.haveInitialisedWindow) { return; @@ -54,7 +54,7 @@ exports.startup = function() { srcDocument.close(); srcDocument.title = windowTitle; srcWindow.addEventListener("beforeunload",function(event) { - delete windows[title]; + delete $tw.windows[title]; $tw.wiki.removeEventListener("change",refreshHandler); },false); // Set up the styles @@ -90,7 +90,7 @@ exports.startup = function() { }); // Close open windows when unloading main window $tw.addUnloadTask(function() { - $tw.utils.each(windows,function(win) { + $tw.utils.each($tw.windows,function(win) { win.close(); }); }); From e54f3368e903d54be83346b456e609cd380fe53e Mon Sep 17 00:00:00 2001 From: Jeremy Ruston <jeremy@jermolene.com> Date: Sat, 28 Nov 2020 21:43:09 +0000 Subject: [PATCH 077/124] Update contributors list in release note --- editions/prerelease/tiddlers/Release 5.1.23.tid | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/editions/prerelease/tiddlers/Release 5.1.23.tid b/editions/prerelease/tiddlers/Release 5.1.23.tid index 9446aa892..796757d73 100644 --- a/editions/prerelease/tiddlers/Release 5.1.23.tid +++ b/editions/prerelease/tiddlers/Release 5.1.23.tid @@ -202,6 +202,7 @@ type: text/vnd.tiddlywiki * [[@BramChen|https://github.com/BramChen]] * [[@BurningTreeC|https://github.com/BurningTreeC]] * [[@danielo515|https://github.com/danielo515]] +* [[@default-kramer|https://github.com/default-kramer]] * [[@ento|https://github.com/ento]] * [[@favadi|https://github.com/favadi]] * [[@fkohrt|https://github.com/fkohrt]] @@ -211,6 +212,7 @@ type: text/vnd.tiddlywiki * [[@idotobi|https://github.com/idotobi]] * [[@jdangerx|https://github.com/jdangerx]] * [[@jjduhamel|https://github.com/jjduhamel]] +* [[@kookma|https://github.com/kookma]] * [[@Kamal-Habash|https://github.com/Kamal-Habash]] * [[@Marxsal|https://github.com/Marxsal]] * [[@mocsa|https://github.com/mocsa]] @@ -218,6 +220,7 @@ type: text/vnd.tiddlywiki * [[@passuf|https://github.com/passuf]] * [[@pmario|https://github.com/pmario]] * [[@rmunn|https://github.com/rmunn]] +* [[@SmilyOrg|https://github.com/SmilyOrg]] * [[@saqimtiaz|https://github.com/saqimtiaz]] * [[@twMat|https://github.com/twMat]] -* [[@default-kramer|https://github.com/default-kramer]] +* [[@xcazin|https://github.com/xcazin]] From 12bb938463f6f3578970eeeab217b258a08187a3 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Sat, 28 Nov 2020 23:05:54 +0100 Subject: [PATCH 078/124] Corrected typo in contributor's name (#5138) --- editions/prerelease/tiddlers/Release 5.1.23.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/prerelease/tiddlers/Release 5.1.23.tid b/editions/prerelease/tiddlers/Release 5.1.23.tid index 796757d73..f3b26ec57 100644 --- a/editions/prerelease/tiddlers/Release 5.1.23.tid +++ b/editions/prerelease/tiddlers/Release 5.1.23.tid @@ -216,7 +216,7 @@ type: text/vnd.tiddlywiki * [[@Kamal-Habash|https://github.com/Kamal-Habash]] * [[@Marxsal|https://github.com/Marxsal]] * [[@mocsa|https://github.com/mocsa]] -* [[@NicolasPeton|https://github.com/NicolasPeton]] +* [[@NicolasPetton|https://github.com/NicolasPetton]] * [[@passuf|https://github.com/passuf]] * [[@pmario|https://github.com/pmario]] * [[@rmunn|https://github.com/rmunn]] From a21428a33a74dcac8360752a624f1fcc4e4dae01 Mon Sep 17 00:00:00 2001 From: Bram Chen <bram.chen@gmail.com> Date: Sun, 29 Nov 2020 20:26:21 +0800 Subject: [PATCH 079/124] Add chinese translations for `Saving/TiddlySpot/ReadOnly` (#5139) --- languages/zh-Hans/ControlPanel.multids | 1 + languages/zh-Hant/ControlPanel.multids | 1 + 2 files changed, 2 insertions(+) diff --git a/languages/zh-Hans/ControlPanel.multids b/languages/zh-Hans/ControlPanel.multids index 41b94baf1..a29cd9a35 100644 --- a/languages/zh-Hans/ControlPanel.multids +++ b/languages/zh-Hans/ControlPanel.multids @@ -127,6 +127,7 @@ Saving/TiddlySpot/Filename: 上传文件名 Saving/TiddlySpot/Heading: ~TiddlySpot Saving/TiddlySpot/Hint: //默认之服务器网址 `http://<wikiname>.tiddlyspot.com/store.cgi`,可改为定制之服务器网址,例如 `http://example.com/store.php`。// Saving/TiddlySpot/Password: 密码 +Saving/TiddlySpot/ReadOnly: ~TiddlySpot 服务目前可能仅提供唯读。详见 http://tiddlyspot.com/ Saving/TiddlySpot/ServerURL: 服务器网址 Saving/TiddlySpot/UploadDir: 上传文件夹 Saving/TiddlySpot/UserName: 用户 diff --git a/languages/zh-Hant/ControlPanel.multids b/languages/zh-Hant/ControlPanel.multids index 5fb35f427..09c088e85 100644 --- a/languages/zh-Hant/ControlPanel.multids +++ b/languages/zh-Hant/ControlPanel.multids @@ -127,6 +127,7 @@ Saving/TiddlySpot/Filename: 上傳檔名 Saving/TiddlySpot/Heading: ~TiddlySpot Saving/TiddlySpot/Hint: //預設之伺服器網址 `http://<wikiname>.tiddlyspot.com/store.cgi`,可改為自訂之伺服器網址,例如 `http://example.com/store.php`。// Saving/TiddlySpot/Password: 密碼 +Saving/TiddlySpot/ReadOnly: ~TiddlySpot 服務目前可能僅提供唯讀。詳見 http://tiddlyspot.com/ Saving/TiddlySpot/ServerURL: 伺服器網址 Saving/TiddlySpot/UploadDir: 上傳資料夾 Saving/TiddlySpot/UserName: 帳號 From cc850d71516459383cde3c70449a7a0c6bfe8fd7 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Sun, 29 Nov 2020 12:38:09 +0000 Subject: [PATCH 080/124] Fix typo in list macro See discussion https://github.com/Jermolene/TiddlyWiki5/pull/3710#issuecomment-735295319 --- core/wiki/macros/list.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/wiki/macros/list.tid b/core/wiki/macros/list.tid index 01b527a07..cb25a7a88 100644 --- a/core/wiki/macros/list.tid +++ b/core/wiki/macros/list.tid @@ -39,7 +39,6 @@ tags: $:/tags/Macro </div> </$droppable> </$list> -</$type$> <$tiddler tiddler=""> <$droppable actions=<<list-links-draggable-drop-actions>> tag="div" enable=<<tv-enable-drag-and-drop>>> <div class="tc-droppable-placeholder"> @@ -48,6 +47,7 @@ tags: $:/tags/Macro <div style="height:0.5em;"/> </$droppable> </$tiddler> +</$type$> </$vars> </span> \end From ce937595d71e78a2470eaf600bbda339c9a02cb5 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sun, 29 Nov 2020 13:52:50 +0100 Subject: [PATCH 081/124] Add Button to remove tags from tiddlers $:/config/NewTiddler/Tags and $:/config/NewJournal/Tags (#5140) * Update Basics.tid * Update ControlPanel.multids * Update Basics.tid * Update ControlPanel.multids * Update ControlPanel.multids * Update ControlPanel.multids --- core/language/en-GB/ControlPanel.multids | 2 ++ core/ui/ControlPanel/Basics.tid | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/language/en-GB/ControlPanel.multids b/core/language/en-GB/ControlPanel.multids index 50f77b40f..54f0d4050 100644 --- a/core/language/en-GB/ControlPanel.multids +++ b/core/language/en-GB/ControlPanel.multids @@ -17,6 +17,8 @@ Basics/NewJournal/Tags/Prompt: Tags for new journal tiddlers Basics/NewTiddler/Title/Prompt: Title of new tiddlers Basics/NewTiddler/Tags/Prompt: Tags for new tiddlers Basics/OverriddenShadowTiddlers/Prompt: Number of overridden shadow tiddlers +Basics/RemoveTags: Update to current format +Basics/RemoveTags/Hint: Update the tags configuration to the latest format Basics/ShadowTiddlers/Prompt: Number of shadow tiddlers Basics/Subtitle/Prompt: Subtitle Basics/SystemTiddlers/Prompt: Number of system tiddlers diff --git a/core/ui/ControlPanel/Basics.tid b/core/ui/ControlPanel/Basics.tid index 43f621901..4897d232a 100644 --- a/core/ui/ControlPanel/Basics.tid +++ b/core/ui/ControlPanel/Basics.tid @@ -26,8 +26,8 @@ caption: {{$:/language/ControlPanel/Basics/Caption}} |<$link to="$:/language/DefaultNewTiddlerTitle"><<lingo NewTiddler/Title/Prompt>></$link> |<$edit-text tiddler="$:/language/DefaultNewTiddlerTitle" default="" tag="input"/> | |<$link to="$:/config/NewJournal/Title"><<lingo NewJournal/Title/Prompt>></$link> |<$edit-text tiddler="$:/config/NewJournal/Title" default="" tag="input"/> | |<$link to="$:/config/NewJournal/Text"><<lingo NewJournal/Text/Prompt>></$link> |<$edit tiddler="$:/config/NewJournal/Text" tag="textarea" class="tc-edit-texteditor" default=""/> | -|<$link to="$:/config/NewTiddler/Tags"><<lingo NewTiddler/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewTiddler/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}</$vars> | -|<$link to="$:/config/NewJournal/Tags"><<lingo NewJournal/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewJournal/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}</$vars> | +|<$link to="$:/config/NewTiddler/Tags"><<lingo NewTiddler/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewTiddler/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> | +|<$link to="$:/config/NewJournal/Tags"><<lingo NewJournal/Tags/Prompt>></$link> |<$vars currentTiddler="$:/config/NewJournal/Tags" tagField="text">{{||$:/core/ui/EditTemplate/tags}}<$list filter="[<currentTiddler>tags[]] +[limit[1]]" variable="ignore"><$button tooltip={{$:/language/ControlPanel/Basics/RemoveTags/Hint}}><<lingo RemoveTags>><$action-listops $tiddler=<<currentTiddler>> $field="text" $subfilter={{{ [<currentTiddler>get[tags]] }}}/><$action-setfield $tiddler=<<currentTiddler>> tags=""/></$button></$list></$vars> | |<$link to="$:/config/AutoFocus"><<lingo AutoFocus/Prompt>></$link> |{{$:/snippets/minifocusswitcher}} | |<<lingo Language/Prompt>> |{{$:/snippets/minilanguageswitcher}} | |<<lingo Tiddlers/Prompt>> |<<show-filter-count "[!is[system]sort[title]]">> | From 5887c6621ece5aa3652c420309f00bee2d39897c Mon Sep 17 00:00:00 2001 From: Robin Munn <rmunn@pobox.com> Date: Sun, 29 Nov 2020 22:45:39 +0700 Subject: [PATCH 082/124] Create "Filter Run Prefix (Examples)" tiddler (#5144) Move the `+` vs `:intersection` example into a separate Examples tiddler which can be expanded on later. --- .../filters/syntax/Filter Expression.tid | 14 ++--------- .../syntax/Filter Run Prefix (Examples).tid | 25 +++++++++++++++++++ 2 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 editions/tw5.com/tiddlers/filters/syntax/Filter Run Prefix (Examples).tid diff --git a/editions/tw5.com/tiddlers/filters/syntax/Filter Expression.tid b/editions/tw5.com/tiddlers/filters/syntax/Filter Expression.tid index 57de4a9f9..fb2a1704e 100644 --- a/editions/tw5.com/tiddlers/filters/syntax/Filter Expression.tid +++ b/editions/tw5.com/tiddlers/filters/syntax/Filter Expression.tid @@ -37,6 +37,8 @@ In technical / logical terms: |`~run` |`:else[run]` |else |... ELSE run | ||`:intersection`|intersection of sets|| +For the difference between `+` and `:intersection`, see [[Filter Run Prefix (Examples)]]. + The input of a run is normally a list of all the non-[[shadow|ShadowTiddlers]] tiddler titles in the wiki (in no particular order). But the `+` prefix can change this: |Prefix|Input|h @@ -56,15 +58,3 @@ In order to remove `$:/baz` in any case, existing or not, simply use the `+` pre * <$link to="is Operator">`foo bar $:/baz +[!is[system]]`</$link> * <$link to="prefix Operator">`foo bar $:/baz +[!prefix[$:/]]`</$link> - -There is also a difference between the `:intersection` and `+` prefixes due to varying inputs. - -The `+` prefix should be thought of as an "AND" in formal logic, e.g. "give me all titles that satisfy condition A ''and'' condition B". But it's not suitable for all cases; if condition B uses a filter operator that replaces its input, then it will be difficult to use the `+` prefix. For example, if you wanted to find out what tags two tiddlers have in common, you might try to write a filter expression like: - -* <$link to="tags Operator">`[[field Operator]tags[]] +[[compare Operator]tags[]]`</$link> - -But that won't work, because the second filter run will end up throwing away its input and replacing it with an input consisting of the single title `[[compare Operator]]`. So the result you'd get from that filter expression would be just the tags of the `compare Operator` tiddler. - -For cases like this, the `:intersection` prefix is what you need. It takes the filter output so far, //sets it aside// in temporary storage, and starts the next filter run with all tiddler titles as input. Then once the latest filter run has completed, it takes the latest output, compares it to the set-aside output, and produces a new output that contains only titles that appeared in both the set-aside output and the latest output. So to get only the tags that the `field Operator` and `compare Operator` tiddlers have in common, you would write a filter expresison like this: - -* <$link to="tags Operator">`[[field Operator]tags[]] :intersection[[compare Operator]tags[]]`</$link> diff --git a/editions/tw5.com/tiddlers/filters/syntax/Filter Run Prefix (Examples).tid b/editions/tw5.com/tiddlers/filters/syntax/Filter Run Prefix (Examples).tid new file mode 100644 index 000000000..eb88c339b --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/syntax/Filter Run Prefix (Examples).tid @@ -0,0 +1,25 @@ +created: 20201117073343969 +modified: 20201117074106350 +tags: [[Filter Syntax]] +title: Filter Run Prefix (Examples) + +!! Difference between `+` and `:intersection` + +The `+` prefix should be thought of as an "AND" in formal logic, e.g. "give me all titles that satisfy condition A ''and'' condition B". But it's not suitable for all cases; if condition B uses a filter operator that replaces its input, then it will be difficult to use the `+` prefix. For example, if you wanted to find out what tags two tiddlers have in common, you might try to write a filter expression like: + +* <$link to="tags Operator">`[[field Operator]tags[]] +[[compare Operator]tags[]]`</$link> + +But that won't work, because the second filter run will end up throwing away its input and replacing it with an input consisting of the single title `[[compare Operator]]`. So the result you'd get from that filter expression would be just the tags of the `compare Operator` tiddler. + +For cases like this, the `:intersection` prefix is what you need. It takes the filter output so far, //sets it aside//, and starts the next filter run with all tiddler titles as input. Then once the latest filter run has completed, it takes the latest output, compares it to the set-aside output, and produces a new output that contains only titles that appeared in both the set-aside output and the latest output. So to get only the tags that the `field Operator` and `compare Operator` tiddlers have in common, you would write a filter expression like this: + +* <$link to="tags Operator">`[[field Operator]tags[]] :intersection[[compare Operator]tags[]]`</$link> + +The following examples use the [[field Operator]] and [[compare Operator]] tiddlers and their respective tags. + +<<.operator-example 1 "[[field Operator]tags[]]">> +<<.operator-example 2 "[[compare Operator]tags[]]">> + +<<.operator-example 3 "[[field Operator]tags[]] +[[compare Operator]tags[]]" """The "field Operator" tiddler's tags are lost, so only the "compare Operator" tiddler's tags are returned""">> + +<<.operator-example 4 "[[field Operator]tags[]] :intersection[[compare Operator]tags[]]" """Returns the tags that both tiddlers have in common""">> From 4d9e6831bbbdcc68cb428c930e979012f43c8b8a Mon Sep 17 00:00:00 2001 From: Jeremy Ruston <jeremy@jermolene.com> Date: Sun, 29 Nov 2020 18:32:22 +0000 Subject: [PATCH 083/124] Rename "references" to "backlinks" in the tiddler info panel (#5143) * Rename "references" to "backlinks" in the tiddler info panel * Change docs references to "references" to "backlinks" --- core/language/en-GB/TiddlerInfo.multids | 2 +- editions/tw5.com/tiddlers/concepts/InfoPanel.tid | 4 ++-- .../Using links to navigate between tiddlers.tid | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/language/en-GB/TiddlerInfo.multids b/core/language/en-GB/TiddlerInfo.multids index a395ce19b..0899320c6 100644 --- a/core/language/en-GB/TiddlerInfo.multids +++ b/core/language/en-GB/TiddlerInfo.multids @@ -14,7 +14,7 @@ List/Caption: List List/Empty: This tiddler does not have a list Listed/Caption: Listed Listed/Empty: This tiddler is not listed by any others -References/Caption: References +References/Caption: Backlinks References/Empty: No tiddlers link to this one Tagging/Caption: Tagging Tagging/Empty: No tiddlers are tagged with this one diff --git a/editions/tw5.com/tiddlers/concepts/InfoPanel.tid b/editions/tw5.com/tiddlers/concepts/InfoPanel.tid index 8c422a5c5..280f417d5 100644 --- a/editions/tw5.com/tiddlers/concepts/InfoPanel.tid +++ b/editions/tw5.com/tiddlers/concepts/InfoPanel.tid @@ -1,5 +1,5 @@ created: 20150917193630604 -modified: 20150917193631731 +modified: 20201129183045031 tags: Features title: InfoPanel type: text/vnd.tiddlywiki @@ -9,7 +9,7 @@ Each tiddler has a panel of additional information. To reveal it, click the <<.i The info panel has the following tabs: * ''Tools'' - This offers buttons for various actions you can perform on the tiddler. The checkbox next to each button lets you promote an action to the tiddler's toolbar - this will affect all of the tiddlers in your wiki -* ''References'', ''Tagging'', ''List'' and ''Listed'' - These list various kinds of related tiddlers. See [[Using links to navigate between tiddlers]] +* ''Backlinks'', ''Tagging'', ''List'' and ''Listed'' - These list various kinds of related tiddlers. See [[Using links to navigate between tiddlers]] * ''Fields'' - This summarises all of the tiddler's [[fields|TiddlerFields]], except for ''text'' * ''Advanced'' - This indicates whether the tiddler is a [[shadow|ShadowTiddlers]]. If it is, this also reveals which plugin it comes from and whether it has been overridden by an ordinary tiddler diff --git a/editions/tw5.com/tiddlers/workingwithtw/Using links to navigate between tiddlers.tid b/editions/tw5.com/tiddlers/workingwithtw/Using links to navigate between tiddlers.tid index bf491a8d6..aa970cff4 100644 --- a/editions/tw5.com/tiddlers/workingwithtw/Using links to navigate between tiddlers.tid +++ b/editions/tw5.com/tiddlers/workingwithtw/Using links to navigate between tiddlers.tid @@ -1,5 +1,5 @@ created: 20140908093600000 -modified: 20171219170302268 +modified: 20201129183020567 tags: [[Working with TiddlyWiki]] title: Using links to navigate between tiddlers type: text/vnd.tiddlywiki @@ -12,7 +12,7 @@ You can use links (normally displayed as blue text) to navigate from one tiddler * The ''InfoPanel'' of each tiddler gives you access to four tabs containing additional lists of related tiddlers: -** The ''References'' tab lists all the tiddlers that link //to// the current tiddler. +** The ''Backlinks'' tab lists all the tiddlers that link //to// the current tiddler. ** The ''Tagging'' tab lists all the tiddlers that have been tagged with the current tiddler's title. From 5cbe4c531739b760f9d4ae81f535c8fd0535e65d Mon Sep 17 00:00:00 2001 From: Mario Pietsch <pmariojo@gmail.com> Date: Mon, 30 Nov 2020 18:28:49 +0100 Subject: [PATCH 084/124] Add radio actions, th-radio-variables hook and fix label refresh problem (#5154) * Add actions to radio-widget, pass trhough all attributes and user parameters, fix label refresh * invoke th-radio-hook instead of hardcoded variables * simplify code and test it with a plugin hook * remove hook --- core/modules/widgets/radio.js | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/core/modules/widgets/radio.js b/core/modules/widgets/radio.js index c22aa5ecb..43b6e5dab 100644 --- a/core/modules/widgets/radio.js +++ b/core/modules/widgets/radio.js @@ -13,7 +13,6 @@ Set a field or index at a given tiddler via radio buttons "use strict"; var Widget = require("$:/core/modules/widgets/widget.js").widget; - var RadioWidget = function(parseTreeNode,options) { this.initialise(parseTreeNode,options); }; @@ -37,8 +36,8 @@ RadioWidget.prototype.render = function(parent,nextSibling) { // Create our elements this.labelDomNode = this.document.createElement("label"); this.labelDomNode.setAttribute("class", - "tc-radio " + this.radioClass + (isChecked ? " tc-radio-selected" : "") - ); + "tc-radio " + this.radioClass + (isChecked ? " tc-radio-selected" : "") + ); this.inputDomNode = this.document.createElement("input"); this.inputDomNode.setAttribute("type","radio"); if(isChecked) { @@ -86,6 +85,10 @@ RadioWidget.prototype.handleChangeEvent = function(event) { if(this.inputDomNode.checked) { this.setValue(); } + // Trigger actions + if(this.radioActions) { + this.invokeActionString(this.radioActions,this,event,{"actionValue": this.radioValue}); + } }; /* @@ -99,6 +102,7 @@ RadioWidget.prototype.execute = function() { this.radioValue = this.getAttribute("value"); this.radioClass = this.getAttribute("class",""); this.isDisabled = this.getAttribute("disabled","no"); + this.radioActions = this.getAttribute("actions",""); // Make the child widgets this.makeChildWidgets(); }; @@ -108,16 +112,11 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ RadioWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.value || changedAttributes["class"] || changedAttributes.disabled) { + if(($tw.utils.count(changedAttributes) > 0) || changedTiddlers[this.radioTitle]) { this.refreshSelf(); return true; } else { - var refreshed = false; - if(changedTiddlers[this.radioTitle]) { - this.inputDomNode.checked = this.getValue() === this.radioValue; - refreshed = true; - } - return this.refreshChildren(changedTiddlers) || refreshed; + return this.refreshChildren(changedTiddlers); } }; From 4623c45d294a719cc9a9e60f03a74f1e5541a808 Mon Sep 17 00:00:00 2001 From: Robin Munn <rmunn@pobox.com> Date: Tue, 1 Dec 2020 00:30:51 +0700 Subject: [PATCH 085/124] Tag trim operator as a string operator (#5147) * Tag trim operator as a string operator With the new functionality of the trim operator in 5.1.23, it's now a general-purpose string manipulation tool. So it should be given the "String operators" tag so that people see it in the same list as removeprefix and removesuffix, etc. * Document suffix of trim operator --- editions/tw5.com/tiddlers/filters/trim Operator.tid | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/editions/tw5.com/tiddlers/filters/trim Operator.tid b/editions/tw5.com/tiddlers/filters/trim Operator.tid index 199c8cd7f..918b4f4c4 100644 --- a/editions/tw5.com/tiddlers/filters/trim Operator.tid +++ b/editions/tw5.com/tiddlers/filters/trim Operator.tid @@ -1,12 +1,14 @@ caption: trim created: 20190613153740241 -modified: 20190613153820282 +modified: 20201130141111438 op-purpose: returns each item in the list with whitespace, or a given character string, trimmed from the start and/or end op-input: a [[selection of titles|Title Selection]] op-parameter: <<.from-version "5.1.23">> a string of characters op-parameter-name: S op-output: the input titles with <<.place S>>, or whitespace if <<.place S>> is not specified, trimmed from the start and/or end -tags: [[Filter Operators]] +op-suffix: `prefix` to trim from the start only, `suffix` to trim from the end only. If omitted (default), trim from both start and end +op-suffix-name: T +tags: [[Filter Operators]] [[String Operators]] title: trim Operator type: text/vnd.tiddlywiki From 8fc6910c032987095e459b49b3f9736842c3fe02 Mon Sep 17 00:00:00 2001 From: saqimtiaz <saq.imtiaz@gmail.com> Date: Mon, 30 Nov 2020 18:43:50 +0100 Subject: [PATCH 086/124] Added string operator pad[] along with tests and docs (#5146) --- core/modules/filters/strings.js | 29 +++++++++++++++++++ editions/test/tiddlers/tests/test-filters.js | 11 +++++++ .../examples/pad Operator (Examples).tid | 13 +++++++++ .../tw5.com/tiddlers/filters/pad Operator.tid | 23 +++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 editions/tw5.com/tiddlers/filters/examples/pad Operator (Examples).tid create mode 100644 editions/tw5.com/tiddlers/filters/pad Operator.tid diff --git a/core/modules/filters/strings.js b/core/modules/filters/strings.js index eb74e39e1..6b76178d4 100644 --- a/core/modules/filters/strings.js +++ b/core/modules/filters/strings.js @@ -143,4 +143,33 @@ exports["search-replace"] = function(source,operator,options) { return results; }; +exports.pad = function(source,operator,options) { + var results = [], + targetLength = operator.operand ? parseInt(operator.operand) : 0, + fill = operator.operands[1] || "0"; + + source(function(tiddler,title) { + if(title && title.length) { + if(title.length >= targetLength) { + results.push(title); + } else { + var padString = "", + padStringLength = targetLength - title.length; + while (padStringLength > padString.length) { + padString += fill; + } + //make sure we do not exceed the specified length + padString = padString.slice(0,padStringLength); + if(operator.suffix && (operator.suffix === "suffix")) { + title = title + padString; + } else { + title = padString + title; + } + results.push(title); + } + } + }); + return results; +} + })(); diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 6649af4e3..bf537ee36 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -777,6 +777,17 @@ function runTests(wiki) { expect(wiki.filterTiddlers("[[Hello There]search-replace::regexp<myregexp>,[]]",anchorWidget).join(",")).toBe("Hllo There"); expect(wiki.filterTiddlers("[[Hello There]search-replace:gi[H],[]]",anchorWidget).join(",")).toBe("ello Tere"); }); + + it("should handle the pad operator", function() { + expect(wiki.filterTiddlers("[[2]pad[]]").join(",")).toBe("2"); + expect(wiki.filterTiddlers("[[2]pad[0]]").join(",")).toBe("2"); + expect(wiki.filterTiddlers("[[2]pad[1]]").join(",")).toBe("2"); + expect(wiki.filterTiddlers("2 20 +[pad[3]]").join(",")).toBe("002,020"); + expect(wiki.filterTiddlers("[[2]pad[9]]").join(",")).toBe("000000002"); + expect(wiki.filterTiddlers("[[2]pad[9],[a]]").join(",")).toBe("aaaaaaaa2"); + expect(wiki.filterTiddlers("[[12]pad[9],[abc]]").join(",")).toBe("abcabca12"); + expect(wiki.filterTiddlers("[[12]pad:suffix[9],[abc]]").join(",")).toBe("12abcabca"); + }); } }); diff --git a/editions/tw5.com/tiddlers/filters/examples/pad Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/pad Operator (Examples).tid new file mode 100644 index 000000000..2ccf8ea77 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/examples/pad Operator (Examples).tid @@ -0,0 +1,13 @@ +created: 20201129174833980 +modified: 20201129180011580 +tags: [[Operator Examples]] [[pad Operator]] +title: pad Operator (Examples) +type: text/vnd.tiddlywiki + +<<.operator-example 1 """[[2]pad[3]]""">> + +<<.operator-example 2 """[[2]pad[3],[a]]""">> + +<<.operator-example 3 """[[12]pad[9],[abc]]""">> + +<<.operator-example 4 """[[12]pad:suffix[9],[abc]]""">> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/filters/pad Operator.tid b/editions/tw5.com/tiddlers/filters/pad Operator.tid new file mode 100644 index 000000000..defacf117 --- /dev/null +++ b/editions/tw5.com/tiddlers/filters/pad Operator.tid @@ -0,0 +1,23 @@ +caption: pad +created: 20201129174215674 +modified: 20201129175301148 +op-input: a [[selection of titles|Title Selection]] +op-output: the input titles padded to the specified length +op-parameter: the <<.op pad>> operator accepts 1 or more parameters, see below for details +op-purpose: returns each item in the list padded to the specified length +op-suffix: (optional). Whether to pad by adding a "suffix" or "prefix". Defaults to "prefix". +tags: [[Filter Operators]] [[String Operators]] +title: pad Operator +type: text/vnd.tiddlywiki + +<<.from-version "5.1.23">> + +The <<.op pad>> operator requires at least one parameter which specifies the desired length of the input titles. A second optional parameter can be used to specify the string to pad with (defaults to "0"). + +``` +[pad[<length>],[<padding-string>]] +``` +* ''length'' : the desired final length of the input titles. +* ''padding-string'': (optional). The string to use to pad to the desired length. Defaults to "0". + +<<.operator-examples "pad">> From fd3e77d38f850f736368a9b97b20af3e2644557c Mon Sep 17 00:00:00 2001 From: Robin Munn <rmunn@pobox.com> Date: Tue, 1 Dec 2020 00:52:46 +0700 Subject: [PATCH 087/124] "dedupe" and "raw" suffixes for enlist-input operator (#5152) Includes unit tests. --- core/modules/filters/strings.js | 4 ++-- editions/test/tiddlers/tests/test-filters.js | 3 +++ editions/tw5.com/tiddlers/filters/enlist-input Operator.tid | 2 ++ .../filters/examples/enlist-input Operator (Examples).tid | 4 +++- 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/core/modules/filters/strings.js b/core/modules/filters/strings.js index 6b76178d4..38e5be231 100644 --- a/core/modules/filters/strings.js +++ b/core/modules/filters/strings.js @@ -61,7 +61,7 @@ exports.split = makeStringBinaryOperator( ); exports["enlist-input"] = makeStringBinaryOperator( - function(a) {return $tw.utils.parseStringArray("" + a);} + function(a,o,s) {return $tw.utils.parseStringArray("" + a,(s === "raw"));} ); exports.join = makeStringReducingOperator( @@ -78,7 +78,7 @@ function makeStringBinaryOperator(fnCalc) { return function(source,operator,options) { var result = []; source(function(tiddler,title) { - Array.prototype.push.apply(result,fnCalc(title,operator.operand || "")); + Array.prototype.push.apply(result,fnCalc(title,operator.operand || "",operator.suffix || "")); }); return result; }; diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index bf537ee36..895c83ca3 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -184,6 +184,9 @@ function runTests(wiki) { it("should handle the enlist-input operator", function() { expect(wiki.filterTiddlers("[[one two three]enlist-input[]]").join(",")).toBe("one,two,three"); + expect(wiki.filterTiddlers("[[one two two three]enlist-input[]]").join(",")).toBe("one,two,three"); + expect(wiki.filterTiddlers("[[one two two three]enlist-input:dedupe[]]").join(",")).toBe("one,two,three"); + expect(wiki.filterTiddlers("[[one two two three]enlist-input:raw[]]").join(",")).toBe("one,two,two,three"); expect(wiki.filterTiddlers("[[one two three]] [[four five six]] +[enlist-input[]]").join(",")).toBe("one,two,three,four,five,six"); expect(wiki.filterTiddlers("[[one two three]] [[four five six]] [[seven eight]] +[enlist-input[]]").join(",")).toBe("one,two,three,four,five,six,seven,eight"); expect(wiki.filterTiddlers("[[]] +[enlist-input[]]").join(",")).toBe(""); diff --git a/editions/tw5.com/tiddlers/filters/enlist-input Operator.tid b/editions/tw5.com/tiddlers/filters/enlist-input Operator.tid index 3a9dd529a..a561a8e12 100644 --- a/editions/tw5.com/tiddlers/filters/enlist-input Operator.tid +++ b/editions/tw5.com/tiddlers/filters/enlist-input Operator.tid @@ -4,6 +4,8 @@ modified: 20201102221854719 op-input: a [[selection of titles|Title Selection]] op-output: the titles stored as a [[title list|Title List]] in each input title op-purpose: select titles by interpreting each input title as a [[title list|Title List]] +op-suffix: `dedupe` (the default) to remove duplicates, `raw` to leave duplicates untouched +op-suffix-name: D tags: [[Filter Operators]] [[String Operators]] [[Selection Constructors]] title: enlist-input Operator type: text/vnd.tiddlywiki diff --git a/editions/tw5.com/tiddlers/filters/examples/enlist-input Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/enlist-input Operator (Examples).tid index c02a85c4c..7e4eee4a7 100644 --- a/editions/tw5.com/tiddlers/filters/examples/enlist-input Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/enlist-input Operator (Examples).tid @@ -7,4 +7,6 @@ type: text/vnd.tiddlywiki <<.operator-example 1 "[[Days of the Week]get[list]enlist-input[]]">> Contrast with: <<.operator-example 2 "[[Days of the Week]get[list]]">> <<.operator-example 3 "'HelloThere GettingStarted [[Customise TiddlyWiki]]' +[enlist-input[]]">> -Contrast with: <<.operator-example 4 "'HelloThere GettingStarted [[Customise TiddlyWiki]]'">> \ No newline at end of file +Contrast with: <<.operator-example 4 "'HelloThere GettingStarted [[Customise TiddlyWiki]]'">> +<<.operator-example 5 "'HelloThere HelloThere GettingStarted [[Customise TiddlyWiki]]' +[enlist-input:raw[]]">> +Contrast with: <<.operator-example 6 "'HelloThere HelloThere GettingStarted [[Customise TiddlyWiki]]' +[enlist-input[]]">> From 4f13848ca2255afa7d5ee9604f48a5064ce4a20b Mon Sep 17 00:00:00 2001 From: Robin Munn <rmunn@pobox.com> Date: Tue, 1 Dec 2020 00:54:45 +0700 Subject: [PATCH 088/124] Document using double hashes for anchor links (#5149) This is based on #3836, updated and revised with the edits made by Watt on the Google Group. --- .../wikitext/Anchor Links using HTML.tid | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 editions/tw5.com/tiddlers/wikitext/Anchor Links using HTML.tid diff --git a/editions/tw5.com/tiddlers/wikitext/Anchor Links using HTML.tid b/editions/tw5.com/tiddlers/wikitext/Anchor Links using HTML.tid new file mode 100644 index 000000000..1bf287c9a --- /dev/null +++ b/editions/tw5.com/tiddlers/wikitext/Anchor Links using HTML.tid @@ -0,0 +1,200 @@ +created: 20190311094603013 +modified: 20201130064330388 +tags: [[HTML in WikiText]] +title: Anchor Links using HTML + +<a id=<<qualify "#Top">>></a> + +<h2 id="#Introduction:Anchor-Links-using-HTML">''HTML Anchor Links in Tiddlers''</h2> + + + +* <a href=<<qualify "##Introduction">>>What do they do?</a> +* <a href=<<qualify "##How-do-I-make-them">>>How do I make them?</a> +* <a href=<<qualify "##Anchor-link-limitations">>>Limitations and things to look out for</a> +* <a href=<<qualify "##More_examples">>>More examples</a> +* <a href=<<qualify "##Suggestions-for-elements">>>Suggestions for HTML elements to use</a> +* <a href=<<qualify "##Suggestions-for-ids">>>Suggestions for target names to use</a> +* <a href=<<qualify "##qualify-example">>>Avoiding duplicate IDs when transcluding</a> +* <a href=<<qualify ##Style_Hints>>>Style Hints</a> + +<a id=<<qualify "#Introduction">>></a> + +!! What do they do? + +In TiddlyWiki anchor links can help us link to target points and distinct sections within rendered tiddlers. They can help the reader navigate longer tiddler content. + +For example this link, <a href=<<qualify "##Bottom_of_tiddler">>>Bottom</a>, should take you to the bottom of this tiddler. The "Back to the top" link below should return you back to the top of this tiddler. + +<a href=<<qualify "##Top">>>Back to the top</a> + +<a id=<<qualify "#How-do-I-make-them">>></a> + +!! How do I make them? + +There are only 2 steps to making anchor links. + +* First, create the target point (called an 'anchor') where you want it. +* Second, add a link to it where the reader might need it. + +That's it. + + +''Step 1: Create an 'anchor' (link target)'' + +``` +<a id="#Bottom_of_tiddler"></a> +``` + +*Add an <<.attr id>> attribute to any HTML5 tag and place a single `#` before the 'address' value. <a href="##Suggestions%0">Here are some suggestions of tags you can use.</a> +* Place this code at the target location. E.g. at the bottom of the tiddler. + +''Step 2: Create a link to the target anchor'' + +``` +<a href="##Bottom_of_tiddler">Bottom</a> +``` +*Create an `<a href>` link using exactly the same 'address' value as the target but with double `##` characters preceding it. +*Place this code where it will most help the reader. + +The above example can be adapted to work for many situations in ~TiddlyWiki, such as the table of contents at the top of this tiddler. + +''Is it really that simple? '' + +Yes, it's that simple. BUT... in ~TiddlyWiki there are some small differences from standard HTML5 anchor links and some specific ~TiddlyWiki limitations. + +<a href=<<qualify "##Top">>>Back to the top</a> + +<h2 id=<<qualify "#Anchor-link-limitations">>>Limitations and things to watch out for</h2> + +''Step 1:'' Creating the target anchor + +* Unlike standard HTML5, in ~TiddlyWiki you must put a single `#` character in front of the target address value that follows the <<.attr id>> attribute. (Notice the single `#` character used in the #Bottom_of_tiddler in Example 1.) +* Unlike standard HTML5, ~TiddlyWiki anchor links are case sensitive. In the example above #Bottom_of_tiddler works, but #bottom_of_Tiddler wouldn't. +* Avoid using the % character in your link, as some browsers have a bug where navigation to anchors containing a % character can sometimes fail (see warning below). +* <a id=<<qualify #note.1-return>>/>Avoid using any whitespace in your link (see <a href=<<qualify ##note.1>> title="click to go to note 1.">note 1</a> below). +* Each link address should be unique in the TiddlyWiki. If transclusions create multiple instances of the same <<.attr id>> attribute, navigation will take place to the first instance found that satisfies the above criteria. To avoid this, you can use the [[qualify macro|qualify Macro]] in both the <<.attr id>> and the <<.attr href>> attributes in a similar style to the example given below: <a href=<<qualify ##qualify-example>> >Avoiding duplicate IDs when transcluding</a>. + +''Step 2:'' Creating the link to the target + +* Remember that the <<.attr href>> value should start with ''two'' `#` characters, one more than the <<.attr id>> value of the target anchor. +* Remember that ~TiddlyWiki anchor links are case sensitive + +''Step 3:'' Navigating to the target + +Normally you can click on the link and ~TiddlyWiki will scroll the window so the target anchor is at the top of the window, but there are several limitations: + +* Anchor links in ~TiddlyWiki do not work if the tiddler is not in the Story River, or is not displayed in the sidebar. +* Anchor links in ~TiddlyWiki do not work if the tidlder is in the Story River or sidebar but anchor marked target point is not visible on the page (e.g., the tiddler is folded or the anchor is within a non-displaying $reveal widget). Ctrl+Click on such an anchor link will open a new browser window/tab loading the base web page and will not navigate to the expected tiddler. +* Anchor links in Tiddlywiki do not work if Control Panel > Appearance > Story View is set to Zoomin (the single page view) and the tiddler is not at the top of the story river (i.e. not displayed). +* When an anchor link is clicked the browser's navigation history will be updated with the link's href value appended to the web page's URL. This will happen even if the Control Panel > Settings > Navigation History value is set to "Do not update history". + +<$macrocall $name=.note _="""<span id=<<qualify #note.1>>><a href=<<qualify ##note.1-return>> title="click to return">1.</a></span> The [ext[HTML5 specification|https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id]] for the <<.attr id>> attribute says that its value should not contain any whitespace. Currently ^^(Dec 2020)^^ an <<.attr id>> value with whitespace can sometimes work. However, it may not work in all browsers and is not guaranteed to work in the future.""" /> + +<<.warning "Some browsers may fail to navigate to an anchor target whose ''id'' value includes a `%` character followed by 2 digits. This is a bug in the browser and nothing that ~TiddlyWiki can fix. To be safe, avoid using the `%` character.">> + +<a href=<<qualify "##Top">>>Back to the top</a> + +<h2 id=<<qualify "#More_examples">>>More examples</h2> +In each case the target code is placed at the destination the reader navigates to, the link code is placed where it will help the reader navigate from. + +``` +<h2 id="#heading-01"> My Target Heading</h2> + +<a href="##heading-01">Link to My Target Heading</a> + +``` + +This looks like: + +<hr> +<h2 id="#heading-01">My Target Heading</h2> + +<a href="##heading-01">Link to My Target Heading</a> +<hr> + +``` +<section id="#unique001"> + +!! My Target section + +A `<section>` HTML tag is generally used to define sections in an HTML document, such as chapters, headers, footers, or any other sections of the document. +</section> + +Clicking this anchor link goes to: <a href="##unique001">Link to My Target Section</a> +``` + +This looks like: + +<hr> +<section id="#unique001"> + +!! My Target section + +A `<section>` HTML tag is generally used to define sections in an HTML document, such as chapters, headers, footers, or any other sections of the document. +</section> + +Clicking this anchor link goes to: <a href="##unique001">Link to My Target Section</a> +<hr> + +<a href=<<qualify "##Top">>>Back to the top</a> + +<h2 id=<<qualify "#Suggestions-for-elements">>>''Suggestions for HTML elements to use''</h2> + +Some suggestions for the HTML element you choose for marking a position using the <<.attr id>> attribute: + +| ! Element | ! Sample code | ! Observations | +|<<.def anchor>> |<$text text="""<a id="#part001-of-TiddlerName"></a>"""/> |Should work perfectly everywhere| +|<<.def heading>> |<$text text="""<h2 id="#a-new-heading">A New Heading</h2>"""/>|Headings can have <<.attr id>> attributes as well| +|<<.def section>> |<$text text="""<section id="#sect001-of-TiddlerName">This is a new section</section>"""/>|If you use the `section` element it should probably have an <<.attr id>> of its own| +|<<.def span>> |<$text text="""<span id="#007">Marker 007 is here!</span>"""/>|`span` elements can be used to insert an <<.attr id>> mid-paragraph| + +<a href=<<qualify "##Top">>>Back to the top</a> + +<h2 id=<<qualify "#Suggestions-for-ids">>>Suggestions for target names to use</h2> + +| ! | ! Sample code | ! Observations | +|<<.def Recommended>> |<$text text="""<a id="#part001-of-TiddlerName"></a>"""/> |Include the tiddler name for easy unique <<.attr id>>s| +|<<.def "Avoid: whitespace">> |<$text text="""<h2 id="#0 0 1">A New Heading</h2>"""/>|Whitespace is not guaranteed to work in all browsers| +|<<.def "Avoid: %">> |<$text text="""<section id="#sect001%20of%20TiddlerName">This is a new section</section>"""/>|URI encoding (turning space into %20 and so on) may not work in some browsers| +|<<.def "Avoid: duplicate IDs">> |<$text text="""<span id="#007">Marker 007 is here!</span>"""/>|<<.attr id>> values should be unique within entire wiki| +|<<.def "Avoid: duplicate IDs">> |<$text text="""<a id="#007"></a>"""/>A different marker 007|If <<.attr id>> values are duplicated, one will be ignored| + +<a href=<<qualify "##Top">>>Back to the top</a> + +<h2 id=<<qualify "#qualify-example">>> ''Avoiding duplicate IDs when transcluding''</h2> +The <<.attr id>> and anchor link to this header has been made as follows: + +``` +<a href=<<qualify "##qualify-example">>>Avoiding duplicate IDs when transcluding</a> + +<h2 id=<<qualify "#qualify-example">>>Avoiding duplicate IDs when transcluding</h2> +``` +;For this to work: + +* The <<.attr href>> and <<.attr id>> values use the [[macro invocation syntax for attributes|HTML in WikiText]], using the [[qualify Macro]] to create a unique <<.attr id>> value. +* Both the <<.attr id>> and the anchor link must be in the same tiddler. +* There must not be any quote characters between the `=` and the `<<`. +* The double quotes around the target name are optional, but recommended. +* There should be a total of three `>` characters after the target name, two `>>` to close the `<<qualify` macro, and one `>` to close the `<a` tag. + +<a href=<<qualify "##Top">>>Back to the top</a> + +<h2 id=<<qualify #Style_Hints>>>''Style Hints'' </h2> + +If you don't want the link to look like an external link, give the `<a>` element's <<.attr class>> attribute the value <<.def tc-tiddlylink>> and if you want the link to also be italic & bold, give the additional classes <<.def "tc-tiddlylink-missing tc-tiddlylink-shadow">> like below: + +``` +<a class="tc-tiddlylink" href="##Introduction:Anchor-Links-using-HTML">Back to the top</a> or just back to <a class="tc-tiddlylink tc-tiddlylink-missing tc-tiddlylink-shadow" href=<<qualify ##Hints>>>Hints</a>. +``` +<a class="tc-tiddlylink" href="##Introduction:Anchor-Links-using-HTML">Back to the top</a> or just back to <a class="tc-tiddlylink tc-tiddlylink-missing tc-tiddlylink-shadow" href=<<qualify ##Style_Hints>>>Style Hints</a>. + +If you want to include an <<.attr id>> attribute to a link in your sidebar Table of Contents, you can include it in your listed tiddler's <<.field caption>> field similar to the way shown below: + +``` +<span id=#some-value>Your caption</span> +``` + +<a id=<<qualify "#Bottom_of_tiddler">>></a> + +<a href=<<qualify "##Top">>>Back to the top</a> From 367854c81b9f9145e068b12689173607677cc79e Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 30 Nov 2020 18:56:19 +0100 Subject: [PATCH 089/124] Update static.tiddler.html.tid (#5148) --- core/templates/static.tiddler.html.tid | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/templates/static.tiddler.html.tid b/core/templates/static.tiddler.html.tid index 0fdd4e2fe..a4537305a 100644 --- a/core/templates/static.tiddler.html.tid +++ b/core/templates/static.tiddler.html.tid @@ -22,9 +22,9 @@ title: $:/core/templates/static.tiddler.html </head> <body class="tc-body"> `{{$:/StaticBanner||$:/core/templates/html-tiddler}}` -<section class="tc-story-river"> +<section class="tc-story-river tc-static-story-river"> `<$view tiddler="$:/core/ui/ViewTemplate" format="htmlwikified"/>` </section> </body> </html> -` \ No newline at end of file +` From 80191903b6b5c61fe16715f35d8f874d57c02045 Mon Sep 17 00:00:00 2001 From: Bram Chen <bram.chen@gmail.com> Date: Tue, 1 Dec 2020 01:58:33 +0800 Subject: [PATCH 090/124] Update chinese translations (#5145) * Improve `References/Caption` * Add `Basics/RemoveTags` and `Basics/RemoveTags/Hint` --- languages/zh-Hans/ControlPanel.multids | 2 ++ languages/zh-Hans/TiddlerInfo.multids | 2 +- languages/zh-Hant/ControlPanel.multids | 2 ++ languages/zh-Hant/TiddlerInfo.multids | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/languages/zh-Hans/ControlPanel.multids b/languages/zh-Hans/ControlPanel.multids index a29cd9a35..1a849b3bc 100644 --- a/languages/zh-Hans/ControlPanel.multids +++ b/languages/zh-Hans/ControlPanel.multids @@ -17,6 +17,8 @@ Basics/NewJournal/Title/Prompt: 新日志条目的名称 Basics/NewTiddler/Tags/Prompt: 新条目的标签 Basics/NewTiddler/Title/Prompt: 新条目的名称 Basics/OverriddenShadowTiddlers/Prompt: 被覆盖的默认条目数量 +Basics/RemoveTags: 更新到当前格式 +Basics/RemoveTags/Hint: 将标签配置更新为最新格式 Basics/ShadowTiddlers/Prompt: 默认条目数量 Basics/Subtitle/Prompt: 副标题 Basics/SystemTiddlers/Prompt: 系统条目数量 diff --git a/languages/zh-Hans/TiddlerInfo.multids b/languages/zh-Hans/TiddlerInfo.multids index 8329fd89e..b5580d1cf 100644 --- a/languages/zh-Hans/TiddlerInfo.multids +++ b/languages/zh-Hans/TiddlerInfo.multids @@ -14,7 +14,7 @@ List/Caption: 列表 List/Empty: 此条目无指定列表 Listed/Caption: 被列于 Listed/Empty: 此条目未出现于其他条目的列表中 -References/Caption: 参照 +References/Caption: 反向链接 References/Empty: 无条目链接至此 Tagging/Caption: 子条目 Tagging/Empty: 无任何条目以此条目之标题为标签 diff --git a/languages/zh-Hant/ControlPanel.multids b/languages/zh-Hant/ControlPanel.multids index 09c088e85..ba5333014 100644 --- a/languages/zh-Hant/ControlPanel.multids +++ b/languages/zh-Hant/ControlPanel.multids @@ -17,6 +17,8 @@ Basics/NewJournal/Title/Prompt: 新日誌條目的名稱 Basics/NewTiddler/Tags/Prompt: 新條目的標籤 Basics/NewTiddler/Title/Prompt: 新條目的名稱 Basics/OverriddenShadowTiddlers/Prompt: 被覆寫的預設條目數量 +Basics/RemoveTags: 更新到當前格式 +Basics/RemoveTags/Hint: 將標籤設定更新為最新格式 Basics/ShadowTiddlers/Prompt: 預設條目數量 Basics/Subtitle/Prompt: 副標題 Basics/SystemTiddlers/Prompt: 系統條目數量 diff --git a/languages/zh-Hant/TiddlerInfo.multids b/languages/zh-Hant/TiddlerInfo.multids index dab4c0c08..ffb16889d 100644 --- a/languages/zh-Hant/TiddlerInfo.multids +++ b/languages/zh-Hant/TiddlerInfo.multids @@ -14,7 +14,7 @@ List/Caption: 列表 List/Empty: 此條目無指定列表 Listed/Caption: 被列於 Listed/Empty: 此條目未出現於其他條目的列表中 -References/Caption: 參照 +References/Caption: 反向連結 References/Empty: 無條目連結至此 Tagging/Caption: 子條目 Tagging/Empty: 無任何條目以此條目之標題為標籤 From 3406b98af62def252bcb0f7df8a72ed4b74818eb Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Mon, 30 Nov 2020 18:48:04 +0000 Subject: [PATCH 091/124] Add "autocomplete" attribute to <$edit> and <$edit-text> widgets --- core/modules/editor/engines/framed.js | 3 +++ core/modules/editor/engines/simple.js | 3 +++ core/modules/editor/factory.js | 3 ++- core/modules/widgets/edit.js | 3 ++- editions/tw5.com/tiddlers/widgets/EditTextWidget.tid | 3 ++- editions/tw5.com/tiddlers/widgets/EditWidget.tid | 10 ++++++---- 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/core/modules/editor/engines/framed.js b/core/modules/editor/engines/framed.js index 08ff0ffd7..c70167f6c 100644 --- a/core/modules/editor/engines/framed.js +++ b/core/modules/editor/engines/framed.js @@ -73,6 +73,9 @@ function FramedEngine(options) { if(this.widget.editTabIndex) { this.iframeNode.setAttribute("tabindex",this.widget.editTabIndex); } + if(this.widget.editAutoComplete) { + this.domNode.setAttribute("autocomplete",this.widget.editAutoComplete); + } if(this.widget.isDisabled === "yes") { this.domNode.setAttribute("disabled",true); } diff --git a/core/modules/editor/engines/simple.js b/core/modules/editor/engines/simple.js index 0f65e7ceb..fe65d1fd9 100644 --- a/core/modules/editor/engines/simple.js +++ b/core/modules/editor/engines/simple.js @@ -52,6 +52,9 @@ function SimpleEngine(options) { if(this.widget.editTabIndex) { this.domNode.setAttribute("tabindex",this.widget.editTabIndex); } + if(this.widget.editAutoComplete) { + this.domNode.setAttribute("autocomplete",this.widget.editAutoComplete); + } if(this.widget.isDisabled === "yes") { this.domNode.setAttribute("disabled",true); } diff --git a/core/modules/editor/factory.js b/core/modules/editor/factory.js index 933c2eb42..3cf595371 100644 --- a/core/modules/editor/factory.js +++ b/core/modules/editor/factory.js @@ -180,6 +180,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { this.editCancelPopups = this.getAttribute("cancelPopups","") === "yes"; this.editInputActions = this.getAttribute("inputActions"); this.editRefreshTitle = this.getAttribute("refreshTitle"); + this.editAutoComplete = this.getAttribute("autocomplete"); this.isDisabled = this.getAttribute("disabled","no"); // Get the default editor element tag and type var tag,type; @@ -212,7 +213,7 @@ function editTextWidgetFactory(toolbarEngine,nonToolbarEngine) { EditTextWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // Completely rerender if any of our attributes have changed - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.placeholder || changedAttributes.size || changedAttributes.autoHeight || changedAttributes.minHeight || changedAttributes.focusPopup || changedAttributes.rows || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || changedTiddlers[HEIGHT_MODE_TITLE] || changedTiddlers[ENABLE_TOOLBAR_TITLE] || changedAttributes.disabled) { this.refreshSelf(); return true; } else if (changedTiddlers[this.editRefreshTitle]) { diff --git a/core/modules/widgets/edit.js b/core/modules/widgets/edit.js index 6ee918170..e7bd49b93 100644 --- a/core/modules/widgets/edit.js +++ b/core/modules/widgets/edit.js @@ -51,6 +51,7 @@ EditWidget.prototype.execute = function() { this.editCancelPopups = this.getAttribute("cancelPopups",""); this.editInputActions = this.getAttribute("inputActions"); this.editRefreshTitle = this.getAttribute("refreshTitle"); + this.editAutoComplete = this.getAttribute("autocomplete"); // Choose the appropriate edit widget this.editorType = this.getEditorType(); // Make the child widgets @@ -89,7 +90,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of EditWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); // Refresh if an attribute has changed, or the type associated with the target tiddler has changed - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) { + if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes.tabindex || changedAttributes.cancelPopups || changedAttributes.inputActions || changedAttributes.refreshTitle || changedAttributes.autocomplete || (changedTiddlers[this.editTitle] && this.getEditorType() !== this.editorType)) { this.refreshSelf(); return true; } else { diff --git a/editions/tw5.com/tiddlers/widgets/EditTextWidget.tid b/editions/tw5.com/tiddlers/widgets/EditTextWidget.tid index 5205741d2..c2e57e755 100644 --- a/editions/tw5.com/tiddlers/widgets/EditTextWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/EditTextWidget.tid @@ -1,6 +1,6 @@ caption: edit-text created: 20131024141900000 -modified: 20201109093034856 +modified: 20201130184701532 tags: Widgets title: EditTextWidget type: text/vnd.tiddlywiki @@ -25,6 +25,7 @@ The content of the `<$edit-text>` widget is ignored. |focusPopup |Title of a state tiddler for a popup that is displayed when the editing element has focus | |focus |Set to "yes" or "true" to automatically focus the editor after creation | |tabindex |Sets the `tabindex` attribute of the input or textarea to the given value | +|autocomplete |<<.from-version 5.1.23>> An optional string to provide a hint to the browser how to handle autocomplete for this input | |tag |Overrides the generated HTML editing element tag. For a multi-line editor use `tag=textarea`. For a single-line editor use `tag=input` | |type |Overrides the generated HTML editing element `type` attribute | |size |The size of the input field (in characters) | diff --git a/editions/tw5.com/tiddlers/widgets/EditWidget.tid b/editions/tw5.com/tiddlers/widgets/EditWidget.tid index 930319d70..78d85f3fe 100644 --- a/editions/tw5.com/tiddlers/widgets/EditWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/EditWidget.tid @@ -1,8 +1,9 @@ -title: EditWidget -created: 201310241419 -modified: 20150220161220000 -tags: Widgets caption: edit +created: 20131024141900000 +modified: 20201130184647904 +tags: Widgets +title: EditWidget +type: text/vnd.tiddlywiki ! Introduction @@ -18,6 +19,7 @@ The content of the `<$edit>` widget is ignored. |index |The index to edit | |class |A CSS class to be added the generated editing widget | |tabindex |Sets the `tabindex` attribute of the input or textarea to the given value | +|autocomplete |<<.from-version 5.1.23>> An optional string to provide a hint to the browser how to handle autocomplete for this input | |cancelPopups |<<.from-version "5.1.23">> if set to "yes", cancels all popups when the input gets focus | |inputActions |<<.from-version 5.1.23>> Optional actions that are triggered every time an input event occurs within the input field or textarea | |refreshTitle |<<.from-version 5.1.23>> An optional tiddler title that makes the input field update whenever the specified tiddler changes | From 1de747b182b546af2d857181b6d07901ab510bc3 Mon Sep 17 00:00:00 2001 From: Mario Pietsch <pmariojo@gmail.com> Date: Mon, 30 Nov 2020 19:48:48 +0100 Subject: [PATCH 092/124] add docs for radio-actions (#5156) --- .../tiddlers/widgets/RadioWidget Example.tid | 32 +++++++++++++++++++ .../widgets/RadioWidget ExampleTemplate.tid | 7 ++++ .../tw5.com/tiddlers/widgets/RadioWidget.tid | 5 ++- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 editions/tw5.com/tiddlers/widgets/RadioWidget Example.tid create mode 100644 editions/tw5.com/tiddlers/widgets/RadioWidget ExampleTemplate.tid diff --git a/editions/tw5.com/tiddlers/widgets/RadioWidget Example.tid b/editions/tw5.com/tiddlers/widgets/RadioWidget Example.tid new file mode 100644 index 000000000..64d8914c1 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/RadioWidget Example.tid @@ -0,0 +1,32 @@ +created: 20201130181015815 +modified: 20201130183426619 +tags: RadioWidget +title: RadioWidget Example +type: text/vnd.tiddlywiki + +\define newText() value: $(actionValue)$ + +\define radioActions() +<$action-sendmessage $message="tm-notify" $param="RadioWidget ExampleTemplate" value=<<actionValue>> current=<<currentTiddler>> /> +<$action-createtiddler $basetitle="$:/temp/test/value" $overwrite="yes" text=<<newText>>/> +<$action-navigate $to="$:/temp/test/value"/> +\end + +!! Using Actions + +If you select an option, the value is written to $:/temp/test/value and the ''id'' field of tiddler: $:/temp/test will be updated. + +A notification showing the ''actionValue'' will be shown. + +<$tiddler tiddler="$:/temp/test"> + <$radio field="id" value="a" actions=<<radioActions>> > Option a </$radio>| + <$radio field="id" value="b" actions=<<radioActions>> > Option b </$radio>| + <$radio field="id" value="c" actions=<<radioActions>> > Option c </$radio>| +</$tiddler> + +--- + +<details> + <summary>Show the code [[RadioWidget Example]]</summary> + <pre><code><$view mode=text&><pre><code> +</details> diff --git a/editions/tw5.com/tiddlers/widgets/RadioWidget ExampleTemplate.tid b/editions/tw5.com/tiddlers/widgets/RadioWidget ExampleTemplate.tid new file mode 100644 index 000000000..13be1572a --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/RadioWidget ExampleTemplate.tid @@ -0,0 +1,7 @@ +created: 20201130181111808 +modified: 20201130182421491 +tags: RadioWidget +title: RadioWidget ExampleTemplate +type: text/vnd.tiddlywiki + +value = <<value>> \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/widgets/RadioWidget.tid b/editions/tw5.com/tiddlers/widgets/RadioWidget.tid index 7a62c03ed..c8798900f 100644 --- a/editions/tw5.com/tiddlers/widgets/RadioWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/RadioWidget.tid @@ -1,6 +1,6 @@ caption: radio created: 20131212195353929 -modified: 20201109091807432 +modified: 20201130184330254 tags: Widgets title: RadioWidget type: text/vnd.tiddlywiki @@ -19,6 +19,7 @@ The content of the `<$radio>` widget is displayed within an HTML `<label>` eleme |index|<<.from-version "5.1.14">> The index of the //tiddler// being [[DataTiddler|DataTiddlers]] bound to the radio button<<.tip "takes precedence over //field//">>| |value |The value for the //field// or //index// of the //tiddler//| |class |The CSS classes assigned to the label around the radio button<$macrocall $name=".tip" _="""<<.from-version "5.1.14">> `tc-radio` is always applied by default, as well as `tc-radio-selected` when selected"""/>| +|actions|<<.from-version "5.1.23">> Optional, A string containing ActionWidgets to be triggered when the value changes. <br>The variable: ''actionValue'' is available for the actions. | |disabled|<<.from-version "5.1.23">> Optional, disables the radio input if set to "yes". Defaults to "no"| @@ -39,3 +40,5 @@ This example sets the `Tree Frog` index in the tiddler AnimalColours: <$radio index="Tree Frog" value="green"> green</$radio> <$radio index="Tree Frog" value="brown"> brown</$radio> </$tiddler>"""/> + +{{RadioWidget Example}} \ No newline at end of file From fe8606759ebf1db50c57a2e779b086a6d7df2ae6 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Mon, 30 Nov 2020 18:56:52 +0000 Subject: [PATCH 093/124] Fix parsing of dates between 0 and 100 AD --- boot/boot.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/boot/boot.js b/boot/boot.js index 9b742120c..7f85417a6 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -305,13 +305,16 @@ $tw.utils.stringifyDate = function(value) { // Parse a date from a UTC YYYYMMDDHHMMSSmmm format string $tw.utils.parseDate = function(value) { if(typeof value === "string") { - return new Date(Date.UTC(parseInt(value.substr(0,4),10), + var year = parseInt(value.substr(0,4),10), + d = new Date(Date.UTC(year, parseInt(value.substr(4,2),10)-1, parseInt(value.substr(6,2),10), parseInt(value.substr(8,2)||"00",10), parseInt(value.substr(10,2)||"00",10), parseInt(value.substr(12,2)||"00",10), parseInt(value.substr(14,3)||"000",10))); + d.setUTCFullYear(year); // See https://stackoverflow.com/a/5870822 + return d; } else if($tw.utils.isDate(value)) { return value; } else { From 6a319940d375825ef661ec90c5472cc2260f0471 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Mon, 30 Nov 2020 22:04:14 +0100 Subject: [PATCH 094/124] Make buttons look like buttons in CupertinoDark, GruvboxDark and DesertSand palette (#5159) * Make buttons look like buttons in CupertinoDark palette * Update GruvBoxDark.tid * Update DesertSand.tid --- core/palettes/CupertinoDark.tid | 6 ++---- core/palettes/DesertSand.tid | 2 -- core/palettes/GruvBoxDark.tid | 6 ++---- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index 44ad38e8b..0880054ca 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -10,9 +10,7 @@ alert-highlight: #FFD60A alert-muted-foreground: <<colour muted-foreground>> background: #282828 blockquote-bar: <<colour page-background>> -button-background: #3F638B -button-foreground: <<colour foreground>> -button-border: transparent +button-foreground: <<colour background>> code-background: <<colour pre-background>> code-border: <<colour pre-border>> code-foreground: rgba(255, 255, 255, 0.54) @@ -53,7 +51,7 @@ pre-border: transparent primary: #0A84FF select-tag-background: <<colour background>> select-tag-foreground: <<colour foreground>> -sidebar-button-foreground: <<colour foreground>> +sidebar-button-foreground: <<colour background>> sidebar-controls-foreground-hover: #FF9F0A sidebar-controls-foreground: #8E8E93 sidebar-foreground-shadow: transparent diff --git a/core/palettes/DesertSand.tid b/core/palettes/DesertSand.tid index ba0581095..ab345d11f 100644 --- a/core/palettes/DesertSand.tid +++ b/core/palettes/DesertSand.tid @@ -10,9 +10,7 @@ alert-highlight: #881122 alert-muted-foreground: #b99e2f background: #E9E0C7 blockquote-bar: <<colour muted-foreground>> -button-background: #BAB29C button-foreground: <<colour foreground>> -button-border: transparent code-background: #F3EDDF code-border: #C3BAA1 code-foreground: #ab3250 diff --git a/core/palettes/GruvBoxDark.tid b/core/palettes/GruvBoxDark.tid index c4b1cfc63..a8db56807 100644 --- a/core/palettes/GruvBoxDark.tid +++ b/core/palettes/GruvBoxDark.tid @@ -11,9 +11,7 @@ alert-highlight: #d79921 alert-muted-foreground: #504945 background: #3c3836 blockquote-bar: <<colour muted-foreground>> -button-background: #504945 -button-foreground: #fbf1c7 -button-border: transparent +button-foreground: <<colour page-background>> code-background: #504945 code-border: #504945 code-foreground: #fb4934 @@ -62,7 +60,7 @@ pre-border: #504945 primary: #d79921 select-tag-background: #665c54 select-tag-foreground: <<colour foreground>> -sidebar-button-foreground: <<colour foreground>> +sidebar-button-foreground: <<colour page-background>> sidebar-controls-foreground-hover: #7c6f64 sidebar-controls-foreground: #504945 sidebar-foreground-shadow: transparent From dde4182830f11bfdbcca558065f432556ccf4e65 Mon Sep 17 00:00:00 2001 From: Joshua Fontany <joshua.fontany@gmail.com> Date: Mon, 30 Nov 2020 14:31:48 -0800 Subject: [PATCH 095/124] Fix filesystem adaptor (#5113) * ignore .env testing new implementation almost there closer bug, desyncing fixed final testing final testing cleanup cleanup * isEditableFile flow fixed * removed `basepath` logic * callback to delete title from $tw.boot.files * comment fix * have syncer delete from boot.files * syntax * bugfix: error on missing directory * bugifx * remove !draft check * fix relative filepaths * cleanup * cleanup !draft * catch undefined filepaths in deleteTiddlerFile() * typo * whitelist wiki dir, encodeURIComponent otherwise * test for wikiPath, not wikiPath/tiddlers * don't need to .normailze() * whitelist wiki directory, move cleanup to util * use cleanup util & fail EPERM & EACCESS gracefully * comments * final bugs fixed * improved sync error --- boot/boot.js | 22 ++- core/modules/syncer.js | 4 + core/modules/utils/filesystem.js | 139 ++++++++++++++++-- .../filesystem/filesystemadaptor.js | 78 ++++++---- 4 files changed, 195 insertions(+), 48 deletions(-) diff --git a/boot/boot.js b/boot/boot.js index 7f85417a6..97bf73837 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -1915,15 +1915,21 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) { } } else { // Process directory specifier - var dirPath = path.resolve(filepath,dirSpec.path), - files = fs.readdirSync(dirPath), - fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"), - metaRegExp = /^.*\.meta$/; - for(var t=0; t<files.length; t++) { - var filename = files[t]; - if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) { - processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile); + var dirPath = path.resolve(filepath,dirSpec.path); + if(fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) { + var files = fs.readdirSync(dirPath), + fileRegExp = new RegExp(dirSpec.filesRegExp || "^.*$"), + metaRegExp = /^.*\.meta$/; + for(var t=0; t<files.length; t++) { + var filename = files[t]; + if(filename !== "tiddlywiki.files" && !metaRegExp.test(filename) && fileRegExp.test(filename)) { + processFile(dirPath + path.sep + filename,dirSpec.isTiddlerFile,dirSpec.fields,dirSpec.isEditableFile); + } } + } else { + console.log("Warning: a directory in a tiddlywiki.files file does not exist."); + console.log("dirPath: " + dirPath); + console.log("tiddlywiki.files location: " + filepath); } } }); diff --git a/core/modules/syncer.js b/core/modules/syncer.js index d5eae1f48..15374d40a 100644 --- a/core/modules/syncer.js +++ b/core/modules/syncer.js @@ -633,6 +633,10 @@ DeleteTiddlerTask.prototype.run = function(callback) { } // Remove the info stored about this tiddler delete self.syncer.tiddlerInfo[self.title]; + if($tw.boot.files){ + // Remove the tiddler from $tw.boot.files + delete $tw.boot.files[self.title]; + } // Invoke the callback callback(null); },{ diff --git a/core/modules/utils/filesystem.js b/core/modules/utils/filesystem.js index df820a63c..7c77eb0d7 100644 --- a/core/modules/utils/filesystem.js +++ b/core/modules/utils/filesystem.js @@ -204,15 +204,17 @@ exports.deleteEmptyDirs = function(dirpath,callback) { /* Create a fileInfo object for saving a tiddler: filepath: the absolute path to the file containing the tiddler - type: the type of the tiddler file (NOT the type of the tiddler) + type: the type of the tiddler file on disk (NOT the type of the tiddler) hasMetaFile: true if the file also has a companion .meta file Options include: directory: absolute path of root directory to which we are saving pathFilters: optional array of filters to be used to generate the base path - wiki: optional wiki for evaluating the pathFilters + extFilters: optional array of filters to be used to generate the base path + wiki: optional wiki for evaluating the pathFilters, + fileInfo: an existing fileInfo to check against */ exports.generateTiddlerFileInfo = function(tiddler,options) { - var fileInfo = {}; + var fileInfo = {}, metaExt; // Check if the tiddler has any unsafe fields that can't be expressed in a .tid or .meta file: containing control characters, or leading/trailing whitespace var hasUnsafeFields = false; $tw.utils.each(tiddler.getFieldStrings(),function(value,fieldName) { @@ -238,19 +240,66 @@ exports.generateTiddlerFileInfo = function(tiddler,options) { fileInfo.type = tiddlerType; fileInfo.hasMetaFile = true; } + if(options.extFilters) { + // Check for extension override + metaExt = $tw.utils.generateTiddlerExtension(tiddler.fields.title,{ + extFilters: options.extFilters, + wiki: options.wiki + }); + if(metaExt === ".tid") { + // Overriding to the .tid extension needs special handling + fileInfo.type = "application/x-tiddler"; + fileInfo.hasMetaFile = false; + } else if (metaExt === ".json") { + // Overriding to the .json extension needs special handling + fileInfo.type = "application/json"; + fileInfo.hasMetaFile = false; + } else if (metaExt) { + //If the new type matches a known extention, use that MIME type's encoding + var extInfo = $tw.utils.getFileExtensionInfo(metaExt); + fileInfo.type = extInfo ? extInfo.type : null; + fileInfo.encoding = $tw.utils.getTypeEncoding(metaExt); + fileInfo.hasMetaFile = true; + } + } } - // Take the file extension from the tiddler content type + // Take the file extension from the tiddler content type or metaExt var contentTypeInfo = $tw.config.contentTypeInfo[fileInfo.type] || {extension: ""}; // Generate the filepath fileInfo.filepath = $tw.utils.generateTiddlerFilepath(tiddler.fields.title,{ - extension: contentTypeInfo.extension, + extension: metaExt || contentTypeInfo.extension, directory: options.directory, pathFilters: options.pathFilters, - wiki: options.wiki + wiki: options.wiki, + fileInfo: options.fileInfo }); return fileInfo; }; +/* +Generate the file extension for saving a tiddler +Options include: + extFilters: optional array of filters to be used to generate the extention + wiki: optional wiki for evaluating the extFilters +*/ +exports.generateTiddlerExtension = function(title,options) { + var self = this, + extension; + // Check if any of the extFilters applies + if(options.extFilters && options.wiki) { + $tw.utils.each(options.extFilters,function(filter) { + if(!extension) { + var source = options.wiki.makeTiddlerIterator([title]), + result = options.wiki.filterTiddlers(filter,null,source); + if(result.length > 0) { + extension = result[0]; + } + } + }); + } + return extension; +}; + /* Generate the filepath for saving a tiddler Options include: @@ -258,12 +307,13 @@ Options include: directory: absolute path of root directory to which we are saving pathFilters: optional array of filters to be used to generate the base path wiki: optional wiki for evaluating the pathFilters + fileInfo: an existing fileInfo object to check against */ exports.generateTiddlerFilepath = function(title,options) { var self = this, directory = options.directory || "", extension = options.extension || "", - filepath; + filepath; // Check if any of the pathFilters applies if(options.pathFilters && options.wiki) { $tw.utils.each(options.pathFilters,function(filter) { @@ -276,7 +326,6 @@ exports.generateTiddlerFilepath = function(title,options) { } }); } - // If not, generate a base pathname if(!filepath) { filepath = title; // If the filepath already ends in the extension then remove it @@ -286,10 +335,13 @@ exports.generateTiddlerFilepath = function(title,options) { // Remove any forward or backward slashes so we don't create directories filepath = filepath.replace(/\/|\\/g,"_"); } - // Don't let the filename start with a dot because such files are invisible on *nix - filepath = filepath.replace(/^\./g,"_"); + //If the path does not start with "." or ".." and a path seperator, then + if(!/^\.{1,2}[/\\]/g.test(filepath)) { + // Don't let the filename start with any dots because such files are invisible on *nix + filepath = filepath.replace(/^\.+/g,"_"); + } // Remove any characters that can't be used in cross-platform filenames - filepath = $tw.utils.transliterate(filepath.replace(/<|>|\:|\"|\||\?|\*|\^/g,"_")); + filepath = $tw.utils.transliterate(filepath.replace(/<|>|~|\:|\"|\||\?|\*|\^/g,"_")); // Truncate the filename if it is too long if(filepath.length > 200) { filepath = filepath.substr(0,200); @@ -306,12 +358,21 @@ exports.generateTiddlerFilepath = function(title,options) { }); } // Add a uniquifier if the file already exists - var fullPath, + var fullPath, oldPath = (options.fileInfo) ? options.fileInfo.filepath : undefined, count = 0; do { fullPath = path.resolve(directory,filepath + (count ? "_" + count : "") + extension); + if(oldPath && oldPath == fullPath) { + break; + } count++; } while(fs.existsSync(fullPath)); + //If the path does not start with the wiki directory, or if the last write failed + var encode = fullPath.indexOf($tw.boot.wikiPath) !== 0 || ((options.fileInfo || {writeError: false}).writeError == true); + if(encode){ + //encodeURIComponent() and then resolve to tiddler directory + fullPath = path.resolve(directory, encodeURIComponent(fullPath)); + } // Return the full path to the file return fullPath; }; @@ -366,4 +427,58 @@ exports.saveTiddlerToFileSync = function(tiddler,fileInfo) { } }; +/* +Delete a file described by the fileInfo if it exits +*/ +exports.deleteTiddlerFile = function(fileInfo, callback) { + //Only attempt to delete files that exist on disk + if(!fileInfo.filepath || !fs.existsSync(fileInfo.filepath)) { + return callback(null); + } + // Delete the file + fs.unlink(fileInfo.filepath,function(err) { + if(err) { + return callback(err); + } + // Delete the metafile if present + if(fileInfo.hasMetaFile && fs.existsSync(fileInfo.filepath + ".meta")) { + fs.unlink(fileInfo.filepath + ".meta",function(err) { + if(err) { + return callback(err); + } + return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback); + }); + } else { + return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback); + } + }); +}; + +/* +Cleanup old files on disk, by comparing the options values: + adaptorInfo from $tw.syncer.tiddlerInfo + bootInfo from $tw.boot.files +*/ +exports.cleanupTiddlerFiles = function(options, callback) { + var adaptorInfo = options.adaptorInfo || {}, + bootInfo = options.bootInfo || {}, + title = options.title || "undefined"; + if(adaptorInfo.filepath && bootInfo.filepath && adaptorInfo.filepath !== bootInfo.filepath) { + return $tw.utils.deleteTiddlerFile(adaptorInfo, function(err){ + if(err) { + if ((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "unlink") { + // Error deleting the previous file on disk, should fail gracefully + $tw.syncer.displayError("Server desynchronized. Error cleaning up previous file for tiddler: "+title, err); + return callback(null); + } else { + return callback(err); + } + } + return callback(null); + }); + } else { + return callback(null); + } +}; + })(); diff --git a/plugins/tiddlywiki/filesystem/filesystemadaptor.js b/plugins/tiddlywiki/filesystem/filesystemadaptor.js index 84da6236e..fce2eaeaa 100644 --- a/plugins/tiddlywiki/filesystem/filesystemadaptor.js +++ b/plugins/tiddlywiki/filesystem/filesystemadaptor.js @@ -35,7 +35,9 @@ FileSystemAdaptor.prototype.isReady = function() { }; FileSystemAdaptor.prototype.getTiddlerInfo = function(tiddler) { - return {}; + //Returns the existing fileInfo for the tiddler. To regenerate, call getTiddlerFileInfo(). + var title = tiddler.fields.title; + return this.boot.files[title]; }; /* @@ -44,24 +46,25 @@ Return a fileInfo object for a tiddler, creating it if necessary: type: the type of the tiddler file (NOT the type of the tiddler -- see below) hasMetaFile: true if the file also has a companion .meta file -The boot process populates this.boot.files for each of the tiddler files that it loads. The type is found by looking up the extension in $tw.config.fileExtensionInfo (eg "application/x-tiddler" for ".tid" files). +The boot process populates this.boot.files for each of the tiddler files that it loads. +The type is found by looking up the extension in $tw.config.fileExtensionInfo (eg "application/x-tiddler" for ".tid" files). It is the responsibility of the filesystem adaptor to update this.boot.files for new files that are created. */ FileSystemAdaptor.prototype.getTiddlerFileInfo = function(tiddler,callback) { // See if we've already got information about this file var title = tiddler.fields.title, - fileInfo = this.boot.files[title]; - if(!fileInfo) { - // Otherwise, we'll need to generate it - fileInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{ - directory: this.boot.wikiTiddlersPath, - pathFilters: this.wiki.getTiddlerText("$:/config/FileSystemPaths","").split("\n"), - wiki: this.wiki - }); - this.boot.files[title] = fileInfo; - } - callback(null,fileInfo); + newInfo, fileInfo = this.boot.files[title]; + // Always generate a fileInfo object when this fuction is called + newInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{ + directory: this.boot.wikiTiddlersPath, + pathFilters: this.wiki.getTiddlerText("$:/config/FileSystemPaths","").split("\n"), + extFilters: this.wiki.getTiddlerText("$:/config/FileSystemExtensions","").split("\n"), + wiki: this.wiki, + fileInfo: fileInfo + }); + this.boot.files[title] = newInfo; + callback(null,newInfo); }; @@ -74,7 +77,31 @@ FileSystemAdaptor.prototype.saveTiddler = function(tiddler,callback) { if(err) { return callback(err); } - $tw.utils.saveTiddlerToFile(tiddler,fileInfo,callback); + $tw.utils.saveTiddlerToFile(tiddler,fileInfo,function(err) { + if(err) { + if ((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "open") { + var bootInfo = self.boot.files[tiddler.fields.title]; + bootInfo.writeError = true; + self.boot.files[tiddler.fields.title] = bootInfo; + $tw.syncer.displayError("Sync for tiddler [["+tiddler.fields.title+"]] will be retried with encoded filepath", encodeURIComponent(bootInfo.filepath)); + return callback(err); + } else { + return callback(err); + } + } + // Cleanup duplicates if the file moved or changed extensions + var options = { + adaptorInfo: ($tw.syncer.tiddlerInfo[tiddler.fields.title] || {adaptorInfo: {} }).adaptorInfo, + bootInfo: self.boot.files[tiddler.fields.title] || {}, + title: tiddler.fields.title + }; + $tw.utils.cleanupTiddlerFiles(options, function(err){ + if(err) { + return callback(err); + } + return callback(null, self.boot.files[tiddler.fields.title]); + }); + }); }); }; @@ -95,22 +122,17 @@ FileSystemAdaptor.prototype.deleteTiddler = function(title,callback,options) { fileInfo = this.boot.files[title]; // Only delete the tiddler if we have writable information for the file if(fileInfo) { - // Delete the file - fs.unlink(fileInfo.filepath,function(err) { + $tw.utils.deleteTiddlerFile(fileInfo, function(err){ if(err) { - return callback(err); - } - // Delete the metafile if present - if(fileInfo.hasMetaFile) { - fs.unlink(fileInfo.filepath + ".meta",function(err) { - if(err) { - return callback(err); - } - return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback); - }); - } else { - return $tw.utils.deleteEmptyDirs(path.dirname(fileInfo.filepath),callback); + if ((err.code == "EPERM" || err.code == "EACCES") && err.syscall == "unlink") { + // Error deleting the file on disk, should fail gracefully + $tw.syncer.displayError("Server desynchronized. Error deleting file for deleted tiddler: "+title, err); + return callback(null); + } else { + return callback(err); + } } + return callback(null); }); } else { callback(null); From 6a91dbfe2f6e52512d7f063b6d5e3742ff77126d Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Tue, 1 Dec 2020 10:39:27 +0000 Subject: [PATCH 096/124] Add support for working with negative dates See discussion https://groups.google.com/g/tiddlywiki/c/aHlyaHr93Io/m/vGcDa6lxAgAJ --- boot/boot.js | 7 ++- core/modules/utils/utils.js | 13 +++-- editions/test/tiddlers/tests/test-utils.js | 25 ++++++++++ .../tw5.com/tiddlers/concepts/Date Fields.tid | 28 ----------- .../tw5.com/tiddlers/features/DateFormat.tid | 48 ------------------- 5 files changed, 41 insertions(+), 80 deletions(-) delete mode 100644 editions/tw5.com/tiddlers/concepts/Date Fields.tid delete mode 100644 editions/tw5.com/tiddlers/features/DateFormat.tid diff --git a/boot/boot.js b/boot/boot.js index 97bf73837..f6341dab0 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -305,7 +305,12 @@ $tw.utils.stringifyDate = function(value) { // Parse a date from a UTC YYYYMMDDHHMMSSmmm format string $tw.utils.parseDate = function(value) { if(typeof value === "string") { - var year = parseInt(value.substr(0,4),10), + var negative = 1; + if(value.charAt(0) === "-") { + negative = -1; + value = value.substr(1); + } + var year = parseInt(value.substr(0,4),10) * negative, d = new Date(Date.UTC(year, parseInt(value.substr(4,2),10)-1, parseInt(value.substr(6,2),10), diff --git a/core/modules/utils/utils.js b/core/modules/utils/utils.js index a606c2a2a..b3c56fb8c 100644 --- a/core/modules/utils/utils.js +++ b/core/modules/utils/utils.js @@ -302,7 +302,7 @@ exports.formatDateString = function(date,template) { return $tw.utils.pad($tw.utils.getHours12(date)); }], [/^wYYYY/, function() { - return $tw.utils.getYearForWeekNo(date); + return $tw.utils.pad($tw.utils.getYearForWeekNo(date),4); }], [/^hh12/, function() { return $tw.utils.getHours12(date); @@ -311,7 +311,14 @@ exports.formatDateString = function(date,template) { return date.getDate() + $tw.utils.getDaySuffix(date); }], [/^YYYY/, function() { - return date.getFullYear(); + return $tw.utils.pad(date.getFullYear(),4); + }], + [/^aYYYY/, function() { + return $tw.utils.pad(Math.abs(date.getFullYear()),4); + }], + [/^\{era:([^,\|}]*)\|([^}\|]*)\|([^}]*)\}/, function(match) { + var year = date.getFullYear(); + return year === 0 ? match[2] : (year < 0 ? match[1] : match[3]); }], [/^0hh/, function() { return $tw.utils.pad(date.getHours()); @@ -400,7 +407,7 @@ exports.formatDateString = function(date,template) { $tw.utils.each(matches, function(m) { var match = m[0].exec(t); if(match) { - matchString = m[1].call(); + matchString = m[1].call(null,match); t = t.substr(match[0].length); return false; } diff --git a/editions/test/tiddlers/tests/test-utils.js b/editions/test/tiddlers/tests/test-utils.js index ec60a6691..d57b0e0dc 100644 --- a/editions/test/tiddlers/tests/test-utils.js +++ b/editions/test/tiddlers/tests/test-utils.js @@ -25,6 +25,16 @@ describe("Utility tests", function() { expect(psa(" [[Tidd\u00a0ler8]] two ")).toEqual(["Tidd\u00a0ler8","two"]); }); + it("should handle parsing a date", function() { + var pd = function(v) { + return $tw.utils.parseDate(v).toString(); + }; + expect(pd("20150428204930183")).toEqual("Tue Apr 28 2015 21:49:30 GMT+0100 (British Summer Time)"); + expect(pd("-20150428204930183")).toEqual("Sun Apr 28 -2015 20:48:15 GMT-0001 (British Summer Time)"); + expect(pd("00730428204930183")).toEqual("Fri Apr 28 0073 20:48:15 GMT-0001 (British Summer Time)"); + expect(pd("-00730428204930183")).toEqual("Thu Apr 28 -0073 20:48:15 GMT-0001 (British Summer Time)"); + }); + it("should handle base64 encoding emojis", function() { var booksEmoji = "📚"; expect(booksEmoji).toBe(booksEmoji); @@ -62,6 +72,8 @@ describe("Utility tests", function() { var fds = $tw.utils.formatDateString, // nov is month: 10! d = new Date(2014,10,9,17,41,28,542); + expect(fds(d,"{era:bce||ce}")).toBe("ce"); + expect(fds(d,"YYYY")).toBe("2014"); expect(fds(d,"DDD DD MMM YYYY")).toBe("Sunday 9 November 2014"); expect(fds(d,"ddd hh mm ssss")).toBe("Sun 17 41 2828"); expect(fds(d,"MM0DD")).toBe("1109"); @@ -92,6 +104,19 @@ describe("Utility tests", function() { d = new Date(2014,11,29,23,59,59); expect(fds(d,"WW")).toBe("1"); expect(fds(d,"wYYYY")).toBe("2015"); + + // Negative years + d = new Date(-2014,10,9,17,41,28,542); + expect(fds(d,"YYYY")).toBe("-2014"); + expect(fds(d,"aYYYY")).toBe("2014"); + expect(fds(d,"{era:bce||ce}")).toBe("bce"); + + // Zero years + d = new Date(0,10,9,17,41,28,542); + d.setUTCFullYear(0); // See https://stackoverflow.com/a/5870822 + expect(fds(d,"YYYY")).toBe("0000"); + expect(fds(d,"aYYYY")).toBe("0000"); + expect(fds(d,"{era:bce|z|ce}")).toBe("z"); }); it("should parse text references", function() { diff --git a/editions/tw5.com/tiddlers/concepts/Date Fields.tid b/editions/tw5.com/tiddlers/concepts/Date Fields.tid deleted file mode 100644 index b1dcbe82d..000000000 --- a/editions/tw5.com/tiddlers/concepts/Date Fields.tid +++ /dev/null @@ -1,28 +0,0 @@ -created: 20150117190213631 -modified: 20150124214537000 -tags: Concepts -title: Date Fields -type: text/vnd.tiddlywiki - -Certain [[fields|TiddlerFields]] of a tiddler are used to store dates and times. - -The two standard date fields are <<.field created>> and <<.field modified>>. - -Values of date fields are 17-character strings: - -* 4 digits for the year -* 2 digits for the month -* 2 digits for the day -* 2 digits for the hour -* 2 digits for the minute -* 2 digits for the second -* 3 digits for the millisecond - -To avoid problems arising from differences of time zone, TiddlyWiki always uses [[UTC|https://en.wikipedia.org/wiki/Coordinated_Universal_Time]]. - -As an example, the <<.field created>> field of this tiddler has the value <<.value """<$view field="created"/>""">>. - -Dates can be [[converted to other formats|DateFormat]] for display: - -<$macrocall $name="wikitext-example-without-html" -src="""<$view field="created" format="date" template="DDD DDth MMM YYYY"/>"""> diff --git a/editions/tw5.com/tiddlers/features/DateFormat.tid b/editions/tw5.com/tiddlers/features/DateFormat.tid deleted file mode 100644 index 4d138e576..000000000 --- a/editions/tw5.com/tiddlers/features/DateFormat.tid +++ /dev/null @@ -1,48 +0,0 @@ -created: 20140418142957325 -modified: 20180730201626985 -tags: Features -title: DateFormat -type: text/vnd.tiddlywiki - -When used to display date values (with the `format` attribute set to ''date''), the ViewWidget accepts a `template` attribute that allows the format of the date values to be specified. The format string is processed with the following substitutions: - -|!Token |!Substituted Value | -|`DDD` |Day of week in full (eg, "Monday") | -|`ddd` |Short day of week (eg, "Mon") | -|`DD` |Day of month | -|`0DD` |Adds a leading zero | -|`DDth` |Adds a suffix | -|`WW` |ISO-8601 week number of year | -|`0WW` |Adds a leading zero | -|`MMM` |Month in full (eg, "July") | -|`mmm` |Short month (eg, "Jul") | -|`MM` |Month number | -|`0MM` |Adds leading zero | -|`YYYY` |Full year | -|`YY` |Two digit year | -|`wYYYY` |Full year with respect to week number | -|`wYY` |Two digit year with respect to week number | -|`hh` |Hours | -|`0hh` |Adds a leading zero | -|`hh12` |Hours in 12 hour clock | -|`0hh12` |Hours in 12 hour clock with leading zero | -|`mm` |Minutes | -|`0mm` |Minutes with leading zero | -|`ss` |Seconds | -|`0ss` |Seconds with leading zero | -|`XXX` |Milliseconds | -|`0XXX` |Milliseconds with leading zero | -|`am` or `pm` |Lower case AM/PM indicator | -|`AM` or `PM` |Upper case AM/PM indicator | -|`TZD` |Timezone offset | -|`\x` |Used to escape a character that would otherwise have special meaning | -|`[UTC]`|Time-shift the represented date to UTC. Must be at very start of format string| - -Note that other text is passed through unchanged, allowing commas, colons or other separators to be used. - -! Examples - -|!Template |!Output | -|`DDth MMM YYYY` |16th February 2011 | -|`DDth MMM \M\M\M YYYY` |16th February MMM 2011 | -|`DDth mmm YYYY 0hh:0mm:0ss` |16th Feb 2011 11:38:42 | From b63049b4df7baff5ec10627ed545f52020ba611d Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Tue, 1 Dec 2020 10:52:24 +0000 Subject: [PATCH 097/124] Fix tests to work in other timezones Oops. --- editions/test/tiddlers/tests/test-utils.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/editions/test/tiddlers/tests/test-utils.js b/editions/test/tiddlers/tests/test-utils.js index d57b0e0dc..e8f4de32f 100644 --- a/editions/test/tiddlers/tests/test-utils.js +++ b/editions/test/tiddlers/tests/test-utils.js @@ -27,12 +27,12 @@ describe("Utility tests", function() { it("should handle parsing a date", function() { var pd = function(v) { - return $tw.utils.parseDate(v).toString(); + return $tw.utils.parseDate(v).toUTCString(); }; - expect(pd("20150428204930183")).toEqual("Tue Apr 28 2015 21:49:30 GMT+0100 (British Summer Time)"); - expect(pd("-20150428204930183")).toEqual("Sun Apr 28 -2015 20:48:15 GMT-0001 (British Summer Time)"); - expect(pd("00730428204930183")).toEqual("Fri Apr 28 0073 20:48:15 GMT-0001 (British Summer Time)"); - expect(pd("-00730428204930183")).toEqual("Thu Apr 28 -0073 20:48:15 GMT-0001 (British Summer Time)"); + expect(pd("20150428204930183")).toEqual("Tue, 28 Apr 2015 20:49:30 GMT"); + expect(pd("-20150428204930183")).toEqual("Sun, 28 Apr -2015 20:49:30 GMT"); + expect(pd("00730428204930183")).toEqual("Fri, 28 Apr 0073 20:49:30 GMT"); + expect(pd("-00730428204930183")).toEqual("Thu, 28 Apr -0073 20:49:30 GMT"); }); it("should handle base64 encoding emojis", function() { From 13b69a9c109ada59e322a99b9cef61f1ac161225 Mon Sep 17 00:00:00 2001 From: "jeremy@jermolene.com" <jeremy@jermolene.com> Date: Tue, 1 Dec 2020 15:51:07 +0000 Subject: [PATCH 098/124] Missing docs for working with negative years --- .../tw5.com/tiddlers/concepts/Date Fields.tid | 29 +++++++++++ .../tw5.com/tiddlers/features/DateFormat.tid | 52 +++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 editions/tw5.com/tiddlers/concepts/Date Fields.tid create mode 100644 editions/tw5.com/tiddlers/features/DateFormat.tid diff --git a/editions/tw5.com/tiddlers/concepts/Date Fields.tid b/editions/tw5.com/tiddlers/concepts/Date Fields.tid new file mode 100644 index 000000000..7ffb40c5c --- /dev/null +++ b/editions/tw5.com/tiddlers/concepts/Date Fields.tid @@ -0,0 +1,29 @@ +created: 20150117190213631 +modified: 20201201154211507 +tags: Concepts +title: Date Fields +type: text/vnd.tiddlywiki + +Certain [[fields|TiddlerFields]] of a tiddler are used to store dates and times. TiddlyWiki supports dates from the year -9999 to the year 9999. + +The two standard date fields are <<.field created>> and <<.field modified>>. + +Values of date fields are 17 or 18-character strings: + +* <<.from-version "5.1.23">> an optional minus sign `-` to indicate a negative year +* 4 digits for the year +* 2 digits for the month +* 2 digits for the day +* 2 digits for the hour +* 2 digits for the minute +* 2 digits for the second +* 3 digits for the millisecond + +To avoid problems arising from differences of time zone, TiddlyWiki always uses [[UTC|https://en.wikipedia.org/wiki/Coordinated_Universal_Time]]. + +As an example, the <<.field created>> field of this tiddler has the value <<.value """<$view field="created"/>""">>. + +Dates can be [[converted to other formats|DateFormat]] for display: + +<$macrocall $name="wikitext-example-without-html" +src="""<$view field="created" format="date" template="DDD DDth MMM YYYY"/>"""> diff --git a/editions/tw5.com/tiddlers/features/DateFormat.tid b/editions/tw5.com/tiddlers/features/DateFormat.tid new file mode 100644 index 000000000..d0426565e --- /dev/null +++ b/editions/tw5.com/tiddlers/features/DateFormat.tid @@ -0,0 +1,52 @@ +created: 20140418142957325 +modified: 20201201154521138 +tags: Features +title: DateFormat +type: text/vnd.tiddlywiki + +When used to display date values (with the `format` attribute set to ''date''), the ViewWidget accepts a `template` attribute that allows the format of the date values to be specified. The format string is processed with the following substitutions: + +|!Token |!Substituted Value | +|`DDD` |Day of week in full (eg, "Monday") | +|`ddd` |Short day of week (eg, "Mon") | +|`DD` |Day of month | +|`0DD` |Adds a leading zero | +|`DDth` |Adds a suffix | +|`WW` |ISO-8601 week number of year | +|`0WW` |Adds a leading zero | +|`MMM` |Month in full (eg, "July") | +|`mmm` |Short month (eg, "Jul") | +|`MM` |Month number | +|`0MM` |Adds leading zero | +|`YYYY` |Full year | +|`YY` |Two digit year | +|`wYYYY` |Full year with respect to week number | +|`aYYYY` |<<.from-version "5.1.23">> Full year but negative dates are displayed as positive | +|`wYY` |Two digit year with respect to week number | +|`{era:BCE||CE}` |<<.from-version "5.1.23">> Displays a different string for years that are negative, zero or positive (see below) | +|`hh` |Hours | +|`0hh` |Adds a leading zero | +|`hh12` |Hours in 12 hour clock | +|`0hh12` |Hours in 12 hour clock with leading zero | +|`mm` |Minutes | +|`0mm` |Minutes with leading zero | +|`ss` |Seconds | +|`0ss` |Seconds with leading zero | +|`XXX` |Milliseconds | +|`0XXX` |Milliseconds with leading zero | +|`am` or `pm` |Lower case AM/PM indicator | +|`AM` or `PM` |Upper case AM/PM indicator | +|`TZD` |Timezone offset | +|`\x` |Used to escape a character that would otherwise have special meaning | +|`[UTC]`|Time-shift the represented date to UTC. Must be at very start of format string| + +Note that other text is passed through unchanged, allowing commas, colons or other separators to be used. + +The `{era:BCE||CE}` notation can specify different strings for years that are negative, zero or positive. For example `{era:BC|Z|AD}` would display `BC` for negative years, `AD` for positive years, and `Z` for year zero. + +! Examples + +|!Template |!Output | +|`DDth MMM YYYY` |16th February 2011 | +|`DDth MMM \M\M\M YYYY` |16th February MMM 2011 | +|`DDth mmm YYYY 0hh:0mm:0ss` |16th Feb 2011 11:38:42 | From 68cb08749f006b7b7dfd15979b64d5f1daa77832 Mon Sep 17 00:00:00 2001 From: Joshua Fontany <joshua.fontany@gmail.com> Date: Tue, 1 Dec 2020 09:36:38 -0800 Subject: [PATCH 099/124] Docs for filesystem adaptor update (#5169) * rebased to master * cleanup typos * typo --- .../Customising Tiddler File Naming.tid | 44 +++++++++++++++---- .../nodejs/tiddlywiki.files_Files.tid | 42 ++++++++++++++++-- 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid b/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid index 8bd4d121c..d13a6ce3b 100644 --- a/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid +++ b/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid @@ -1,25 +1,51 @@ created: 20160424181300000 -modified: 20160424181300000 +modified: 20201201000000000 tags: [[TiddlyWiki on Node.js]] title: Customising Tiddler File Naming type: text/vnd.tiddlywiki -By default, a [[TiddlyWiki on Node.js]] instance using a [[wiki folder|TiddlyWikiFolders]] will create new tiddler files by using the sanitised and disambiguated title as filename. +By default, a [[TiddlyWiki on Node.js]] instance using a [[wiki folder|TiddlyWikiFolders]] will create new tiddler files by using the sanitised and disambiguated title as filename and write them to the wiki folder's `tiddlers/` directory. The default file extension of `.tid` is used for tiddlers that are missing the `type` field, or for tiddlers of type "text/vnd.tiddlywiki". Tidders of other types are saved according to their IMIE types (defined at boot startup). Both the logical path (directory and file name) and the file extension can be customized independently by creating optional tiddlers: [[$:/config/FileSystemPaths]] and [[$:/config/FileSystemExtensions]]. -This can be customised by creating a tiddler [[$:/config/FileSystemPaths]] containing one or more [[filter expressions|Filter Syntax]], each on a line of its own. Newly created tiddlers are matched to each filter in turn, and the first output of the first filter to produce any output is taken as a logical path to be used for the tiddler file. Logical paths don't include the `.tid` extension, and they can use `/` or `\` as directory separator (when generating the physical path, this is replaced by the correct separator for the platform ~TiddlyWiki is running on). If none of the filters matches, the logical path is simply the title with all occurences of `/` replaced by `_` (for backwards compatibility). +! File System Paths -In both cases, the characters `<>:"\|?*^` are replaced by `_` in order to guarantee that the resulting path is legal on all supported platforms. +The logical path can be customised by creating a tiddler [[$:/config/FileSystemPaths]] containing one or more [[filter expressions|Filter Syntax]], each on a line of its own. Newly created tiddlers are matched to each filter in turn, and the first output of the first filter to produce any output is taken as a logical path to be used for the tiddler file. Tiddlers are also tested against the [[$:/config/FileSystemPaths]] on every save to disk, and if the logical path has changed a new file is created and the old file deleted. + +Tiddlers are limited to being written to the [[wiki folder|TiddlyWikiFolders]]. Any error saving a tiddler to disk, with a logical path that does not start with the wiki folder's path the most common error, causes the filepath to be encoded via Javascript's `encodeURIComponent()` method and the tiddler is saved as this file in the wiki folder's `tiddlers/` directory. + +Logical paths do not include the file-on-disk's extension (see below), and they can use `/` or `\` as directory separator (when generating the physical path, this is replaced by the correct separator for the platform ~TiddlyWiki is running on). If none of the filters matches, the logical path is simply the title with all occurences of `/` replaced by `_` (for backwards compatibility). + +In both cases, the characters `<>~:"\|?*^` are replaced by `_` in order to guarantee that the resulting path is legal on all supported platforms. !! Example ``` -[is[system]removeprefix[$:/]addprefix[_system/]] +[is[system]!has[draft.of]removeprefix[$:/]addprefix[_system/]] +[is[draft]search-replace:g:regexp[/|\\],[_]addprefix[drafts/]] [tag[task]addprefix[mytasks/]] -[!has[draft.of]] +[tag[externalnote]addprefix[../externalnotes/]] +[addprefix[wiki/]] ``` -This will store newly created system tiddlers in `tiddlers/_system` (after stripping the `$:/` prefix), tiddlers tagged [[task]] in a subdirectory `tiddlers/mytasks`, and also create subdirectory structures for all other non-draft tiddlers. +This will store newly created system tiddlers that are not drafts of other tiddlers in `tiddlers/_system` (after stripping the `$:/` prefix). Next, all drafts have the path seperator characters in their titles replaced by "_" and are stored in `tiddlers/drafts/`. Then tiddlers tagged [[task]] are stored in a subdirectory `tiddlers/mytasks/`. Next, all tiddlers tagged "externalnote" will be written to `<wikiFolder>/tiddlers/../externalnotes/`, which resolves to `<wikiFolder>/externalnotes/` and places these tiddlers outside of the tiddler folder. Use [[tiddlywiki.files Files|tiddlywiki.files_Files]] to reimport these tiddlers when the wiki server is restarted. Finally, all tidders will match the final `[addprefix[wiki/]]` storing these in `<wikiFolder>/tiddlers/wiki/`. -Thus, $:/config/FileSystemPaths itself will end up in `tiddlers/_system/config/FileSystemPaths.tid` or `tiddlers\_system\config\FileSystemPaths.tid`, depending on the platform. +Because there was a filter match, any `/` or `\` in the tiddler title is mapped to a path separator. With the above filters, the non-system, non-draft tiddler `some/thing/entirely/new` (with no tags) will be saved to `<wikiFolder>/tiddlers/wiki/some/thing/entirely/new.tid` (ie, the file `new.tid` in a directory called `entirely/`). Thus, $:/config/FileSystemPaths itself will end up in `tiddlers/_system/config/FileSystemPaths.tid` or `tiddlers\_system\config\FileSystemPaths.tid`, depending on the platform. -The final `[!has[draft.of]]` will match all remaining non-draft tiddlers. Because there was a match, any `/` or `\` in the tiddler title is mapped to a path separator. Thus, `some/thing/entirely/new` will be saved to `tiddlers/some/thing/entirely/new.tid` (ie, the file `new.tid` in a directory called `entirely`). +! File System Extensions + +Normally, the file system extension of a tiddler on disk is determined by the existance of bad fields (multi-line fields other than the text field, fields that can be trimmed of spaces from the fron or back, etc), in which case the single-file ".json" tiddler-file format is used. If the tiddler does not have bad fields, then the `type` field is referenced to find a matching file-type. Tiddlywiki's boot engine defines a set of these tiddler-type to file-type relationships in the [[$:/boot/boot.js]] tiddler. Search for `// Add file extension information` to find the section of code that defines these relationships. + +The file extension of individual tidders can be customised by creating a tiddler [[$:/config/FileSystemExtensions]] containing one or more [[filter expressions|Filter Syntax]], each on a line of its own. Newly created tiddlers are matched to each filter in turn, and the first output of the first filter to produce any output is taken as the file extension to be used for the tiddler file. Extensions should always start with a leading dot (see example). Tiddlers are also tested against the $:/config/FileSystemExtensions on every save to disk, and if the extension has changed a new file is created and the old file deleted. If no filter matches, the default extension is used. + +Two special cases should be noted: Result of ".tid" will force the tiddler to be written to disk as a single-file text tiddler. A result of ".json" will force the tiddler to be written to disk as a single-file tiddler in json-format (a single tiddler fields object in an array), NOT as a tiddler of type "application/json". All other recognized file-types will be saved using their defined extention along with an acompanying *.meta file of the same name which describes all fields but the "text" field. + +!! Example + +``` +[tag[.txt]then[.txt]] +[tag[.json]then[.json]] +[tag[.tid]then[.tid]] +``` + +This will cause all tidders that have the tag ".txt" in their tags field to be saved at the filepath determined by the File System Paths filters, but with their text field saved as a *.txt file, and all other fields saved as a *.txt.meta file. + +Next, all tiddlers that have the ".json" tag are saved as *.json single-file tiddlers. Finally, all tiddlers that have tag ".tid" are saved as single-file text tiddlers. If a tiddler matches none of the filters, the default extension determined by the tiddler's `type` field would be used. \ No newline at end of file diff --git a/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid b/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid index 59c9a679d..389643175 100644 --- a/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid +++ b/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid @@ -1,5 +1,5 @@ created: 20161015114118243 -modified: 20161015170604353 +modified: 20201201000000000 tags: TiddlyWikiFolders title: tiddlywiki.files Files type: text/vnd.tiddlywiki @@ -51,7 +51,7 @@ Directory specifications in the `directories` array may take the following forms ** ''path'' - (required) the absolute or relative path to the directory containing the tiddler files (relative paths are interpreted relative to the path of the `tiddlywiki.files` file). Note that the directory is not recursively searched; sub-directories are ignored ** ''filesRegExp'' - (optional) a [[regular expression|https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions]] that matches the filenames of the files that should be processed within the directory ** ''isTiddlerFile'' - (required) if `true`, the file will be treated as a [[tiddler file|TiddlerFiles]] and deserialised to extract the tiddlers. Otherwise, the raw content of the file is assigned to the `text` field without any parsing -** ''isEditableFile'' - (optional) if `true`, changes to the tiddler be saved back to the original file. <<.from-version "5.1.23">> +** ''isEditableFile'' - (optional) if `true`, changes to the tiddler be saved back to the original file. The ''path'' of the current directory being read must be within the wiki's base directory, and a $:/config/FileSystemPath filter is required to add the correct logical path to the tiddler's title (see second **Example**). <<.from-version "5.1.23">> ** ''fields'' - (required) an object containing values that override or customise the fields provided in the tiddler file (see above) Fields can be overridden for particular files by creating a file with the same name plus the suffix `.meta` -- see TiddlerFiles. @@ -64,7 +64,7 @@ There are also several examples of `tiddlywiki.files` files in the main [[Tiddly !! Importing a folder of PDFs -This example retrieves all the files with the extension `.pdf` from a folder specified by a relative path. Each tiddler is set up for LazyLoading with the following fields: +This example retrieves all the files with the extension `.pdf` from a folder specified by a relative path. This path starts with "../../../" indicating 3 directory levels above the folder holdng this confog fole. Each tiddler is set up for LazyLoading with the following fields: * ''title'' - set to the URI decoded base filename of the PDF file. [[URI decoding|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent]] allows characters like "/" to be included in titles by URI encoding them as "%2F" * ''created'' - set to the creation date/time of the PDF file @@ -94,3 +94,39 @@ This example retrieves all the files with the extension `.pdf` from a folder spe ] } ``` +!! Importing a folder of text files + +This example retrieves all the files with the extension `.txt` from a folder specified by a relative path. This folder is within the wiki's base directory, and the current config file is in a directory within the wiki's "tiddlers/" directory. So, in this case the path starts with "../../" to traverse upwards two directory levels, and then down into the "externalnotes/" directory. Each tiddler is set up with the following fields: + +* ''title'' - set to the URI decoded base filename of the text file. [[URI decoding|https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent]] allows characters like "/" to be included in titles by URI encoding them as "%2F" +* ''created'' - set to the creation date/time of the text file +* ''modified'' - set to the modification date/time of the text file +* ''type'' - set to `text/plain` +* ''tags'' - set to `[[note]] [[externalnote]]` (using array notation) +* ''text'' - not set, thus the content of the file is loaded as the text field + +``` +{ + "directories": [ + { + "path": "../../externalnotes", + "filesRegExp": ".+\\.txt", + "isTiddlerFile": false, + "isEditableFile": true, + "fields": { + "title": {"source": "basename-uri-decoded"}, + "created": {"source": "created"}, + "modified": {"source": "modified"}, + "type": "text/plain", + "tags": ["note", "externalnote", ".txt"] + } + } + ] +} +``` + +This will load all text files in the `<wikiBase>/externalnotes/` directory into the wiki as individual tiddlers. These can be a collection of snippets in various markup-languages. Then, the `type` field of each of these tiddlers can be changed to match their languages For example, "text/vnd.tiddlywiki" for wikitext, or "text/markdown" for markdown files. Then, using $:/config/FileSystemPaths and $:/config/FileSystemExtentions tiddlers with the following lines we can cause any changes to these tiddlers to be saved back to the directory they started from, and as "*.txt" files with accompanying "*.txt.meta" files. These meta files will then over-ride any fields generated from the config `tiddlywiki.files` file (such as the tiddler's `type` field) when the server is restarted. + +From the examples in [[Customising Tiddler File Naming]] we see that the `[tag[externalnote]addprefix[../externalnotes/]]` filter in the $:/config/FileSystemPaths tiddler catches all tiddlers tagged with `externalnotes` (that have not matched an earlier filter). These tiddlers have "../externalnotes/" appended to their titles to render the final logical path. As this path starts in the wiki's "tiddlers/" folder by default (one folder above the folder holding the above config file) it differes by one set of "../". + +Then, the `[tag[.txt]then[.txt]]` filter in the $:/config/FileSystemExtensions tiddler forces all these text files (which start with tag ".txt") to be saved back to disk as *.txt and accompanying *.txt.meta files (overriding the normal tiddler-type to file-type mapping). In this case, allowing the snippets of Tiddlywiki wikitext or markdown-text to be saved back to "text" *.txt files. \ No newline at end of file From 880930da8bced8f4c161cfd31f5f3324aaabacac Mon Sep 17 00:00:00 2001 From: Mario Pietsch <pmariojo@gmail.com> Date: Tue, 1 Dec 2020 19:11:09 +0100 Subject: [PATCH 100/124] Add actions parameter to range-widget + docs! (#5158) * add actionsStart, -Stop and actions to range-widgets * fix indent --- core/modules/widgets/range.js | 84 ++++++++++++++++--- .../tiddlers/widgets/RangeWidget Example.tid | 54 ++++++++++++ .../tw5.com/tiddlers/widgets/RangeWidget.tid | 7 +- 3 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 editions/tw5.com/tiddlers/widgets/RangeWidget Example.tid diff --git a/core/modules/widgets/range.js b/core/modules/widgets/range.js index 46e12061a..4dd55dc3c 100644 --- a/core/modules/widgets/range.js +++ b/core/modules/widgets/range.js @@ -52,8 +52,10 @@ RangeWidget.prototype.render = function(parent,nextSibling) { this.inputDomNode.value = this.getValue(); // Add a click event handler $tw.utils.addEventListeners(this.inputDomNode,[ - {name: "input", handlerObject: this, handlerMethod: "handleInputEvent"}, - {name: "change", handlerObject: this, handlerMethod: "handleInputEvent"} + {name:"mousedown", handlerObject:this, handlerMethod:"handleMouseDownEvent"}, + {name:"mouseup", handlerObject:this, handlerMethod:"handleMouseUpEvent"}, + {name:"change", handlerObject:this, handlerMethod:"handleChangeEvent"}, + {name:"input", handlerObject:this, handlerMethod:"handleInputEvent"}, ]); // Insert the label into the DOM and render any children parent.insertBefore(this.inputDomNode,nextSibling); @@ -62,23 +64,77 @@ RangeWidget.prototype.render = function(parent,nextSibling) { RangeWidget.prototype.getValue = function() { var tiddler = this.wiki.getTiddler(this.tiddlerTitle), - fieldName = this.tiddlerField || "text", - value = this.defaultValue; + fieldName = this.tiddlerField, + value = this.defaultValue; if(tiddler) { if(this.tiddlerIndex) { - value = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue || ""); + value = this.wiki.extractTiddlerDataItem(tiddler,this.tiddlerIndex,this.defaultValue); } else { if($tw.utils.hop(tiddler.fields,fieldName)) { value = tiddler.fields[fieldName] || ""; } else { - value = this.defaultValue || ""; + value = this.defaultValue; } } } return value; }; +RangeWidget.prototype.getActionVariables = function(options) { + options = options || {}; + var hasChanged = (this.startValue !== this.inputDomNode.value) ? "yes" : "no"; + // Trigger actions. Use variables = {key:value, key:value ...} + // the "value" is needed. + return $tw.utils.extend({"actionValue": this.inputDomNode.value, "actionValueHasChanged": hasChanged}, options); +} + +// actionsStart +RangeWidget.prototype.handleMouseDownEvent = function(event) { + this.mouseDown = true; // TODO remove once IE is gone. + this.startValue = this.inputDomNode.value; // TODO remove this line once IE is gone! + this.handleEvent(event); + // Trigger actions + if(this.actionsMouseDown) { + var variables = this.getActionVariables() // TODO this line will go into the function call below. + this.invokeActionString(this.actionsMouseDown,this,event,variables); + } +} + +// actionsStop +RangeWidget.prototype.handleMouseUpEvent = function(event) { + this.mouseDown = false; // TODO remove once IE is gone. + this.handleEvent(event); + // Trigger actions + if(this.actionsMouseUp) { + var variables = this.getActionVariables() + this.invokeActionString(this.actionsMouseUp,this,event,variables); + } + // TODO remove the following if() once IE is gone! + if ($tw.browser.isIE) { + if (this.startValue !== this.inputDomNode.value) { + this.handleChangeEvent(event); + this.startValue = this.inputDomNode.value; + } + } +} + +RangeWidget.prototype.handleChangeEvent = function(event) { + if (this.mouseDown) { // TODO refactor this function once IE is gone. + this.handleInputEvent(event); + } +}; + RangeWidget.prototype.handleInputEvent = function(event) { + this.handleEvent(event); + // Trigger actions + if(this.actionsInput) { + // "tiddler" parameter may be missing. See .execute() below + var variables = this.getActionVariables({"actionValueHasChanged": "yes"}) // TODO this line will go into the function call below. + this.invokeActionString(this.actionsInput,this,event,variables); + } +}; + +RangeWidget.prototype.handleEvent = function(event) { if(this.getValue() !== this.inputDomNode.value) { if(this.tiddlerIndex) { this.wiki.setText(this.tiddlerTitle,"",this.tiddlerIndex,this.inputDomNode.value); @@ -92,16 +148,24 @@ RangeWidget.prototype.handleInputEvent = function(event) { Compute the internal state of the widget */ RangeWidget.prototype.execute = function() { + // TODO remove the next 1 lines once IE is gone! + this.mouseUp = true; // Needed for IE10 // Get the parameters from the attributes this.tiddlerTitle = this.getAttribute("tiddler",this.getVariable("currentTiddler")); - this.tiddlerField = this.getAttribute("field"); + this.tiddlerField = this.getAttribute("field","text"); this.tiddlerIndex = this.getAttribute("index"); this.minValue = this.getAttribute("min"); this.maxValue = this.getAttribute("max"); this.increment = this.getAttribute("increment"); - this.defaultValue = this.getAttribute("default"); + this.defaultValue = this.getAttribute("default",""); this.elementClass = this.getAttribute("class",""); this.isDisabled = this.getAttribute("disabled","no"); + // Actions since 5.1.23 + // Next 2 only fire once! + this.actionsMouseDown = this.getAttribute("actionsStart",""); + this.actionsMouseUp = this.getAttribute("actionsStop",""); + // Input fires very often! + this.actionsInput = this.getAttribute("actions",""); // Make the child widgets this.makeChildWidgets(); }; @@ -111,7 +175,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ RangeWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.tiddler || changedAttributes.field || changedAttributes.index || changedAttributes['min'] || changedAttributes['max'] || changedAttributes['increment'] || changedAttributes["default"] || changedAttributes["class"] || changedAttributes.disabled) { + if($tw.utils.count(changedAttributes) > 0) { this.refreshSelf(); return true; } else { @@ -119,7 +183,7 @@ RangeWidget.prototype.refresh = function(changedTiddlers) { if(changedTiddlers[this.tiddlerTitle]) { var value = this.getValue(); if(this.inputDomNode.value !== value) { - this.inputDomNode.value = value; + this.inputDomNode.value = value; } refreshed = true; } diff --git a/editions/tw5.com/tiddlers/widgets/RangeWidget Example.tid b/editions/tw5.com/tiddlers/widgets/RangeWidget Example.tid new file mode 100644 index 000000000..822313374 --- /dev/null +++ b/editions/tw5.com/tiddlers/widgets/RangeWidget Example.tid @@ -0,0 +1,54 @@ +created: 20201130191618831 +modified: 20201130194441670 +tags: RangeWidget +title: RangeWidget Example +type: text/vnd.tiddlywiki + +\define getText() $(text)$ - value: $(value)$ - changed: $(actionValueHasChanged)$ + +\define range-log(text:"", value:"", tiddler:"$:/temp/range/log") +<$vars text="""$text$""" value="""$value$""" > +<$action-setfield $tiddler="""$tiddler$""" $index=<<now "0hh-0mm-0ss:0XXX">> $value=<<getText>>/> +</$vars> +\end + +\define clear-range-log(tiddler:"$:/temp/range/log") +<$action-setfield $tiddler="""$tiddler$""" text="{}" show=show/> +\end + +\define logTiddler()$:/temp/range/log + +\define clearLogButton()<$button actions=<<clear-range-log>>>Clear Log</$button> + +\define actionsStop() +<$macrocall $name="range-log" text=" actionsStop" value=<<actionValue>> /> +\end + +\define actionsStart() +<$macrocall $name="range-log" text=" actionsStart" value=<<actionValue>> /> +\end + +\define actions() +<$macrocall $name="range-log" text="actions" value=<<actionValue>> /> +\end + +!! Using Actions + +<$range tiddler="$:/temp/range/1__" min="-1" max="10" default="1" increment="1" + actionsStart=<<actionsStart>> actionsStop=<<actionsStop>> actions=<<actions>>/> {{$:/temp/range/1__}} + +<$range tiddler="$:/temp/range/__2" min="0" max="1" default=".01" increment=".01" + actionsStart=<<actionsStart>> actionsStop=<<actionsStop>> actions=<<actions>> /> {{$:/temp/range/__2}} + +<$checkbox tiddler=<<logTiddler>> field="show" checked="show" unchecked="hide"> Show log</$checkbox> <<clearLogButton>> + +<$reveal stateTitle=<<logTiddler>> stateField="show" type="match" text="show"> +<$transclude tiddler=<<logTiddler>> /> +</$reveal> + +--- + +<details> + <summary>Show the code [[RangeWidget Example]]</summary> + <pre><code><$view mode=text&><pre><code> +</details> diff --git a/editions/tw5.com/tiddlers/widgets/RangeWidget.tid b/editions/tw5.com/tiddlers/widgets/RangeWidget.tid index bcabe646c..195b32fec 100644 --- a/editions/tw5.com/tiddlers/widgets/RangeWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/RangeWidget.tid @@ -1,6 +1,6 @@ caption: range created: 20171102134825376 -modified: 20201109091723430 +modified: 20201130193635857 tags: Widgets title: RangeWidget type: text/vnd.tiddlywiki @@ -22,6 +22,9 @@ The content of the `<$range>` widget is ignored. |increment |The minimum amount by which a value may be changed. Defaults to 1 | |default |If the field is missing or empty this is the default position for the widget handle relative to the min and max values.| |class |CSS classes to be assigned to the label around the range slider | +|actions|<<.from-version "5.1.23">> Optional, A string containing ActionWidgets to be triggered when the value changes. <br>The variable: ''actionValue'' is available for ''all'' actions.<br>The variable: ''actionValueHasChanged'' is always `yes` here.| +|actionsStart|<<.from-version "5.1.23">> Optional, A string containing ~ActionWidgets to be triggered when the "handle" is ''clicked''. <br>The variable: ''actionValueHasChanged'' is always `no` here.| +|actionsStop|<<.from-version "5.1.23">> Optional, A string containing ~ActionWidgets to be triggered when the "handle" is ''released''. <br>The variable: ''actionValueHasChanged'' is `yes`, ''if'' the new-value is different to the start-value | |disabled|<<.from-version "5.1.23">> Optional, disables the range input if set to "yes". Defaults to "no"| ! Examples @@ -36,3 +39,5 @@ src="""<$range tiddler="$:/_RangeDemo/1" min="-1" max="10" default="1" increment <$macrocall $name='wikitext-example-without-html' src="""<$range tiddler="$:/_RangeDemo/2" min="0" max="1" default=".01" increment=".01"/> {{$:/_RangeDemo/2}}"""/> + +{{RangeWidget Example}} \ No newline at end of file From cc1f32067f78a6b3360db979c43510c3ed733677 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Tue, 1 Dec 2020 19:11:40 +0100 Subject: [PATCH 101/124] Update CodeMirror to 5.58.3 - fix vim-mode cursor invisible (#5172) * Update codemirror to v5.58.3 * Update jump-to-line.js * Update search.js --- .../files/addon/search/jump-to-line.js | 2 +- .../codemirror-search-replace/files/addon/search/search.js | 2 +- plugins/tiddlywiki/codemirror/files/codemirror.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/jump-to-line.js b/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/jump-to-line.js index c4285a645..05172fa03 100644 --- a/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/jump-to-line.js +++ b/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/jump-to-line.js @@ -1,3 +1,3 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/LICENSE -!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror"),require("../dialog/dialog")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../dialog/dialog"],e):e(CodeMirror)}(function(e){"use strict";function u(e,o){var r=Number(o);return/^[-+]/.test(o)?e.getCursor().line+r:r-1}e.commands.jumpToLine=function(t){var e,o,r,s,i,n,l=t.getCursor();o=(n=e=t).phrase("Jump to line:")+' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">'+n.phrase("(Use line:column or scroll% syntax)")+"</span>",r=t.phrase("Jump to line:"),s=l.line+1+":"+l.ch,i=function(e){var o,r;e&&((o=/^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(e))?t.setCursor(u(t,o[1]),Number(o[2])):(o=/^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(e))?(r=Math.round(t.lineCount()*Number(o[1])/100),/^[-+]/.test(o[1])&&(r=l.line+r+1),t.setCursor(r-1,l.ch)):(o=/^\s*\:?\s*([\+\-]?\d+)\s*/.exec(e))&&t.setCursor(u(t,o[1]),l.ch))},e.openDialog?e.openDialog(o,i,{value:s,selectValueOnOpen:!0}):i(prompt(r,s))},e.keyMap.default["Alt-G"]="jumpToLine"}); +!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror"),require("../dialog/dialog")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","../dialog/dialog"],e):e(CodeMirror)}(function(e){"use strict";function u(e,o){var r=Number(o);return/^[-+]/.test(o)?e.getCursor().line+r:r-1}e.defineOption("search",{bottom:!1}),e.commands.jumpToLine=function(t){var e,o,r,s,i,n,l=t.getCursor();o=(n=e=t).phrase("Jump to line:")+' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">'+n.phrase("(Use line:column or scroll% syntax)")+"</span>",r=t.phrase("Jump to line:"),s=l.line+1+":"+l.ch,i=function(e){var o,r;e&&((o=/^\s*([\+\-]?\d+)\s*\:\s*(\d+)\s*$/.exec(e))?t.setCursor(u(t,o[1]),Number(o[2])):(o=/^\s*([\+\-]?\d+(\.\d+)?)\%\s*/.exec(e))?(r=Math.round(t.lineCount()*Number(o[1])/100),/^[-+]/.test(o[1])&&(r=l.line+r+1),t.setCursor(r-1,l.ch)):(o=/^\s*\:?\s*([\+\-]?\d+)\s*/.exec(e))&&t.setCursor(u(t,o[1]),l.ch))},e.openDialog?e.openDialog(o,i,{value:s,selectValueOnOpen:!0,bottom:e.options.search.bottom}):i(prompt(r,s))},e.keyMap.default["Alt-G"]="jumpToLine"}); diff --git a/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/search.js b/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/search.js index 7efd7994a..134d0f307 100644 --- a/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/search.js +++ b/plugins/tiddlywiki/codemirror-search-replace/files/addon/search/search.js @@ -1,3 +1,3 @@ // CodeMirror, copyright (c) by Marijn Haverbeke and others // Distributed under an MIT license: https://codemirror.net/LICENSE -!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror"),require("./searchcursor"),require("../dialog/dialog")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./searchcursor","../dialog/dialog"],e):e(CodeMirror)}(function(d){"use strict";function n(){this.posFrom=this.posTo=this.lastQuery=this.query=null,this.overlay=null}function y(e){return e.state.search||(e.state.search=new n)}function a(e){return"string"==typeof e&&e==e.toLowerCase()}function m(e,n,o){return e.getSearchCursor(n,o,{caseFold:a(n),multiline:!0})}function h(e,n,o,r,t){e.openDialog?e.openDialog(n,t,{value:r,selectValueOnOpen:!0}):t(prompt(o,r))}function r(e){return e.replace(/\\([nrt\\])/g,function(e,n){return"n"==n?"\n":"r"==n?"\r":"t"==n?"\t":"\\"==n?"\\":e})}function s(e){var n=e.match(/^\/(.*)\/([a-z]*)$/);if(n)try{e=new RegExp(n[1],-1==n[2].indexOf("i")?"":"i")}catch(e){}else e=r(e);return("string"==typeof e?""==e:e.test(""))&&(e=/x^/),e}function g(e,n,o){var r,t;n.queryText=o,n.query=s(o),e.removeOverlay(n.overlay,a(n.query)),n.overlay=(r=n.query,t=a(n.query),"string"==typeof r?r=new RegExp(r.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),t?"gi":"g"):r.global||(r=new RegExp(r.source,r.ignoreCase?"gi":"g")),{token:function(e){r.lastIndex=e.pos;var n=r.exec(e.string);if(n&&n.index==e.pos)return e.pos+=n[0].length||1,"searching";n?e.pos=n.index:e.skipToEnd()}}),e.addOverlay(n.overlay),e.showMatchesOnScrollbar&&(n.annotate&&(n.annotate.clear(),n.annotate=null),n.annotate=e.showMatchesOnScrollbar(n.query,a(n.query)))}function o(a,n,e,o){var r=y(a);if(r.query)return x(a,n);var t,s,i,c,l,u,p,f=a.getSelection()||r.lastQuery;f instanceof RegExp&&"x^"==f.source&&(f=null),e&&a.openDialog?(t=null,s=function(e,n){d.e_stop(n),e&&(e!=r.queryText&&(g(a,r,e),r.posFrom=r.posTo=a.getCursor()),t&&(t.style.opacity=1),x(a,n.shiftKey,function(e,n){var o;n.line<3&&document.querySelector&&(o=a.display.wrapper.querySelector(".CodeMirror-dialog"))&&o.getBoundingClientRect().bottom-4>a.cursorCoords(n,"window").top&&((t=o).style.opacity=.4)}))},c=C(i=a),l=f,u=s,p=function(e,n){var o=d.keyName(e),r=a.getOption("extraKeys"),t=r&&r[o]||d.keyMap[a.getOption("keyMap")][o];"findNext"==t||"findPrev"==t||"findPersistentNext"==t||"findPersistentPrev"==t?(d.e_stop(e),g(a,y(a),n),a.execCommand(t)):"find"!=t&&"findPersistent"!=t||(d.e_stop(e),s(n,e))},i.openDialog(c,u,{value:l,selectValueOnOpen:!0,closeOnEnter:!1,onClose:function(){v(i)},onKeyDown:p}),o&&f&&(g(a,r,f),x(a,n))):h(a,C(a),"Search for:",f,function(e){e&&!r.query&&a.operation(function(){g(a,r,e),r.posFrom=r.posTo=a.getCursor(),x(a,n)})})}function x(o,r,t){o.operation(function(){var e=y(o),n=m(o,e.query,r?e.posFrom:e.posTo);(n.find(r)||(n=m(o,e.query,r?d.Pos(o.lastLine()):d.Pos(o.firstLine(),0))).find(r))&&(o.setSelection(n.from(),n.to()),o.scrollIntoView({from:n.from(),to:n.to()},20),e.posFrom=n.from(),e.posTo=n.to(),t&&t(n.from(),n.to()))})}function v(n){n.operation(function(){var e=y(n);e.lastQuery=e.query,e.query&&(e.query=e.queryText=null,n.removeOverlay(e.overlay),e.annotate&&(e.annotate.clear(),e.annotate=null))})}function C(e){return'<span class="CodeMirror-search-label">'+e.phrase("Search:")+'</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">'+e.phrase("(Use /re/ syntax for regexp search)")+"</span>"}function q(n,r,t){n.operation(function(){for(var o,e=m(n,r);e.findNext();){"string"!=typeof r?(o=n.getRange(e.from(),e.to()).match(r),e.replace(t.replace(/\$(\d)/g,function(e,n){return o[n]}))):e.replace(t)}})}function t(f,e){var n,o;f.getOption("readOnly")||(n=f.getSelection()||y(f).lastQuery,o='<span class="CodeMirror-search-label">'+(e?f.phrase("Replace all:"):f.phrase("Replace:"))+"</span>",h(f,o+(' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">'+f.phrase("(Use /re/ syntax for regexp search)")+"</span>"),o,n,function(p){p&&(p=s(p),h(f,'<span class="CodeMirror-search-label">'+f.phrase("With:")+'</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>',f.phrase("Replace with:"),"",function(i){var c,l,u;i=r(i),e?q(f,p,i):(v(f),c=m(f,p,f.getCursor("from")),l=function(){var e,n,o,r,t,a,s=c.from();!(e=c.findNext())&&(c=m(f,p),!(e=c.findNext())||s&&c.from().line==s.line&&c.from().ch==s.ch)||(f.setSelection(c.from(),c.to()),f.scrollIntoView({from:c.from(),to:c.to()}),o='<span class="CodeMirror-search-label">'+(a=n=f).phrase("Replace?")+"</span> <button>"+a.phrase("Yes")+"</button> <button>"+a.phrase("No")+"</button> <button>"+a.phrase("All")+"</button> <button>"+a.phrase("Stop")+"</button> ",r=f.phrase("Replace?"),t=[function(){u(e)},l,function(){q(f,p,i)}],n.openConfirm?n.openConfirm(o,t):confirm(r)&&t[0]())},u=function(o){c.replace("string"==typeof p?i:i.replace(/\$(\d)/g,function(e,n){return o[n]})),l()},l())}))}))}d.commands.find=function(e){v(e),o(e)},d.commands.findPersistent=function(e){v(e),o(e,!1,!0)},d.commands.findPersistentNext=function(e){o(e,!1,!0,!0)},d.commands.findPersistentPrev=function(e){o(e,!0,!0,!0)},d.commands.findNext=o,d.commands.findPrev=function(e){o(e,!0)},d.commands.clearSearch=v,d.commands.replace=t,d.commands.replaceAll=function(e){t(e,!0)}}); +!function(e){"object"==typeof exports&&"object"==typeof module?e(require("../../lib/codemirror"),require("./searchcursor"),require("../dialog/dialog")):"function"==typeof define&&define.amd?define(["../../lib/codemirror","./searchcursor","../dialog/dialog"],e):e(CodeMirror)}(function(d){"use strict";function o(){this.posFrom=this.posTo=this.lastQuery=this.query=null,this.overlay=null}function m(e){return e.state.search||(e.state.search=new o)}function a(e){return"string"==typeof e&&e==e.toLowerCase()}function y(e,o,n){return e.getSearchCursor(o,n,{caseFold:a(o),multiline:!0})}function h(e,o,n,r,t){e.openDialog?e.openDialog(o,t,{value:r,selectValueOnOpen:!0,bottom:e.options.search.bottom}):t(prompt(n,r))}function r(e){return e.replace(/\\([nrt\\])/g,function(e,o){return"n"==o?"\n":"r"==o?"\r":"t"==o?"\t":"\\"==o?"\\":e})}function s(e){var o=e.match(/^\/(.*)\/([a-z]*)$/);if(o)try{e=new RegExp(o[1],-1==o[2].indexOf("i")?"":"i")}catch(e){}else e=r(e);return("string"==typeof e?""==e:e.test(""))&&(e=/x^/),e}function g(e,o,n){var r,t;o.queryText=n,o.query=s(n),e.removeOverlay(o.overlay,a(o.query)),o.overlay=(r=o.query,t=a(o.query),"string"==typeof r?r=new RegExp(r.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&"),t?"gi":"g"):r.global||(r=new RegExp(r.source,r.ignoreCase?"gi":"g")),{token:function(e){r.lastIndex=e.pos;var o=r.exec(e.string);if(o&&o.index==e.pos)return e.pos+=o[0].length||1,"searching";o?e.pos=o.index:e.skipToEnd()}}),e.addOverlay(o.overlay),e.showMatchesOnScrollbar&&(o.annotate&&(o.annotate.clear(),o.annotate=null),o.annotate=e.showMatchesOnScrollbar(o.query,a(o.query)))}function n(a,o,e,n){var r=m(a);if(r.query)return x(a,o);var t,s,i,c,l,u,p,f=a.getSelection()||r.lastQuery;f instanceof RegExp&&"x^"==f.source&&(f=null),e&&a.openDialog?(t=null,s=function(e,o){d.e_stop(o),e&&(e!=r.queryText&&(g(a,r,e),r.posFrom=r.posTo=a.getCursor()),t&&(t.style.opacity=1),x(a,o.shiftKey,function(e,o){var n;o.line<3&&document.querySelector&&(n=a.display.wrapper.querySelector(".CodeMirror-dialog"))&&n.getBoundingClientRect().bottom-4>a.cursorCoords(o,"window").top&&((t=n).style.opacity=.4)}))},c=b(i=a),l=f,u=s,p=function(e,o){var n=d.keyName(e),r=a.getOption("extraKeys"),t=r&&r[n]||d.keyMap[a.getOption("keyMap")][n];"findNext"==t||"findPrev"==t||"findPersistentNext"==t||"findPersistentPrev"==t?(d.e_stop(e),g(a,m(a),o),a.execCommand(t)):"find"!=t&&"findPersistent"!=t||(d.e_stop(e),s(o,e))},i.openDialog(c,u,{value:l,selectValueOnOpen:!0,closeOnEnter:!1,onClose:function(){v(i)},onKeyDown:p,bottom:i.options.search.bottom}),n&&f&&(g(a,r,f),x(a,o))):h(a,b(a),"Search for:",f,function(e){e&&!r.query&&a.operation(function(){g(a,r,e),r.posFrom=r.posTo=a.getCursor(),x(a,o)})})}function x(n,r,t){n.operation(function(){var e=m(n),o=y(n,e.query,r?e.posFrom:e.posTo);(o.find(r)||(o=y(n,e.query,r?d.Pos(n.lastLine()):d.Pos(n.firstLine(),0))).find(r))&&(n.setSelection(o.from(),o.to()),n.scrollIntoView({from:o.from(),to:o.to()},20),e.posFrom=o.from(),e.posTo=o.to(),t&&t(o.from(),o.to()))})}function v(o){o.operation(function(){var e=m(o);e.lastQuery=e.query,e.query&&(e.query=e.queryText=null,o.removeOverlay(e.overlay),e.annotate&&(e.annotate.clear(),e.annotate=null))})}function b(e){return'<span class="CodeMirror-search-label">'+e.phrase("Search:")+'</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">'+e.phrase("(Use /re/ syntax for regexp search)")+"</span>"}function C(o,r,t){o.operation(function(){for(var n,e=y(o,r);e.findNext();){"string"!=typeof r?(n=o.getRange(e.from(),e.to()).match(r),e.replace(t.replace(/\$(\d)/g,function(e,o){return n[o]}))):e.replace(t)}})}function t(f,e){var o,n;f.getOption("readOnly")||(o=f.getSelection()||m(f).lastQuery,n='<span class="CodeMirror-search-label">'+(e?f.phrase("Replace all:"):f.phrase("Replace:"))+"</span>",h(f,n+(' <input type="text" style="width: 10em" class="CodeMirror-search-field"/> <span style="color: #888" class="CodeMirror-search-hint">'+f.phrase("(Use /re/ syntax for regexp search)")+"</span>"),n,o,function(p){p&&(p=s(p),h(f,'<span class="CodeMirror-search-label">'+f.phrase("With:")+'</span> <input type="text" style="width: 10em" class="CodeMirror-search-field"/>',f.phrase("Replace with:"),"",function(i){var c,l,u;i=r(i),e?C(f,p,i):(v(f),c=y(f,p,f.getCursor("from")),l=function(){var e,o,n,r,t,a,s=c.from();!(e=c.findNext())&&(c=y(f,p),!(e=c.findNext())||s&&c.from().line==s.line&&c.from().ch==s.ch)||(f.setSelection(c.from(),c.to()),f.scrollIntoView({from:c.from(),to:c.to()}),n='<span class="CodeMirror-search-label">'+(a=o=f).phrase("Replace?")+"</span> <button>"+a.phrase("Yes")+"</button> <button>"+a.phrase("No")+"</button> <button>"+a.phrase("All")+"</button> <button>"+a.phrase("Stop")+"</button> ",r=f.phrase("Replace?"),t=[function(){u(e)},l,function(){C(f,p,i)}],o.openConfirm?o.openConfirm(n,t):confirm(r)&&t[0]())},u=function(n){c.replace("string"==typeof p?i:i.replace(/\$(\d)/g,function(e,o){return n[o]})),l()},l())}))}))}d.defineOption("search",{bottom:!1}),d.commands.find=function(e){v(e),n(e)},d.commands.findPersistent=function(e){v(e),n(e,!1,!0)},d.commands.findPersistentNext=function(e){n(e,!1,!0,!0)},d.commands.findPersistentPrev=function(e){n(e,!0,!0,!0)},d.commands.findNext=n,d.commands.findPrev=function(e){n(e,!0)},d.commands.clearSearch=v,d.commands.replace=t,d.commands.replaceAll=function(e){t(e,!0)}}); diff --git a/plugins/tiddlywiki/codemirror/files/codemirror.js b/plugins/tiddlywiki/codemirror/files/codemirror.js index 231e8a0da..0c80808ae 100755 --- a/plugins/tiddlywiki/codemirror/files/codemirror.js +++ b/plugins/tiddlywiki/codemirror/files/codemirror.js @@ -1 +1 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,g=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),r=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),i=/Edge\/(\d+)/.exec(e),x=n||r||i,C=x&&(n?document.documentMode||6:+(i||r)[1]),v=!i&&/WebKit\//.test(e),o=v&&/Qt\/\d+\.\d+/.test(e),l=!i&&/Chrome\//.test(e),m=/Opera\//.test(e),c=/Apple Computer/.test(navigator.vendor),s=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),u=/PhantomJS/.test(e),a=!i&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),h=/Android/.test(e),d=a||h||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=a||/Mac/.test(t),f=/\bCrOS\b/.test(e),p=/win/i.test(t),b=m&&e.match(/Version\/(\d*\.\d*)/);(b=b&&Number(b[1]))&&15<=b&&(v=!(m=!1));var w=y&&(o||m&&(null==b||b<12.11)),S=g||x&&9<=C;function L(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var k,T=function(e,t){var n,r=e.className,i=L(t).exec(r);i&&(n=r.slice(i.index+i[0].length),e.className=r.slice(0,i.index)+(n?i[1]+n:""))};function M(e){for(var t=e.childNodes.length;0<t;--t)e.removeChild(e.firstChild);return e}function N(e,t){return M(e).appendChild(t)}function O(e,t,n,r){var i=document.createElement(e);if(n&&(i.className=n),r&&(i.style.cssText=r),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function A(e,t,n,r){var i=O(e,t,n,r);return i.setAttribute("role","presentation"),i}function D(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do{if(11==t.nodeType&&(t=t.host),t==e)return!0}while(t=t.parentNode)}function W(){var t;try{t=document.activeElement}catch(e){t=document.body||null}for(;t&&t.shadowRoot&&t.shadowRoot.activeElement;)t=t.shadowRoot.activeElement;return t}function H(e,t){var n=e.className;L(t).test(n)||(e.className+=(n?" ":"")+t)}function F(e,t){for(var n=e.split(" "),r=0;r<n.length;r++)n[r]&&!L(n[r]).test(t)&&(t+=" "+n[r]);return t}k=document.createRange?function(e,t,n,r){var i=document.createRange();return i.setEnd(r||e,n),i.setStart(e,t),i}:function(e,t,n){var r=document.body.createTextRange();try{r.moveToElementText(e.parentNode)}catch(e){return r}return r.collapse(!0),r.moveEnd("character",n),r.moveStart("character",t),r};var P=function(e){e.select()};function E(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function I(e,t,n){for(var r in t=t||{},e)!e.hasOwnProperty(r)||!1===n&&t.hasOwnProperty(r)||(t[r]=e[r]);return t}function R(e,t,n,r,i){null==t&&-1==(t=e.search(/[^\s\u00a0]/))&&(t=e.length);for(var o=r||0,l=i||0;;){var s=e.indexOf("\t",o);if(s<0||t<=s)return l+(t-o);l+=s-o,l+=n-l%n,o=s+1}}a?P=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:x&&(P=function(e){try{e.select()}catch(e){}});var z=function(){this.id=null,this.f=null,this.time=0,this.handler=E(this.onTimeout,this)};function B(e,t){for(var n=0;n<e.length;++n)if(e[n]==t)return n;return-1}z.prototype.onTimeout=function(e){e.id=0,e.time<=+new Date?e.f():setTimeout(e.handler,e.time-new Date)},z.prototype.set=function(e,t){this.f=t;var n=+new Date+e;(!this.id||n<this.time)&&(clearTimeout(this.id),this.id=setTimeout(this.handler,e),this.time=n)};var G=50,U={toString:function(){return"CodeMirror.Pass"}},V={scroll:!1},K={origin:"*mouse"},j={origin:"+move"};function X(e,t,n){for(var r=0,i=0;;){var o=e.indexOf("\t",r);-1==o&&(o=e.length);var l=o-r;if(o==e.length||t<=i+l)return r+Math.min(l,t-i);if(i+=o-r,r=o+1,t<=(i+=n-i%n))return r}}var Y=[""];function _(e){for(;Y.length<=e;)Y.push($(Y)+" ");return Y[e]}function $(e){return e[e.length-1]}function q(e,t){for(var n=[],r=0;r<e.length;r++)n[r]=t(e[r],r);return n}function Z(){}function Q(e,t){var n=Object.create?Object.create(e):(Z.prototype=e,new Z);return t&&I(t,n),n}var J=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function ee(e){return/\w/.test(e)||"€"<e&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(-1<t.source.indexOf("\\w")&&ee(e))||t.test(e):ee(e)}function ne(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return;return 1}var re=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return 768<=e.charCodeAt(0)&&re.test(e)}function oe(e,t,n){for(;(n<0?0<t:t<e.length)&&ie(e.charAt(t));)t+=n;return t}function le(e,t,n){for(var r=n<t?-1:1;;){if(t==n)return t;var i=(t+n)/2,o=r<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:n;e(o)?n=o:t=o+r}}var se=null;function ae(e,t,n){var r;se=null;for(var i=0;i<e.length;++i){var o=e[i];if(o.from<t&&o.to>t)return i;o.to==t&&(o.from!=o.to&&"before"==n?r=i:se=i),o.from==t&&(o.from!=o.to&&"before"!=n?r=i:se=i)}return null!=r?r:se}var ue,ce,he,de,fe,pe,ge,me=(ue="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",ce="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111",he=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,de=/[stwN]/,fe=/[LRr]/,pe=/[Lb1n]/,ge=/[1n]/,function(e,t){var n="ltr"==t?"L":"R";if(0==e.length||"ltr"==t&&!he.test(e))return!1;for(var r,i=e.length,o=[],l=0;l<i;++l)o.push((r=e.charCodeAt(l))<=247?ue.charAt(r):1424<=r&&r<=1524?"R":1536<=r&&r<=1785?ce.charAt(r-1536):1774<=r&&r<=2220?"r":8192<=r&&r<=8203?"w":8204==r?"b":"L");for(var s=0,a=n;s<i;++s){var u=o[s];"m"==u?o[s]=a:a=u}for(var c=0,h=n;c<i;++c){var d=o[c];"1"==d&&"r"==h?o[c]="n":fe.test(d)&&"r"==(h=d)&&(o[c]="R")}for(var f=1,p=o[0];f<i-1;++f){var g=o[f];"+"==g&&"1"==p&&"1"==o[f+1]?o[f]="1":","!=g||p!=o[f+1]||"1"!=p&&"n"!=p||(o[f]=p),p=g}for(var m=0;m<i;++m){var v=o[m];if(","==v)o[m]="N";else if("%"==v){for(var y=void 0,y=m+1;y<i&&"%"==o[y];++y);for(var b=m&&"!"==o[m-1]||y<i&&"1"==o[y]?"1":"N",w=m;w<y;++w)o[w]=b;m=y-1}}for(var x=0,C=n;x<i;++x){var S=o[x];"L"==C&&"1"==S?o[x]="L":fe.test(S)&&(C=S)}for(var L=0;L<i;++L)if(de.test(o[L])){for(var k=void 0,k=L+1;k<i&&de.test(o[k]);++k);for(var T="L"==(L?o[L-1]:n),M=T==("L"==(k<i?o[k]:n))?T?"L":"R":n,N=L;N<k;++N)o[N]=M;L=k-1}for(var A,O=[],D=0;D<i;)if(pe.test(o[D])){var W=D;for(++D;D<i&&pe.test(o[D]);++D);O.push(new ve(0,W,D))}else{var H=D,F=O.length,P="rtl"==t?1:0;for(++D;D<i&&"L"!=o[D];++D);for(var E=H;E<D;)if(ge.test(o[E])){H<E&&(O.splice(F,0,new ve(1,H,E)),F+=P);var I=E;for(++E;E<D&&ge.test(o[E]);++E);O.splice(F,0,new ve(2,I,E)),F+=P,H=E}else++E;H<D&&O.splice(F,0,new ve(1,H,D))}return"ltr"==t&&(1==O[0].level&&(A=e.match(/^\s+/))&&(O[0].from=A[0].length,O.unshift(new ve(0,0,A[0].length))),1==$(O).level&&(A=e.match(/\s+$/))&&($(O).to-=A[0].length,O.push(new ve(0,i-A[0].length,i)))),"rtl"==t?O.reverse():O});function ve(e,t,n){this.level=e,this.from=t,this.to=n}function ye(e,t){var n=e.order;return null==n&&(n=e.order=me(e.text,t)),n}var be=[],we=function(e,t,n){var r;e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):(r=e._handlers||(e._handlers={}))[t]=(r[t]||be).concat(n)};function xe(e,t){return e._handlers&&e._handlers[t]||be}function Ce(e,t,n){var r,i,o;e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):!(i=(r=e._handlers)&&r[t])||-1<(o=B(i,n))&&(r[t]=i.slice(0,o).concat(i.slice(o+1)))}function Se(e,t){var n=xe(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),i=0;i<n.length;++i)n[i].apply(null,r)}function Le(e,t,n){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),Se(e,n||t.type,e,t),Oe(t)||t.codemirrorIgnore}function ke(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var n=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),r=0;r<t.length;++r)-1==B(n,t[r])&&n.push(t[r])}function Te(e,t){return 0<xe(e,t).length}function Me(e){e.prototype.on=function(e,t){we(this,e,t)},e.prototype.off=function(e,t){Ce(this,e,t)}}function Ne(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Ae(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Oe(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function De(e){Ne(e),Ae(e)}function We(e){return e.target||e.srcElement}function He(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Fe,Pe,Ee=function(){if(x&&C<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();var Ie,Re=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(n.push(o.slice(0,l)),t+=l+1):(n.push(o),t=i+1)}return n}:function(e){return e.split(/\r\n?|\n/)},ze=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Be="oncopy"in(Ie=O("div"))||(Ie.setAttribute("oncopy","return;"),"function"==typeof Ie.oncopy),Ge=null;var Ue={},Ve={};function Ke(e){if("string"==typeof e&&Ve.hasOwnProperty(e))e=Ve[e];else if(e&&"string"==typeof e.name&&Ve.hasOwnProperty(e.name)){var t=Ve[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Ke("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Ke("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function je(e,t){t=Ke(t);var n=Ue[t.name];if(!n)return je(e,"text/plain");var r=n(e,t);if(Xe.hasOwnProperty(t.name)){var i=Xe[t.name];for(var o in i)i.hasOwnProperty(o)&&(r.hasOwnProperty(o)&&(r["_"+o]=r[o]),r[o]=i[o])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)r[l]=t.modeProps[l];return r}var Xe={};function Ye(e,t){I(t,Xe.hasOwnProperty(e)?Xe[e]:Xe[e]={})}function _e(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function $e(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function qe(e,t,n){return!e.startState||e.startState(t,n)}var Ze=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};function Qe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var i=n.children[r],o=i.chunkSize();if(t<o){n=i;break}t-=o}return n.lines[t]}function Je(e,n,r){var i=[],o=n.line;return e.iter(n.line,r.line+1,function(e){var t=e.text;o==r.line&&(t=t.slice(0,r.ch)),o==n.line&&(t=t.slice(n.ch)),i.push(t),++o}),i}function et(e,t,n){var r=[];return e.iter(t,n,function(e){r.push(e.text)}),r}function tt(e,t){var n=t-e.height;if(n)for(var r=e;r;r=r.parent)r.height+=n}function nt(e){if(null==e.parent)return null;for(var t=e.parent,n=B(t.lines,e),r=t.parent;r;r=(t=r).parent)for(var i=0;r.children[i]!=t;++i)n+=r.children[i].chunkSize();return n+t.first}function rt(e,t){var n=e.first;e:do{for(var r=0;r<e.children.length;++r){var i=e.children[r],o=i.height;if(t<o){e=i;continue e}t-=o,n+=i.chunkSize()}return n}while(!e.lines);for(var l=0;l<e.lines.length;++l){var s=e.lines[l].height;if(t<s)break;t-=s}return n+l}function it(e,t){return t>=e.first&&t<e.first+e.size}function ot(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function lt(e,t,n){if(void 0===n&&(n=null),!(this instanceof lt))return new lt(e,t,n);this.line=e,this.ch=t,this.sticky=n}function st(e,t){return e.line-t.line||e.ch-t.ch}function at(e,t){return e.sticky==t.sticky&&0==st(e,t)}function ut(e){return lt(e.line,e.ch)}function ct(e,t){return st(e,t)<0?t:e}function ht(e,t){return st(e,t)<0?e:t}function dt(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function ft(e,t){if(t.line<e.first)return lt(e.first,0);var n,r,i,o=e.first+e.size-1;return t.line>o?lt(o,Qe(e,o).text.length):(r=Qe(e,(n=t).line).text.length,null==(i=n.ch)||r<i?lt(n.line,r):i<0?lt(n.line,0):n)}function pt(e,t){for(var n=[],r=0;r<t.length;r++)n[r]=ft(e,t[r]);return n}Ze.prototype.eol=function(){return this.pos>=this.string.length},Ze.prototype.sol=function(){return this.pos==this.lineStart},Ze.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Ze.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},Ze.prototype.eat=function(e){var t=this.string.charAt(this.pos),n="string"==typeof e?t==e:t&&(e.test?e.test(t):e(t));if(n)return++this.pos,t},Ze.prototype.eatWhile=function(e){for(var t=this.pos;this.eat(e););return this.pos>t},Ze.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Ze.prototype.skipToEnd=function(){this.pos=this.string.length},Ze.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(-1<t)return this.pos=t,!0},Ze.prototype.backUp=function(e){this.pos-=e},Ze.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=R(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},Ze.prototype.indentation=function(){return R(this.string,null,this.tabSize)-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},Ze.prototype.match=function(e,t,n){if("string"!=typeof e){var r=this.string.slice(this.pos).match(e);return r&&0<r.index?null:(r&&!1!==t&&(this.pos+=r[0].length),r)}function i(e){return n?e.toLowerCase():e}if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},Ze.prototype.current=function(){return this.string.slice(this.start,this.pos)},Ze.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Ze.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Ze.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var gt=function(e,t){this.state=e,this.lookAhead=t},mt=function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1};function vt(t,n,r,e){var a=[t.state.modeGen],i={};Tt(t,n.text,t.doc.mode,r,function(e,t){return a.push(e,t)},i,e);for(var u=r.state,o=0;o<t.state.overlays.length;++o)!function(e){r.baseTokens=a;var o=t.state.overlays[e],l=1,s=0;r.state=!0,Tt(t,n.text,o.mode,r,function(e,t){for(var n=l;s<e;){var r=a[l];e<r&&a.splice(l,1,e,a[l+1],r),l+=2,s=Math.min(e,r)}if(t)if(o.opaque)a.splice(n,l-n,e,"overlay "+t),l=n+2;else for(;n<l;n+=2){var i=a[n+1];a[n+1]=(i?i+" ":"")+"overlay "+t}},i),r.state=u,r.baseTokens=null,r.baseTokenPos=1}(o);return{styles:a,classes:i.bgClass||i.textClass?i:null}}function yt(e,t,n){var r,i,o;return t.styles&&t.styles[0]==e.state.modeGen||(r=bt(e,nt(t)),i=t.text.length>e.options.maxHighlightLength&&_e(e.doc.mode,r.state),o=vt(e,t,r),i&&(r.state=i),t.stateAfter=r.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))),t.styles}function bt(n,r,e){var t=n.doc,i=n.display;if(!t.mode.startState)return new mt(t,!0,r);var o=function(e,t,n){for(var r,i,o=e.doc,l=n?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;l<s;--s){if(s<=o.first)return o.first;var a=Qe(o,s-1),u=a.stateAfter;if(u&&(!n||s+(u instanceof gt?u.lookAhead:0)<=o.modeFrontier))return s;var c=R(a.text,null,e.options.tabSize);(null==i||c<r)&&(i=s-1,r=c)}return i}(n,r,e),l=o>t.first&&Qe(t,o-1).stateAfter,s=l?mt.fromSaved(t,l,o):new mt(t,qe(t.mode),o);return t.iter(o,r,function(e){wt(n,e.text,s);var t=s.line;e.stateAfter=t==r-1||t%5==0||t>=i.viewFrom&&t<i.viewTo?s.save():null,s.nextLine()}),e&&(t.modeFrontier=s.line),s}function wt(e,t,n,r){var i=e.doc.mode,o=new Ze(t,e.options.tabSize,n);for(o.start=o.pos=r||0,""==t&&xt(i,n.state);!o.eol();)Ct(i,o,n.state),o.start=o.pos}function xt(e,t){if(e.blankLine)return e.blankLine(t);if(e.innerMode){var n=$e(e,t);return n.mode.blankLine?n.mode.blankLine(n.state):void 0}}function Ct(e,t,n,r){for(var i=0;i<10;i++){r&&(r[0]=$e(e,n).mode);var o=e.token(t,n);if(t.pos>t.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}mt.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},mt.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},mt.prototype.nextLine=function(){this.line++,0<this.maxLookAhead&&this.maxLookAhead--},mt.fromSaved=function(e,t,n){return t instanceof gt?new mt(e,_e(e.mode,t.state),n,t.lookAhead):new mt(e,_e(e.mode,t),n)},mt.prototype.save=function(e){var t=!1!==e?_e(this.doc.mode,this.state):this.state;return 0<this.maxLookAhead?new gt(t,this.maxLookAhead):t};var St=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function Lt(e,t,n,r){var i,o,l=e.doc,s=l.mode,a=Qe(l,(t=ft(l,t)).line),u=bt(e,t.line,n),c=new Ze(a.text,e.options.tabSize,u);for(r&&(o=[]);(r||c.pos<t.ch)&&!c.eol();)c.start=c.pos,i=Ct(s,c,u.state),r&&o.push(new St(c,i,_e(l.mode,u.state)));return r?o:new St(c,i,u.state)}function kt(e,t){if(e)for(;;){var n=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!n)break;e=e.slice(0,n.index)+e.slice(n.index+n[0].length);var r=n[1]?"bgClass":"textClass";null==t[r]?t[r]=n[2]:new RegExp("(?:^|\\s)"+n[2]+"(?:$|\\s)").test(t[r])||(t[r]+=" "+n[2])}return e}function Tt(e,t,n,r,i,o,l){var s=n.flattenSpans;null==s&&(s=e.options.flattenSpans);var a=0,u=null,c=new Ze(t,e.options.tabSize,r),h=e.options.addModeClass&&[null];for(""==t&&kt(xt(n,r.state),o);!c.eol();){var d,f=c.pos>e.options.maxHighlightLength?(s=!1,l&&wt(e,t,r,c.pos),c.pos=t.length,null):kt(Ct(n,c,r.state,h),o);if(!h||(d=h[0].name)&&(f="m-"+(f?d+" "+f:d)),!s||u!=f){for(;a<c.start;)i(a=Math.min(c.start,a+5e3),u);u=f}c.start=c.pos}for(;a<c.pos;){var p=Math.min(c.pos,a+5e3);i(p,u),a=p}}var Mt=!1,Nt=!1;function At(e,t,n){this.marker=e,this.from=t,this.to=n}function Ot(e,t){if(e)for(var n=0;n<e.length;++n){var r=e[n];if(r.marker==t)return r}}function Dt(e,t){if(t.full)return null;var n=it(e,t.from.line)&&Qe(e,t.from.line).markedSpans,r=it(e,t.to.line)&&Qe(e,t.to.line).markedSpans;if(!n&&!r)return null;var i=t.from.ch,o=t.to.ch,l=0==st(t.from,t.to),s=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t))&&(l.from!=t||"bookmark"!=s.type||n&&l.marker.insertLeft)||(o=null==l.to||(s.inclusiveRight?l.to>=t:l.to>t),(r=r||[]).push(new At(s,l.from,o?null:l.to)))}return r}(n,i,l),a=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.to||(s.inclusiveRight?l.to>=t:l.to>t))&&(l.from!=t||"bookmark"!=s.type||n&&!l.marker.insertLeft)||(o=null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t),(r=r||[]).push(new At(s,o?null:l.from-t,null==l.to?null:l.to-t)))}return r}(r,o,l),u=1==t.text.length,c=$(t.text).length+(u?i:0);if(s)for(var h=0;h<s.length;++h){var d,f=s[h];null==f.to&&((d=Ot(a,f.marker))?u&&(f.to=null==d.to?null:d.to+c):f.to=i)}if(a)for(var p=0;p<a.length;++p){var g=a[p];null!=g.to&&(g.to+=c),null==g.from?Ot(s,g.marker)||(g.from=c,u&&(s=s||[]).push(g)):(g.from+=c,u&&(s=s||[]).push(g))}s=s&&Wt(s),a&&a!=s&&(a=Wt(a));var m=[s];if(!u){var v,y=t.text.length-2;if(0<y&&s)for(var b=0;b<s.length;++b)null==s[b].to&&(v=v||[]).push(new At(s[b].marker,null,null));for(var w=0;w<y;++w)m.push(v);m.push(a)}return m}function Wt(e){for(var t=0;t<e.length;++t){var n=e[t];null!=n.from&&n.from==n.to&&!1!==n.marker.clearWhenEmpty&&e.splice(t--,1)}return e.length?e:null}function Ht(e){var t=e.markedSpans;if(t){for(var n=0;n<t.length;++n)t[n].marker.detachLine(e);e.markedSpans=null}}function Ft(e,t){if(t){for(var n=0;n<t.length;++n)t[n].marker.attachLine(e);e.markedSpans=t}}function Pt(e){return e.inclusiveLeft?-1:0}function Et(e){return e.inclusiveRight?1:0}function It(e,t){var n=e.lines.length-t.lines.length;if(0!=n)return n;var r=e.find(),i=t.find(),o=st(r.from,i.from)||Pt(e)-Pt(t);if(o)return-o;var l=st(r.to,i.to)||Et(e)-Et(t);return l||t.id-e.id}function Rt(e,t){var n,r=Nt&&e.markedSpans;if(r)for(var i=void 0,o=0;o<r.length;++o)(i=r[o]).marker.collapsed&&null==(t?i.from:i.to)&&(!n||It(n,i.marker)<0)&&(n=i.marker);return n}function zt(e){return Rt(e,!0)}function Bt(e){return Rt(e,!1)}function Gt(e,t,n,r,i){var o=Qe(e,t),l=Nt&&o.markedSpans;if(l)for(var s=0;s<l.length;++s){var a=l[s];if(a.marker.collapsed){var u=a.marker.find(0),c=st(u.from,n)||Pt(a.marker)-Pt(i),h=st(u.to,r)||Et(a.marker)-Et(i);if(!(0<=c&&h<=0||c<=0&&0<=h)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?0<=st(u.to,n):0<st(u.to,n))||0<=c&&(a.marker.inclusiveRight&&i.inclusiveLeft?st(u.from,r)<=0:st(u.from,r)<0)))return 1}}}function Ut(e){for(var t;t=zt(e);)e=t.find(-1,!0).line;return e}function Vt(e,t){var n=Qe(e,t),r=Ut(n);return n==r?t:nt(r)}function Kt(e,t){if(t>e.lastLine())return t;var n,r=Qe(e,t);if(!jt(e,r))return t;for(;n=Bt(r);)r=n.find(1,!0).line;return nt(r)+1}function jt(e,t){var n=Nt&&t.markedSpans;if(n)for(var r=void 0,i=0;i<n.length;++i)if((r=n[i]).marker.collapsed){if(null==r.from)return!0;if(!r.marker.widgetNode&&0==r.from&&r.marker.inclusiveLeft&&function e(t,n,r){if(null==r.to){var i=r.marker.find(1,!0);return e(t,i.line,Ot(i.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==n.text.length)return!0;for(var o=void 0,l=0;l<n.markedSpans.length;++l)if((o=n.markedSpans[l]).marker.collapsed&&!o.marker.widgetNode&&o.from==r.to&&(null==o.to||o.to!=r.from)&&(o.marker.inclusiveLeft||r.marker.inclusiveRight)&&e(t,n,o))return!0}(e,t,r))return!0}}function Xt(e){for(var t=0,n=(e=Ut(e)).parent,r=0;r<n.lines.length;++r){var i=n.lines[r];if(i==e)break;t+=i.height}for(var o=n.parent;o;o=(n=o).parent)for(var l=0;l<o.children.length;++l){var s=o.children[l];if(s==n)break;t+=s.height}return t}function Yt(e){if(0==e.height)return 0;for(var t,n=e.text.length,r=e;t=zt(r);){var i=t.find(0,!0),r=i.from.line;n+=i.from.ch-i.to.ch}for(r=e;t=Bt(r);){var o=t.find(0,!0);n-=r.text.length-o.from.ch,n+=(r=o.to.line).text.length-o.to.ch}return n}function _t(e){var n=e.display,t=e.doc;n.maxLine=Qe(t,t.first),n.maxLineLength=Yt(n.maxLine),n.maxLineChanged=!0,t.iter(function(e){var t=Yt(e);t>n.maxLineLength&&(n.maxLineLength=t,n.maxLine=e)})}var $t=function(e,t,n){this.text=e,Ft(this,t),this.height=n?n(this):1};$t.prototype.lineNo=function(){return nt(this)},Me($t);var qt={},Zt={};function Qt(e,t){if(!e||/^\s*$/.test(e))return null;var n=t.addModeClass?Zt:qt;return n[e]||(n[e]=e.replace(/\S+/g,"cm-$&"))}function Jt(e,t){var n=A("span",null,null,v?"padding-right: .1px":null),r={pre:A("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i,o=0;o<=(t.rest?t.rest.length:0);o++){var l=o?t.rest[o-1]:t.line,s=void 0;r.pos=0,r.addToken=tn,function(e){if(null!=Pe)return Pe;var t=N(e,document.createTextNode("AخA")),n=k(t,0,1).getBoundingClientRect(),r=k(t,1,2).getBoundingClientRect();return M(e),n&&n.left!=n.right&&(Pe=r.right-n.right<3)}(e.display.measure)&&(s=ye(l,e.doc.direction))&&(r.addToken=function(h,d){return function(e,t,n,r,i,o,l){n=n?n+" cm-force-border":"cm-force-border";for(var s=e.pos,a=s+t.length;;){for(var u=void 0,c=0;c<d.length&&!((u=d[c]).to>s&&u.from<=s);c++);if(u.to>=a)return h(e,t,n,r,i,o,l);h(e,t.slice(0,u.to-s),n,r,null,o,l),r=null,t=t.slice(u.to-s),s=u.to}}}(r.addToken,s)),r.map=[],function(e,t,n){var r=e.markedSpans,i=e.text,o=0;if(!r){for(var l=1;l<n.length;l+=2)t.addToken(t,i.slice(o,o=n[l]),Qt(n[l+1],t.cm.options));return}for(var s,a,u,c,h,d,f,p=i.length,g=0,m=1,v="",y=0;;){if(y==g){u=c=h=a="",d=f=null,y=1/0;for(var b=[],w=void 0,x=0;x<r.length;++x){var C=r[x],S=C.marker;if("bookmark"==S.type&&C.from==g&&S.widgetNode)b.push(S);else if(C.from<=g&&(null==C.to||C.to>g||S.collapsed&&C.to==g&&C.from==g)){if(null!=C.to&&C.to!=g&&y>C.to&&(y=C.to,c=""),S.className&&(u+=" "+S.className),S.css&&(a=(a?a+";":"")+S.css),S.startStyle&&C.from==g&&(h+=" "+S.startStyle),S.endStyle&&C.to==y&&(w=w||[]).push(S.endStyle,C.to),S.title&&((f=f||{}).title=S.title),S.attributes)for(var L in S.attributes)(f=f||{})[L]=S.attributes[L];S.collapsed&&(!d||It(d.marker,S)<0)&&(d=C)}else C.from>g&&y>C.from&&(y=C.from)}if(w)for(var k=0;k<w.length;k+=2)w[k+1]==y&&(c+=" "+w[k]);if(!d||d.from==g)for(var T=0;T<b.length;++T)nn(t,0,b[T]);if(d&&(d.from||0)==g){if(nn(t,(null==d.to?p+1:d.to)-g,d.marker,null==d.from),null==d.to)return;d.to==g&&(d=!1)}}if(p<=g)break;for(var M=Math.min(p,y);;){if(v){var N,A=g+v.length;if(d||(N=M<A?v.slice(0,M-g):v,t.addToken(t,N,s?s+u:u,h,g+N.length==y?c:"",a,f)),M<=A){v=v.slice(M-g),g=M;break}g=A,h=""}v=i.slice(o,o=n[m++]),s=Qt(n[m++],t.cm.options)}}}(l,r,yt(e,l,t!=e.display.externalMeasured&&nt(l))),l.styleClasses&&(l.styleClasses.bgClass&&(r.bgClass=F(l.styleClasses.bgClass,r.bgClass||"")),l.styleClasses.textClass&&(r.textClass=F(l.styleClasses.textClass,r.textClass||""))),0==r.map.length&&r.map.push(0,0,r.content.appendChild(function(e){var t;null==Fe&&(t=O("span","​"),N(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Fe=t.offsetWidth<=1&&2<t.offsetHeight&&!(x&&C<8)));var n=Fe?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}(e.display.measure))),0==o?(t.measure.map=r.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(r.map),(t.measure.caches||(t.measure.caches=[])).push({}))}return v&&(i=r.content.lastChild,(/\bcm-tab\b/.test(i.className)||i.querySelector&&i.querySelector(".cm-tab"))&&(r.content.className="cm-tab-wrap-hack")),Se(e,"renderLine",e,t.line,r.pre),r.pre.className&&(r.textClass=F(r.pre.className,r.textClass||"")),r}function en(e){var t=O("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function tn(e,t,n,r,i,o,l){if(t){var s,a=e.splitSpaces?function(e,t){if(1<e.length&&!/ /.test(e))return e;for(var n=t,r="",i=0;i<e.length;i++){var o=e.charAt(i);" "!=o||!n||i!=e.length-1&&32!=e.charCodeAt(i+1)||(o=" "),r+=o,n=" "==o}return r}(t,e.trailingSpace):t,u=e.cm.state.specialChars,c=!1;if(u.test(t)){s=document.createDocumentFragment();for(var h=0;;){u.lastIndex=h;var d,f=u.exec(t),p=f?f.index-h:t.length-h;if(p&&(d=document.createTextNode(a.slice(h,h+p)),x&&C<9?s.appendChild(O("span",[d])):s.appendChild(d),e.map.push(e.pos,e.pos+p,d),e.col+=p,e.pos+=p),!f)break;h+=1+p;var g,m,v=void 0;"\t"==f[0]?(m=(g=e.cm.options.tabSize)-e.col%g,(v=s.appendChild(O("span",_(m),"cm-tab"))).setAttribute("role","presentation"),v.setAttribute("cm-text","\t"),e.col+=m):("\r"==f[0]||"\n"==f[0]?(v=s.appendChild(O("span","\r"==f[0]?"␍":"␤","cm-invalidchar"))).setAttribute("cm-text",f[0]):((v=e.cm.options.specialCharPlaceholder(f[0])).setAttribute("cm-text",f[0]),x&&C<9?s.appendChild(O("span",[v])):s.appendChild(v)),e.col+=1),e.map.push(e.pos,e.pos+1,v),e.pos++}}else e.col+=t.length,s=document.createTextNode(a),e.map.push(e.pos,e.pos+t.length,s),x&&C<9&&(c=!0),e.pos+=t.length;if(e.trailingSpace=32==a.charCodeAt(t.length-1),n||r||i||c||o||l){var y=n||"";r&&(y+=r),i&&(y+=i);var b=O("span",[s],y,o);if(l)for(var w in l)l.hasOwnProperty(w)&&"style"!=w&&"class"!=w&&b.setAttribute(w,l[w]);return e.content.appendChild(b)}e.content.appendChild(s)}}function nn(e,t,n,r){var i=!r&&n.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!r&&e.cm.display.input.needsContentAttribute&&(i=i||e.content.appendChild(document.createElement("span"))).setAttribute("cm-marker",n.id),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function rn(e,t,n){this.line=t,this.rest=function(e){for(var t,n;t=Bt(e);)e=t.find(1,!0).line,(n=n||[]).push(e);return n}(t),this.size=this.rest?nt($(this.rest))-n+1:1,this.node=this.text=null,this.hidden=jt(e,t)}function on(e,t,n){for(var r=[],i=t;i<n;i=l){var o=new rn(e.doc,Qe(e.doc,i),i),l=i+o.size;r.push(o)}return r}var ln=null;function sn(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n<t.length;n++)t[n].call(null);for(var r=0;r<e.ops.length;r++){var i=e.ops[r];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++].call(null,i.cm)}}while(n<t.length)}(n)}finally{ln=null,t(n)}}var an=null;function un(e,t){var n=xe(e,t);if(n.length){var r,i=Array.prototype.slice.call(arguments,2);ln?r=ln.delayedCallbacks:an?r=an:(r=an=[],setTimeout(cn,0));for(var o=0;o<n.length;++o)!function(e){r.push(function(){return n[e].apply(null,i)})}(o)}}function cn(){var e=an;an=null;for(var t=0;t<e.length;++t)e[t]()}function hn(e,t,n,r){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?function(e,t){var n=t.text.className,r=fn(e,t);t.text==t.node&&(t.node=r.pre);t.text.parentNode.replaceChild(r.pre,t.text),t.text=r.pre,r.bgClass!=t.bgClass||r.textClass!=t.textClass?(t.bgClass=r.bgClass,t.textClass=r.textClass,pn(e,t)):n&&(t.text.className=n)}(e,t):"gutter"==o?gn(e,t,n,r):"class"==o?pn(e,t):"widget"==o&&function(e,t,n){t.alignable&&(t.alignable=null);for(var r=L("CodeMirror-linewidget"),i=t.node.firstChild,o=void 0;i;i=o)o=i.nextSibling,r.test(i.className)&&t.node.removeChild(i);mn(e,t,n)}(e,t,r)}t.changes=null}function dn(e){return e.node==e.text&&(e.node=O("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),x&&C<8&&(e.node.style.zIndex=2)),e.node}function fn(e,t){var n=e.display.externalMeasured;return n&&n.line==t.line?(e.display.externalMeasured=null,t.measure=n.measure,n.built):Jt(e,t)}function pn(e,t){var n,r,i,o;n=e,(o=(r=t).bgClass?r.bgClass+" "+(r.line.bgClass||""):r.line.bgClass)&&(o+=" CodeMirror-linebackground"),r.background?o?r.background.className=o:(r.background.parentNode.removeChild(r.background),r.background=null):o&&(i=dn(r),r.background=i.insertBefore(O("div",null,o),i.firstChild),n.display.input.setUneditable(r.background)),t.line.wrapClass?dn(t).className=t.line.wrapClass:t.node!=t.text&&(t.node.className="");var l=t.textClass?t.textClass+" "+(t.line.textClass||""):t.line.textClass;t.text.className=l||""}function gn(e,t,n,r){var i;t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null),t.gutterBackground&&(t.node.removeChild(t.gutterBackground),t.gutterBackground=null),t.line.gutterClass&&(i=dn(t),t.gutterBackground=O("div",null,"CodeMirror-gutter-background "+t.line.gutterClass,"left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px; width: "+r.gutterTotalWidth+"px"),e.display.input.setUneditable(t.gutterBackground),i.insertBefore(t.gutterBackground,t.text));var o=t.line.gutterMarkers;if(e.options.lineNumbers||o){var l=dn(t),s=t.gutter=O("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px");if(e.display.input.setUneditable(s),l.insertBefore(s,t.text),t.line.gutterClass&&(s.className+=" "+t.line.gutterClass),!e.options.lineNumbers||o&&o["CodeMirror-linenumbers"]||(t.lineNumber=s.appendChild(O("div",ot(e.options,n),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+r.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),o)for(var a=0;a<e.display.gutterSpecs.length;++a){var u=e.display.gutterSpecs[a].className,c=o.hasOwnProperty(u)&&o[u];c&&s.appendChild(O("div",[c],"CodeMirror-gutter-elt","left: "+r.gutterLeft[u]+"px; width: "+r.gutterWidth[u]+"px"))}}}function mn(e,t,n){if(vn(e,t.line,t,n,!0),t.rest)for(var r=0;r<t.rest.length;r++)vn(e,t.rest[r],t,n,!1)}function vn(e,t,n,r,i){if(t.widgets)for(var o=dn(n),l=0,s=t.widgets;l<s.length;++l){var a=s[l],u=O("div",[a.node],"CodeMirror-linewidget"+(a.className?" "+a.className:""));a.handleMouseEvents||u.setAttribute("cm-ignore-events","true"),function(e,t,n,r){{var i;e.noHScroll&&((n.alignable||(n.alignable=[])).push(t),i=r.wrapperWidth,t.style.left=r.fixedPos+"px",e.coverGutter||(i-=r.gutterTotalWidth,t.style.paddingLeft=r.gutterTotalWidth+"px"),t.style.width=i+"px")}e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-r.gutterTotalWidth+"px"))}(a,u,n,r),e.display.input.setUneditable(u),i&&a.above?o.insertBefore(u,n.gutter||n.text):o.appendChild(u),un(a,"redraw")}}function yn(e){if(null!=e.height)return e.height;var t,n=e.doc.cm;return n?(D(document.body,e.node)||(t="position: relative;",e.coverGutter&&(t+="margin-left: -"+n.display.gutters.offsetWidth+"px;"),e.noHScroll&&(t+="width: "+n.display.wrapper.clientWidth+"px;"),N(n.display.measure,O("div",[e.node],null,t))),e.height=e.node.parentNode.offsetHeight):0}function bn(e,t){for(var n=We(t);n!=e.wrapper;n=n.parentNode)if(!n||1==n.nodeType&&"true"==n.getAttribute("cm-ignore-events")||n.parentNode==e.sizer&&n!=e.mover)return 1}function wn(e){return e.lineSpace.offsetTop}function xn(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function Cn(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=N(e.measure,O("pre","x","CodeMirror-line-like")),n=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,r={left:parseInt(n.paddingLeft),right:parseInt(n.paddingRight)};return isNaN(r.left)||isNaN(r.right)||(e.cachedPaddingH=r),r}function Sn(e){return G-e.display.nativeBarWidth}function Ln(e){return e.display.scroller.clientWidth-Sn(e)-e.display.barWidth}function kn(e){return e.display.scroller.clientHeight-Sn(e)-e.display.barHeight}function Tn(e,t,n){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var r=0;r<e.rest.length;r++)if(e.rest[r]==t)return{map:e.measure.maps[r],cache:e.measure.caches[r]};for(var i=0;i<e.rest.length;i++)if(nt(e.rest[i])>n)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Mn(e,t,n,r){return On(e,An(e,t),n,r)}function Nn(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[rr(e,t)];var n=e.display.externalMeasured;return n&&t>=n.lineN&&t<n.lineN+n.size?n:void 0}function An(e,t){var n=nt(t),r=Nn(e,n);r&&!r.text?r=null:r&&r.changes&&(hn(e,r,n,Qn(e)),e.curOp.forceUpdate=!0);var i=Tn(r=r||function(e,t){var n=nt(t=Ut(t)),r=e.display.externalMeasured=new rn(e.doc,t,n);r.lineN=n;var i=r.built=Jt(e,r);return r.text=i.pre,N(e.display.lineMeasure,i.pre),r}(e,t),t,n);return{line:t,view:r,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function On(e,t,n,r,i){t.before&&(n=-1);var o,l=n+(r||"");return t.cache.hasOwnProperty(l)?o=t.cache[l]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||(function(e,t,n){var r=e.options.lineWrapping,i=r&&Ln(e);if(!t.measure.heights||r&&t.measure.width!=i){var o=t.measure.heights=[];if(r){t.measure.width=i;for(var l=t.text.firstChild.getClientRects(),s=0;s<l.length-1;s++){var a=l[s],u=l[s+1];2<Math.abs(a.bottom-u.bottom)&&o.push((a.bottom+u.top)/2-n.top)}}o.push(n.bottom-n.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,n,r){var i,o,l=Hn(t.map,n,r),s=l.node,a=l.start,u=l.end,c=l.collapse;if(3==s.nodeType){for(var h=0;h<4;h++){for(;a&&ie(t.line.text.charAt(l.coverStart+a));)--a;for(;l.coverStart+u<l.coverEnd&&ie(t.line.text.charAt(l.coverStart+u));)++u;if((i=x&&C<9&&0==a&&u==l.coverEnd-l.coverStart?s.parentNode.getBoundingClientRect():function(e,t){var n=Wn;if("left"==t)for(var r=0;r<e.length&&(n=e[r]).left==n.right;r++);else for(var i=e.length-1;0<=i&&(n=e[i]).left==n.right;i--);return n}(k(s,a,u).getClientRects(),r)).left||i.right||0==a)break;u=a,--a,c="right"}x&&C<11&&(i=function(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!function(e){if(null!=Ge)return Ge;var t=N(e,O("span","x")),n=t.getBoundingClientRect(),r=k(t,0,1).getBoundingClientRect();return Ge=1<Math.abs(n.left-r.left)}(e))return t;var n=screen.logicalXDPI/screen.deviceXDPI,r=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*n,right:t.right*n,top:t.top*r,bottom:t.bottom*r}}(e.display.measure,i))}else 0<a&&(c=r="right"),i=e.options.lineWrapping&&1<(o=s.getClientRects()).length?o["right"==r?o.length-1:0]:s.getBoundingClientRect();{var d;!(x&&C<9)||a||i&&(i.left||i.right)||(d=s.parentNode.getClientRects()[0],i=d?{left:d.left,right:d.left+Zn(e.display),top:d.top,bottom:d.bottom}:Wn)}for(var f=i.top-t.rect.top,p=i.bottom-t.rect.top,g=(f+p)/2,m=t.view.measure.heights,v=0;v<m.length-1&&!(g<m[v]);v++);var y=v?m[v-1]:0,b=m[v],w={left:("right"==c?i.right:i.left)-t.rect.left,right:("left"==c?i.left:i.right)-t.rect.left,top:y,bottom:b};i.left||i.right||(w.bogus=!0);e.options.singleCursorHeightPerLine||(w.rtop=f,w.rbottom=p);return w}(e,t,n,r)).bogus||(t.cache[l]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}var Dn,Wn={left:0,right:0,top:0,bottom:0};function Hn(e,t,n){for(var r,i,o,l,s,a,u=0;u<e.length;u+=3)if(s=e[u],a=e[u+1],t<s?(i=0,o=1,l="left"):t<a?o=(i=t-s)+1:(u==e.length-3||t==a&&e[u+3]>t)&&(i=(o=a-s)-1,a<=t&&(l="right")),null!=i){if(r=e[u+2],s==a&&n==(r.insertLeft?"left":"right")&&(l=n),"left"==n&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)r=e[2+(u-=3)],l="left";if("right"==n&&i==a-s)for(;u<e.length-3&&e[u+3]==e[u+4]&&!e[u+5].insertLeft;)r=e[(u+=3)+2],l="right";break}return{node:r,start:i,end:o,collapse:l,coverStart:s,coverEnd:a}}function Fn(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function Pn(e){e.display.externalMeasure=null,M(e.display.lineMeasure);for(var t=0;t<e.display.view.length;t++)Fn(e.display.view[t])}function En(e){Pn(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function In(){return l&&h?-(document.body.getBoundingClientRect().left-parseInt(getComputedStyle(document.body).marginLeft)):window.pageXOffset||(document.documentElement||document.body).scrollLeft}function Rn(){return l&&h?-(document.body.getBoundingClientRect().top-parseInt(getComputedStyle(document.body).marginTop)):window.pageYOffset||(document.documentElement||document.body).scrollTop}function zn(e){var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;++n)e.widgets[n].above&&(t+=yn(e.widgets[n]));return t}function Bn(e,t,n,r,i){var o;if(i||(o=zn(t),n.top+=o,n.bottom+=o),"line"==r)return n;r=r||"local";var l,s,a=Xt(t);return"local"==r?a+=wn(e.display):a-=e.display.viewOffset,"page"!=r&&"window"!=r||(a+=(l=e.display.lineSpace.getBoundingClientRect()).top+("window"==r?0:Rn()),s=l.left+("window"==r?0:In()),n.left+=s,n.right+=s),n.top+=a,n.bottom+=a,n}function Gn(e,t,n){if("div"==n)return t;var r,i=t.left,o=t.top;"page"==n?(i-=In(),o-=Rn()):"local"!=n&&n||(i+=(r=e.display.sizer.getBoundingClientRect()).left,o+=r.top);var l=e.display.lineSpace.getBoundingClientRect();return{left:i-l.left,top:o-l.top}}function Un(e,t,n,r,i){return Bn(e,r=r||Qe(e.doc,t.line),Mn(e,r,t.ch,i),n)}function Vn(r,e,i,o,l,s){function a(e,t){var n=On(r,l,e,t?"right":"left",s);return t?n.left=n.right:n.right=n.left,Bn(r,o,n,i)}o=o||Qe(r.doc,e.line),l=l||An(r,o);var u=ye(o,r.doc.direction),t=e.ch,n=e.sticky;if(t>=o.text.length?(t=o.text.length,n="before"):t<=0&&(t=0,n="after"),!u)return a("before"==n?t-1:t,"before"==n);function c(e,t,n){return a(n?e-1:e,1==u[t].level!=n)}var h=ae(u,t,n),d=se,f=c(t,h,"before"==n);return null!=d&&(f.other=c(t,d,"before"!=n)),f}function Kn(e,t){var n=0;t=ft(e.doc,t),e.options.lineWrapping||(n=Zn(e.display)*t.ch);var r=Qe(e.doc,t.line),i=Xt(r)+wn(e.display);return{left:n,right:n,top:i,bottom:i+r.height}}function jn(e,t,n,r,i){var o=lt(e,t,n);return o.xRel=i,r&&(o.outside=r),o}function Xn(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return jn(r.first,0,null,-1,-1);var i=rt(r,n),o=r.first+r.size-1;if(o<i)return jn(r.first+r.size-1,Qe(r,o).text.length,null,1,1);t<0&&(t=0);for(var l=Qe(r,i);;){var s=function(n,e,t,r,i){i-=Xt(e);var o=An(n,e),l=zn(e),s=0,a=e.text.length,u=!0,c=ye(e,n.doc.direction);{var h;c&&(h=(n.options.lineWrapping?function(e,t,n,r,i,o,l){var s=Yn(e,t,r,l),a=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,h=null,d=0;d<i.length;d++){var f,p,g,m=i[d];m.from>=u||m.to<=a||(f=1!=m.level,p=On(e,r,f?Math.min(u,m.to)-1:Math.max(a,m.from)).right,g=p<o?o-p+1e9:p-o,(!c||g<h)&&(c=m,h=g))}c=c||i[i.length-1];c.from<a&&(c={from:a,to:c.to,level:c.level});c.to>u&&(c={from:c.from,to:u,level:c.level});return c}:function(r,i,o,l,s,a,u){var e=le(function(e){var t=s[e],n=1!=t.level;return $n(Vn(r,lt(o,n?t.to:t.from,n?"before":"after"),"line",i,l),a,u,!0)},0,s.length-1),t=s[e];{var n,c;0<e&&(n=1!=t.level,$n(c=Vn(r,lt(o,n?t.from:t.to,n?"after":"before"),"line",i,l),a,u,!0)&&c.top>u&&(t=s[e-1]))}return t})(n,e,t,o,c,r,i),u=1!=h.level,s=u?h.from:h.to-1,a=u?h.to:h.from-1)}var d,f,p=null,g=null,m=le(function(e){var t=On(n,o,e);return t.top+=l,t.bottom+=l,$n(t,r,i,!1)&&(t.top<=i&&t.left<=r&&(p=e,g=t),1)},s,a),v=!1;{var y,b,w;g?(y=r-g.left<g.right-r,m=p+((b=y==u)?0:1),f=b?"after":"before",d=y?g.left:g.right):(u||m!=a&&m!=s||m++,f=0==m||m!=e.text.length&&On(n,o,m-(u?1:0)).bottom+l<=i==u?"after":"before",w=Vn(n,lt(t,m,f),"line",e,o),d=w.left,v=i<w.top?-1:i>=w.bottom?1:0)}return m=oe(e.text,m,1),jn(t,m,f,v,r-d)}(e,l,i,t,n),a=function(e,t){var n,r=Nt&&e.markedSpans;if(r)for(var i=0;i<r.length;++i){var o=r[i];o.marker.collapsed&&(null==o.from||o.from<t)&&(null==o.to||o.to>t)&&(!n||It(n,o.marker)<0)&&(n=o.marker)}return n}(l,s.ch+(0<s.xRel||0<s.outside?1:0));if(!a)return s;var u=a.find(1);if(u.line==i)return u;l=Qe(r,i=u.line)}}function Yn(t,e,n,r){r-=zn(e);var i=e.text.length,o=le(function(e){return On(t,n,e-1).bottom<=r},i,0);return{begin:o,end:i=le(function(e){return On(t,n,e).top>r},o,i)}}function _n(e,t,n,r){return Yn(e,t,n=n||An(e,t),Bn(e,t,On(e,n,r),"line").top)}function $n(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function qn(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Dn){Dn=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Dn.appendChild(document.createTextNode("x")),Dn.appendChild(O("br"));Dn.appendChild(document.createTextNode("x"))}N(e.measure,Dn);var n=Dn.offsetHeight/50;return 3<n&&(e.cachedTextHeight=n),M(e.measure),n||1}function Zn(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),n=O("pre",[t],"CodeMirror-line-like");N(e.measure,n);var r=t.getBoundingClientRect(),i=(r.right-r.left)/10;return 2<i&&(e.cachedCharWidth=i),i||10}function Qn(e){for(var t=e.display,n={},r={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;n[s]=o.offsetLeft+o.clientLeft+i,r[s]=o.clientWidth}return{fixedPos:Jn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function Jn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function er(r){var i=qn(r.display),o=r.options.lineWrapping,l=o&&Math.max(5,r.display.scroller.clientWidth/Zn(r.display)-3);return function(e){if(jt(r.doc,e))return 0;var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;n++)e.widgets[n].height&&(t+=e.widgets[n].height);return o?t+(Math.ceil(e.text.length/l)||1)*i:t+i}}function tr(e){var t=e.doc,n=er(e);t.iter(function(e){var t=n(e);t!=e.height&&tt(e,t)})}function nr(e,t,n,r){var i=e.display;if(!n&&"true"==We(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(e){return null}var a,u,c=Xn(e,o,l);return r&&0<c.xRel&&(a=Qe(e.doc,c.line).text).length==c.ch&&(u=R(a,a.length,e.options.tabSize)-a.length,c=lt(c.line,Math.max(0,Math.round((o-Cn(e.display).left)/Zn(e.display))-u))),c}function rr(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;r<n.length;r++)if((t-=n[r].size)<0)return r}function ir(e,t,n,r){null==t&&(t=e.doc.first),null==n&&(n=e.doc.first+e.doc.size),r=r||0;var i,o,l,s,a=e.display;r&&n<a.viewTo&&(null==a.updateLineNumbers||a.updateLineNumbers>t)&&(a.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=a.viewTo?Nt&&Vt(e.doc,t)<a.viewTo&&lr(e):n<=a.viewFrom?Nt&&Kt(e.doc,n+r)>a.viewFrom?lr(e):(a.viewFrom+=r,a.viewTo+=r):t<=a.viewFrom&&n>=a.viewTo?lr(e):t<=a.viewFrom?(i=sr(e,n,n+r,1))?(a.view=a.view.slice(i.index),a.viewFrom=i.lineN,a.viewTo+=r):lr(e):n>=a.viewTo?(o=sr(e,t,t,-1))?(a.view=a.view.slice(0,o.index),a.viewTo=o.lineN):lr(e):(l=sr(e,t,t,-1),s=sr(e,n,n+r,1),l&&s?(a.view=a.view.slice(0,l.index).concat(on(e,l.lineN,s.lineN)).concat(a.view.slice(s.index)),a.viewTo+=r):lr(e));var u=a.externalMeasured;u&&(n<u.lineN?u.lineN+=r:t<u.lineN+u.size&&(a.externalMeasured=null))}function or(e,t,n){e.curOp.viewChanged=!0;var r,i,o=e.display,l=e.display.externalMeasured;l&&t>=l.lineN&&t<l.lineN+l.size&&(o.externalMeasured=null),t<o.viewFrom||t>=o.viewTo||(null==(r=o.view[rr(e,t)]).node||-1==B(i=r.changes||(r.changes=[]),n)&&i.push(n))}function lr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function sr(e,t,n,r){var i,o=rr(e,t),l=e.display.view;if(!Nt||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var s=e.display.viewFrom,a=0;a<o;a++)s+=l[a].size;if(s!=t){if(0<r){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,n+=i}for(;Vt(e.doc,n)!=n;){if(o==(r<0?0:l.length-1))return null;n+=r*l[o-(r<0?1:0)].size,o+=r}return{index:o,lineN:n}}function ar(e){for(var t=e.display.view,n=0,r=0;r<t.length;r++){var i=t[r];i.hidden||i.node&&!i.changes||++n}return n}function ur(e){e.display.input.showSelection(e.display.input.prepareSelection())}function cr(e,t){void 0===t&&(t=!0);for(var n,r,i=e.doc,o={},l=o.cursors=document.createDocumentFragment(),s=o.selection=document.createDocumentFragment(),a=0;a<i.sel.ranges.length;a++){!t&&a==i.sel.primIndex||((n=i.sel.ranges[a]).from().line>=e.display.viewTo||n.to().line<e.display.viewFrom||(((r=n.empty())||e.options.showCursorWhenSelecting)&&hr(e,n.head,l),r||function(l,e,t){var n=l.display,r=l.doc,i=document.createDocumentFragment(),o=Cn(l.display),T=o.left,M=Math.max(n.sizerWidth,Ln(l)-n.sizer.offsetLeft)-o.right,N="ltr"==r.direction;function A(e,t,n,r){t<0&&(t=0),t=Math.round(t),r=Math.round(r),i.appendChild(O("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==n?M-e:n)+"px;\n height: "+(r-t)+"px"))}function s(n,y,b){var w,x,o=Qe(r,n),C=o.text.length;function S(e,t){return Un(l,lt(n,e),"div",o,t)}function L(e,t,n){var r=_n(l,o,null,e),i="ltr"==t==("after"==n)?"left":"right";return S("after"==n?r.begin:r.end-(/\s/.test(o.text.charAt(r.end-1))?2:1),i)[i]}var k=ye(o,r.direction);return function(e,t,n,r){if(!e)return r(t,n,"ltr",0);for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<n&&l.to>t||t==n&&l.to==t)&&(r(Math.max(l.from,t),Math.min(l.to,n),1==l.level?"rtl":"ltr",o),i=!0)}i||r(t,n,"ltr")}(k,y||0,null==b?C:b,function(e,t,n,r){var i,o,l,s,a,u,c,h="ltr"==n,d=S(e,h?"left":"right"),f=S(t-1,h?"right":"left"),p=null==y&&0==e,g=null==b&&t==C,m=0==r,v=!k||r==k.length-1;f.top-d.top<=3?(i=(N?g:p)&&v,o=(N?p:g)&&m?T:(h?d:f).left,l=i?M:(h?f:d).right,A(o,d.top,l-o,d.bottom)):(c=h?(s=N&&p&&m?T:d.left,a=N?M:L(e,n,"before"),u=N?T:L(t,n,"after"),N&&g&&v?M:f.right):(s=N?L(e,n,"before"):T,a=!N&&p&&m?M:d.right,u=!N&&g&&v?T:f.left,N?L(t,n,"after"):M),A(s,d.top,a-s,d.bottom),d.bottom<f.top&&A(T,d.bottom,null,f.top),A(u,f.top,c-u,f.bottom)),(!w||dr(d,w)<0)&&(w=d),dr(f,w)<0&&(w=f),(!x||dr(d,x)<0)&&(x=d),dr(f,x)<0&&(x=f)}),{start:w,end:x}}var a=e.from(),u=e.to();{var c,h,d,f,p;a.line==u.line?s(a.line,a.ch,u.ch):(c=Qe(r,a.line),h=Qe(r,u.line),d=Ut(c)==Ut(h),f=s(a.line,a.ch,d?c.text.length+1:null).end,p=s(u.line,d?0:null,u.ch).start,d&&(f.top<p.top-2?(A(f.right,f.top,null,f.bottom),A(T,p.top,p.left,p.bottom)):A(f.right,f.top,p.left-f.right,f.bottom)),f.bottom<p.top&&A(T,f.bottom,null,p.top))}t.appendChild(i)}(e,n,s)))}return o}function hr(e,t,n){var r,i=Vn(e,t,"div",null,null,!e.options.singleCursorHeightPerLine),o=n.appendChild(O("div"," ","CodeMirror-cursor"));o.style.left=i.left+"px",o.style.top=i.top+"px",o.style.height=Math.max(0,i.bottom-i.top)*e.options.cursorHeight+"px",i.other&&((r=n.appendChild(O("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"))).style.display="",r.style.left=i.other.left+"px",r.style.top=i.other.top+"px",r.style.height=.85*(i.other.bottom-i.other.top)+"px")}function dr(e,t){return e.top-t.top||e.left-t.left}function fr(e){var t,n;e.state.focused&&(t=e.display,clearInterval(t.blinker),n=!0,t.cursorDiv.style.visibility="",0<e.options.cursorBlinkRate?t.blinker=setInterval(function(){e.hasFocus()||vr(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden"))}function pr(e){e.state.focused||(e.display.input.focus(),mr(e))}function gr(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,vr(e))},100)}function mr(e,t){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(Se(e,"focus",e,t),e.state.focused=!0,H(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),v&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),fr(e))}function vr(e,t){e.state.delayingBlurEvent||(e.state.focused&&(Se(e,"blur",e,t),e.state.focused=!1,T(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function yr(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=0;r<t.view.length;r++){var i,o,l=t.view[r],s=e.options.lineWrapping,a=void 0,u=0;if(!l.hidden){x&&C<8?(a=(i=l.node.offsetTop+l.node.offsetHeight)-n,n=i):(a=(o=l.node.getBoundingClientRect()).bottom-o.top,!s&&l.text.firstChild&&(u=l.text.firstChild.getBoundingClientRect().right-o.left-1));var c,h=l.line.height-a;if((.005<h||h<-.005)&&(tt(l.line,a),br(l.line),l.rest))for(var d=0;d<l.rest.length;d++)br(l.rest[d]);u>e.display.sizerWidth&&((c=Math.ceil(u/Zn(e.display)))>e.display.maxLineLength&&(e.display.maxLineLength=c,e.display.maxLine=l.line,e.display.maxLineChanged=!0))}}}function br(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t){var n=e.widgets[t],r=n.node.parentNode;r&&(n.height=r.offsetHeight)}}function wr(e,t,n){var r,i,o=n&&null!=n.top?Math.max(0,n.top):e.scroller.scrollTop,o=Math.floor(o-wn(e)),l=n&&null!=n.bottom?n.bottom:o+e.wrapper.clientHeight,s=rt(t,o),a=rt(t,l);return n&&n.ensure&&(r=n.ensure.from.line,i=n.ensure.to.line,r<s?a=rt(t,Xt(Qe(t,s=r))+e.wrapper.clientHeight):Math.min(i,t.lastLine())>=a&&(s=rt(t,Xt(Qe(t,i))-e.wrapper.clientHeight),a=i)),{from:s,to:Math.max(a,s+1)}}function xr(e,t){var n=e.display,r=qn(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:n.scroller.scrollTop,o=kn(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s,a=e.doc.height+xn(n),u=t.top<r,c=t.bottom>a-r;t.top<i?l.scrollTop=u?0:t.top:t.bottom>i+o&&((s=Math.min(t.top,(c?a:t.bottom)-o))!=i&&(l.scrollTop=s));var h=e.options.fixedGutter?0:n.gutters.offsetWidth,d=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-h,f=Ln(e)-n.gutters.offsetWidth,p=t.right-t.left>f;return p&&(t.right=t.left+f),t.left<10?l.scrollLeft=0:t.left<d?l.scrollLeft=Math.max(0,t.left+h-(p?0:10)):t.right>f+d-3&&(l.scrollLeft=t.right+(p?0:10)-f),l}function Cr(e,t){null!=t&&(kr(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function Sr(e){kr(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function Lr(e,t,n){null==t&&null==n||kr(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function kr(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Tr(e,Kn(e,t.from),Kn(e,t.to),t.margin))}function Tr(e,t,n,r){var i=xr(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});Lr(e,i.scrollLeft,i.scrollTop)}function Mr(e,t){Math.abs(e.doc.scrollTop-t)<2||(g||$r(e,{top:t}),Nr(e,t,!0),g&&$r(e),Kr(e,100))}function Nr(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),e.display.scroller.scrollTop==t&&!n||(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Ar(e,t,n,r){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,Qr(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Or(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+xn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+Sn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}function Dr(e,t,n){this.cm=n;var r=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");r.tabIndex=i.tabIndex=-1,e(r),e(i),we(r,"scroll",function(){r.clientHeight&&t(r.scrollTop,"vertical")}),we(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,x&&C<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}Dr.prototype.update=function(e){var t,n,r=e.scrollWidth>e.clientWidth+1,i=e.scrollHeight>e.clientHeight+1,o=e.nativeBarWidth;return i?(this.vert.style.display="block",this.vert.style.bottom=r?o+"px":"0",t=e.viewHeight-(r?o:0),this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+t)+"px"):(this.vert.style.display="",this.vert.firstChild.style.height="0"),r?(this.horiz.style.display="block",this.horiz.style.right=i?o+"px":"0",this.horiz.style.left=e.barLeft+"px",n=e.viewWidth-e.barLeft-(i?o:0),this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+n)+"px"):(this.horiz.style.display="",this.horiz.firstChild.style.width="0"),!this.checkedZeroWidth&&0<e.clientHeight&&(0==o&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:i?o:0,bottom:r?o:0}},Dr.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},Dr.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},Dr.prototype.zeroWidthHack=function(){var e=y&&!s?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new z,this.disableVert=new z},Dr.prototype.enableZeroWidthBar=function(n,r,i){n.style.pointerEvents="auto",r.set(1e3,function e(){var t=n.getBoundingClientRect();("vert"==i?document.elementFromPoint(t.right-1,(t.top+t.bottom)/2):document.elementFromPoint((t.right+t.left)/2,t.bottom-1))!=n?n.style.pointerEvents="none":r.set(1e3,e)})},Dr.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};function Wr(){}function Hr(e,t){t=t||Or(e);var n=e.display.barWidth,r=e.display.barHeight;Fr(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&yr(e),Fr(e,Or(e)),n=e.display.barWidth,r=e.display.barHeight}function Fr(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}Wr.prototype.update=function(){return{bottom:0,right:0}},Wr.prototype.setScrollLeft=function(){},Wr.prototype.setScrollTop=function(){},Wr.prototype.clear=function(){};var Pr={native:Dr,null:Wr};function Er(n){n.display.scrollbars&&(n.display.scrollbars.clear(),n.display.scrollbars.addClass&&T(n.display.wrapper,n.display.scrollbars.addClass)),n.display.scrollbars=new Pr[n.options.scrollbarStyle](function(e){n.display.wrapper.insertBefore(e,n.display.scrollbarFiller),we(e,"mousedown",function(){n.state.focused&&setTimeout(function(){return n.display.input.focus()},0)}),e.setAttribute("cm-not-content","true")},function(e,t){("horizontal"==t?Ar:Mr)(n,e)},n),n.display.scrollbars.addClass&&H(n.display.wrapper,n.display.scrollbars.addClass)}var Ir=0;function Rr(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Ir},t=e.curOp,ln?ln.ops.push(t):t.ownsGroup=ln={ops:[t],delayedCallbacks:[]}}function zr(e){var t=e.curOp;t&&sn(t,function(e){for(var t=0;t<e.ops.length;t++)e.ops[t].cm.curOp=null;!function(e){for(var t=e.ops,n=0;n<t.length;n++)!function(e){var t=e.cm,n=t.display;(function(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=Sn(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=Sn(e)+"px",t.scrollbarsClipped=!0)})(t),e.updateMaxLine&&_t(t);e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<n.viewFrom||e.scrollToPos.to.line>=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new Xr(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}(t[n]);for(var r=0;r<t.length;r++)!function(e){e.updatedDisplay=e.mustUpdate&&Yr(e.cm,e.update)}(t[r]);for(var i=0;i<t.length;i++)!function(e){var t=e.cm,n=t.display;e.updatedDisplay&&yr(t);e.barMeasure=Or(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Mn(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Sn(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Ln(t)));(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}(t[i]);for(var o=0;o<t.length;o++)!function(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&Ar(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1);var n=e.focus&&e.focus==W();e.preparedSelection&&t.display.input.showSelection(e.preparedSelection,n);!e.updatedDisplay&&e.startHeight==t.doc.height||Hr(t,e.barMeasure);e.updatedDisplay&&Zr(t,e.barMeasure);e.selectionChanged&&fr(t);t.state.focused&&e.updateInput&&t.display.input.reset(e.typing);n&&pr(e.cm)}(t[o]);for(var l=0;l<t.length;l++)!function(e){var t=e.cm,n=t.display,r=t.doc;e.updatedDisplay&&_r(t,e.update);null==n.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(n.wheelStartX=n.wheelStartY=null);null!=e.scrollTop&&Nr(t,e.scrollTop,e.forceScroll);null!=e.scrollLeft&&Ar(t,e.scrollLeft,!0,!0);{var i;e.scrollToPos&&(i=function(e,t,n,r){null==r&&(r=0),e.options.lineWrapping||t!=n||(n="before"==(t=t.ch?lt(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?lt(t.line,t.ch+1,"before"):t);for(var i=0;i<5;i++){var o,l=!1,s=Vn(e,t),a=n&&n!=t?Vn(e,n):s,u=xr(e,o={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-r,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+r}),c=e.doc.scrollTop,h=e.doc.scrollLeft;if(null!=u.scrollTop&&(Mr(e,u.scrollTop),1<Math.abs(e.doc.scrollTop-c)&&(l=!0)),null!=u.scrollLeft&&(Ar(e,u.scrollLeft),1<Math.abs(e.doc.scrollLeft-h)&&(l=!0)),!l)break}return o}(t,ft(r,e.scrollToPos.from),ft(r,e.scrollToPos.to),e.scrollToPos.margin),function(e,t){var n,r,i,o;Le(e,"scrollCursorIntoView")||(r=(n=e.display).sizer.getBoundingClientRect(),i=null,t.top+r.top<0?i=!0:t.bottom+r.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null==i||u||(o=O("div","​",null,"position: absolute;\n top: "+(t.top-n.viewOffset-wn(e.display))+"px;\n height: "+(t.bottom-t.top+Sn(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;"),e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)))}(t,i))}var o=e.maybeHiddenMarkers,l=e.maybeUnhiddenMarkers;if(o)for(var s=0;s<o.length;++s)o[s].lines.length||Se(o[s],"hide");if(l)for(var a=0;a<l.length;++a)l[a].lines.length&&Se(l[a],"unhide");n.wrapper.offsetHeight&&(r.scrollTop=t.display.scroller.scrollTop);e.changeObjs&&Se(t,"changes",t,e.changeObjs);e.update&&e.update.finish()}(t[l])}(e)})}function Br(e,t){if(e.curOp)return t();Rr(e);try{return t()}finally{zr(e)}}function Gr(e,t){return function(){if(e.curOp)return t.apply(e,arguments);Rr(e);try{return t.apply(e,arguments)}finally{zr(e)}}}function Ur(e){return function(){if(this.curOp)return e.apply(this,arguments);Rr(this);try{return e.apply(this,arguments)}finally{zr(this)}}}function Vr(t){return function(){var e=this.cm;if(!e||e.curOp)return t.apply(this,arguments);Rr(e);try{return t.apply(this,arguments)}finally{zr(e)}}}function Kr(e,t){e.doc.highlightFrontier<e.display.viewTo&&e.state.highlight.set(t,E(jr,e))}function jr(a){var u,c,h,d=a.doc;d.highlightFrontier>=a.display.viewTo||(u=+new Date+a.options.workTime,c=bt(a,d.highlightFrontier),h=[],d.iter(c.line,Math.min(d.first+d.size,a.display.viewTo+500),function(e){if(c.line>=a.display.viewFrom){var t=e.styles,n=e.text.length>a.options.maxHighlightLength?_e(d.mode,c.state):null,r=vt(a,e,c,!0);n&&(c.state=n),e.styles=r.styles;var i=e.styleClasses,o=r.classes;o?e.styleClasses=o:i&&(e.styleClasses=null);for(var l=!t||t.length!=e.styles.length||i!=o&&(!i||!o||i.bgClass!=o.bgClass||i.textClass!=o.textClass),s=0;!l&&s<t.length;++s)l=t[s]!=e.styles[s];l&&h.push(c.line),e.stateAfter=c.save(),c.nextLine()}else e.text.length<=a.options.maxHighlightLength&&wt(a,e.text,c),e.stateAfter=c.line%5==0?c.save():null,c.nextLine();if(+new Date>u)return Kr(a,a.options.workDelay),!0}),d.highlightFrontier=c.line,d.modeFrontier=Math.max(d.modeFrontier,c.line),h.length&&Br(a,function(){for(var e=0;e<h.length;e++)or(a,h[e],"text")}))}var Xr=function(e,t,n){var r=e.display;this.viewport=t,this.visible=wr(r,e.doc,t),this.editorIsHidden=!r.wrapper.offsetWidth,this.wrapperHeight=r.wrapper.clientHeight,this.wrapperWidth=r.wrapper.clientWidth,this.oldDisplayWidth=Ln(e),this.force=n,this.dims=Qn(e),this.events=[]};function Yr(e,t){var n=e.display,r=e.doc;if(t.editorIsHidden)return lr(e),!1;if(!t.force&&t.visible.from>=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==ar(e))return!1;Jr(e)&&(lr(e),t.dims=Qn(e));var i=r.first+r.size,o=Math.max(t.visible.from-e.options.viewportMargin,r.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);n.viewFrom<o&&o-n.viewFrom<20&&(o=Math.max(r.first,n.viewFrom)),n.viewTo>l&&n.viewTo-l<20&&(l=Math.min(i,n.viewTo)),Nt&&(o=Vt(e.doc,o),l=Kt(e.doc,l));var s,a,u,c,h=o!=n.viewFrom||l!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;a=o,u=l,0==(c=(s=e).display).view.length||a>=c.viewTo||u<=c.viewFrom?(c.view=on(s,a,u),c.viewFrom=a):(c.viewFrom>a?c.view=on(s,a,c.viewFrom).concat(c.view):c.viewFrom<a&&(c.view=c.view.slice(rr(s,a))),c.viewFrom=a,c.viewTo<u?c.view=c.view.concat(on(s,c.viewTo,u)):c.viewTo>u&&(c.view=c.view.slice(0,rr(s,u)))),c.viewTo=u,n.viewOffset=Xt(Qe(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var d=ar(e);if(!h&&0==d&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var f,p,g,m=function(e){if(e.hasFocus())return null;var t=W();if(!t||!D(e.display.lineDiv,t))return null;var n,r={activeElt:t};return!window.getSelection||(n=window.getSelection()).anchorNode&&n.extend&&D(e.display.lineDiv,n.anchorNode)&&(r.anchorNode=n.anchorNode,r.anchorOffset=n.anchorOffset,r.focusNode=n.focusNode,r.focusOffset=n.focusOffset),r}(e);return 4<d&&(n.lineDiv.style.display="none"),function(n,e,t){var r=n.display,i=n.options.lineNumbers,o=r.lineDiv,l=o.firstChild;function s(e){var t=e.nextSibling;return v&&y&&n.display.currentWheelTarget==e?e.style.display="none":e.parentNode.removeChild(e),t}for(var a=r.view,u=r.viewFrom,c=0;c<a.length;c++){var h=a[c];if(!h.hidden)if(h.node&&h.node.parentNode==o){for(;l!=h.node;)l=s(l);var d=i&&null!=e&&e<=u&&h.lineNumber;h.changes&&(-1<B(h.changes,"gutter")&&(d=!1),hn(n,h,u,t)),d&&(M(h.lineNumber),h.lineNumber.appendChild(document.createTextNode(ot(n.options,u)))),l=h.node.nextSibling}else{var f=function(e,t,n,r){var i=fn(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),pn(e,t),gn(e,t,n,r),mn(e,t,r),t.node}(n,h,u,t);o.insertBefore(f,l)}u+=h.size}for(;l;)l=s(l)}(e,n.updateLineNumbers,t.dims),4<d&&(n.lineDiv.style.display=""),n.renderedView=n.view,(f=m)&&f.activeElt&&f.activeElt!=W()&&(f.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(f.activeElt.nodeName)&&f.anchorNode&&D(document.body,f.anchorNode)&&D(document.body,f.focusNode)&&(p=window.getSelection(),(g=document.createRange()).setEnd(f.anchorNode,f.anchorOffset),g.collapse(!1),p.removeAllRanges(),p.addRange(g),p.extend(f.focusNode,f.focusOffset))),M(n.cursorDiv),M(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,h&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,Kr(e,400)),!(n.updateLineNumbers=null)}function _r(e,t){for(var n=t.viewport,r=!0;;r=!1){if(r&&e.options.lineWrapping&&t.oldDisplayWidth!=Ln(e))r&&(t.visible=wr(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+xn(e.display)-kn(e),n.top)}),t.visible=wr(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!Yr(e,t))break;yr(e);var i=Or(e);ur(e),Hr(e,i),Zr(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function $r(e,t){var n,r=new Xr(e,t);Yr(e,r)&&(yr(e),_r(e,r),n=Or(e),ur(e),Hr(e,n),Zr(e,n),r.finish())}function qr(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function Zr(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Sn(e)+"px"}function Qr(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=Jn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=r+"px",l=0;l<n.length;l++)if(!n[l].hidden){e.options.fixedGutter&&(n[l].gutter&&(n[l].gutter.style.left=o),n[l].gutterBackground&&(n[l].gutterBackground.style.left=o));var s=n[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=r+i+"px")}}function Jr(e){if(e.options.lineNumbers){var t=e.doc,n=ot(e.options,t.first+t.size-1),r=e.display;if(n.length!=r.lineNumChars){var i=r.measure.appendChild(O("div",[O("div",n)],"CodeMirror-linenumber CodeMirror-gutter-elt")),o=i.firstChild.offsetWidth,l=i.offsetWidth-o;return r.lineGutter.style.width="",r.lineNumInnerWidth=Math.max(o,r.lineGutter.offsetWidth-l)+1,r.lineNumWidth=r.lineNumInnerWidth+l,r.lineNumChars=r.lineNumInnerWidth?n.length:-1,r.lineGutter.style.width=r.lineNumWidth+"px",qr(e.display),1}}}function ei(e,t){for(var n=[],r=!1,i=0;i<e.length;i++){var o=e[i],l=null;if("string"!=typeof o&&(l=o.style,o=o.className),"CodeMirror-linenumbers"==o){if(!t)continue;r=!0}n.push({className:o,style:l})}return t&&!r&&n.push({className:"CodeMirror-linenumbers",style:null}),n}function ti(e){var t=e.gutters,n=e.gutterSpecs;M(t),e.lineGutter=null;for(var r=0;r<n.length;++r){var i=n[r],o=i.className,l=i.style,s=t.appendChild(O("div",null,"CodeMirror-gutter "+o));l&&(s.style.cssText=l),"CodeMirror-linenumbers"==o&&((e.lineGutter=s).style.width=(e.lineNumWidth||1)+"px")}t.style.display=n.length?"":"none",qr(e)}function ni(e){ti(e.display),ir(e),Qr(e)}function ri(e,t,n,r){var i=this;this.input=n,i.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),i.scrollbarFiller.setAttribute("cm-not-content","true"),i.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),i.gutterFiller.setAttribute("cm-not-content","true"),i.lineDiv=A("div",null,"CodeMirror-code"),i.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),i.cursorDiv=O("div",null,"CodeMirror-cursors"),i.measure=O("div",null,"CodeMirror-measure"),i.lineMeasure=O("div",null,"CodeMirror-measure"),i.lineSpace=A("div",[i.measure,i.lineMeasure,i.selectionDiv,i.cursorDiv,i.lineDiv],null,"position: relative; outline: none");var o=A("div",[i.lineSpace],"CodeMirror-lines");i.mover=O("div",[o],null,"position: relative"),i.sizer=O("div",[i.mover],"CodeMirror-sizer"),i.sizerWidth=null,i.heightForcer=O("div",null,null,"position: absolute; height: "+G+"px; width: 1px;"),i.gutters=O("div",null,"CodeMirror-gutters"),i.lineGutter=null,i.scroller=O("div",[i.sizer,i.heightForcer,i.gutters],"CodeMirror-scroll"),i.scroller.setAttribute("tabIndex","-1"),i.wrapper=O("div",[i.scrollbarFiller,i.gutterFiller,i.scroller],"CodeMirror"),x&&C<8&&(i.gutters.style.zIndex=-1,i.scroller.style.paddingRight=0),v||g&&d||(i.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(i.wrapper):e(i.wrapper)),i.viewFrom=i.viewTo=t.first,i.reportedViewFrom=i.reportedViewTo=t.first,i.view=[],i.renderedView=null,i.externalMeasured=null,i.viewOffset=0,i.lastWrapHeight=i.lastWrapWidth=0,i.updateLineNumbers=null,i.nativeBarWidth=i.barHeight=i.barWidth=0,i.scrollbarsClipped=!1,i.lineNumWidth=i.lineNumInnerWidth=i.lineNumChars=null,i.alignWidgets=!1,i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.maxLine=null,i.maxLineLength=0,i.maxLineChanged=!1,i.wheelDX=i.wheelDY=i.wheelStartX=i.wheelStartY=null,i.shift=!1,i.selForContextMenu=null,i.activeTouch=null,i.gutterSpecs=ei(r.gutters,r.lineNumbers),ti(i),n.init(i)}Xr.prototype.signal=function(e,t){Te(e,t)&&this.events.push(arguments)},Xr.prototype.finish=function(){for(var e=0;e<this.events.length;e++)Se.apply(null,this.events[e])};var ii=0,oi=null;function li(e){var t=e.wheelDeltaX,n=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==n&&e.detail&&e.axis==e.VERTICAL_AXIS?n=e.detail:null==n&&(n=e.wheelDelta),{x:t,y:n}}function si(e){var t=li(e);return t.x*=oi,t.y*=oi,t}function ai(e,t){var n,r,i,o=li(t),l=o.x,s=o.y,a=e.display,u=a.scroller,c=u.scrollWidth>u.clientWidth,h=u.scrollHeight>u.clientHeight;if(l&&c||s&&h){if(s&&y&&v)e:for(var d=t.target,f=a.view;d!=u;d=d.parentNode)for(var p=0;p<f.length;p++)if(f[p].node==d){e.display.currentWheelTarget=d;break e}if(l&&!g&&!m&&null!=oi)return s&&h&&Mr(e,Math.max(0,u.scrollTop+s*oi)),Ar(e,Math.max(0,u.scrollLeft+l*oi)),(!s||s&&h)&&Ne(t),void(a.wheelStartX=null);s&&null!=oi&&(n=s*oi,i=(r=e.doc.scrollTop)+a.wrapper.clientHeight,n<0?r=Math.max(0,r+n-50):i=Math.min(e.doc.height,i+n+50),$r(e,{top:r,bottom:i})),ii<20&&(null==a.wheelStartX?(a.wheelStartX=u.scrollLeft,a.wheelStartY=u.scrollTop,a.wheelDX=l,a.wheelDY=s,setTimeout(function(){var e,t,n;null!=a.wheelStartX&&(e=u.scrollLeft-a.wheelStartX,n=(t=u.scrollTop-a.wheelStartY)&&a.wheelDY&&t/a.wheelDY||e&&a.wheelDX&&e/a.wheelDX,a.wheelStartX=a.wheelStartY=null,n&&(oi=(oi*ii+n)/(ii+1),++ii))},200)):(a.wheelDX+=l,a.wheelDY+=s))}}x?oi=-.53:g?oi=15:l?oi=-.7:c&&(oi=-1/3);var ui=function(e,t){this.ranges=e,this.primIndex=t};ui.prototype.primary=function(){return this.ranges[this.primIndex]},ui.prototype.equals=function(e){if(e==this)return!0;if(e.primIndex!=this.primIndex||e.ranges.length!=this.ranges.length)return!1;for(var t=0;t<this.ranges.length;t++){var n=this.ranges[t],r=e.ranges[t];if(!at(n.anchor,r.anchor)||!at(n.head,r.head))return!1}return!0},ui.prototype.deepCopy=function(){for(var e=[],t=0;t<this.ranges.length;t++)e[t]=new ci(ut(this.ranges[t].anchor),ut(this.ranges[t].head));return new ui(e,this.primIndex)},ui.prototype.somethingSelected=function(){for(var e=0;e<this.ranges.length;e++)if(!this.ranges[e].empty())return!0;return!1},ui.prototype.contains=function(e,t){t=t||e;for(var n=0;n<this.ranges.length;n++){var r=this.ranges[n];if(0<=st(t,r.from())&&st(e,r.to())<=0)return n}return-1};var ci=function(e,t){this.anchor=e,this.head=t};function hi(e,t,n){var r=e&&e.options.selectionsMayTouch,i=t[n];t.sort(function(e,t){return st(e.from(),t.from())}),n=B(t,i);for(var o=1;o<t.length;o++){var l,s,a,u=t[o],c=t[o-1],h=st(c.to(),u.from());(r&&!u.empty()?0<h:0<=h)&&(l=ht(c.from(),u.from()),s=ct(c.to(),u.to()),a=c.empty()?u.from()==u.head:c.from()==c.head,o<=n&&--n,t.splice(--o,2,new ci(a?s:l,a?l:s)))}return new ui(t,n)}function di(e,t){return new ui([new ci(e,t||e)],0)}function fi(e){return e.text?lt(e.from.line+e.text.length-1,$(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function pi(e,t){if(st(e,t.from)<0)return e;if(st(e,t.to)<=0)return fi(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=fi(t).ch-t.to.ch),lt(n,r)}function gi(e,t){for(var n=[],r=0;r<e.sel.ranges.length;r++){var i=e.sel.ranges[r];n.push(new ci(pi(i.anchor,t),pi(i.head,t)))}return hi(e.cm,n,e.sel.primIndex)}function mi(e,t,n){return e.line==t.line?lt(n.line,e.ch-t.ch+n.ch):lt(n.line+(e.line-t.line),e.ch)}function vi(e){e.doc.mode=je(e.options,e.doc.modeOption),yi(e)}function yi(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.modeFrontier=e.doc.highlightFrontier=e.doc.first,Kr(e,100),e.state.modeGen++,e.curOp&&ir(e)}function bi(e,t){return 0==t.from.ch&&0==t.to.ch&&""==$(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function wi(e,r,t,i){function o(e){return t?t[e]:null}function n(e,t,n){!function(e,t,n,r){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),Ht(e),Ft(e,n);var i=r?r(e):1;i!=e.height&&tt(e,i)}(e,t,n,i),un(e,"change",e,r)}function l(e,t){for(var n=[],r=e;r<t;++r)n.push(new $t(d[r],o(r),i));return n}var s,a,u,c=r.from,h=r.to,d=r.text,f=Qe(e,c.line),p=Qe(e,h.line),g=$(d),m=o(d.length-1),v=h.line-c.line;r.full?(e.insert(0,l(0,d.length)),e.remove(d.length,e.size-d.length)):bi(e,r)?(s=l(0,d.length-1),n(p,p.text,m),v&&e.remove(c.line,v),s.length&&e.insert(c.line,s)):f==p?1==d.length?n(f,f.text.slice(0,c.ch)+g+f.text.slice(h.ch),m):((a=l(1,d.length-1)).push(new $t(g+f.text.slice(h.ch),m,i)),n(f,f.text.slice(0,c.ch)+d[0],o(0)),e.insert(c.line+1,a)):1==d.length?(n(f,f.text.slice(0,c.ch)+d[0]+p.text.slice(h.ch),o(0)),e.remove(c.line+1,v)):(n(f,f.text.slice(0,c.ch)+d[0],o(0)),n(p,g+p.text.slice(h.ch),m),u=l(1,d.length-1),1<v&&e.remove(c.line+1,v-1),e.insert(c.line+1,u)),un(e,"change",e,r)}function xi(e,s,a){!function e(t,n,r){if(t.linked)for(var i=0;i<t.linked.length;++i){var o,l=t.linked[i];l.doc!=n&&(o=r&&l.sharedHist,a&&!o||(s(l.doc,o),e(l.doc,t,o)))}}(e,null,!0)}function Ci(e,t){if(t.cm)throw new Error("This document is already in use.");tr((e.doc=t).cm=e),vi(e),Si(e),e.options.lineWrapping||_t(e),e.options.mode=t.modeOption,ir(e)}function Si(e){("rtl"==e.doc.direction?H:T)(e.display.lineDiv,"CodeMirror-rtl")}function Li(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function ki(e,t){var n={from:ut(t.from),to:fi(t),text:Je(e,t.from,t.to)};return Oi(e,n,t.from.line,t.to.line+1),xi(e,function(e){return Oi(e,n,t.from.line,t.to.line+1),0},!0),n}function Ti(e){for(;e.length;){if(!$(e).ranges)break;e.pop()}}function Mi(e,t,n,r){var i=e.history;i.undone.length=0;var o,l,s,a=+new Date;if((i.lastOp==r||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>a-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=(s=i).lastOp==r?(Ti(s.done),$(s.done)):s.done.length&&!$(s.done).ranges?$(s.done):1<s.done.length&&!s.done[s.done.length-2].ranges?(s.done.pop(),$(s.done)):void 0))l=$(o.changes),0==st(t.from,t.to)&&0==st(t.from,l.to)?l.to=fi(t):o.changes.push(ki(e,t));else{var u=$(i.done);for(u&&u.ranges||Ai(e.sel,i.done),o={changes:[ki(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(n),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=a,i.lastOp=i.lastSelOp=r,i.lastOrigin=i.lastSelOrigin=t.origin,l||Se(e,"historyAdded")}function Ni(e,t,n,r){var i,o,l,s,a,u=e.history,c=r&&r.origin;n==u.lastSelOp||c&&u.lastSelOrigin==c&&(u.lastModTime==u.lastSelTime&&u.lastOrigin==c||(i=e,o=c,l=$(u.done),s=t,"*"==(a=o.charAt(0))||"+"==a&&l.ranges.length==s.ranges.length&&l.somethingSelected()==s.somethingSelected()&&new Date-i.history.lastSelTime<=(i.cm?i.cm.options.historyEventDelay:500)))?u.done[u.done.length-1]=t:Ai(t,u.done),u.lastSelTime=+new Date,u.lastSelOrigin=c,u.lastSelOp=n,r&&!1!==r.clearRedo&&Ti(u.undone)}function Ai(e,t){var n=$(t);n&&n.ranges&&n.equals(e)||t.push(e)}function Oi(t,n,e,r){var i=n["spans_"+t.id],o=0;t.iter(Math.max(t.first,e),Math.min(t.first+t.size,r),function(e){e.markedSpans&&((i=i||(n["spans_"+t.id]={}))[o]=e.markedSpans),++o})}function Di(e,t){var n=t["spans_"+e.id];if(!n)return null;for(var r=[],i=0;i<t.text.length;++i)r.push(function(e){if(!e)return null;for(var t,n=0;n<e.length;++n)e[n].marker.explicitlyCleared?t=t||e.slice(0,n):t&&t.push(e[n]);return t?t.length?t:null:e}(n[i]));return r}function Wi(e,t){var n=Di(e,t),r=Dt(e,t);if(!n)return r;if(!r)return n;for(var i=0;i<n.length;++i){var o=n[i],l=r[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(n[i]=l)}return n}function Hi(e,t,n){for(var r=[],i=0;i<e.length;++i){var o=e[i];if(o.ranges)r.push(n?ui.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];r.push({changes:s});for(var a=0;a<l.length;++a){var u=l[a],c=void 0;if(s.push({from:u.from,to:u.to,text:u.text}),t)for(var h in u)(c=h.match(/^spans_(\d+)$/))&&-1<B(t,Number(c[1]))&&($(s)[h]=u[h],delete u[h])}}}return r}function Fi(e,t,n,r){if(r){var i,o=e.anchor;return n&&((i=st(t,o)<0)!=st(n,o)<0?(o=t,t=n):i!=st(t,n)<0&&(t=n)),new ci(o,t)}return new ci(n||t,t)}function Pi(e,t,n,r,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),Bi(e,new ui([Fi(e.sel.primary(),t,n,i)],0),r)}function Ei(e,t,n){for(var r=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o<e.sel.ranges.length;o++)r[o]=Fi(e.sel.ranges[o],t[o],null,i);Bi(e,hi(e.cm,r,e.sel.primIndex),n)}function Ii(e,t,n,r){var i=e.sel.ranges.slice(0);i[t]=n,Bi(e,hi(e.cm,i,e.sel.primIndex),r)}function Ri(e,t,n,r){Bi(e,di(t,n),r)}function zi(e,t,n){var r=e.history.done,i=$(r);i&&i.ranges?Gi(e,r[r.length-1]=t,n):Bi(e,t,n)}function Bi(e,t,n){Gi(e,t,n),Ni(e,e.sel,e.cm?e.cm.curOp.id:NaN,n)}function Gi(e,t,n){var r,i,o,l;(Te(e,"beforeSelectionChange")||e.cm&&Te(e.cm,"beforeSelectionChange"))&&(r=e,o=n,l={ranges:(i=t).ranges,update:function(e){this.ranges=[];for(var t=0;t<e.length;t++)this.ranges[t]=new ci(ft(r,e[t].anchor),ft(r,e[t].head))},origin:o&&o.origin},Se(r,"beforeSelectionChange",r,l),r.cm&&Se(r.cm,"beforeSelectionChange",r.cm,l),t=l.ranges!=i.ranges?hi(r.cm,l.ranges,l.ranges.length-1):i);var s=n&&n.bias||(st(t.primary().head,e.sel.primary().head)<0?-1:1);Ui(e,Ki(e,t,s,!0)),n&&!1===n.scroll||!e.cm||Sr(e.cm)}function Ui(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=1,e.cm.curOp.selectionChanged=!0,ke(e.cm)),un(e,"cursorActivity",e))}function Vi(e){Ui(e,Ki(e,e.sel,null,!1))}function Ki(e,t,n,r){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=t.ranges.length==e.sel.ranges.length&&e.sel.ranges[o],a=Xi(e,l.anchor,s&&s.anchor,n,r),u=Xi(e,l.head,s&&s.head,n,r);!i&&a==l.anchor&&u==l.head||((i=i||t.ranges.slice(0,o))[o]=new ci(a,u))}return i?hi(e.cm,i,t.primIndex):t}function ji(e,t,n,r,i){var o=Qe(e,t.line);if(o.markedSpans)for(var l=0;l<o.markedSpans.length;++l){var s=o.markedSpans[l],a=s.marker,u="selectLeft"in a?!a.selectLeft:a.inclusiveLeft,c="selectRight"in a?!a.selectRight:a.inclusiveRight;if((null==s.from||(u?s.from<=t.ch:s.from<t.ch))&&(null==s.to||(c?s.to>=t.ch:s.to>t.ch))){if(i&&(Se(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(n){var h=a.find(r<0?1:-1),d=void 0;if((r<0?c:u)&&(h=Yi(e,h,-r,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(d=st(h,n))&&(r<0?d<0:0<d))return ji(e,h,t,r,i)}var f=a.find(r<0?-1:1);return(r<0?u:c)&&(f=Yi(e,f,r,f.line==t.line?o:null)),f?ji(e,f,t,r,i):null}}return t}function Xi(e,t,n,r,i){var o=r||1,l=ji(e,t,n,o,i)||!i&&ji(e,t,n,o,!0)||ji(e,t,n,-o,i)||!i&&ji(e,t,n,-o,!0);return l||(e.cantEdit=!0,lt(e.first,0))}function Yi(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?ft(e,lt(t.line-1)):null:0<n&&t.ch==(r||Qe(e,t.line)).text.length?t.line<e.first+e.size-1?lt(t.line+1,0):null:new lt(t.line,t.ch+n)}function _i(e){e.setSelection(lt(e.firstLine(),0),lt(e.lastLine()),V)}function $i(i,e,t){var o={canceled:!1,from:e.from,to:e.to,text:e.text,origin:e.origin,cancel:function(){return o.canceled=!0}};return t&&(o.update=function(e,t,n,r){e&&(o.from=ft(i,e)),t&&(o.to=ft(i,t)),n&&(o.text=n),void 0!==r&&(o.origin=r)}),Se(i,"beforeChange",i,o),i.cm&&Se(i.cm,"beforeChange",i.cm,o),o.canceled?(i.cm&&(i.cm.curOp.updateInput=2),null):{from:o.from,to:o.to,text:o.text,origin:o.origin}}function qi(e,t,n){if(e.cm){if(!e.cm.curOp)return Gr(e.cm,qi)(e,t,n);if(e.cm.state.suppressEdits)return}if(!(Te(e,"beforeChange")||e.cm&&Te(e.cm,"beforeChange"))||(t=$i(e,t,!0))){var r=Mt&&!n&&function(e,t,n){var r=null;if(e.iter(t.line,n.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var n=e.markedSpans[t].marker;!n.readOnly||r&&-1!=B(r,n)||(r=r||[]).push(n)}}),!r)return null;for(var i=[{from:t,to:n}],o=0;o<r.length;++o)for(var l=r[o],s=l.find(0),a=0;a<i.length;++a){var u,c,h,d=i[a];st(d.to,s.from)<0||0<st(d.from,s.to)||(u=[a,1],c=st(d.from,s.from),h=st(d.to,s.to),(c<0||!l.inclusiveLeft&&!c)&&u.push({from:d.from,to:s.from}),(0<h||!l.inclusiveRight&&!h)&&u.push({from:s.to,to:d.to}),i.splice.apply(i,u),a+=u.length-3)}return i}(e,t.from,t.to);if(r)for(var i=r.length-1;0<=i;--i)Zi(e,{from:r[i].from,to:r[i].to,text:i?[""]:t.text,origin:t.origin});else Zi(e,t)}}function Zi(e,n){var t,r;1==n.text.length&&""==n.text[0]&&0==st(n.from,n.to)||(t=gi(e,n),Mi(e,n,t,e.cm?e.cm.curOp.id:NaN),eo(e,n,t,Dt(e,n)),r=[],xi(e,function(e,t){t||-1!=B(r,e.history)||(io(e.history,n),r.push(e.history)),eo(e,n,null,Dt(e,n))}))}function Qi(i,o,e){var t=i.cm&&i.cm.state.suppressEdits;if(!t||e){for(var l,n=i.history,r=i.sel,s="undo"==o?n.done:n.undone,a="undo"==o?n.undone:n.done,u=0;u<s.length&&(l=s[u],e?!l.ranges||l.equals(i.sel):l.ranges);u++);if(u!=s.length){for(n.lastOrigin=n.lastSelOrigin=null;;){if(!(l=s.pop()).ranges){if(t)return void s.push(l);break}if(Ai(l,a),e&&!l.equals(i.sel))return void Bi(i,l,{clearRedo:!1});r=l}var c=[];Ai(r,a),a.push({changes:c,generation:n.generation}),n.generation=l.generation||++n.maxGeneration;for(var h=Te(i,"beforeChange")||i.cm&&Te(i.cm,"beforeChange"),d=l.changes.length-1;0<=d;--d){var f=function(e){var n=l.changes[e];if(n.origin=o,h&&!$i(i,n,!1))return s.length=0,{};c.push(ki(i,n));var t=e?gi(i,n):$(s);eo(i,n,t,Wi(i,n)),!e&&i.cm&&i.cm.scrollIntoView({from:n.from,to:fi(n)});var r=[];xi(i,function(e,t){t||-1!=B(r,e.history)||(io(e.history,n),r.push(e.history)),eo(e,n,null,Wi(e,n))})}(d);if(f)return f.v}}}}function Ji(e,t){if(0!=t&&(e.first+=t,e.sel=new ui(q(e.sel.ranges,function(e){return new ci(lt(e.anchor.line+t,e.anchor.ch),lt(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){ir(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;r<n.viewTo;r++)or(e.cm,r,"gutter")}}function eo(e,t,n,r){if(e.cm&&!e.cm.curOp)return Gr(e.cm,eo)(e,t,n,r);var i,o;t.to.line<e.first?Ji(e,t.text.length-1-(t.to.line-t.from.line)):t.from.line>e.lastLine()||(t.from.line<e.first&&(Ji(e,i=t.text.length-1-(e.first-t.from.line)),t={from:lt(e.first,0),to:lt(t.to.line+i,t.to.ch),text:[$(t.text)],origin:t.origin}),o=e.lastLine(),t.to.line>o&&(t={from:t.from,to:lt(o,Qe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Je(e,t.from,t.to),n=n||gi(e,t),e.cm?function(e,t,n){var r=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=nt(Ut(Qe(r,o.line))),r.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0}));-1<r.sel.contains(t.from,t.to)&&ke(e);wi(r,t,n,er(e)),e.options.lineWrapping||(r.iter(a,o.line+t.text.length,function(e){var t=Yt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontier<t-10)){for(var n=e.first,r=t-1;n<r;r--){var i=Qe(e,r).stateAfter;if(i&&(!(i instanceof gt)||r+i.lookAhead<t)){n=r+1;break}}e.highlightFrontier=Math.min(e.highlightFrontier,n)}})(r,o.line),Kr(e,400);var u=t.text.length-(l.line-o.line)-1;t.full?ir(e):o.line!=l.line||1!=t.text.length||bi(e.doc,t)?ir(e,o.line,l.line+1,u):or(e,o.line,"text");var c=Te(e,"changes"),h=Te(e,"change");{var d;(h||c)&&(d={from:o,to:l,text:t.text,removed:t.removed,origin:t.origin},h&&un(e,"change",e,d),c&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(d))}e.display.selForContextMenu=null}(e.cm,t,r):wi(e,t,r),Gi(e,n,V),e.cantEdit&&Xi(e,lt(e.firstLine(),0))&&(e.cantEdit=!1))}function to(e,t,n,r,i){var o;st(r=r||n,n)<0&&(n=(o=[r,n])[0],r=o[1]),"string"==typeof t&&(t=e.splitLines(t)),qi(e,{from:n,to:r,text:t,origin:i})}function no(e,t,n,r){n<e.line?e.line+=r:t<e.line&&(e.line=t,e.ch=0)}function ro(e,t,n,r){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||((o=e[i]=o.deepCopy()).copied=!0);for(var s=0;s<o.ranges.length;s++)no(o.ranges[s].anchor,t,n,r),no(o.ranges[s].head,t,n,r)}else{for(var a=0;a<o.changes.length;++a){var u=o.changes[a];if(n<u.from.line)u.from=lt(u.from.line+r,u.from.ch),u.to=lt(u.to.line+r,u.to.ch);else if(t<=u.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function io(e,t){var n=t.from.line,r=t.to.line,i=t.text.length-(r-n)-1;ro(e.done,n,r,i),ro(e.undone,n,r,i)}function oo(e,t,n,r){var i=t,o=t;return"number"==typeof t?o=Qe(e,dt(e,t)):i=nt(t),null==i?null:(r(o,i)&&e.cm&&or(e.cm,i,n),o)}function lo(e){this.lines=e,this.parent=null;for(var t=0,n=0;n<e.length;++n)e[n].parent=this,t+=e[n].height;this.height=t}function so(e){this.children=e;for(var t=0,n=0,r=0;r<e.length;++r){var i=e[r];t+=i.chunkSize(),n+=i.height,i.parent=this}this.size=t,this.height=n,this.parent=null}ci.prototype.from=function(){return ht(this.anchor,this.head)},ci.prototype.to=function(){return ct(this.anchor,this.head)},ci.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch},lo.prototype={chunkSize:function(){return this.lines.length},removeInner:function(e,t){for(var n,r=e,i=e+t;r<i;++r){var o=this.lines[r];this.height-=o.height,(n=o).parent=null,Ht(n),un(o,"delete")}this.lines.splice(e,t)},collapse:function(e){e.push.apply(e,this.lines)},insertInner:function(e,t,n){this.height+=n,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var r=0;r<t.length;++r)t[r].parent=this},iterN:function(e,t,n){for(var r=e+t;e<r;++e)if(n(this.lines[e]))return!0}},so.prototype={chunkSize:function(){return this.size},removeInner:function(e,t){this.size-=t;for(var n,r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e),s=i.height;if(i.removeInner(e,l),this.height-=s-i.height,o==l&&(this.children.splice(r--,1),i.parent=null),0==(t-=l))break;e=0}else e-=o}this.size-t<25&&(1<this.children.length||!(this.children[0]instanceof lo))&&(n=[],this.collapse(n),this.children=[new lo(n)],this.children[0].parent=this)},collapse:function(e){for(var t=0;t<this.children.length;++t)this.children[t].collapse(e)},insertInner:function(e,t,n){this.size+=t.length,this.height+=n;for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<=o){if(i.insertInner(e,t,n),i.lines&&50<i.lines.length){for(var l=i.lines.length%25+25,s=l;s<i.lines.length;){var a=new lo(i.lines.slice(s,s+=25));i.height-=a.height,this.children.splice(++r,0,a),a.parent=this}i.lines=i.lines.slice(0,l),this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(!(this.children.length<=10)){var e=this;do{var t,n,r=new so(e.children.splice(e.children.length-5,5));e.parent?(e.size-=r.size,e.height-=r.height,t=B(e.parent.children,e),e.parent.children.splice(t+1,0,r)):(((n=new so(e.children)).parent=e).children=[n,r],e=n),r.parent=e.parent}while(10<e.children.length);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e);if(i.iterN(e,l,n))return!0;if(0==(t-=l))break;e=0}else e-=o}}};function ao(e,t,n){if(n)for(var r in n)n.hasOwnProperty(r)&&(this[r]=n[r]);this.doc=e,this.node=t}function uo(e,t,n){Xt(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&Cr(e,n)}ao.prototype.clear=function(){var e=this.doc.cm,t=this.line.widgets,n=this.line,r=nt(n);if(null!=r&&t){for(var i=0;i<t.length;++i)t[i]==this&&t.splice(i--,1);t.length||(n.widgets=null);var o=yn(this);tt(n,Math.max(0,n.height-o)),e&&(Br(e,function(){uo(e,n,-o),or(e,r,"widget")}),un(e,"lineWidgetCleared",e,this,r))}},ao.prototype.changed=function(){var e=this,t=this.height,n=this.doc.cm,r=this.line;this.height=null;var i=yn(this)-t;i&&(jt(this.doc,r)||tt(r,r.height+i),n&&Br(n,function(){n.curOp.forceUpdate=!0,uo(n,r,i),un(n,"lineWidgetChanged",n,e,nt(r))}))},Me(ao);var co=0,ho=function(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++co};function fo(t,r,i,e,n){if(e&&e.shared)return function(e,n,r,i,o){(i=I(i)).shared=!1;var l=[fo(e,n,r,i,o)],s=l[0],a=i.widgetNode;return xi(e,function(e){a&&(i.widgetNode=a.cloneNode(!0)),l.push(fo(e,ft(e,n),ft(e,r),i,o));for(var t=0;t<e.linked.length;++t)if(e.linked[t].isParent)return;s=$(l)}),new po(l,s)}(t,r,i,e,n);if(t.cm&&!t.cm.curOp)return Gr(t.cm,fo)(t,r,i,e,n);var o=new ho(t,n),l=st(r,i);if(e&&I(e,o,!1),0<l||0==l&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),e.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),e.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Gt(t,r.line,r,i,o)||r.line!=i.line&&Gt(t,i.line,r,i,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Nt=!0}o.addToHistory&&Mi(t,{from:r,to:i,origin:"markText"},t.sel,NaN);var s,a=r.line,u=t.cm;if(t.iter(a,i.line+1,function(e){var t,n;u&&o.collapsed&&!u.options.lineWrapping&&Ut(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=r.line&&tt(e,0),t=e,n=new At(o,a==r.line?r.ch:null,a==i.line?i.ch:null),t.markedSpans=t.markedSpans?t.markedSpans.concat([n]):[n],n.marker.attachLine(t),++a}),o.collapsed&&t.iter(r.line,i.line+1,function(e){jt(t,e)&&tt(e,0)}),o.clearOnEnter&&we(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(Mt=!0,(t.history.done.length||t.history.undone.length)&&t.clearHistory()),o.collapsed&&(o.id=++co,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)ir(u,r.line,i.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=r.line;c<=i.line;c++)or(u,c,"text");o.atomic&&Vi(u.doc),un(u,"markerAdded",u,o)}return o}ho.prototype.clear=function(){if(!this.explicitlyCleared){var e,t=this.doc.cm,n=t&&!t.curOp;n&&Rr(t),!Te(this,"clear")||(e=this.find())&&un(this,"clear",e.from,e.to);for(var r=null,i=null,o=0;o<this.lines.length;++o){var l=this.lines[o],s=Ot(l.markedSpans,this);t&&!this.collapsed?or(t,nt(l),"text"):t&&(null!=s.to&&(i=nt(l)),null!=s.from&&(r=nt(l))),l.markedSpans=function(e,t){for(var n,r=0;r<e.length;++r)e[r]!=t&&(n=n||[]).push(e[r]);return n}(l.markedSpans,s),null==s.from&&this.collapsed&&!jt(this.doc,l)&&t&&tt(l,qn(t.display))}if(t&&this.collapsed&&!t.options.lineWrapping)for(var a=0;a<this.lines.length;++a){var u=Ut(this.lines[a]),c=Yt(u);c>t.display.maxLineLength&&(t.display.maxLine=u,t.display.maxLineLength=c,t.display.maxLineChanged=!0)}null!=r&&t&&this.collapsed&&ir(t,r,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,t&&Vi(t.doc)),t&&un(t,"markerCleared",t,this,r,i),n&&zr(t),this.parent&&this.parent.clear()}},ho.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i<this.lines.length;++i){var o=this.lines[i],l=Ot(o.markedSpans,this);if(null!=l.from&&(n=lt(t?o:nt(o),l.from),-1==e))return n;if(null!=l.to&&(r=lt(t?o:nt(o),l.to),1==e))return r}return n&&{from:n,to:r}},ho.prototype.changed=function(){var o=this,l=this.find(-1,!0),s=this,a=this.doc.cm;l&&a&&Br(a,function(){var e,t,n=l.line,r=nt(l.line),i=Nn(a,r);i&&(Fn(i),a.curOp.selectionChanged=a.curOp.forceUpdate=!0),a.curOp.updateMaxLine=!0,jt(s.doc,n)||null==s.height||(e=s.height,s.height=null,(t=yn(s)-e)&&tt(n,n.height+t)),un(a,"markerChanged",a,o)})},ho.prototype.attachLine=function(e){var t;!this.lines.length&&this.doc.cm&&((t=this.doc.cm.curOp).maybeHiddenMarkers&&-1!=B(t.maybeHiddenMarkers,this)||(t.maybeUnhiddenMarkers||(t.maybeUnhiddenMarkers=[])).push(this)),this.lines.push(e)},ho.prototype.detachLine=function(e){var t;this.lines.splice(B(this.lines,e),1),!this.lines.length&&this.doc.cm&&((t=this.doc.cm.curOp).maybeHiddenMarkers||(t.maybeHiddenMarkers=[])).push(this)},Me(ho);var po=function(e,t){this.markers=e,this.primary=t;for(var n=0;n<e.length;++n)e[n].parent=this};function go(e){return e.findMarks(lt(e.first,0),e.clipPos(lt(e.lastLine())),function(e){return e.parent})}po.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var e=0;e<this.markers.length;++e)this.markers[e].clear();un(this,"clear")}},po.prototype.find=function(e,t){return this.primary.find(e,t)},Me(po);var mo=0,vo=function(e,t,n,r,i){if(!(this instanceof vo))return new vo(e,t,n,r,i);null==n&&(n=0),so.call(this,[new lo([new $t("",null)])]),this.first=n,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1;var o=lt(this.modeFrontier=this.highlightFrontier=n,0);this.sel=di(o),this.history=new Li(null),this.id=++mo,this.modeOption=t,this.lineSep=r,this.direction="rtl"==i?"rtl":"ltr",this.extend=!1,"string"==typeof e&&(e=this.splitLines(e)),wi(this,{from:o,to:o,text:e}),Bi(this,di(o),V)};vo.prototype=Q(so.prototype,{constructor:vo,iter:function(e,t,n){n?this.iterN(e-this.first,t-e,n):this.iterN(this.first,this.first+this.size,e)},insert:function(e,t){for(var n=0,r=0;r<t.length;++r)n+=t[r].height;this.insertInner(e-this.first,t,n)},remove:function(e,t){this.removeInner(e-this.first,t)},getValue:function(e){var t=et(this,this.first,this.first+this.size);return!1===e?t:t.join(e||this.lineSeparator())},setValue:Vr(function(e){var t=lt(this.first,0),n=this.first+this.size-1;qi(this,{from:t,to:lt(n,Qe(this,n).text.length),text:this.splitLines(e),origin:"setValue",full:!0},!0),this.cm&&Lr(this.cm,0,0),Bi(this,di(t),V)}),replaceRange:function(e,t,n,r){to(this,e,t=ft(this,t),n=n?ft(this,n):t,r)},getRange:function(e,t,n){var r=Je(this,ft(this,e),ft(this,t));return!1===n?r:r.join(n||this.lineSeparator())},getLine:function(e){var t=this.getLineHandle(e);return t&&t.text},getLineHandle:function(e){if(it(this,e))return Qe(this,e)},getLineNumber:nt,getLineHandleVisualStart:function(e){return"number"==typeof e&&(e=Qe(this,e)),Ut(e)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(e){return ft(this,e)},getCursor:function(e){var t=this.sel.primary(),n=null==e||"head"==e?t.head:"anchor"==e?t.anchor:"end"==e||"to"==e||!1===e?t.to():t.from();return n},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Vr(function(e,t,n){Ri(this,ft(this,"number"==typeof e?lt(e,t||0):e),null,n)}),setSelection:Vr(function(e,t,n){Ri(this,ft(this,e),ft(this,t||e),n)}),extendSelection:Vr(function(e,t,n){Pi(this,ft(this,e),t&&ft(this,t),n)}),extendSelections:Vr(function(e,t){Ei(this,pt(this,e),t)}),extendSelectionsBy:Vr(function(e,t){Ei(this,pt(this,q(this.sel.ranges,e)),t)}),setSelections:Vr(function(e,t,n){if(e.length){for(var r=[],i=0;i<e.length;i++)r[i]=new ci(ft(this,e[i].anchor),ft(this,e[i].head));null==t&&(t=Math.min(e.length-1,this.sel.primIndex)),Bi(this,hi(this.cm,r,t),n)}}),addSelection:Vr(function(e,t,n){var r=this.sel.ranges.slice(0);r.push(new ci(ft(this,e),ft(this,t||e))),Bi(this,hi(this.cm,r,r.length-1),n)}),getSelection:function(e){for(var t=this.sel.ranges,n=0;n<t.length;n++)var r=Je(this,t[n].from(),t[n].to()),i=i?i.concat(r):r;return!1===e?i:i.join(e||this.lineSeparator())},getSelections:function(e){for(var t=[],n=this.sel.ranges,r=0;r<n.length;r++){var i=Je(this,n[r].from(),n[r].to());!1!==e&&(i=i.join(e||this.lineSeparator())),t[r]=i}return t},replaceSelection:function(e,t,n){for(var r=[],i=0;i<this.sel.ranges.length;i++)r[i]=e;this.replaceSelections(r,t,n||"+input")},replaceSelections:Vr(function(e,t,n){for(var r=[],i=this.sel,o=0;o<i.ranges.length;o++){var l=i.ranges[o];r[o]={from:l.from(),to:l.to(),text:this.splitLines(e[o]),origin:n}}for(var s=t&&"end"!=t&&function(e,t,n){for(var r=[],i=h=lt(e.first,0),o=0;o<t.length;o++){var l,s,a=t[o],u=mi(a.from,h,i),c=mi(fi(a),h,i),h=a.to,i=c;"around"==n?(s=st((l=e.sel.ranges[o]).head,l.anchor)<0,r[o]=new ci(s?c:u,s?u:c)):r[o]=new ci(u,u)}return new ui(r,e.sel.primIndex)}(this,r,t),a=r.length-1;0<=a;a--)qi(this,r[a]);s?zi(this,s):this.cm&&Sr(this.cm)}),undo:Vr(function(){Qi(this,"undo")}),redo:Vr(function(){Qi(this,"redo")}),undoSelection:Vr(function(){Qi(this,"undo",!0)}),redoSelection:Vr(function(){Qi(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r<e.done.length;r++)e.done[r].ranges||++t;for(var i=0;i<e.undone.length;i++)e.undone[i].ranges||++n;return{undo:t,redo:n}},clearHistory:function(){var t=this;this.history=new Li(this.history.maxGeneration),xi(this,function(e){return e.history=t.history},!0)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(e){return e&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(e){return this.history.generation==(e||this.cleanGeneration)},getHistory:function(){return{done:Hi(this.history.done),undone:Hi(this.history.undone)}},setHistory:function(e){var t=this.history=new Li(this.history.maxGeneration);t.done=Hi(e.done.slice(0),null,!0),t.undone=Hi(e.undone.slice(0),null,!0)},setGutterMarker:Vr(function(e,n,r){return oo(this,e,"gutter",function(e){var t=e.gutterMarkers||(e.gutterMarkers={});return!(t[n]=r)&&ne(t)&&(e.gutterMarkers=null),1})}),clearGutter:Vr(function(t){var n=this;this.iter(function(e){e.gutterMarkers&&e.gutterMarkers[t]&&oo(n,e,"gutter",function(){return e.gutterMarkers[t]=null,ne(e.gutterMarkers)&&(e.gutterMarkers=null),1})})}),lineInfo:function(e){var t;if("number"==typeof e){if(!it(this,e))return null;if(!(e=Qe(this,t=e)))return null}else if(null==(t=nt(e)))return null;return{line:t,handle:e,text:e.text,gutterMarkers:e.gutterMarkers,textClass:e.textClass,bgClass:e.bgClass,wrapClass:e.wrapClass,widgets:e.widgets}},addLineClass:Vr(function(e,n,r){return oo(this,e,"gutter"==n?"gutter":"class",function(e){var t="text"==n?"textClass":"background"==n?"bgClass":"gutter"==n?"gutterClass":"wrapClass";if(e[t]){if(L(r).test(e[t]))return;e[t]+=" "+r}else e[t]=r;return 1})}),removeLineClass:Vr(function(e,o,l){return oo(this,e,"gutter"==o?"gutter":"class",function(e){var t="text"==o?"textClass":"background"==o?"bgClass":"gutter"==o?"gutterClass":"wrapClass",n=e[t];if(n){if(null==l)e[t]=null;else{var r=n.match(L(l));if(!r)return;var i=r.index+r[0].length;e[t]=n.slice(0,r.index)+(r.index&&i!=n.length?" ":"")+n.slice(i)||null}return 1}})}),addLineWidget:Vr(function(e,t,n){return i=e,o=new ao(r=this,t,n),(l=r.cm)&&o.noHScroll&&(l.display.alignWidgets=!0),oo(r,i,"widget",function(e){var t,n=e.widgets||(e.widgets=[]);return null==o.insertAt?n.push(o):n.splice(Math.min(n.length-1,Math.max(0,o.insertAt)),0,o),o.line=e,l&&!jt(r,e)&&(t=Xt(e)<r.scrollTop,tt(e,e.height+yn(o)),t&&Cr(l,o.height),l.curOp.forceUpdate=!0),1}),l&&un(l,"lineWidgetAdded",l,o,"number"==typeof i?i:nt(i)),o;var r,i,o,l}),removeLineWidget:function(e){e.clear()},markText:function(e,t,n){return fo(this,ft(this,e),ft(this,t),n,n&&n.type||"range")},setBookmark:function(e,t){var n={replacedWith:t&&(null==t.nodeType?t.widget:t),insertLeft:t&&t.insertLeft,clearWhenEmpty:!1,shared:t&&t.shared,handleMouseEvents:t&&t.handleMouseEvents};return fo(this,e=ft(this,e),e,n,"bookmark")},findMarksAt:function(e){var t=[],n=Qe(this,(e=ft(this,e)).line).markedSpans;if(n)for(var r=0;r<n.length;++r){var i=n[r];(null==i.from||i.from<=e.ch)&&(null==i.to||i.to>=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(i,o,l){i=ft(this,i),o=ft(this,o);var s=[],a=i.line;return this.iter(i.line,o.line+1,function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;n++){var r=t[n];null!=r.to&&a==i.line&&i.ch>=r.to||null==r.from&&a!=i.line||null!=r.from&&a==o.line&&r.from>=o.ch||l&&!l(r.marker)||s.push(r.marker.parent||r.marker)}++a}),s},getAllMarks:function(){var r=[];return this.iter(function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;++n)null!=t[n].from&&r.push(t[n].marker)}),r},posFromIndex:function(n){var r,i=this.first,o=this.lineSeparator().length;return this.iter(function(e){var t=e.text.length+o;if(n<t)return r=n,!0;n-=t,++i}),ft(this,lt(i,r))},indexFromPos:function(e){var t=(e=ft(this,e)).ch;if(e.line<this.first||e.ch<0)return 0;var n=this.lineSeparator().length;return this.iter(this.first,e.line,function(e){t+=e.text.length+n}),t},copy:function(e){var t=new vo(et(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft,t.sel=this.sel,t.extend=!1,e&&(t.history.undoDepth=this.history.undoDepth,t.setHistory(this.getHistory())),t},linkedDoc:function(e){e=e||{};var t=this.first,n=this.first+this.size;null!=e.from&&e.from>t&&(t=e.from),null!=e.to&&e.to<n&&(n=e.to);var r=new vo(et(this,t,n),e.mode||this.modeOption,t,this.lineSep,this.direction);return e.sharedHist&&(r.history=this.history),(this.linked||(this.linked=[])).push({doc:r,sharedHist:e.sharedHist}),r.linked=[{doc:this,isParent:!0,sharedHist:e.sharedHist}],function(e,t){for(var n=0;n<t.length;n++){var r,i=t[n],o=i.find(),l=e.clipPos(o.from),s=e.clipPos(o.to);st(l,s)&&(r=fo(e,l,s,i.primary,i.primary.type),i.markers.push(r),r.parent=i)}}(r,go(this)),r},unlinkDoc:function(e){if(e instanceof pl&&(e=e.doc),this.linked)for(var t=0;t<this.linked.length;++t){if(this.linked[t].doc==e){this.linked.splice(t,1),e.unlinkDoc(this),function(o){for(var e=0;e<o.length;e++)!function(e){var t=o[e],n=[t.primary.doc];xi(t.primary.doc,function(e){return n.push(e)});for(var r=0;r<t.markers.length;r++){var i=t.markers[r];-1==B(n,i.doc)&&(i.parent=null,t.markers.splice(r--,1))}}(e)}(go(this));break}}var n;e.history==this.history&&(n=[e.id],xi(e,function(e){return n.push(e.id)},!0),e.history=new Li(null),e.history.done=Hi(this.history.done,n),e.history.undone=Hi(this.history.undone,n))},iterLinkedDocs:function(e){xi(this,e)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(e){return this.lineSep?e.split(this.lineSep):Re(e)},lineSeparator:function(){return this.lineSep||"\n"},setDirection:Vr(function(e){var t;"rtl"!=e&&(e="ltr"),e!=this.direction&&(this.direction=e,this.iter(function(e){return e.order=null}),this.cm&&Br(t=this.cm,function(){Si(t),ir(t)}))})}),vo.prototype.eachLine=vo.prototype.iter;var yo=0;function bo(e){var r=this;if(wo(r),!Le(r,e)&&!bn(r.display,e)){Ne(e),x&&(yo=+new Date);var t=nr(r,e,!0),n=e.dataTransfer.files;if(t&&!r.isReadOnly())if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),l=0,s=function(){++l==i&&Gr(r,function(){var e={from:t=ft(r.doc,t),to:t,text:r.doc.splitLines(o.filter(function(e){return null!=e}).join(r.doc.lineSeparator())),origin:"paste"};qi(r.doc,e),zi(r.doc,di(ft(r.doc,t),ft(r.doc,fi(e))))})()},a=0;a<n.length;a++)!function(e,t){var n;r.options.allowDropFileTypes&&-1==B(r.options.allowDropFileTypes,e.type)?s():((n=new FileReader).onerror=s,n.onload=function(){var e=n.result;/[\x00-\x08\x0e-\x1f]{2}/.test(e)||(o[t]=e),s()},n.readAsText(e))}(n[a],a);else{if(r.state.draggingText&&-1<r.doc.sel.contains(t))return r.state.draggingText(e),void setTimeout(function(){return r.display.input.focus()},20);try{var u,c=e.dataTransfer.getData("Text");if(c){if(r.state.draggingText&&!r.state.draggingText.copy&&(u=r.listSelections()),Gi(r.doc,di(t,t)),u)for(var h=0;h<u.length;++h)to(r.doc,"",u[h].anchor,u[h].head,"drag");r.replaceSelection(c,"around","paste"),r.display.input.focus()}}catch(e){}}}}function wo(e){e.display.dragCursor&&(e.display.lineSpace.removeChild(e.display.dragCursor),e.display.dragCursor=null)}function xo(t){if(document.getElementsByClassName){for(var e=document.getElementsByClassName("CodeMirror"),n=[],r=0;r<e.length;r++){var i=e[r].CodeMirror;i&&n.push(i)}n.length&&n[0].operation(function(){for(var e=0;e<n.length;e++)t(n[e])})}}var Co=!1;function So(){var e;Co||(we(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,xo(Lo)},100))}),we(window,"blur",function(){return xo(vr)}),Co=!0)}function Lo(e){var t=e.display;t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize()}for(var ko={3:"Pause",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",145:"ScrollLock",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",224:"Mod",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"},To=0;To<10;To++)ko[To+48]=ko[To+96]=String(To);for(var Mo=65;Mo<=90;Mo++)ko[Mo]=String.fromCharCode(Mo);for(var No=1;No<=12;No++)ko[No+111]=ko[No+63235]="F"+No;var Ao={};function Oo(e){var t,n,r,i,o=e.split(/-(?!$)/);e=o[o.length-1];for(var l=0;l<o.length-1;l++){var s=o[l];if(/^(cmd|meta|m)$/i.test(s))i=!0;else if(/^a(lt)?$/i.test(s))t=!0;else if(/^(c|ctrl|control)$/i.test(s))n=!0;else{if(!/^s(hift)?$/i.test(s))throw new Error("Unrecognized modifier name: "+s);r=!0}}return t&&(e="Alt-"+e),n&&(e="Ctrl-"+e),i&&(e="Cmd-"+e),r&&(e="Shift-"+e),e}function Do(e){var t={};for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];if(/^(name|fallthrough|(de|at)tach)$/.test(n))continue;if("..."==r){delete e[n];continue}for(var i=q(n.split(" "),Oo),o=0;o<i.length;o++){var l=void 0,s=void 0,l=o==i.length-1?(s=i.join(" "),r):(s=i.slice(0,o+1).join(" "),"..."),a=t[s];if(a){if(a!=l)throw new Error("Inconsistent bindings for "+s)}else t[s]=l}delete e[n]}for(var u in t)e[u]=t[u];return e}function Wo(e,t,n,r){var i=(t=Eo(t)).call?t.call(e,r):t[e];if(!1===i)return"nothing";if("..."===i)return"multi";if(null!=i&&n(i))return"handled";if(t.fallthrough){if("[object Array]"!=Object.prototype.toString.call(t.fallthrough))return Wo(e,t.fallthrough,n,r);for(var o=0;o<t.fallthrough.length;o++){var l=Wo(e,t.fallthrough[o],n,r);if(l)return l}}}function Ho(e){var t="string"==typeof e?e:ko[e.keyCode];return"Ctrl"==t||"Alt"==t||"Shift"==t||"Mod"==t}function Fo(e,t,n){var r=e;return t.altKey&&"Alt"!=r&&(e="Alt-"+e),(w?t.metaKey:t.ctrlKey)&&"Ctrl"!=r&&(e="Ctrl-"+e),(w?t.ctrlKey:t.metaKey)&&"Mod"!=r&&(e="Cmd-"+e),!n&&t.shiftKey&&"Shift"!=r&&(e="Shift-"+e),e}function Po(e,t){if(m&&34==e.keyCode&&e.char)return!1;var n=ko[e.keyCode];return null!=n&&!e.altGraphKey&&(3==e.keyCode&&e.code&&(n=e.code),Fo(n,e,t))}function Eo(e){return"string"==typeof e?Ao[e]:e}function Io(t,e){for(var n=t.doc.sel.ranges,r=[],i=0;i<n.length;i++){for(var o=e(n[i]);r.length&&st(o.from,$(r).to)<=0;){var l=r.pop();if(st(l.from,o.from)<0){o.from=l.from;break}}r.push(o)}Br(t,function(){for(var e=r.length-1;0<=e;e--)to(t.doc,"",r[e].from,r[e].to,"+delete");Sr(t)})}function Ro(e,t,n){var r=oe(e.text,t+n,n);return r<0||r>e.text.length?null:r}function zo(e,t,n){var r=Ro(e,t.ch,n);return null==r?null:new lt(t.line,r,n<0?"after":"before")}function Bo(e,t,n,r,i){if(e){"rtl"==t.doc.direction&&(i=-i);var o=ye(n,t.doc.direction);if(o){var l,s,a,u=i<0?$(o):o[0],c=i<0==(1==u.level)?"after":"before";return 0<u.level||"rtl"==t.doc.direction?(l=An(t,n),s=i<0?n.text.length-1:0,a=On(t,l,s).top,s=le(function(e){return On(t,l,e).top==a},i<0==(1==u.level)?u.from:u.to-1,s),"before"==c&&(s=Ro(n,s,1))):s=i<0?u.to:u.from,new lt(r,s,c)}}return new lt(r,i<0?n.text.length:0,i<0?"before":"after")}function Go(t,n,s,e){var a=ye(n,t.doc.direction);if(!a)return zo(n,s,e);s.ch>=n.text.length?(s.ch=n.text.length,s.sticky="before"):s.ch<=0&&(s.ch=0,s.sticky="after");var r=ae(a,s.ch,s.sticky),i=a[r];if("ltr"==t.doc.direction&&i.level%2==0&&(0<e?i.to>s.ch:i.from<s.ch))return zo(n,s,e);function u(e,t){return Ro(n,e instanceof lt?e.ch:e,t)}function o(e){return t.options.lineWrapping?(l=l||An(t,n),_n(t,n,l,e)):{begin:0,end:n.text.length}}var l,c=o("before"==s.sticky?u(s,-1):s.ch);if("rtl"==t.doc.direction||1==i.level){var h=1==i.level==e<0,d=u(s,h?1:-1);if(null!=d&&(h?d<=i.to&&d<=c.end:d>=i.from&&d>=c.begin)){var f=h?"before":"after";return new lt(s.line,d,f)}}function p(e,t,n){for(var r=function(e,t){return t?new lt(s.line,u(e,1),"before"):new lt(s.line,e,"after")};0<=e&&e<a.length;e+=t){var i=a[e],o=0<t==(1!=i.level),l=o?n.begin:u(n.end,-1);if(i.from<=l&&l<i.to)return r(l,o);if(l=o?i.from:u(i.to,-1),n.begin<=l&&l<n.end)return r(l,o)}}var g=p(r+e,e,c);if(g)return g;var m=0<e?c.end:u(c.begin,-1);return null==m||0<e&&m==n.text.length||!(g=p(0<e?0:a.length-1,e,o(m)))?null:g}Ao.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Ao.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Ao.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Ao.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Ao.default=y?Ao.macDefault:Ao.pcDefault;var Uo={selectAll:_i,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),V)},killLine:function(n){return Io(n,function(e){if(e.empty()){var t=Qe(n.doc,e.head.line).text.length;return e.head.ch==t&&e.head.line<n.lastLine()?{from:e.head,to:lt(e.head.line+1,0)}:{from:e.head,to:lt(e.head.line,t)}}return{from:e.from(),to:e.to()}})},deleteLine:function(t){return Io(t,function(e){return{from:lt(e.from().line,0),to:ft(t.doc,lt(e.to().line+1,0))}})},delLineLeft:function(e){return Io(e,function(e){return{from:lt(e.from().line,0),to:e.from()}})},delWrappedLineLeft:function(n){return Io(n,function(e){var t=n.charCoords(e.head,"div").top+5;return{from:n.coordsChar({left:0,top:t},"div"),to:e.from()}})},delWrappedLineRight:function(r){return Io(r,function(e){var t=r.charCoords(e.head,"div").top+5,n=r.coordsChar({left:r.display.lineDiv.offsetWidth+100,top:t},"div");return{from:e.from(),to:n}})},undo:function(e){return e.undo()},redo:function(e){return e.redo()},undoSelection:function(e){return e.undoSelection()},redoSelection:function(e){return e.redoSelection()},goDocStart:function(e){return e.extendSelection(lt(e.firstLine(),0))},goDocEnd:function(e){return e.extendSelection(lt(e.lastLine()))},goLineStart:function(t){return t.extendSelectionsBy(function(e){return Vo(t,e.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(t){return t.extendSelectionsBy(function(e){return Ko(t,e.head)},{origin:"+move",bias:1})},goLineEnd:function(t){return t.extendSelectionsBy(function(e){return function(e,t){var n=Qe(e.doc,t),r=function(e){for(var t;t=Bt(e);)e=t.find(1,!0).line;return e}(n);r!=n&&(t=nt(r));return Bo(!0,e,n,t,-1)}(t,e.head.line)},{origin:"+move",bias:-1})},goLineRight:function(n){return n.extendSelectionsBy(function(e){var t=n.cursorCoords(e.head,"div").top+5;return n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:t},"div")},j)},goLineLeft:function(n){return n.extendSelectionsBy(function(e){var t=n.cursorCoords(e.head,"div").top+5;return n.coordsChar({left:0,top:t},"div")},j)},goLineLeftSmart:function(r){return r.extendSelectionsBy(function(e){var t=r.cursorCoords(e.head,"div").top+5,n=r.coordsChar({left:0,top:t},"div");return n.ch<r.getLine(n.line).search(/\S/)?Ko(r,e.head):n},j)},goLineUp:function(e){return e.moveV(-1,"line")},goLineDown:function(e){return e.moveV(1,"line")},goPageUp:function(e){return e.moveV(-1,"page")},goPageDown:function(e){return e.moveV(1,"page")},goCharLeft:function(e){return e.moveH(-1,"char")},goCharRight:function(e){return e.moveH(1,"char")},goColumnLeft:function(e){return e.moveH(-1,"column")},goColumnRight:function(e){return e.moveH(1,"column")},goWordLeft:function(e){return e.moveH(-1,"word")},goGroupRight:function(e){return e.moveH(1,"group")},goGroupLeft:function(e){return e.moveH(-1,"group")},goWordRight:function(e){return e.moveH(1,"word")},delCharBefore:function(e){return e.deleteH(-1,"codepoint")},delCharAfter:function(e){return e.deleteH(1,"char")},delWordBefore:function(e){return e.deleteH(-1,"word")},delWordAfter:function(e){return e.deleteH(1,"word")},delGroupBefore:function(e){return e.deleteH(-1,"group")},delGroupAfter:function(e){return e.deleteH(1,"group")},indentAuto:function(e){return e.indentSelection("smart")},indentMore:function(e){return e.indentSelection("add")},indentLess:function(e){return e.indentSelection("subtract")},insertTab:function(e){return e.replaceSelection("\t")},insertSoftTab:function(e){for(var t=[],n=e.listSelections(),r=e.options.tabSize,i=0;i<n.length;i++){var o=n[i].from(),l=R(e.getLine(o.line),o.ch,r);t.push(_(r-l%r))}e.replaceSelections(t)},defaultTab:function(e){e.somethingSelected()?e.indentSelection("add"):e.execCommand("insertTab")},transposeChars:function(l){return Br(l,function(){for(var e,t,n,r=l.listSelections(),i=[],o=0;o<r.length;o++){r[o].empty()&&(e=r[o].head,(t=Qe(l.doc,e.line).text)&&(e.ch==t.length&&(e=new lt(e.line,e.ch-1)),0<e.ch?(e=new lt(e.line,e.ch+1),l.replaceRange(t.charAt(e.ch-1)+t.charAt(e.ch-2),lt(e.line,e.ch-2),e,"+transpose")):e.line>l.doc.first&&((n=Qe(l.doc,e.line-1).text)&&(e=new lt(e.line,1),l.replaceRange(t.charAt(0)+l.doc.lineSeparator()+n.charAt(n.length-1),lt(e.line-1,n.length-1),e,"+transpose")))),i.push(new ci(e,e)))}l.setSelections(i)})},newlineAndIndent:function(r){return Br(r,function(){for(var e=r.listSelections(),t=e.length-1;0<=t;t--)r.replaceRange(r.doc.lineSeparator(),e[t].anchor,e[t].head,"+input");e=r.listSelections();for(var n=0;n<e.length;n++)r.indentLine(e[n].from().line,null,!0);Sr(r)})},openLine:function(e){return e.replaceSelection("\n","start")},toggleOverwrite:function(e){return e.toggleOverwrite()}};function Vo(e,t){var n=Qe(e.doc,t),r=Ut(n);return r!=n&&(t=nt(r)),Bo(!0,e,r,t,1)}function Ko(e,t){var n=Vo(e,t.line),r=Qe(e.doc,n.line),i=ye(r,e.doc.direction);if(i&&0!=i[0].level)return n;var o=Math.max(n.ch,r.text.search(/\S/)),l=t.line==n.line&&t.ch<=o&&t.ch;return lt(n.line,l?0:o,n.sticky)}function jo(e,t,n){if("string"==typeof t&&!(t=Uo[t]))return!1;e.display.input.ensurePolled();var r=e.display.shift,i=!1;try{e.isReadOnly()&&(e.state.suppressEdits=!0),n&&(e.display.shift=!1),i=t(e)!=U}finally{e.display.shift=r,e.state.suppressEdits=!1}return i}var Xo=new z;function Yo(e,t,n,r){var i=e.state.keySeq;if(i){if(Ho(t))return"handled";if(/\'$/.test(t)?e.state.keySeq=null:Xo.set(50,function(){e.state.keySeq==i&&(e.state.keySeq=null,e.display.input.reset())}),_o(e,i+" "+t,n,r))return!0}return _o(e,t,n,r)}function _o(e,t,n,r){var i=function(e,t,n){for(var r=0;r<e.state.keyMaps.length;r++){var i=Wo(t,e.state.keyMaps[r],n,e);if(i)return i}return e.options.extraKeys&&Wo(t,e.options.extraKeys,n,e)||Wo(t,e.options.keyMap,n,e)}(e,t,r);return"multi"==i&&(e.state.keySeq=t),"handled"==i&&un(e,"keyHandled",e,t,n),"handled"!=i&&"multi"!=i||(Ne(n),fr(e)),!!i}function $o(t,e){var n=Po(e,!0);return!!n&&(e.shiftKey&&!t.state.keySeq?Yo(t,"Shift-"+n,e,function(e){return jo(t,e,!0)})||Yo(t,n,e,function(e){if("string"==typeof e?/^go[A-Z]/.test(e):e.motion)return jo(t,e)}):Yo(t,n,e,function(e){return jo(t,e)}))}var qo=null;function Zo(e){var t,n,r,i=this;function o(e){18!=e.keyCode&&e.altKey||(T(r,"CodeMirror-crosshair"),Ce(document,"keyup",o),Ce(document,"mouseover",o))}e.target&&e.target!=i.display.input.getField()||(i.curOp.focus=W(),Le(i,e)||(x&&C<11&&27==e.keyCode&&(e.returnValue=!1),t=e.keyCode,i.display.shift=16==t||e.shiftKey,n=$o(i,e),m&&(qo=n?t:null,!n&&88==t&&!Be&&(y?e.metaKey:e.ctrlKey)&&i.replaceSelection("",null,"cut")),g&&!y&&!n&&46==t&&e.shiftKey&&!e.ctrlKey&&document.execCommand&&document.execCommand("cut"),18!=t||/\bCodeMirror-crosshair\b/.test(i.display.lineDiv.className)||(H(r=i.display.lineDiv,"CodeMirror-crosshair"),we(document,"keyup",o),we(document,"mouseover",o))))}function Qo(e){16==e.keyCode&&(this.doc.sel.shift=!1),Le(this,e)}function Jo(e){var t=this;if(!(e.target&&e.target!=t.display.input.getField()||bn(t.display,e)||Le(t,e)||e.ctrlKey&&!e.altKey||y&&e.metaKey)){var n,r,i=e.keyCode,o=e.charCode;if(m&&i==qo)return qo=null,void Ne(e);m&&(!e.which||e.which<10)&&$o(t,e)||"\b"!=(n=String.fromCharCode(null==o?i:o))&&(Yo(r=t,"'"+n+"'",e,function(e){return jo(r,e,!0)})||t.display.input.onKeyPress(e))}}var el,tl,nl=function(e,t,n){this.time=e,this.pos=t,this.button=n};function rl(e){var t,n,r,i,o,l,s=this,a=s.display;Le(s,e)||a.activeTouch&&a.input.supportsTouch()||(a.input.ensurePolled(),a.shift=e.shiftKey,bn(a,e)?v||(a.scroller.draggable=!1,setTimeout(function(){return a.scroller.draggable=!0},100)):ll(s,e)||(t=nr(s,e),n=He(e),r=t?(i=t,o=n,l=+new Date,tl&&tl.compare(l,i,o)?(el=tl=null,"triple"):el&&el.compare(l,i,o)?(tl=new nl(l,i,o),el=null,"double"):(el=new nl(l,i,o),tl=null,"single")):"single",window.focus(),1==n&&s.state.selectingText&&s.state.selectingText(e),t&&function(n,e,r,t,i){var o="Click";"double"==t?o="Double"+o:"triple"==t&&(o="Triple"+o);return Yo(n,Fo(o=(1==e?"Left":2==e?"Middle":"Right")+o,i),i,function(e){if("string"==typeof e&&(e=Uo[e]),!e)return!1;var t=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),t=e(n,r)!=U}finally{n.state.suppressEdits=!1}return t})}(s,n,t,r,e)||(1==n?t?function(e,t,n,r){x?setTimeout(E(pr,e),0):e.curOp.focus=W();var i,o=function(e,t,n){var r=e.getOption("configureMouse"),i=r?r(e,t,n):{};{var o;null==i.unit&&(o=f?n.shiftKey&&n.metaKey:n.altKey,i.unit=o?"rectangle":"single"==t?"char":"double"==t?"word":"line")}null!=i.extend&&!e.doc.extend||(i.extend=e.doc.extend||n.shiftKey);null==i.addNew&&(i.addNew=y?n.metaKey:n.ctrlKey);null==i.moveOnDrag&&(i.moveOnDrag=!(y?n.altKey:n.ctrlKey));return i}(e,n,r),l=e.doc.sel;(e.options.dragDrop&&Ee&&!e.isReadOnly()&&"single"==n&&-1<(i=l.contains(t))&&(st((i=l.ranges[i]).from(),t)<0||0<t.xRel)&&(0<st(i.to(),t)||t.xRel<0)?function(t,n,r,i){var o=t.display,l=!1,s=Gr(t,function(e){v&&(o.scroller.draggable=!1),t.state.draggingText=!1,Ce(o.wrapper.ownerDocument,"mouseup",s),Ce(o.wrapper.ownerDocument,"mousemove",a),Ce(o.scroller,"dragstart",u),Ce(o.scroller,"drop",s),l||(Ne(e),i.addNew||Pi(t.doc,r,null,null,i.extend),v&&!c||x&&9==C?setTimeout(function(){o.wrapper.ownerDocument.body.focus({preventScroll:!0}),o.input.focus()},20):o.input.focus())}),a=function(e){l=l||10<=Math.abs(n.clientX-e.clientX)+Math.abs(n.clientY-e.clientY)},u=function(){return l=!0};v&&(o.scroller.draggable=!0);(t.state.draggingText=s).copy=!i.moveOnDrag,o.scroller.dragDrop&&o.scroller.dragDrop();we(o.wrapper.ownerDocument,"mouseup",s),we(o.wrapper.ownerDocument,"mousemove",a),we(o.scroller,"dragstart",u),we(o.scroller,"drop",s),gr(t),setTimeout(function(){return o.input.focus()},20)}:function(m,e,v,y){var l=m.display,b=m.doc;Ne(e);var w,x,C=b.sel,t=C.ranges;y.addNew&&!y.extend?(x=b.sel.contains(v),w=-1<x?t[x]:new ci(v,v)):(w=b.sel.primary(),x=b.sel.primIndex);{var n;"rectangle"==y.unit?(y.addNew||(w=new ci(v,v)),v=nr(m,e,!0,!0),x=-1):(n=il(m,v,y.unit),w=y.extend?Fi(w,n.anchor,n.head,y.extend):n)}y.addNew?-1==x?(x=t.length,Bi(b,hi(m,t.concat([w]),x),{scroll:!1,origin:"*mouse"})):1<t.length&&t[x].empty()&&"char"==y.unit&&!y.extend?(Bi(b,hi(m,t.slice(0,x).concat(t.slice(x+1)),0),{scroll:!1,origin:"*mouse"}),C=b.sel):Ii(b,x,w,K):(Bi(b,new ui([w],x=0),K),C=b.sel);var S=v;function s(e){if(0!=st(S,e))if(S=e,"rectangle"==y.unit){for(var t=[],n=m.options.tabSize,r=R(Qe(b,v.line).text,v.ch,n),i=R(Qe(b,e.line).text,e.ch,n),o=Math.min(r,i),l=Math.max(r,i),s=Math.min(v.line,e.line),a=Math.min(m.lastLine(),Math.max(v.line,e.line));s<=a;s++){var u=Qe(b,s).text,c=X(u,o,n);o==l?t.push(new ci(lt(s,c),lt(s,c))):u.length>c&&t.push(new ci(lt(s,c),lt(s,X(u,l,n))))}t.length||t.push(new ci(v,v)),Bi(b,hi(m,C.ranges.slice(0,x).concat(t),x),{origin:"*mouse",scroll:!1}),m.scrollIntoView(e)}else{var h,d=w,f=il(m,e,y.unit),p=d.anchor,p=0<st(f.anchor,p)?(h=f.head,ht(d.from(),f.anchor)):(h=f.anchor,ct(d.to(),f.head)),g=C.ranges.slice(0);g[x]=function(e,t){var n=t.anchor,r=t.head,i=Qe(e.doc,n.line);if(0==st(n,r)&&n.sticky==r.sticky)return t;var o=ye(i);if(!o)return t;var l=ae(o,n.ch,n.sticky),s=o[l];if(s.from!=n.ch&&s.to!=n.ch)return t;var a,u=l+(s.from==n.ch==(1!=s.level)?0:1);if(0==u||u==o.length)return t;{var c,h;a=r.line!=n.line?0<(r.line-n.line)*("ltr"==e.doc.direction?1:-1):(c=ae(o,r.ch,r.sticky),h=c-l||(r.ch-n.ch)*(1==s.level?-1:1),c==u-1||c==u?h<0:0<h)}var d=o[u+(a?-1:0)],f=a==(1==d.level),p=f?d.from:d.to,g=f?"after":"before";return n.ch==p&&n.sticky==g?t:new ci(new lt(n.line,p,g),r)}(m,new ci(ft(b,p),h)),Bi(b,hi(m,g,x),K)}}var a=l.wrapper.getBoundingClientRect(),u=0;function r(e){m.state.selectingText=!1,u=1/0,e&&(Ne(e),l.input.focus()),Ce(l.wrapper.ownerDocument,"mousemove",i),Ce(l.wrapper.ownerDocument,"mouseup",o),b.history.lastSelOrigin=null}var i=Gr(m,function(e){(0!==e.buttons&&He(e)?function e(t){var n,r,i=++u,o=nr(m,t,!0,"rectangle"==y.unit);o&&(0!=st(o,S)?(m.curOp.focus=W(),s(o),n=wr(l,b),(o.line>=n.to||o.line<n.from)&&setTimeout(Gr(m,function(){u==i&&e(t)}),150)):(r=t.clientY<a.top?-20:t.clientY>a.bottom?20:0)&&setTimeout(Gr(m,function(){u==i&&(l.scroller.scrollTop+=r,e(t))}),50))}:r)(e)}),o=Gr(m,r);m.state.selectingText=o,we(l.wrapper.ownerDocument,"mousemove",i),we(l.wrapper.ownerDocument,"mouseup",o)})(e,r,t,o)}(s,t,r,e):We(e)==a.scroller&&Ne(e):2==n?(t&&Pi(s.doc,t),setTimeout(function(){return a.input.focus()},20)):3==n&&(S?s.display.input.onContextMenu(e):gr(s)))))}function il(e,t,n){if("char"==n)return new ci(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new ci(lt(t.line,0),ft(e.doc,lt(t.line+1,0)));var r=n(e,t);return new ci(r.from,r.to)}function ol(e,t,n,r){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(e){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&&Ne(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!Te(e,n))return Oe(t);o-=s.top-l.viewOffset;for(var a=0;a<e.display.gutterSpecs.length;++a){var u=l.gutters.childNodes[a];if(u&&u.getBoundingClientRect().right>=i)return Se(e,n,e,rt(e.doc,o),e.display.gutterSpecs[a].className,t),Oe(t)}}function ll(e,t){return ol(e,t,"gutterClick",!0)}function sl(e,t){var n,r;bn(e.display,t)||(r=t,Te(n=e,"gutterContextMenu")&&ol(n,r,"gutterContextMenu",!1))||Le(e,t,"contextmenu")||S||e.display.input.onContextMenu(t)}function al(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),En(e)}nl.prototype.compare=function(e,t,n){return this.time+400>e&&0==st(t,this.pos)&&n==this.button};var ul={toString:function(){return"CodeMirror.Init"}},cl={},hl={};function dl(e,t,n){var r,i;!t!=!(n&&n!=ul)&&(r=e.display.dragFunctions,(i=t?we:Ce)(e.display.scroller,"dragstart",r.start),i(e.display.scroller,"dragenter",r.enter),i(e.display.scroller,"dragover",r.over),i(e.display.scroller,"dragleave",r.leave),i(e.display.scroller,"drop",r.drop))}function fl(e){e.options.lineWrapping?(H(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(T(e.display.wrapper,"CodeMirror-wrap"),_t(e)),tr(e),ir(e),En(e),setTimeout(function(){return Hr(e)},100)}function pl(e,t){var n=this;if(!(this instanceof pl))return new pl(e,t);this.options=t=t?I(t):{},I(cl,t,!1);var r=t.value;"string"==typeof r?r=new vo(r,t.mode,null,t.lineSeparator,t.direction):t.mode&&(r.modeOption=t.mode),this.doc=r;var i=new pl.inputStyles[t.inputStyle](this),o=this.display=new ri(e,r,i,t);for(var l in al(o.wrapper.CodeMirror=this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Er(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new z,keySeq:null,specialChars:null},t.autofocus&&!d&&o.input.focus(),x&&C<11&&setTimeout(function(){return n.display.input.reset(!0)},20),function(i){var o=i.display;we(o.scroller,"mousedown",Gr(i,rl)),we(o.scroller,"dblclick",x&&C<11?Gr(i,function(e){var t,n;Le(i,e)||(!(t=nr(i,e))||ll(i,e)||bn(i.display,e)||(Ne(e),n=i.findWordAt(t),Pi(i.doc,n.anchor,n.head)))}):function(e){return Le(i,e)||Ne(e)});we(o.scroller,"contextmenu",function(e){return sl(i,e)}),we(o.input.getField(),"contextmenu",function(e){o.scroller.contains(e.target)||sl(i,e)});var n,r={end:0};function l(){o.activeTouch&&(n=setTimeout(function(){return o.activeTouch=null},1e3),(r=o.activeTouch).end=+new Date)}function s(e,t){if(null==t.left)return 1;var n=t.left-e.left,r=t.top-e.top;return 400<n*n+r*r}we(o.scroller,"touchstart",function(e){var t;Le(i,e)||function(e){if(1==e.touches.length){var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}}(e)||ll(i,e)||(o.input.ensurePolled(),clearTimeout(n),t=+new Date,o.activeTouch={start:t,moved:!1,prev:t-r.end<=300?r:null},1==e.touches.length&&(o.activeTouch.left=e.touches[0].pageX,o.activeTouch.top=e.touches[0].pageY))}),we(o.scroller,"touchmove",function(){o.activeTouch&&(o.activeTouch.moved=!0)}),we(o.scroller,"touchend",function(e){var t,n,r=o.activeTouch;r&&!bn(o,e)&&null!=r.left&&!r.moved&&new Date-r.start<300&&(t=i.coordsChar(o.activeTouch,"page"),n=!r.prev||s(r,r.prev)?new ci(t,t):!r.prev.prev||s(r,r.prev.prev)?i.findWordAt(t):new ci(lt(t.line,0),ft(i.doc,lt(t.line+1,0))),i.setSelection(n.anchor,n.head),i.focus(),Ne(e)),l()}),we(o.scroller,"touchcancel",l),we(o.scroller,"scroll",function(){o.scroller.clientHeight&&(Mr(i,o.scroller.scrollTop),Ar(i,o.scroller.scrollLeft,!0),Se(i,"scroll",i))}),we(o.scroller,"mousewheel",function(e){return ai(i,e)}),we(o.scroller,"DOMMouseScroll",function(e){return ai(i,e)}),we(o.wrapper,"scroll",function(){return o.wrapper.scrollTop=o.wrapper.scrollLeft=0}),o.dragFunctions={enter:function(e){Le(i,e)||De(e)},over:function(e){var t,n,r;Le(i,e)||((r=nr(t=i,e))&&(hr(t,r,n=document.createDocumentFragment()),t.display.dragCursor||(t.display.dragCursor=O("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),t.display.lineSpace.insertBefore(t.display.dragCursor,t.display.cursorDiv)),N(t.display.dragCursor,n)),De(e))},start:function(e){return t=i,n=e,void(x&&(!t.state.draggingText||new Date-yo<100)?De(n):Le(t,n)||bn(t.display,n)||(n.dataTransfer.setData("Text",t.getSelection()),n.dataTransfer.effectAllowed="copyMove",n.dataTransfer.setDragImage&&!c&&((r=O("img",null,null,"position: fixed; left: 0; top: 0;")).src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",m&&(r.width=r.height=1,t.display.wrapper.appendChild(r),r._top=r.offsetTop),n.dataTransfer.setDragImage(r,0,0),m&&r.parentNode.removeChild(r))));var t,n,r},drop:Gr(i,bo),leave:function(e){Le(i,e)||wo(i)}};var e=o.input.getField();we(e,"keyup",function(e){return Qo.call(i,e)}),we(e,"keydown",Gr(i,Zo)),we(e,"keypress",Gr(i,Jo)),we(e,"focus",function(e){return mr(i,e)}),we(e,"blur",function(e){return vr(i,e)})}(this),So(),Rr(this),this.curOp.forceUpdate=!0,Ci(this,r),t.autofocus&&!d||this.hasFocus()?setTimeout(function(){n.hasFocus()&&!n.state.focused&&mr(n)},20):vr(this),hl)hl.hasOwnProperty(l)&&hl[l](this,t[l],ul);Jr(this),t.finishInit&&t.finishInit(this);for(var s=0;s<gl.length;++s)gl[s](this);zr(this),v&&t.lineWrapping&&"optimizelegibility"==getComputedStyle(o.lineDiv).textRendering&&(o.lineDiv.style.textRendering="auto")}pl.defaults=cl,pl.optionHandlers=hl;var gl=[];function ml(e,t,n,r){var i,o=e.doc;null==n&&(n="add"),"smart"==n&&(o.mode.indent?i=bt(e,t).state:n="prev");var l=e.options.tabSize,s=Qe(o,t),a=R(s.text,null,l);s.stateAfter&&(s.stateAfter=null);var u,c=s.text.match(/^\s*/)[0];if(r||/\S/.test(s.text)){if("smart"==n&&((u=o.mode.indent(i,s.text.slice(c.length),s.text))==U||150<u)){if(!r)return;n="prev"}}else u=0,n="not";"prev"==n?u=t>o.first?R(Qe(o,t-1).text,null,l):0:"add"==n?u=a+e.options.indentUnit:"subtract"==n?u=a-e.options.indentUnit:"number"==typeof n&&(u=a+n),u=Math.max(0,u);var h="",d=0;if(e.options.indentWithTabs)for(var f=Math.floor(u/l);f;--f)d+=l,h+="\t";if(d<u&&(h+=_(u-d)),h!=c)return to(o,h,lt(t,0),lt(t,c.length),"+input"),!(s.stateAfter=null);for(var p=0;p<o.sel.ranges.length;p++){var g=o.sel.ranges[p];if(g.head.line==t&&g.head.ch<c.length){var m=lt(t,c.length);Ii(o,p,new ci(m,m));break}}}pl.defineInitHook=function(e){return gl.push(e)};var vl=null;function yl(e){vl=e}function bl(e,t,n,r,i){var o=e.doc;e.display.shift=!1,r=r||o.sel;var l=new Date-200,s="paste"==i||e.state.pasteIncoming>l,a=Re(t),u=null;if(s&&1<r.ranges.length)if(vl&&vl.text.join("\n")==t){if(r.ranges.length%vl.text.length==0){u=[];for(var c=0;c<vl.text.length;c++)u.push(o.splitLines(vl.text[c]))}}else a.length==r.ranges.length&&e.options.pasteLinesPerSelection&&(u=q(a,function(e){return[e]}));for(var h=e.curOp.updateInput,d=r.ranges.length-1;0<=d;d--){var f=r.ranges[d],p=f.from(),g=f.to();f.empty()&&(n&&0<n?p=lt(p.line,p.ch-n):e.state.overwrite&&!s?g=lt(g.line,Math.min(Qe(o,g.line).text.length,g.ch+$(a).length)):s&&vl&&vl.lineWise&&vl.text.join("\n")==a.join("\n")&&(p=g=lt(p.line,0)));var m={from:p,to:g,text:u?u[d%u.length]:a,origin:i||(s?"paste":e.state.cutIncoming>l?"cut":"+input")};qi(e.doc,m),un(e,"inputRead",e,m)}t&&!s&&xl(e,t),Sr(e),e.curOp.updateInput<2&&(e.curOp.updateInput=h),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function wl(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");return n&&(e.preventDefault(),t.isReadOnly()||t.options.disableInput||Br(t,function(){return bl(t,n,0,null,"paste")}),1)}function xl(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;0<=r;r--){var i=n.ranges[r];if(!(100<i.head.ch||r&&n.ranges[r-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s<o.electricChars.length;s++)if(-1<t.indexOf(o.electricChars.charAt(s))){l=ml(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Qe(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=ml(e,i.head.line,"smart"));l&&un(e,"electricInput",e,i.head.line)}}}function Cl(e){for(var t=[],n=[],r=0;r<e.doc.sel.ranges.length;r++){var i=e.doc.sel.ranges[r].head.line,o={anchor:lt(i,0),head:lt(i+1,0)};n.push(o),t.push(e.getRange(o.anchor,o.head))}return{text:t,ranges:n}}function Sl(e,t,n,r){e.setAttribute("autocorrect",n?"":"off"),e.setAttribute("autocapitalize",r?"":"off"),e.setAttribute("spellcheck",!!t)}function Ll(){var e=O("textarea",null,null,"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"),t=O("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return v?e.style.width="1000px":e.setAttribute("wrap","off"),a&&(e.style.border="1px solid black"),Sl(e),t}function kl(i,o,l,s,a){var e=o,t=l,u=Qe(i,o.line),c=a&&"rtl"==i.direction?-l:l;function n(e){var t,n,r;if(null==(n="codepoint"==s?(t=u.text.charCodeAt(o.ch+(0<s?0:-1)),isNaN(t)?null:new lt(o.line,Math.max(0,Math.min(u.text.length,o.ch+l*(55296<=t&&t<56320?2:1))),-l)):a?Go(i.cm,u,o,l):zo(u,o,l))){if(e||(r=o.line+c)<i.first||r>=i.first+i.size||(o=new lt(r,o.ch,o.sticky),!(u=Qe(i,r))))return;o=Bo(a,i.cm,u,o.line,c)}else o=n;return 1}if("char"==s||"codepoint"==s)n();else if("column"==s)n(!0);else if("word"==s||"group"==s)for(var r=null,h="group"==s,d=i.cm&&i.cm.getHelper(o,"wordChars"),f=!0;!(l<0)||n(!f);f=!1){var p=u.text.charAt(o.ch)||"\n",g=te(p,d)?"w":h&&"\n"==p?"n":!h||/\s/.test(p)?null:"p";if(!h||f||g||(g="s"),r&&r!=g){l<0&&(l=1,n(),o.sticky="after");break}if(g&&(r=g),0<l&&!n(!f))break}var m=Xi(i,o,e,t,!0);return at(e,m)&&(m.hitSide=!0),m}function Tl(e,t,n,r){var i,o,l,s,a=e.doc,u=t.left;for("page"==r?(i=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),o=Math.max(i-.5*qn(e.display),3),l=(0<n?t.bottom:t.top)+n*o):"line"==r&&(l=0<n?t.bottom+3:t.top-3);(s=Xn(e,u,l)).outside;){if(n<0?l<=0:l>=a.height){s.hitSide=!0;break}l+=5*n}return s}function Ml(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new z,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null}function Nl(e,t){var n=Nn(e,t.line);if(!n||n.hidden)return null;var r=Qe(e.doc,t.line),i=Tn(n,r,t.line),o=ye(r,e.doc.direction),l="left";o&&(l=ae(o,t.ch)%2?"right":"left");var s=Hn(i.map,t.ch,l);return s.offset="right"==s.collapse?s.end:s.start,s}function Al(e,t){return t&&(e.bad=!0),e}function Ol(e,t,n){var r;if(t==e.display.lineDiv){if(!(r=e.display.lineDiv.childNodes[n]))return Al(e.clipPos(lt(e.display.viewTo-1)),!0);t=null,n=0}else for(r=t;;r=r.parentNode){if(!r||r==e.display.lineDiv)return null;if(r.parentNode&&r.parentNode==e.display.lineDiv)break}for(var i=0;i<e.display.view.length;i++){var o=e.display.view[i];if(o.node==r)return function(u,e,t){var n=u.text.firstChild,r=!1;if(!e||!D(n,e))return Al(lt(nt(u.line),0),!0);if(e==n&&(r=!0,e=n.childNodes[t],t=0,!e)){var i=u.rest?$(u.rest):u.line;return Al(lt(nt(i),i.text.length),r)}var o=3==e.nodeType?e:null,l=e;o||1!=e.childNodes.length||3!=e.firstChild.nodeType||(o=e.firstChild,t=t&&o.nodeValue.length);for(;l.parentNode!=n;)l=l.parentNode;var c=u.measure,h=c.maps;function s(e,t,n){for(var r=-1;r<(h?h.length:0);r++)for(var i=r<0?c.map:h[r],o=0;o<i.length;o+=3){var l=i[o+2];if(l==e||l==t){var s=nt(r<0?u.line:u.rest[r]),a=i[o]+n;return(n<0||l!=e)&&(a=i[o+(n?1:0)]),lt(s,a)}}}var a=s(o,l,t);if(a)return Al(a,r);for(var d=l.nextSibling,f=o?o.nodeValue.length-t:0;d;d=d.nextSibling){if(a=s(d,d.firstChild,0))return Al(lt(a.line,a.ch-f),r);f+=d.textContent.length}for(var p=l.previousSibling,g=t;p;p=p.previousSibling){if(a=s(p,p.firstChild,-1))return Al(lt(a.line,a.ch+g),r);g+=p.textContent.length}}(o,t,n)}}Ml.prototype.init=function(e){var t=this,l=this,s=l.cm,a=l.div=e.lineDiv;function u(e){for(var t=e.target;t;t=t.parentNode){if(t==a)return 1;if(/\bCodeMirror-(?:line)?widget\b/.test(t.className))break}}function n(e){if(u(e)&&!Le(s,e)){if(s.somethingSelected())yl({lineWise:!1,text:s.getSelections()}),"cut"==e.type&&s.replaceSelection("",null,"cut");else{if(!s.options.lineWiseCopyCut)return;var t=Cl(s);yl({lineWise:!0,text:t.text}),"cut"==e.type&&s.operation(function(){s.setSelections(t.ranges,0,V),s.replaceSelection("",null,"cut")})}if(e.clipboardData){e.clipboardData.clearData();var n=vl.text.join("\n");if(e.clipboardData.setData("Text",n),e.clipboardData.getData("Text")==n)return void e.preventDefault()}var r=Ll(),i=r.firstChild;s.display.lineSpace.insertBefore(r,s.display.lineSpace.firstChild),i.value=vl.text.join("\n");var o=document.activeElement;P(i),setTimeout(function(){s.display.lineSpace.removeChild(r),o.focus(),o==a&&l.showPrimarySelection()},50)}}Sl(a,s.options.spellcheck,s.options.autocorrect,s.options.autocapitalize),we(a,"paste",function(e){!u(e)||Le(s,e)||wl(e,s)||C<=11&&setTimeout(Gr(s,function(){return t.updateFromDOM()}),20)}),we(a,"compositionstart",function(e){t.composing={data:e.data,done:!1}}),we(a,"compositionupdate",function(e){t.composing||(t.composing={data:e.data,done:!1})}),we(a,"compositionend",function(e){t.composing&&(e.data!=t.composing.data&&t.readFromDOMSoon(),t.composing.done=!0)}),we(a,"touchstart",function(){return l.forceCompositionEnd()}),we(a,"input",function(){t.composing||t.readFromDOMSoon()}),we(a,"copy",n),we(a,"cut",n)},Ml.prototype.screenReaderLabelChanged=function(e){e?this.div.setAttribute("aria-label",e):this.div.removeAttribute("aria-label")},Ml.prototype.prepareSelection=function(){var e=cr(this.cm,!1);return e.focus=document.activeElement==this.div,e},Ml.prototype.showSelection=function(e,t){e&&this.cm.display.view.length&&((e.focus||t)&&this.showPrimarySelection(),this.showMultipleSelections(e))},Ml.prototype.getSelection=function(){return this.cm.display.wrapper.ownerDocument.getSelection()},Ml.prototype.showPrimarySelection=function(){var e=this.getSelection(),t=this.cm,n=t.doc.sel.primary(),r=n.from(),i=n.to();if(t.display.viewTo==t.display.viewFrom||r.line>=t.display.viewTo||i.line<t.display.viewFrom)e.removeAllRanges();else{var o=Ol(t,e.anchorNode,e.anchorOffset),l=Ol(t,e.focusNode,e.focusOffset);if(!o||o.bad||!l||l.bad||0!=st(ht(o,l),r)||0!=st(ct(o,l),i)){var s,a,u=t.display.view,c=r.line>=t.display.viewFrom&&Nl(t,r)||{node:u[0].measure.map[2],offset:0},h=i.line<t.display.viewTo&&Nl(t,i);if(h||(h={node:(a=(s=u[u.length-1].measure).maps?s.maps[s.maps.length-1]:s.map)[a.length-1],offset:a[a.length-2]-a[a.length-3]}),c&&h){var d,f=e.rangeCount&&e.getRangeAt(0);try{d=k(c.node,c.offset,h.offset,h.node)}catch(e){}d&&(!g&&t.state.focused?(e.collapse(c.node,c.offset),d.collapsed||(e.removeAllRanges(),e.addRange(d))):(e.removeAllRanges(),e.addRange(d)),f&&null==e.anchorNode?e.addRange(f):g&&this.startGracePeriod()),this.rememberSelection()}else e.removeAllRanges()}}},Ml.prototype.startGracePeriod=function(){var e=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){e.gracePeriod=!1,e.selectionChanged()&&e.cm.operation(function(){return e.cm.curOp.selectionChanged=!0})},20)},Ml.prototype.showMultipleSelections=function(e){N(this.cm.display.cursorDiv,e.cursors),N(this.cm.display.selectionDiv,e.selection)},Ml.prototype.rememberSelection=function(){var e=this.getSelection();this.lastAnchorNode=e.anchorNode,this.lastAnchorOffset=e.anchorOffset,this.lastFocusNode=e.focusNode,this.lastFocusOffset=e.focusOffset},Ml.prototype.selectionInEditor=function(){var e=this.getSelection();if(!e.rangeCount)return!1;var t=e.getRangeAt(0).commonAncestorContainer;return D(this.div,t)},Ml.prototype.focus=function(){"nocursor"!=this.cm.options.readOnly&&(this.selectionInEditor()&&document.activeElement==this.div||this.showSelection(this.prepareSelection(),!0),this.div.focus())},Ml.prototype.blur=function(){this.div.blur()},Ml.prototype.getField=function(){return this.div},Ml.prototype.supportsTouch=function(){return!0},Ml.prototype.receivedFocus=function(){var t=this;this.selectionInEditor()?this.pollSelection():Br(this.cm,function(){return t.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,function e(){t.cm.state.focused&&(t.pollSelection(),t.polling.set(t.cm.options.pollInterval,e))})},Ml.prototype.selectionChanged=function(){var e=this.getSelection();return e.anchorNode!=this.lastAnchorNode||e.anchorOffset!=this.lastAnchorOffset||e.focusNode!=this.lastFocusNode||e.focusOffset!=this.lastFocusOffset},Ml.prototype.pollSelection=function(){if(null==this.readDOMTimeout&&!this.gracePeriod&&this.selectionChanged()){var e,t,n=this.getSelection(),r=this.cm;if(h&&l&&this.cm.display.gutterSpecs.length&&function(e){for(var t=e;t;t=t.parentNode)if(/CodeMirror-gutter-wrapper/.test(t.className))return!0;return!1}(n.anchorNode))return this.cm.triggerOnKeyDown({type:"keydown",keyCode:8,preventDefault:Math.abs}),this.blur(),void this.focus();this.composing||(this.rememberSelection(),e=Ol(r,n.anchorNode,n.anchorOffset),t=Ol(r,n.focusNode,n.focusOffset),e&&t&&Br(r,function(){Bi(r.doc,di(e,t),V),(e.bad||t.bad)&&(r.curOp.selectionChanged=!0)}))}},Ml.prototype.pollContent=function(){null!=this.readDOMTimeout&&(clearTimeout(this.readDOMTimeout),this.readDOMTimeout=null);var e,t,n,r=this.cm,i=r.display,o=r.doc.sel.primary(),l=o.from(),s=o.to();if(0==l.ch&&l.line>r.firstLine()&&(l=lt(l.line-1,Qe(r.doc,l.line-1).length)),s.ch==Qe(r.doc,s.line).text.length&&s.line<r.lastLine()&&(s=lt(s.line+1,0)),l.line<i.viewFrom||s.line>i.viewTo-1)return!1;n=l.line==i.viewFrom||0==(e=rr(r,l.line))?(t=nt(i.view[0].line),i.view[0].node):(t=nt(i.view[e].line),i.view[e-1].node.nextSibling);var a,u=rr(r,s.line),c=u==i.view.length-1?(a=i.viewTo-1,i.lineDiv.lastChild):(a=nt(i.view[u+1].line)-1,i.view[u+1].node.previousSibling);if(!n)return!1;for(var h=r.doc.splitLines(function(u,e,t,c,h){var n="",d=!1,f=u.doc.lineSeparator(),p=!1;function g(){d&&(n+=f,p&&(n+=f),d=p=!1)}function m(e){e&&(g(),n+=e)}for(;!function e(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)return void m(n);var r,i=t.getAttribute("cm-marker");if(i){var o=u.findMarks(lt(c,0),lt(h+1,0),(a=+i,function(e){return e.id==a}));return void(o.length&&(r=o[0].find(0))&&m(Je(u.doc,r.from,r.to).join(f)))}if("false"==t.getAttribute("contenteditable"))return;var l=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;l&&g();for(var s=0;s<t.childNodes.length;s++)e(t.childNodes[s]);/^(pre|p)$/i.test(t.nodeName)&&(p=!0),l&&(d=!0)}else 3==t.nodeType&&m(t.nodeValue.replace(/\u200b/g,"").replace(/\u00a0/g," "));var a}(e),e!=t;)e=e.nextSibling,p=!1;return n}(r,n,c,t,a)),d=Je(r.doc,lt(t,0),lt(a,Qe(r.doc,a).text.length));1<h.length&&1<d.length;)if($(h)==$(d))h.pop(),d.pop(),a--;else{if(h[0]!=d[0])break;h.shift(),d.shift(),t++}for(var f=0,p=0,g=h[0],m=d[0],v=Math.min(g.length,m.length);f<v&&g.charCodeAt(f)==m.charCodeAt(f);)++f;for(var y=$(h),b=$(d),w=Math.min(y.length-(1==h.length?f:0),b.length-(1==d.length?f:0));p<w&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)++p;if(1==h.length&&1==d.length&&t==l.line)for(;f&&f>l.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)f--,p++;h[h.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),h[0]=h[0].slice(f).replace(/\u200b+$/,"");var x=lt(t,f),C=lt(a,d.length?$(d).length-p:0);return 1<h.length||h[0]||st(x,C)?(to(r.doc,h,x,C,"+input"),!0):void 0},Ml.prototype.ensurePolled=function(){this.forceCompositionEnd()},Ml.prototype.reset=function(){this.forceCompositionEnd()},Ml.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Ml.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},Ml.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||Br(this.cm,function(){return ir(e.cm)})},Ml.prototype.setUneditable=function(e){e.contentEditable="false"},Ml.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Gr(this.cm,bl)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Ml.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Ml.prototype.onContextMenu=function(){},Ml.prototype.resetPosition=function(){},Ml.prototype.needsContentAttribute=!0;function Dl(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new z,this.hasSelection=!1,this.composing=null}var Wl,Hl,Fl,Pl,El;function Il(e,t,r,n){Wl.defaults[e]=t,r&&(Hl[e]=n?function(e,t,n){n!=ul&&r(e,t,n)}:r)}Dl.prototype.init=function(n){var e=this,r=this,i=this.cm;this.createField(n);var o=this.textarea;function t(e){if(!Le(i,e)){if(i.somethingSelected())yl({lineWise:!1,text:i.getSelections()});else{if(!i.options.lineWiseCopyCut)return;var t=Cl(i);yl({lineWise:!0,text:t.text}),"cut"==e.type?i.setSelections(t.ranges,null,V):(r.prevInput="",o.value=t.text.join("\n"),P(o))}"cut"==e.type&&(i.state.cutIncoming=+new Date)}}n.wrapper.insertBefore(this.wrapper,n.wrapper.firstChild),a&&(o.style.width="0px"),we(o,"input",function(){x&&9<=C&&e.hasSelection&&(e.hasSelection=null),r.poll()}),we(o,"paste",function(e){Le(i,e)||wl(e,i)||(i.state.pasteIncoming=+new Date,r.fastPoll())}),we(o,"cut",t),we(o,"copy",t),we(n.scroller,"paste",function(e){if(!bn(n,e)&&!Le(i,e)){if(!o.dispatchEvent)return i.state.pasteIncoming=+new Date,void r.focus();var t=new Event("paste");t.clipboardData=e.clipboardData,o.dispatchEvent(t)}}),we(n.lineSpace,"selectstart",function(e){bn(n,e)||Ne(e)}),we(o,"compositionstart",function(){var e=i.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:i.markText(e,i.getCursor("to"),{className:"CodeMirror-composing"})}}),we(o,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},Dl.prototype.createField=function(e){this.wrapper=Ll(),this.textarea=this.wrapper.firstChild},Dl.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},Dl.prototype.prepareSelection=function(){var e,t,n,r=this.cm,i=r.display,o=r.doc,l=cr(r);return r.options.moveInputWithCursor&&(e=Vn(r,o.sel.primary().head,"div"),t=i.wrapper.getBoundingClientRect(),n=i.lineDiv.getBoundingClientRect(),l.teTop=Math.max(0,Math.min(i.wrapper.clientHeight-10,e.top+n.top-t.top)),l.teLeft=Math.max(0,Math.min(i.wrapper.clientWidth-10,e.left+n.left-t.left))),l},Dl.prototype.showSelection=function(e){var t=this.cm.display;N(t.cursorDiv,e.cursors),N(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Dl.prototype.reset=function(e){var t,n;this.contextMenuPending||this.composing||((t=this.cm).somethingSelected()?(this.prevInput="",n=t.getSelection(),this.textarea.value=n,t.state.focused&&P(this.textarea),x&&9<=C&&(this.hasSelection=n)):e||(this.prevInput=this.textarea.value="",x&&9<=C&&(this.hasSelection=null)))},Dl.prototype.getField=function(){return this.textarea},Dl.prototype.supportsTouch=function(){return!1},Dl.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!d||W()!=this.textarea))try{this.textarea.focus()}catch(e){}},Dl.prototype.blur=function(){this.textarea.blur()},Dl.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Dl.prototype.receivedFocus=function(){this.slowPoll()},Dl.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},Dl.prototype.fastPoll=function(){var t=!1,n=this;n.pollingFast=!0,n.polling.set(20,function e(){n.poll()||t?(n.pollingFast=!1,n.slowPoll()):(t=!0,n.polling.set(60,e))})},Dl.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||ze(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=n.value;if(i==r&&!t.somethingSelected())return!1;if(x&&9<=C&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||r||(r="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var l=0,s=Math.min(r.length,i.length);l<s&&r.charCodeAt(l)==i.charCodeAt(l);)++l;return Br(t,function(){bl(t,i.slice(l),r.length-l,null,e.composing?"*compose":null),1e3<i.length||-1<i.indexOf("\n")?n.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},Dl.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Dl.prototype.onKeyPress=function(){x&&9<=C&&(this.hasSelection=null),this.fastPoll()},Dl.prototype.onContextMenu=function(e){var n=this,r=n.cm,i=r.display,o=n.textarea;n.contextMenuPending&&n.contextMenuPending();var l,s,t,a,u,c=nr(r,e),h=i.scroller.scrollTop;function d(){var e,t;null!=o.selectionStart&&(t="​"+((e=r.somethingSelected())?o.value:""),o.value="⇚",o.value=t,n.prevInput=e?"":"​",o.selectionStart=1,o.selectionEnd=t.length,i.selForContextMenu=r.doc.sel)}function f(){var e,t;n.contextMenuPending==f&&(n.contextMenuPending=!1,n.wrapper.style.cssText=s,o.style.cssText=l,x&&C<9&&i.scrollbars.setScrollTop(i.scroller.scrollTop=h),null!=o.selectionStart&&((!x||x&&C<9)&&d(),e=0,t=function(){i.selForContextMenu==r.doc.sel&&0==o.selectionStart&&0<o.selectionEnd&&"​"==n.prevInput?Gr(r,_i)(r):e++<10?i.detectingSelectAll=setTimeout(t,500):(i.selForContextMenu=null,i.input.reset())},i.detectingSelectAll=setTimeout(t,200)))}c&&!m&&(r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(c)&&Gr(r,Bi)(r.doc,di(c),V),l=o.style.cssText,s=n.wrapper.style.cssText,t=n.wrapper.offsetParent.getBoundingClientRect(),n.wrapper.style.cssText="position: static",o.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-t.top-5)+"px; left: "+(e.clientX-t.left-5)+"px;\n z-index: 1000; background: "+(x?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",v&&(a=window.scrollY),i.input.focus(),v&&window.scrollTo(null,a),i.input.reset(),r.somethingSelected()||(o.value=n.prevInput=" "),n.contextMenuPending=f,i.selForContextMenu=r.doc.sel,clearTimeout(i.detectingSelectAll),x&&9<=C&&d(),S?(De(e),u=function(){Ce(window,"mouseup",u),setTimeout(f,20)},we(window,"mouseup",u)):setTimeout(f,50))},Dl.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},Dl.prototype.setUneditable=function(){},Dl.prototype.needsContentAttribute=!1,Hl=(Wl=pl).optionHandlers,Wl.defineOption=Il,Wl.Init=ul,Il("value","",function(e,t){return e.setValue(t)},!0),Il("mode",null,function(e,t){e.doc.modeOption=t,vi(e)},!0),Il("indentUnit",2,vi,!0),Il("indentWithTabs",!1),Il("smartIndent",!0),Il("tabSize",4,function(e){yi(e),En(e),ir(e)},!0),Il("lineSeparator",null,function(e,r){if(e.doc.lineSep=r){var i=[],o=e.doc.first;e.doc.iter(function(e){for(var t=0;;){var n=e.text.indexOf(r,t);if(-1==n)break;t=n+r.length,i.push(lt(o,n))}o++});for(var t=i.length-1;0<=t;t--)to(e.doc,r,i[t],lt(i[t].line,i[t].ch+r.length))}}),Il("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=ul&&e.refresh()}),Il("specialCharPlaceholder",en,function(e){return e.refresh()},!0),Il("electricChars",!0),Il("inputStyle",d?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),Il("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),Il("autocorrect",!1,function(e,t){return e.getInputField().autocorrect=t},!0),Il("autocapitalize",!1,function(e,t){return e.getInputField().autocapitalize=t},!0),Il("rtlMoveVisually",!p),Il("wholeLineUpdateBefore",!0),Il("theme","default",function(e){al(e),ni(e)},!0),Il("keyMap","default",function(e,t,n){var r=Eo(t),i=n!=ul&&Eo(n);i&&i.detach&&i.detach(e,r),r.attach&&r.attach(e,i||null)}),Il("extraKeys",null),Il("configureMouse",null),Il("lineWrapping",!1,fl,!0),Il("gutters",[],function(e,t){e.display.gutterSpecs=ei(t,e.options.lineNumbers),ni(e)},!0),Il("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?Jn(e.display)+"px":"0",e.refresh()},!0),Il("coverGutterNextToScrollbar",!1,function(e){return Hr(e)},!0),Il("scrollbarStyle","native",function(e){Er(e),Hr(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),Il("lineNumbers",!1,function(e,t){e.display.gutterSpecs=ei(e.options.gutters,t),ni(e)},!0),Il("firstLineNumber",1,ni,!0),Il("lineNumberFormatter",function(e){return e},ni,!0),Il("showCursorWhenSelecting",!1,ur,!0),Il("resetSelectionOnContextMenu",!0),Il("lineWiseCopyCut",!0),Il("pasteLinesPerSelection",!0),Il("selectionsMayTouch",!1),Il("readOnly",!1,function(e,t){"nocursor"==t&&(vr(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),Il("screenReaderLabel",null,function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)}),Il("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),Il("dragDrop",!0,dl),Il("allowDropFileTypes",null),Il("cursorBlinkRate",530),Il("cursorScrollMargin",0),Il("cursorHeight",1,ur,!0),Il("singleCursorHeightPerLine",!0,ur,!0),Il("workTime",100),Il("workDelay",100),Il("flattenSpans",!0,yi,!0),Il("addModeClass",!1,yi,!0),Il("pollInterval",100),Il("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),Il("historyEventDelay",1250),Il("viewportMargin",10,function(e){return e.refresh()},!0),Il("maxHighlightLength",1e4,yi,!0),Il("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),Il("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),Il("autofocus",null),Il("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0),Il("phrases",null),Pl=(Fl=pl).optionHandlers,El=Fl.helpers={},Fl.prototype={constructor:Fl,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,t){var n=this.options,r=n[e];n[e]==t&&"mode"!=e||(n[e]=t,Pl.hasOwnProperty(e)&&Gr(this,Pl[e])(this,t,r),Se(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Eo(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,n=0;n<t.length;++n)if(t[n]==e||t[n].name==e)return t.splice(n,1),!0},addOverlay:Ur(function(e,t){var n=e.token?e:Fl.getMode(this.options,e);if(n.startState)throw new Error("Overlays may not be stateful.");!function(e,t,n){for(var r=0,i=n(t);r<e.length&&n(e[r])<=i;)r++;e.splice(r,0,t)}(this.state.overlays,{mode:n,modeSpec:e,opaque:t&&t.opaque,priority:t&&t.priority||0},function(e){return e.priority}),this.state.modeGen++,ir(this)}),removeOverlay:Ur(function(e){for(var t=this.state.overlays,n=0;n<t.length;++n){var r=t[n].modeSpec;if(r==e||"string"==typeof e&&r.name==e)return t.splice(n,1),this.state.modeGen++,void ir(this)}}),indentLine:Ur(function(e,t,n){"string"!=typeof t&&"number"!=typeof t&&(t=null==t?this.options.smartIndent?"smart":"prev":t?"add":"subtract"),it(this.doc,e)&&ml(this,e,t,n)}),indentSelection:Ur(function(e){for(var t=this.doc.sel.ranges,n=-1,r=0;r<t.length;r++){var i=t[r];if(i.empty())i.head.line>n&&(ml(this,i.head.line,e,!0),n=i.head.line,r==this.doc.sel.primIndex&&Sr(this));else{for(var o=i.from(),l=i.to(),s=Math.max(n,o.line),n=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1,a=s;a<n;++a)ml(this,a,e);var u=this.doc.sel.ranges;0==o.ch&&t.length==u.length&&0<u[r].from().ch&&Ii(this.doc,r,new ci(o,u[r].to()),V)}}}),getTokenAt:function(e,t){return Lt(this,e,t)},getLineTokens:function(e,t){return Lt(this,lt(e),t,!0)},getTokenTypeAt:function(e){e=ft(this.doc,e);var t,n=yt(this,Qe(this.doc,e.line)),r=0,i=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var l=r+i>>1;if((l?n[2*l-1]:0)>=o)i=l;else{if(!(n[2*l+1]<o)){t=n[2*l+2];break}r=1+l}}var s=t?t.indexOf("overlay "):-1;return s<0?t:0==s?null:t.slice(0,s-1)},getModeAt:function(e){var t=this.doc.mode;return t.innerMode?Fl.innerMode(t,this.getTokenAt(e).state).mode:t},getHelper:function(e,t){return this.getHelpers(e,t)[0]},getHelpers:function(e,t){var n=[];if(!El.hasOwnProperty(t))return n;var r=El[t],i=this.getModeAt(e);if("string"==typeof i[t])r[i[t]]&&n.push(r[i[t]]);else if(i[t])for(var o=0;o<i[t].length;o++){var l=r[i[t][o]];l&&n.push(l)}else i.helperType&&r[i.helperType]?n.push(r[i.helperType]):r[i.name]&&n.push(r[i.name]);for(var s=0;s<r._global.length;s++){var a=r._global[s];a.pred(i,this)&&-1==B(n,a.val)&&n.push(a.val)}return n},getStateAfter:function(e,t){var n=this.doc;return bt(this,(e=dt(n,null==e?n.first+n.size-1:e))+1,t).state},cursorCoords:function(e,t){var n=this.doc.sel.primary(),r=null==e?n.head:"object"==typeof e?ft(this.doc,e):e?n.from():n.to();return Vn(this,r,t||"page")},charCoords:function(e,t){return Un(this,ft(this.doc,e),t||"page")},coordsChar:function(e,t){return Xn(this,(e=Gn(this,e,t||"page")).left,e.top)},lineAtHeight:function(e,t){return e=Gn(this,{top:e,left:0},t||"page").top,rt(this.doc,e+this.display.viewOffset)},heightAtLine:function(e,t,n){var r,i=!1,o="number"==typeof e?(r=this.doc.first+this.doc.size-1,e<this.doc.first?e=this.doc.first:r<e&&(e=r,i=!0),Qe(this.doc,e)):e;return Bn(this,o,{top:0,left:0},t||"page",n||i).top+(i?this.doc.height-Xt(o):0)},defaultTextHeight:function(){return qn(this.display)},defaultCharWidth:function(){return Zn(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,i){var o,l,s,a,u,c=this.display,h=(e=Vn(this,ft(this.doc,e))).bottom,d=e.left;t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),c.sizer.appendChild(t),"over"==r?h=e.top:"above"!=r&&"near"!=r||(o=Math.max(c.wrapper.clientHeight,this.doc.height),l=Math.max(c.sizer.clientWidth,c.lineSpace.clientWidth),("above"==r||e.bottom+t.offsetHeight>o)&&e.top>t.offsetHeight?h=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=o&&(h=e.bottom),d+t.offsetWidth>l&&(d=l-t.offsetWidth)),t.style.top=h+"px",t.style.left=t.style.right="","right"==i?(d=c.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?d=0:"middle"==i&&(d=(c.sizer.clientWidth-t.offsetWidth)/2),t.style.left=d+"px"),n&&(s=this,a={left:d,top:h,right:d+t.offsetWidth,bottom:h+t.offsetHeight},null!=(u=xr(s,a)).scrollTop&&Mr(s,u.scrollTop),null!=u.scrollLeft&&Ar(s,u.scrollLeft))},triggerOnKeyDown:Ur(Zo),triggerOnKeyPress:Ur(Jo),triggerOnKeyUp:Qo,triggerOnMouseDown:Ur(rl),execCommand:function(e){if(Uo.hasOwnProperty(e))return Uo[e].call(null,this)},triggerElectric:Ur(function(e){xl(this,e)}),findPosH:function(e,t,n,r){var i=1;t<0&&(i=-1,t=-t);for(var o=ft(this.doc,e),l=0;l<t&&!(o=kl(this.doc,o,i,n,r)).hitSide;++l);return o},moveH:Ur(function(t,n){var r=this;this.extendSelectionsBy(function(e){return r.display.shift||r.doc.extend||e.empty()?kl(r.doc,e.head,t,n,r.options.rtlMoveVisually):t<0?e.from():e.to()},j)}),deleteH:Ur(function(n,r){var e=this.doc.sel,i=this.doc;e.somethingSelected()?i.replaceSelection("",null,"+delete"):Io(this,function(e){var t=kl(i,e.head,n,r,!1);return n<0?{from:t,to:e.head}:{from:e.head,to:t}})}),findPosV:function(e,t,n,r){var i=1,o=r;t<0&&(i=-1,t=-t);for(var l=ft(this.doc,e),s=0;s<t;++s){var a=Vn(this,l,"div");if(null==o?o=a.left:a.left=o,(l=Tl(this,a,i,n)).hitSide)break}return l},moveV:Ur(function(r,i){var o=this,l=this.doc,s=[],a=!this.display.shift&&!l.extend&&l.sel.somethingSelected();if(l.extendSelectionsBy(function(e){if(a)return r<0?e.from():e.to();var t=Vn(o,e.head,"div");null!=e.goalColumn&&(t.left=e.goalColumn),s.push(t.left);var n=Tl(o,t,r,i);return"page"==i&&e==l.sel.primary()&&Cr(o,Un(o,n,"div").top-t.top),n},j),s.length)for(var e=0;e<l.sel.ranges.length;e++)l.sel.ranges[e].goalColumn=s[e]}),findWordAt:function(e){var t=Qe(this.doc,e.line).text,n=e.ch,r=e.ch;if(t){var i=this.getHelper(e,"wordChars");"before"!=e.sticky&&r!=t.length||!n?++r:--n;for(var o=t.charAt(n),l=te(o,i)?function(e){return te(e,i)}:/\s/.test(o)?function(e){return/\s/.test(e)}:function(e){return!/\s/.test(e)&&!te(e)};0<n&&l(t.charAt(n-1));)--n;for(;r<t.length&&l(t.charAt(r));)++r}return new ci(lt(e.line,n),lt(e.line,r))},toggleOverwrite:function(e){null!=e&&e==this.state.overwrite||(((this.state.overwrite=!this.state.overwrite)?H:T)(this.display.cursorDiv,"CodeMirror-overwrite"),Se(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==W()},isReadOnly:function(){return!(!this.options.readOnly&&!this.doc.cantEdit)},scrollTo:Ur(function(e,t){Lr(this,e,t)}),getScrollInfo:function(){var e=this.display.scroller;return{left:e.scrollLeft,top:e.scrollTop,height:e.scrollHeight-Sn(this)-this.display.barHeight,width:e.scrollWidth-Sn(this)-this.display.barWidth,clientHeight:kn(this),clientWidth:Ln(this)}},scrollIntoView:Ur(function(e,t){var n,r;null==e?(e={from:this.doc.sel.primary().head,to:null},null==t&&(t=this.options.cursorScrollMargin)):"number"==typeof e?e={from:lt(e,0),to:null}:null==e.from&&(e={from:e,to:null}),e.to||(e.to=e.from),e.margin=t||0,null!=e.from.line?(r=e,kr(n=this),n.curOp.scrollToPos=r):Tr(this,e.from,e.to,e.margin)}),setSize:Ur(function(e,t){function n(e){return"number"==typeof e||/^\d+$/.test(String(e))?e+"px":e}var r=this;null!=e&&(this.display.wrapper.style.width=n(e)),null!=t&&(this.display.wrapper.style.height=n(t)),this.options.lineWrapping&&Pn(this);var i=this.display.viewFrom;this.doc.iter(i,this.display.viewTo,function(e){if(e.widgets)for(var t=0;t<e.widgets.length;t++)if(e.widgets[t].noHScroll){or(r,i,"widget");break}++i}),this.curOp.forceUpdate=!0,Se(this,"refresh",this)}),operation:function(e){return Br(this,e)},startOperation:function(){return Rr(this)},endOperation:function(){return zr(this)},refresh:Ur(function(){var e=this.display.cachedTextHeight;ir(this),this.curOp.forceUpdate=!0,En(this),Lr(this,this.doc.scrollLeft,this.doc.scrollTop),qr(this.display),(null==e||.5<Math.abs(e-qn(this.display))||this.options.lineWrapping)&&tr(this),Se(this,"refresh",this)}),swapDoc:Ur(function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Ci(this,e),En(this),this.display.input.reset(),Lr(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,un(this,"swapDoc",this,t),t}),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Me(Fl),Fl.registerHelper=function(e,t,n){El.hasOwnProperty(e)||(El[e]=Fl[e]={_global:[]}),El[e][t]=n},Fl.registerGlobalHelper=function(e,t,n,r){Fl.registerHelper(e,t,r),El[e]._global.push({pred:n,val:r})};var Rl,zl="iter insert remove copy getEditor constructor".split(" ");for(var Bl in vo.prototype)vo.prototype.hasOwnProperty(Bl)&&B(zl,Bl)<0&&(pl.prototype[Bl]=function(e){return function(){return e.apply(this.doc,arguments)}}(vo.prototype[Bl]));return Me(vo),pl.inputStyles={textarea:Dl,contenteditable:Ml},pl.defineMode=function(e){pl.defaults.mode||"null"==e||(pl.defaults.mode=e),function(e,t){2<arguments.length&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ue[e]=t}.apply(this,arguments)},pl.defineMIME=function(e,t){Ve[e]=t},pl.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),pl.defineMIME("text/plain","null"),pl.defineExtension=function(e,t){pl.prototype[e]=t},pl.defineDocExtension=function(e,t){vo.prototype[e]=t},pl.fromTextArea=function(t,n){var e;function r(){t.value=s.getValue()}if((n=n?I(n):{}).value=t.value,!n.tabindex&&t.tabIndex&&(n.tabindex=t.tabIndex),!n.placeholder&&t.placeholder&&(n.placeholder=t.placeholder),null==n.autofocus&&(e=W(),n.autofocus=e==t||null!=t.getAttribute("autofocus")&&e==document.body),t.form&&(we(t.form,"submit",r),!n.leaveSubmitMethodAlone)){var i=t.form,o=i.submit;try{var l=i.submit=function(){r(),i.submit=o,i.submit(),i.submit=l}}catch(e){}}n.finishInit=function(e){e.save=r,e.getTextArea=function(){return t},e.toTextArea=function(){e.toTextArea=isNaN,r(),t.parentNode.removeChild(e.getWrapperElement()),t.style.display="",t.form&&(Ce(t.form,"submit",r),n.leaveSubmitMethodAlone||"function"!=typeof t.form.submit||(t.form.submit=o))}},t.style.display="none";var s=pl(function(e){return t.parentNode.insertBefore(e,t.nextSibling)},n);return s},(Rl=pl).off=Ce,Rl.on=we,Rl.wheelEventPixels=si,Rl.Doc=vo,Rl.splitLines=Re,Rl.countColumn=R,Rl.findColumn=X,Rl.isWordChar=ee,Rl.Pass=U,Rl.signal=Se,Rl.Line=$t,Rl.changeEnd=fi,Rl.scrollbarModel=Pr,Rl.Pos=lt,Rl.cmpPos=st,Rl.modes=Ue,Rl.mimeModes=Ve,Rl.resolveMode=Ke,Rl.getMode=je,Rl.modeExtensions=Xe,Rl.extendMode=Ye,Rl.copyState=_e,Rl.startState=qe,Rl.innerMode=$e,Rl.commands=Uo,Rl.keyMap=Ao,Rl.keyName=Po,Rl.isModifierKey=Ho,Rl.lookupKey=Wo,Rl.normalizeKeyMap=Do,Rl.StringStream=Ze,Rl.SharedTextMarker=po,Rl.TextMarker=ho,Rl.LineWidget=ao,Rl.e_preventDefault=Ne,Rl.e_stopPropagation=Ae,Rl.e_stop=De,Rl.addClass=H,Rl.contains=D,Rl.rmClass=T,Rl.keyNames=ko,pl.version="5.58.2",pl}); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,g=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),r=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),i=/Edge\/(\d+)/.exec(e),L=n||r||i,x=L&&(n?document.documentMode||6:+(i||r)[1]),v=!i&&/WebKit\//.test(e),o=v&&/Qt\/\d+\.\d+/.test(e),l=!i&&/Chrome\//.test(e),m=/Opera\//.test(e),c=/Apple Computer/.test(navigator.vendor),s=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),u=/PhantomJS/.test(e),a=!i&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),h=/Android/.test(e),d=a||h||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=a||/Mac/.test(t),f=/\bCrOS\b/.test(e),p=/win/i.test(t),b=m&&e.match(/Version\/(\d*\.\d*)/);(b=b&&Number(b[1]))&&15<=b&&(v=!(m=!1));var w=y&&(o||m&&(null==b||b<12.11)),C=g||L&&9<=x;function S(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var k,T=function(e,t){var n,r=e.className,i=S(t).exec(r);i&&(n=r.slice(i.index+i[0].length),e.className=r.slice(0,i.index)+(n?i[1]+n:""))};function M(e){for(var t=e.childNodes.length;0<t;--t)e.removeChild(e.firstChild);return e}function N(e,t){return M(e).appendChild(t)}function O(e,t,n,r){var i=document.createElement(e);if(n&&(i.className=n),r&&(i.style.cssText=r),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function A(e,t,n,r){var i=O(e,t,n,r);return i.setAttribute("role","presentation"),i}function D(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do{if(11==t.nodeType&&(t=t.host),t==e)return!0}while(t=t.parentNode)}function W(){var t;try{t=document.activeElement}catch(e){t=document.body||null}for(;t&&t.shadowRoot&&t.shadowRoot.activeElement;)t=t.shadowRoot.activeElement;return t}function H(e,t){var n=e.className;S(t).test(n)||(e.className+=(n?" ":"")+t)}function F(e,t){for(var n=e.split(" "),r=0;r<n.length;r++)n[r]&&!S(n[r]).test(t)&&(t+=" "+n[r]);return t}k=document.createRange?function(e,t,n,r){var i=document.createRange();return i.setEnd(r||e,n),i.setStart(e,t),i}:function(e,t,n){var r=document.body.createTextRange();try{r.moveToElementText(e.parentNode)}catch(e){return r}return r.collapse(!0),r.moveEnd("character",n),r.moveStart("character",t),r};var E=function(e){e.select()};function P(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function I(e,t,n){for(var r in t=t||{},e)!e.hasOwnProperty(r)||!1===n&&t.hasOwnProperty(r)||(t[r]=e[r]);return t}function R(e,t,n,r,i){null==t&&-1==(t=e.search(/[^\s\u00a0]/))&&(t=e.length);for(var o=r||0,l=i||0;;){var s=e.indexOf("\t",o);if(s<0||t<=s)return l+(t-o);l+=s-o,l+=n-l%n,o=s+1}}a?E=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:L&&(E=function(e){try{e.select()}catch(e){}});var z=function(){this.id=null,this.f=null,this.time=0,this.handler=P(this.onTimeout,this)};function B(e,t){for(var n=0;n<e.length;++n)if(e[n]==t)return n;return-1}z.prototype.onTimeout=function(e){e.id=0,e.time<=+new Date?e.f():setTimeout(e.handler,e.time-new Date)},z.prototype.set=function(e,t){this.f=t;var n=+new Date+e;(!this.id||n<this.time)&&(clearTimeout(this.id),this.id=setTimeout(this.handler,e),this.time=n)};var G=50,U={toString:function(){return"CodeMirror.Pass"}},V={scroll:!1},K={origin:"*mouse"},j={origin:"+move"};function X(e,t,n){for(var r=0,i=0;;){var o=e.indexOf("\t",r);-1==o&&(o=e.length);var l=o-r;if(o==e.length||t<=i+l)return r+Math.min(l,t-i);if(i+=o-r,r=o+1,t<=(i+=n-i%n))return r}}var Y=[""];function _(e){for(;Y.length<=e;)Y.push($(Y)+" ");return Y[e]}function $(e){return e[e.length-1]}function q(e,t){for(var n=[],r=0;r<e.length;r++)n[r]=t(e[r],r);return n}function Z(){}function Q(e,t){var n=Object.create?Object.create(e):(Z.prototype=e,new Z);return t&&I(t,n),n}var J=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function ee(e){return/\w/.test(e)||"€"<e&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(-1<t.source.indexOf("\\w")&&ee(e))||t.test(e):ee(e)}function ne(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return;return 1}var re=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return 768<=e.charCodeAt(0)&&re.test(e)}function oe(e,t,n){for(;(n<0?0<t:t<e.length)&&ie(e.charAt(t));)t+=n;return t}function le(e,t,n){for(var r=n<t?-1:1;;){if(t==n)return t;var i=(t+n)/2,o=r<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:n;e(o)?n=o:t=o+r}}var se=null;function ae(e,t,n){var r;se=null;for(var i=0;i<e.length;++i){var o=e[i];if(o.from<t&&o.to>t)return i;o.to==t&&(o.from!=o.to&&"before"==n?r=i:se=i),o.from==t&&(o.from!=o.to&&"before"!=n?r=i:se=i)}return null!=r?r:se}var ue,ce,he,de,fe,pe,ge,me=(ue="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",ce="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111",he=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,de=/[stwN]/,fe=/[LRr]/,pe=/[Lb1n]/,ge=/[1n]/,function(e,t){var n="ltr"==t?"L":"R";if(0==e.length||"ltr"==t&&!he.test(e))return!1;for(var r,i=e.length,o=[],l=0;l<i;++l)o.push((r=e.charCodeAt(l))<=247?ue.charAt(r):1424<=r&&r<=1524?"R":1536<=r&&r<=1785?ce.charAt(r-1536):1774<=r&&r<=2220?"r":8192<=r&&r<=8203?"w":8204==r?"b":"L");for(var s=0,a=n;s<i;++s){var u=o[s];"m"==u?o[s]=a:a=u}for(var c=0,h=n;c<i;++c){var d=o[c];"1"==d&&"r"==h?o[c]="n":fe.test(d)&&"r"==(h=d)&&(o[c]="R")}for(var f=1,p=o[0];f<i-1;++f){var g=o[f];"+"==g&&"1"==p&&"1"==o[f+1]?o[f]="1":","!=g||p!=o[f+1]||"1"!=p&&"n"!=p||(o[f]=p),p=g}for(var m=0;m<i;++m){var v=o[m];if(","==v)o[m]="N";else if("%"==v){for(var y=void 0,y=m+1;y<i&&"%"==o[y];++y);for(var b=m&&"!"==o[m-1]||y<i&&"1"==o[y]?"1":"N",w=m;w<y;++w)o[w]=b;m=y-1}}for(var x=0,C=n;x<i;++x){var S=o[x];"L"==C&&"1"==S?o[x]="L":fe.test(S)&&(C=S)}for(var L=0;L<i;++L)if(de.test(o[L])){for(var k=void 0,k=L+1;k<i&&de.test(o[k]);++k);for(var T="L"==(L?o[L-1]:n),M=T==("L"==(k<i?o[k]:n))?T?"L":"R":n,N=L;N<k;++N)o[N]=M;L=k-1}for(var A,O=[],D=0;D<i;)if(pe.test(o[D])){var W=D;for(++D;D<i&&pe.test(o[D]);++D);O.push(new ve(0,W,D))}else{var H=D,F=O.length,E="rtl"==t?1:0;for(++D;D<i&&"L"!=o[D];++D);for(var P=H;P<D;)if(ge.test(o[P])){H<P&&(O.splice(F,0,new ve(1,H,P)),F+=E);var I=P;for(++P;P<D&&ge.test(o[P]);++P);O.splice(F,0,new ve(2,I,P)),F+=E,H=P}else++P;H<D&&O.splice(F,0,new ve(1,H,D))}return"ltr"==t&&(1==O[0].level&&(A=e.match(/^\s+/))&&(O[0].from=A[0].length,O.unshift(new ve(0,0,A[0].length))),1==$(O).level&&(A=e.match(/\s+$/))&&($(O).to-=A[0].length,O.push(new ve(0,i-A[0].length,i)))),"rtl"==t?O.reverse():O});function ve(e,t,n){this.level=e,this.from=t,this.to=n}function ye(e,t){var n=e.order;return null==n&&(n=e.order=me(e.text,t)),n}var be=[],we=function(e,t,n){var r;e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):(r=e._handlers||(e._handlers={}))[t]=(r[t]||be).concat(n)};function xe(e,t){return e._handlers&&e._handlers[t]||be}function Ce(e,t,n){var r,i,o;e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):!(i=(r=e._handlers)&&r[t])||-1<(o=B(i,n))&&(r[t]=i.slice(0,o).concat(i.slice(o+1)))}function Se(e,t){var n=xe(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),i=0;i<n.length;++i)n[i].apply(null,r)}function Le(e,t,n){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),Se(e,n||t.type,e,t),Oe(t)||t.codemirrorIgnore}function ke(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var n=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),r=0;r<t.length;++r)-1==B(n,t[r])&&n.push(t[r])}function Te(e,t){return 0<xe(e,t).length}function Me(e){e.prototype.on=function(e,t){we(this,e,t)},e.prototype.off=function(e,t){Ce(this,e,t)}}function Ne(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Ae(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Oe(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function De(e){Ne(e),Ae(e)}function We(e){return e.target||e.srcElement}function He(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Fe,Ee,Pe=function(){if(L&&x<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();var Ie,Re=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(n.push(o.slice(0,l)),t+=l+1):(n.push(o),t=i+1)}return n}:function(e){return e.split(/\r\n?|\n/)},ze=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Be="oncopy"in(Ie=O("div"))||(Ie.setAttribute("oncopy","return;"),"function"==typeof Ie.oncopy),Ge=null;var Ue={},Ve={};function Ke(e){if("string"==typeof e&&Ve.hasOwnProperty(e))e=Ve[e];else if(e&&"string"==typeof e.name&&Ve.hasOwnProperty(e.name)){var t=Ve[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Ke("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Ke("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function je(e,t){t=Ke(t);var n=Ue[t.name];if(!n)return je(e,"text/plain");var r=n(e,t);if(Xe.hasOwnProperty(t.name)){var i=Xe[t.name];for(var o in i)i.hasOwnProperty(o)&&(r.hasOwnProperty(o)&&(r["_"+o]=r[o]),r[o]=i[o])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)r[l]=t.modeProps[l];return r}var Xe={};function Ye(e,t){I(t,Xe.hasOwnProperty(e)?Xe[e]:Xe[e]={})}function _e(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function $e(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function qe(e,t,n){return!e.startState||e.startState(t,n)}var Ze=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};function Qe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var i=n.children[r],o=i.chunkSize();if(t<o){n=i;break}t-=o}return n.lines[t]}function Je(e,n,r){var i=[],o=n.line;return e.iter(n.line,r.line+1,function(e){var t=e.text;o==r.line&&(t=t.slice(0,r.ch)),o==n.line&&(t=t.slice(n.ch)),i.push(t),++o}),i}function et(e,t,n){var r=[];return e.iter(t,n,function(e){r.push(e.text)}),r}function tt(e,t){var n=t-e.height;if(n)for(var r=e;r;r=r.parent)r.height+=n}function nt(e){if(null==e.parent)return null;for(var t=e.parent,n=B(t.lines,e),r=t.parent;r;r=(t=r).parent)for(var i=0;r.children[i]!=t;++i)n+=r.children[i].chunkSize();return n+t.first}function rt(e,t){var n=e.first;e:do{for(var r=0;r<e.children.length;++r){var i=e.children[r],o=i.height;if(t<o){e=i;continue e}t-=o,n+=i.chunkSize()}return n}while(!e.lines);for(var l=0;l<e.lines.length;++l){var s=e.lines[l].height;if(t<s)break;t-=s}return n+l}function it(e,t){return t>=e.first&&t<e.first+e.size}function ot(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function lt(e,t,n){if(void 0===n&&(n=null),!(this instanceof lt))return new lt(e,t,n);this.line=e,this.ch=t,this.sticky=n}function st(e,t){return e.line-t.line||e.ch-t.ch}function at(e,t){return e.sticky==t.sticky&&0==st(e,t)}function ut(e){return lt(e.line,e.ch)}function ct(e,t){return st(e,t)<0?t:e}function ht(e,t){return st(e,t)<0?e:t}function dt(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function ft(e,t){if(t.line<e.first)return lt(e.first,0);var n,r,i,o=e.first+e.size-1;return t.line>o?lt(o,Qe(e,o).text.length):(r=Qe(e,(n=t).line).text.length,null==(i=n.ch)||r<i?lt(n.line,r):i<0?lt(n.line,0):n)}function pt(e,t){for(var n=[],r=0;r<t.length;r++)n[r]=ft(e,t[r]);return n}Ze.prototype.eol=function(){return this.pos>=this.string.length},Ze.prototype.sol=function(){return this.pos==this.lineStart},Ze.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Ze.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},Ze.prototype.eat=function(e){var t=this.string.charAt(this.pos),n="string"==typeof e?t==e:t&&(e.test?e.test(t):e(t));if(n)return++this.pos,t},Ze.prototype.eatWhile=function(e){for(var t=this.pos;this.eat(e););return this.pos>t},Ze.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Ze.prototype.skipToEnd=function(){this.pos=this.string.length},Ze.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(-1<t)return this.pos=t,!0},Ze.prototype.backUp=function(e){this.pos-=e},Ze.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=R(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},Ze.prototype.indentation=function(){return R(this.string,null,this.tabSize)-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},Ze.prototype.match=function(e,t,n){if("string"!=typeof e){var r=this.string.slice(this.pos).match(e);return r&&0<r.index?null:(r&&!1!==t&&(this.pos+=r[0].length),r)}function i(e){return n?e.toLowerCase():e}if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},Ze.prototype.current=function(){return this.string.slice(this.start,this.pos)},Ze.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Ze.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Ze.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var gt=function(e,t){this.state=e,this.lookAhead=t},mt=function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1};function vt(t,n,r,e){var a=[t.state.modeGen],i={};Tt(t,n.text,t.doc.mode,r,function(e,t){return a.push(e,t)},i,e);for(var u=r.state,o=0;o<t.state.overlays.length;++o)!function(e){r.baseTokens=a;var o=t.state.overlays[e],l=1,s=0;r.state=!0,Tt(t,n.text,o.mode,r,function(e,t){for(var n=l;s<e;){var r=a[l];e<r&&a.splice(l,1,e,a[l+1],r),l+=2,s=Math.min(e,r)}if(t)if(o.opaque)a.splice(n,l-n,e,"overlay "+t),l=n+2;else for(;n<l;n+=2){var i=a[n+1];a[n+1]=(i?i+" ":"")+"overlay "+t}},i),r.state=u,r.baseTokens=null,r.baseTokenPos=1}(o);return{styles:a,classes:i.bgClass||i.textClass?i:null}}function yt(e,t,n){var r,i,o;return t.styles&&t.styles[0]==e.state.modeGen||(r=bt(e,nt(t)),i=t.text.length>e.options.maxHighlightLength&&_e(e.doc.mode,r.state),o=vt(e,t,r),i&&(r.state=i),t.stateAfter=r.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))),t.styles}function bt(n,r,e){var t=n.doc,i=n.display;if(!t.mode.startState)return new mt(t,!0,r);var o=function(e,t,n){for(var r,i,o=e.doc,l=n?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;l<s;--s){if(s<=o.first)return o.first;var a=Qe(o,s-1),u=a.stateAfter;if(u&&(!n||s+(u instanceof gt?u.lookAhead:0)<=o.modeFrontier))return s;var c=R(a.text,null,e.options.tabSize);(null==i||c<r)&&(i=s-1,r=c)}return i}(n,r,e),l=o>t.first&&Qe(t,o-1).stateAfter,s=l?mt.fromSaved(t,l,o):new mt(t,qe(t.mode),o);return t.iter(o,r,function(e){wt(n,e.text,s);var t=s.line;e.stateAfter=t==r-1||t%5==0||t>=i.viewFrom&&t<i.viewTo?s.save():null,s.nextLine()}),e&&(t.modeFrontier=s.line),s}function wt(e,t,n,r){var i=e.doc.mode,o=new Ze(t,e.options.tabSize,n);for(o.start=o.pos=r||0,""==t&&xt(i,n.state);!o.eol();)Ct(i,o,n.state),o.start=o.pos}function xt(e,t){if(e.blankLine)return e.blankLine(t);if(e.innerMode){var n=$e(e,t);return n.mode.blankLine?n.mode.blankLine(n.state):void 0}}function Ct(e,t,n,r){for(var i=0;i<10;i++){r&&(r[0]=$e(e,n).mode);var o=e.token(t,n);if(t.pos>t.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}mt.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},mt.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},mt.prototype.nextLine=function(){this.line++,0<this.maxLookAhead&&this.maxLookAhead--},mt.fromSaved=function(e,t,n){return t instanceof gt?new mt(e,_e(e.mode,t.state),n,t.lookAhead):new mt(e,_e(e.mode,t),n)},mt.prototype.save=function(e){var t=!1!==e?_e(this.doc.mode,this.state):this.state;return 0<this.maxLookAhead?new gt(t,this.maxLookAhead):t};var St=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function Lt(e,t,n,r){var i,o,l=e.doc,s=l.mode,a=Qe(l,(t=ft(l,t)).line),u=bt(e,t.line,n),c=new Ze(a.text,e.options.tabSize,u);for(r&&(o=[]);(r||c.pos<t.ch)&&!c.eol();)c.start=c.pos,i=Ct(s,c,u.state),r&&o.push(new St(c,i,_e(l.mode,u.state)));return r?o:new St(c,i,u.state)}function kt(e,t){if(e)for(;;){var n=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!n)break;e=e.slice(0,n.index)+e.slice(n.index+n[0].length);var r=n[1]?"bgClass":"textClass";null==t[r]?t[r]=n[2]:new RegExp("(?:^|\\s)"+n[2]+"(?:$|\\s)").test(t[r])||(t[r]+=" "+n[2])}return e}function Tt(e,t,n,r,i,o,l){var s=n.flattenSpans;null==s&&(s=e.options.flattenSpans);var a=0,u=null,c=new Ze(t,e.options.tabSize,r),h=e.options.addModeClass&&[null];for(""==t&&kt(xt(n,r.state),o);!c.eol();){var d,f=c.pos>e.options.maxHighlightLength?(s=!1,l&&wt(e,t,r,c.pos),c.pos=t.length,null):kt(Ct(n,c,r.state,h),o);if(!h||(d=h[0].name)&&(f="m-"+(f?d+" "+f:d)),!s||u!=f){for(;a<c.start;)i(a=Math.min(c.start,a+5e3),u);u=f}c.start=c.pos}for(;a<c.pos;){var p=Math.min(c.pos,a+5e3);i(p,u),a=p}}var Mt=!1,Nt=!1;function At(e,t,n){this.marker=e,this.from=t,this.to=n}function Ot(e,t){if(e)for(var n=0;n<e.length;++n){var r=e[n];if(r.marker==t)return r}}function Dt(e,t){if(t.full)return null;var n=it(e,t.from.line)&&Qe(e,t.from.line).markedSpans,r=it(e,t.to.line)&&Qe(e,t.to.line).markedSpans;if(!n&&!r)return null;var i=t.from.ch,o=t.to.ch,l=0==st(t.from,t.to),s=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t))&&(l.from!=t||"bookmark"!=s.type||n&&l.marker.insertLeft)||(o=null==l.to||(s.inclusiveRight?l.to>=t:l.to>t),(r=r||[]).push(new At(s,l.from,o?null:l.to)))}return r}(n,i,l),a=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.to||(s.inclusiveRight?l.to>=t:l.to>t))&&(l.from!=t||"bookmark"!=s.type||n&&!l.marker.insertLeft)||(o=null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t),(r=r||[]).push(new At(s,o?null:l.from-t,null==l.to?null:l.to-t)))}return r}(r,o,l),u=1==t.text.length,c=$(t.text).length+(u?i:0);if(s)for(var h=0;h<s.length;++h){var d,f=s[h];null==f.to&&((d=Ot(a,f.marker))?u&&(f.to=null==d.to?null:d.to+c):f.to=i)}if(a)for(var p=0;p<a.length;++p){var g=a[p];null!=g.to&&(g.to+=c),null==g.from?Ot(s,g.marker)||(g.from=c,u&&(s=s||[]).push(g)):(g.from+=c,u&&(s=s||[]).push(g))}s=s&&Wt(s),a&&a!=s&&(a=Wt(a));var m=[s];if(!u){var v,y=t.text.length-2;if(0<y&&s)for(var b=0;b<s.length;++b)null==s[b].to&&(v=v||[]).push(new At(s[b].marker,null,null));for(var w=0;w<y;++w)m.push(v);m.push(a)}return m}function Wt(e){for(var t=0;t<e.length;++t){var n=e[t];null!=n.from&&n.from==n.to&&!1!==n.marker.clearWhenEmpty&&e.splice(t--,1)}return e.length?e:null}function Ht(e){var t=e.markedSpans;if(t){for(var n=0;n<t.length;++n)t[n].marker.detachLine(e);e.markedSpans=null}}function Ft(e,t){if(t){for(var n=0;n<t.length;++n)t[n].marker.attachLine(e);e.markedSpans=t}}function Et(e){return e.inclusiveLeft?-1:0}function Pt(e){return e.inclusiveRight?1:0}function It(e,t){var n=e.lines.length-t.lines.length;if(0!=n)return n;var r=e.find(),i=t.find(),o=st(r.from,i.from)||Et(e)-Et(t);if(o)return-o;var l=st(r.to,i.to)||Pt(e)-Pt(t);return l||t.id-e.id}function Rt(e,t){var n,r=Nt&&e.markedSpans;if(r)for(var i=void 0,o=0;o<r.length;++o)(i=r[o]).marker.collapsed&&null==(t?i.from:i.to)&&(!n||It(n,i.marker)<0)&&(n=i.marker);return n}function zt(e){return Rt(e,!0)}function Bt(e){return Rt(e,!1)}function Gt(e,t,n,r,i){var o=Qe(e,t),l=Nt&&o.markedSpans;if(l)for(var s=0;s<l.length;++s){var a=l[s];if(a.marker.collapsed){var u=a.marker.find(0),c=st(u.from,n)||Et(a.marker)-Et(i),h=st(u.to,r)||Pt(a.marker)-Pt(i);if(!(0<=c&&h<=0||c<=0&&0<=h)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?0<=st(u.to,n):0<st(u.to,n))||0<=c&&(a.marker.inclusiveRight&&i.inclusiveLeft?st(u.from,r)<=0:st(u.from,r)<0)))return 1}}}function Ut(e){for(var t;t=zt(e);)e=t.find(-1,!0).line;return e}function Vt(e,t){var n=Qe(e,t),r=Ut(n);return n==r?t:nt(r)}function Kt(e,t){if(t>e.lastLine())return t;var n,r=Qe(e,t);if(!jt(e,r))return t;for(;n=Bt(r);)r=n.find(1,!0).line;return nt(r)+1}function jt(e,t){var n=Nt&&t.markedSpans;if(n)for(var r=void 0,i=0;i<n.length;++i)if((r=n[i]).marker.collapsed){if(null==r.from)return!0;if(!r.marker.widgetNode&&0==r.from&&r.marker.inclusiveLeft&&function e(t,n,r){if(null==r.to){var i=r.marker.find(1,!0);return e(t,i.line,Ot(i.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==n.text.length)return!0;for(var o=void 0,l=0;l<n.markedSpans.length;++l)if((o=n.markedSpans[l]).marker.collapsed&&!o.marker.widgetNode&&o.from==r.to&&(null==o.to||o.to!=r.from)&&(o.marker.inclusiveLeft||r.marker.inclusiveRight)&&e(t,n,o))return!0}(e,t,r))return!0}}function Xt(e){for(var t=0,n=(e=Ut(e)).parent,r=0;r<n.lines.length;++r){var i=n.lines[r];if(i==e)break;t+=i.height}for(var o=n.parent;o;o=(n=o).parent)for(var l=0;l<o.children.length;++l){var s=o.children[l];if(s==n)break;t+=s.height}return t}function Yt(e){if(0==e.height)return 0;for(var t,n=e.text.length,r=e;t=zt(r);){var i=t.find(0,!0),r=i.from.line;n+=i.from.ch-i.to.ch}for(r=e;t=Bt(r);){var o=t.find(0,!0);n-=r.text.length-o.from.ch,n+=(r=o.to.line).text.length-o.to.ch}return n}function _t(e){var n=e.display,t=e.doc;n.maxLine=Qe(t,t.first),n.maxLineLength=Yt(n.maxLine),n.maxLineChanged=!0,t.iter(function(e){var t=Yt(e);t>n.maxLineLength&&(n.maxLineLength=t,n.maxLine=e)})}var $t=function(e,t,n){this.text=e,Ft(this,t),this.height=n?n(this):1};$t.prototype.lineNo=function(){return nt(this)},Me($t);var qt={},Zt={};function Qt(e,t){if(!e||/^\s*$/.test(e))return null;var n=t.addModeClass?Zt:qt;return n[e]||(n[e]=e.replace(/\S+/g,"cm-$&"))}function Jt(e,t){var n=A("span",null,null,v?"padding-right: .1px":null),r={pre:A("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i,o=0;o<=(t.rest?t.rest.length:0);o++){var l=o?t.rest[o-1]:t.line,s=void 0;r.pos=0,r.addToken=tn,function(e){if(null!=Ee)return Ee;var t=N(e,document.createTextNode("AخA")),n=k(t,0,1).getBoundingClientRect(),r=k(t,1,2).getBoundingClientRect();return M(e),n&&n.left!=n.right&&(Ee=r.right-n.right<3)}(e.display.measure)&&(s=ye(l,e.doc.direction))&&(r.addToken=function(h,d){return function(e,t,n,r,i,o,l){n=n?n+" cm-force-border":"cm-force-border";for(var s=e.pos,a=s+t.length;;){for(var u=void 0,c=0;c<d.length&&!((u=d[c]).to>s&&u.from<=s);c++);if(u.to>=a)return h(e,t,n,r,i,o,l);h(e,t.slice(0,u.to-s),n,r,null,o,l),r=null,t=t.slice(u.to-s),s=u.to}}}(r.addToken,s)),r.map=[],function(e,t,n){var r=e.markedSpans,i=e.text,o=0;if(!r){for(var l=1;l<n.length;l+=2)t.addToken(t,i.slice(o,o=n[l]),Qt(n[l+1],t.cm.options));return}for(var s,a,u,c,h,d,f,p=i.length,g=0,m=1,v="",y=0;;){if(y==g){u=c=h=a="",d=f=null,y=1/0;for(var b=[],w=void 0,x=0;x<r.length;++x){var C=r[x],S=C.marker;if("bookmark"==S.type&&C.from==g&&S.widgetNode)b.push(S);else if(C.from<=g&&(null==C.to||C.to>g||S.collapsed&&C.to==g&&C.from==g)){if(null!=C.to&&C.to!=g&&y>C.to&&(y=C.to,c=""),S.className&&(u+=" "+S.className),S.css&&(a=(a?a+";":"")+S.css),S.startStyle&&C.from==g&&(h+=" "+S.startStyle),S.endStyle&&C.to==y&&(w=w||[]).push(S.endStyle,C.to),S.title&&((f=f||{}).title=S.title),S.attributes)for(var L in S.attributes)(f=f||{})[L]=S.attributes[L];S.collapsed&&(!d||It(d.marker,S)<0)&&(d=C)}else C.from>g&&y>C.from&&(y=C.from)}if(w)for(var k=0;k<w.length;k+=2)w[k+1]==y&&(c+=" "+w[k]);if(!d||d.from==g)for(var T=0;T<b.length;++T)nn(t,0,b[T]);if(d&&(d.from||0)==g){if(nn(t,(null==d.to?p+1:d.to)-g,d.marker,null==d.from),null==d.to)return;d.to==g&&(d=!1)}}if(p<=g)break;for(var M=Math.min(p,y);;){if(v){var N,A=g+v.length;if(d||(N=M<A?v.slice(0,M-g):v,t.addToken(t,N,s?s+u:u,h,g+N.length==y?c:"",a,f)),M<=A){v=v.slice(M-g),g=M;break}g=A,h=""}v=i.slice(o,o=n[m++]),s=Qt(n[m++],t.cm.options)}}}(l,r,yt(e,l,t!=e.display.externalMeasured&&nt(l))),l.styleClasses&&(l.styleClasses.bgClass&&(r.bgClass=F(l.styleClasses.bgClass,r.bgClass||"")),l.styleClasses.textClass&&(r.textClass=F(l.styleClasses.textClass,r.textClass||""))),0==r.map.length&&r.map.push(0,0,r.content.appendChild(function(e){var t;null==Fe&&(t=O("span","​"),N(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Fe=t.offsetWidth<=1&&2<t.offsetHeight&&!(L&&x<8)));var n=Fe?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}(e.display.measure))),0==o?(t.measure.map=r.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(r.map),(t.measure.caches||(t.measure.caches=[])).push({}))}return v&&(i=r.content.lastChild,(/\bcm-tab\b/.test(i.className)||i.querySelector&&i.querySelector(".cm-tab"))&&(r.content.className="cm-tab-wrap-hack")),Se(e,"renderLine",e,t.line,r.pre),r.pre.className&&(r.textClass=F(r.pre.className,r.textClass||"")),r}function en(e){var t=O("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function tn(e,t,n,r,i,o,l){if(t){var s,a=e.splitSpaces?function(e,t){if(1<e.length&&!/ /.test(e))return e;for(var n=t,r="",i=0;i<e.length;i++){var o=e.charAt(i);" "!=o||!n||i!=e.length-1&&32!=e.charCodeAt(i+1)||(o=" "),r+=o,n=" "==o}return r}(t,e.trailingSpace):t,u=e.cm.state.specialChars,c=!1;if(u.test(t)){s=document.createDocumentFragment();for(var h=0;;){u.lastIndex=h;var d,f=u.exec(t),p=f?f.index-h:t.length-h;if(p&&(d=document.createTextNode(a.slice(h,h+p)),L&&x<9?s.appendChild(O("span",[d])):s.appendChild(d),e.map.push(e.pos,e.pos+p,d),e.col+=p,e.pos+=p),!f)break;h+=1+p;var g,m,v=void 0;"\t"==f[0]?(m=(g=e.cm.options.tabSize)-e.col%g,(v=s.appendChild(O("span",_(m),"cm-tab"))).setAttribute("role","presentation"),v.setAttribute("cm-text","\t"),e.col+=m):("\r"==f[0]||"\n"==f[0]?(v=s.appendChild(O("span","\r"==f[0]?"␍":"␤","cm-invalidchar"))).setAttribute("cm-text",f[0]):((v=e.cm.options.specialCharPlaceholder(f[0])).setAttribute("cm-text",f[0]),L&&x<9?s.appendChild(O("span",[v])):s.appendChild(v)),e.col+=1),e.map.push(e.pos,e.pos+1,v),e.pos++}}else e.col+=t.length,s=document.createTextNode(a),e.map.push(e.pos,e.pos+t.length,s),L&&x<9&&(c=!0),e.pos+=t.length;if(e.trailingSpace=32==a.charCodeAt(t.length-1),n||r||i||c||o||l){var y=n||"";r&&(y+=r),i&&(y+=i);var b=O("span",[s],y,o);if(l)for(var w in l)l.hasOwnProperty(w)&&"style"!=w&&"class"!=w&&b.setAttribute(w,l[w]);return e.content.appendChild(b)}e.content.appendChild(s)}}function nn(e,t,n,r){var i=!r&&n.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!r&&e.cm.display.input.needsContentAttribute&&(i=i||e.content.appendChild(document.createElement("span"))).setAttribute("cm-marker",n.id),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function rn(e,t,n){this.line=t,this.rest=function(e){for(var t,n;t=Bt(e);)e=t.find(1,!0).line,(n=n||[]).push(e);return n}(t),this.size=this.rest?nt($(this.rest))-n+1:1,this.node=this.text=null,this.hidden=jt(e,t)}function on(e,t,n){for(var r=[],i=t;i<n;i=l){var o=new rn(e.doc,Qe(e.doc,i),i),l=i+o.size;r.push(o)}return r}var ln=null;function sn(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n<t.length;n++)t[n].call(null);for(var r=0;r<e.ops.length;r++){var i=e.ops[r];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++].call(null,i.cm)}}while(n<t.length)}(n)}finally{ln=null,t(n)}}var an=null;function un(e,t){var n=xe(e,t);if(n.length){var r,i=Array.prototype.slice.call(arguments,2);ln?r=ln.delayedCallbacks:an?r=an:(r=an=[],setTimeout(cn,0));for(var o=0;o<n.length;++o)!function(e){r.push(function(){return n[e].apply(null,i)})}(o)}}function cn(){var e=an;an=null;for(var t=0;t<e.length;++t)e[t]()}function hn(e,t,n,r){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?function(e,t){var n=t.text.className,r=fn(e,t);t.text==t.node&&(t.node=r.pre);t.text.parentNode.replaceChild(r.pre,t.text),t.text=r.pre,r.bgClass!=t.bgClass||r.textClass!=t.textClass?(t.bgClass=r.bgClass,t.textClass=r.textClass,pn(e,t)):n&&(t.text.className=n)}(e,t):"gutter"==o?gn(e,t,n,r):"class"==o?pn(e,t):"widget"==o&&function(e,t,n){t.alignable&&(t.alignable=null);for(var r=S("CodeMirror-linewidget"),i=t.node.firstChild,o=void 0;i;i=o)o=i.nextSibling,r.test(i.className)&&t.node.removeChild(i);mn(e,t,n)}(e,t,r)}t.changes=null}function dn(e){return e.node==e.text&&(e.node=O("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),L&&x<8&&(e.node.style.zIndex=2)),e.node}function fn(e,t){var n=e.display.externalMeasured;return n&&n.line==t.line?(e.display.externalMeasured=null,t.measure=n.measure,n.built):Jt(e,t)}function pn(e,t){var n,r,i,o;n=e,(o=(r=t).bgClass?r.bgClass+" "+(r.line.bgClass||""):r.line.bgClass)&&(o+=" CodeMirror-linebackground"),r.background?o?r.background.className=o:(r.background.parentNode.removeChild(r.background),r.background=null):o&&(i=dn(r),r.background=i.insertBefore(O("div",null,o),i.firstChild),n.display.input.setUneditable(r.background)),t.line.wrapClass?dn(t).className=t.line.wrapClass:t.node!=t.text&&(t.node.className="");var l=t.textClass?t.textClass+" "+(t.line.textClass||""):t.line.textClass;t.text.className=l||""}function gn(e,t,n,r){var i;t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null),t.gutterBackground&&(t.node.removeChild(t.gutterBackground),t.gutterBackground=null),t.line.gutterClass&&(i=dn(t),t.gutterBackground=O("div",null,"CodeMirror-gutter-background "+t.line.gutterClass,"left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px; width: "+r.gutterTotalWidth+"px"),e.display.input.setUneditable(t.gutterBackground),i.insertBefore(t.gutterBackground,t.text));var o=t.line.gutterMarkers;if(e.options.lineNumbers||o){var l=dn(t),s=t.gutter=O("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px");if(e.display.input.setUneditable(s),l.insertBefore(s,t.text),t.line.gutterClass&&(s.className+=" "+t.line.gutterClass),!e.options.lineNumbers||o&&o["CodeMirror-linenumbers"]||(t.lineNumber=s.appendChild(O("div",ot(e.options,n),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+r.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),o)for(var a=0;a<e.display.gutterSpecs.length;++a){var u=e.display.gutterSpecs[a].className,c=o.hasOwnProperty(u)&&o[u];c&&s.appendChild(O("div",[c],"CodeMirror-gutter-elt","left: "+r.gutterLeft[u]+"px; width: "+r.gutterWidth[u]+"px"))}}}function mn(e,t,n){if(vn(e,t.line,t,n,!0),t.rest)for(var r=0;r<t.rest.length;r++)vn(e,t.rest[r],t,n,!1)}function vn(e,t,n,r,i){if(t.widgets)for(var o=dn(n),l=0,s=t.widgets;l<s.length;++l){var a=s[l],u=O("div",[a.node],"CodeMirror-linewidget"+(a.className?" "+a.className:""));a.handleMouseEvents||u.setAttribute("cm-ignore-events","true"),function(e,t,n,r){{var i;e.noHScroll&&((n.alignable||(n.alignable=[])).push(t),i=r.wrapperWidth,t.style.left=r.fixedPos+"px",e.coverGutter||(i-=r.gutterTotalWidth,t.style.paddingLeft=r.gutterTotalWidth+"px"),t.style.width=i+"px")}e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-r.gutterTotalWidth+"px"))}(a,u,n,r),e.display.input.setUneditable(u),i&&a.above?o.insertBefore(u,n.gutter||n.text):o.appendChild(u),un(a,"redraw")}}function yn(e){if(null!=e.height)return e.height;var t,n=e.doc.cm;return n?(D(document.body,e.node)||(t="position: relative;",e.coverGutter&&(t+="margin-left: -"+n.display.gutters.offsetWidth+"px;"),e.noHScroll&&(t+="width: "+n.display.wrapper.clientWidth+"px;"),N(n.display.measure,O("div",[e.node],null,t))),e.height=e.node.parentNode.offsetHeight):0}function bn(e,t){for(var n=We(t);n!=e.wrapper;n=n.parentNode)if(!n||1==n.nodeType&&"true"==n.getAttribute("cm-ignore-events")||n.parentNode==e.sizer&&n!=e.mover)return 1}function wn(e){return e.lineSpace.offsetTop}function xn(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function Cn(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=N(e.measure,O("pre","x","CodeMirror-line-like")),n=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,r={left:parseInt(n.paddingLeft),right:parseInt(n.paddingRight)};return isNaN(r.left)||isNaN(r.right)||(e.cachedPaddingH=r),r}function Sn(e){return G-e.display.nativeBarWidth}function Ln(e){return e.display.scroller.clientWidth-Sn(e)-e.display.barWidth}function kn(e){return e.display.scroller.clientHeight-Sn(e)-e.display.barHeight}function Tn(e,t,n){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var r=0;r<e.rest.length;r++)if(e.rest[r]==t)return{map:e.measure.maps[r],cache:e.measure.caches[r]};for(var i=0;i<e.rest.length;i++)if(nt(e.rest[i])>n)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Mn(e,t,n,r){return On(e,An(e,t),n,r)}function Nn(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[rr(e,t)];var n=e.display.externalMeasured;return n&&t>=n.lineN&&t<n.lineN+n.size?n:void 0}function An(e,t){var n=nt(t),r=Nn(e,n);r&&!r.text?r=null:r&&r.changes&&(hn(e,r,n,Qn(e)),e.curOp.forceUpdate=!0);var i=Tn(r=r||function(e,t){var n=nt(t=Ut(t)),r=e.display.externalMeasured=new rn(e.doc,t,n);r.lineN=n;var i=r.built=Jt(e,r);return r.text=i.pre,N(e.display.lineMeasure,i.pre),r}(e,t),t,n);return{line:t,view:r,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function On(e,t,n,r,i){t.before&&(n=-1);var o,l=n+(r||"");return t.cache.hasOwnProperty(l)?o=t.cache[l]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||(function(e,t,n){var r=e.options.lineWrapping,i=r&&Ln(e);if(!t.measure.heights||r&&t.measure.width!=i){var o=t.measure.heights=[];if(r){t.measure.width=i;for(var l=t.text.firstChild.getClientRects(),s=0;s<l.length-1;s++){var a=l[s],u=l[s+1];2<Math.abs(a.bottom-u.bottom)&&o.push((a.bottom+u.top)/2-n.top)}}o.push(n.bottom-n.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,n,r){var i,o,l=Hn(t.map,n,r),s=l.node,a=l.start,u=l.end,c=l.collapse;if(3==s.nodeType){for(var h=0;h<4;h++){for(;a&&ie(t.line.text.charAt(l.coverStart+a));)--a;for(;l.coverStart+u<l.coverEnd&&ie(t.line.text.charAt(l.coverStart+u));)++u;if((i=L&&x<9&&0==a&&u==l.coverEnd-l.coverStart?s.parentNode.getBoundingClientRect():function(e,t){var n=Wn;if("left"==t)for(var r=0;r<e.length&&(n=e[r]).left==n.right;r++);else for(var i=e.length-1;0<=i&&(n=e[i]).left==n.right;i--);return n}(k(s,a,u).getClientRects(),r)).left||i.right||0==a)break;u=a,--a,c="right"}L&&x<11&&(i=function(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!function(e){if(null!=Ge)return Ge;var t=N(e,O("span","x")),n=t.getBoundingClientRect(),r=k(t,0,1).getBoundingClientRect();return Ge=1<Math.abs(n.left-r.left)}(e))return t;var n=screen.logicalXDPI/screen.deviceXDPI,r=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*n,right:t.right*n,top:t.top*r,bottom:t.bottom*r}}(e.display.measure,i))}else 0<a&&(c=r="right"),i=e.options.lineWrapping&&1<(o=s.getClientRects()).length?o["right"==r?o.length-1:0]:s.getBoundingClientRect();{var d;!(L&&x<9)||a||i&&(i.left||i.right)||(d=s.parentNode.getClientRects()[0],i=d?{left:d.left,right:d.left+Zn(e.display),top:d.top,bottom:d.bottom}:Wn)}for(var f=i.top-t.rect.top,p=i.bottom-t.rect.top,g=(f+p)/2,m=t.view.measure.heights,v=0;v<m.length-1&&!(g<m[v]);v++);var y=v?m[v-1]:0,b=m[v],w={left:("right"==c?i.right:i.left)-t.rect.left,right:("left"==c?i.left:i.right)-t.rect.left,top:y,bottom:b};i.left||i.right||(w.bogus=!0);e.options.singleCursorHeightPerLine||(w.rtop=f,w.rbottom=p);return w}(e,t,n,r)).bogus||(t.cache[l]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}var Dn,Wn={left:0,right:0,top:0,bottom:0};function Hn(e,t,n){for(var r,i,o,l,s,a,u=0;u<e.length;u+=3)if(s=e[u],a=e[u+1],t<s?(i=0,o=1,l="left"):t<a?o=(i=t-s)+1:(u==e.length-3||t==a&&e[u+3]>t)&&(i=(o=a-s)-1,a<=t&&(l="right")),null!=i){if(r=e[u+2],s==a&&n==(r.insertLeft?"left":"right")&&(l=n),"left"==n&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)r=e[2+(u-=3)],l="left";if("right"==n&&i==a-s)for(;u<e.length-3&&e[u+3]==e[u+4]&&!e[u+5].insertLeft;)r=e[(u+=3)+2],l="right";break}return{node:r,start:i,end:o,collapse:l,coverStart:s,coverEnd:a}}function Fn(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function En(e){e.display.externalMeasure=null,M(e.display.lineMeasure);for(var t=0;t<e.display.view.length;t++)Fn(e.display.view[t])}function Pn(e){En(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function In(){return l&&h?-(document.body.getBoundingClientRect().left-parseInt(getComputedStyle(document.body).marginLeft)):window.pageXOffset||(document.documentElement||document.body).scrollLeft}function Rn(){return l&&h?-(document.body.getBoundingClientRect().top-parseInt(getComputedStyle(document.body).marginTop)):window.pageYOffset||(document.documentElement||document.body).scrollTop}function zn(e){var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;++n)e.widgets[n].above&&(t+=yn(e.widgets[n]));return t}function Bn(e,t,n,r,i){var o;if(i||(o=zn(t),n.top+=o,n.bottom+=o),"line"==r)return n;r=r||"local";var l,s,a=Xt(t);return"local"==r?a+=wn(e.display):a-=e.display.viewOffset,"page"!=r&&"window"!=r||(a+=(l=e.display.lineSpace.getBoundingClientRect()).top+("window"==r?0:Rn()),s=l.left+("window"==r?0:In()),n.left+=s,n.right+=s),n.top+=a,n.bottom+=a,n}function Gn(e,t,n){if("div"==n)return t;var r,i=t.left,o=t.top;"page"==n?(i-=In(),o-=Rn()):"local"!=n&&n||(i+=(r=e.display.sizer.getBoundingClientRect()).left,o+=r.top);var l=e.display.lineSpace.getBoundingClientRect();return{left:i-l.left,top:o-l.top}}function Un(e,t,n,r,i){return Bn(e,r=r||Qe(e.doc,t.line),Mn(e,r,t.ch,i),n)}function Vn(r,e,i,o,l,s){function a(e,t){var n=On(r,l,e,t?"right":"left",s);return t?n.left=n.right:n.right=n.left,Bn(r,o,n,i)}o=o||Qe(r.doc,e.line),l=l||An(r,o);var u=ye(o,r.doc.direction),t=e.ch,n=e.sticky;if(t>=o.text.length?(t=o.text.length,n="before"):t<=0&&(t=0,n="after"),!u)return a("before"==n?t-1:t,"before"==n);function c(e,t,n){return a(n?e-1:e,1==u[t].level!=n)}var h=ae(u,t,n),d=se,f=c(t,h,"before"==n);return null!=d&&(f.other=c(t,d,"before"!=n)),f}function Kn(e,t){var n=0;t=ft(e.doc,t),e.options.lineWrapping||(n=Zn(e.display)*t.ch);var r=Qe(e.doc,t.line),i=Xt(r)+wn(e.display);return{left:n,right:n,top:i,bottom:i+r.height}}function jn(e,t,n,r,i){var o=lt(e,t,n);return o.xRel=i,r&&(o.outside=r),o}function Xn(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return jn(r.first,0,null,-1,-1);var i=rt(r,n),o=r.first+r.size-1;if(o<i)return jn(r.first+r.size-1,Qe(r,o).text.length,null,1,1);t<0&&(t=0);for(var l=Qe(r,i);;){var s=function(n,e,t,r,i){i-=Xt(e);var o=An(n,e),l=zn(e),s=0,a=e.text.length,u=!0,c=ye(e,n.doc.direction);{var h;c&&(h=(n.options.lineWrapping?function(e,t,n,r,i,o,l){var s=Yn(e,t,r,l),a=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,h=null,d=0;d<i.length;d++){var f,p,g,m=i[d];m.from>=u||m.to<=a||(f=1!=m.level,p=On(e,r,f?Math.min(u,m.to)-1:Math.max(a,m.from)).right,g=p<o?o-p+1e9:p-o,(!c||g<h)&&(c=m,h=g))}c=c||i[i.length-1];c.from<a&&(c={from:a,to:c.to,level:c.level});c.to>u&&(c={from:c.from,to:u,level:c.level});return c}:function(r,i,o,l,s,a,u){var e=le(function(e){var t=s[e],n=1!=t.level;return $n(Vn(r,lt(o,n?t.to:t.from,n?"before":"after"),"line",i,l),a,u,!0)},0,s.length-1),t=s[e];{var n,c;0<e&&(n=1!=t.level,$n(c=Vn(r,lt(o,n?t.from:t.to,n?"after":"before"),"line",i,l),a,u,!0)&&c.top>u&&(t=s[e-1]))}return t})(n,e,t,o,c,r,i),u=1!=h.level,s=u?h.from:h.to-1,a=u?h.to:h.from-1)}var d,f,p=null,g=null,m=le(function(e){var t=On(n,o,e);return t.top+=l,t.bottom+=l,$n(t,r,i,!1)&&(t.top<=i&&t.left<=r&&(p=e,g=t),1)},s,a),v=!1;{var y,b,w;g?(y=r-g.left<g.right-r,m=p+((b=y==u)?0:1),f=b?"after":"before",d=y?g.left:g.right):(u||m!=a&&m!=s||m++,f=0==m||m!=e.text.length&&On(n,o,m-(u?1:0)).bottom+l<=i==u?"after":"before",w=Vn(n,lt(t,m,f),"line",e,o),d=w.left,v=i<w.top?-1:i>=w.bottom?1:0)}return m=oe(e.text,m,1),jn(t,m,f,v,r-d)}(e,l,i,t,n),a=function(e,t){var n,r=Nt&&e.markedSpans;if(r)for(var i=0;i<r.length;++i){var o=r[i];o.marker.collapsed&&(null==o.from||o.from<t)&&(null==o.to||o.to>t)&&(!n||It(n,o.marker)<0)&&(n=o.marker)}return n}(l,s.ch+(0<s.xRel||0<s.outside?1:0));if(!a)return s;var u=a.find(1);if(u.line==i)return u;l=Qe(r,i=u.line)}}function Yn(t,e,n,r){r-=zn(e);var i=e.text.length,o=le(function(e){return On(t,n,e-1).bottom<=r},i,0);return{begin:o,end:i=le(function(e){return On(t,n,e).top>r},o,i)}}function _n(e,t,n,r){return Yn(e,t,n=n||An(e,t),Bn(e,t,On(e,n,r),"line").top)}function $n(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function qn(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Dn){Dn=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Dn.appendChild(document.createTextNode("x")),Dn.appendChild(O("br"));Dn.appendChild(document.createTextNode("x"))}N(e.measure,Dn);var n=Dn.offsetHeight/50;return 3<n&&(e.cachedTextHeight=n),M(e.measure),n||1}function Zn(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),n=O("pre",[t],"CodeMirror-line-like");N(e.measure,n);var r=t.getBoundingClientRect(),i=(r.right-r.left)/10;return 2<i&&(e.cachedCharWidth=i),i||10}function Qn(e){for(var t=e.display,n={},r={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;n[s]=o.offsetLeft+o.clientLeft+i,r[s]=o.clientWidth}return{fixedPos:Jn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function Jn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function er(r){var i=qn(r.display),o=r.options.lineWrapping,l=o&&Math.max(5,r.display.scroller.clientWidth/Zn(r.display)-3);return function(e){if(jt(r.doc,e))return 0;var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;n++)e.widgets[n].height&&(t+=e.widgets[n].height);return o?t+(Math.ceil(e.text.length/l)||1)*i:t+i}}function tr(e){var t=e.doc,n=er(e);t.iter(function(e){var t=n(e);t!=e.height&&tt(e,t)})}function nr(e,t,n,r){var i=e.display;if(!n&&"true"==We(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(e){return null}var a,u,c=Xn(e,o,l);return r&&0<c.xRel&&(a=Qe(e.doc,c.line).text).length==c.ch&&(u=R(a,a.length,e.options.tabSize)-a.length,c=lt(c.line,Math.max(0,Math.round((o-Cn(e.display).left)/Zn(e.display))-u))),c}function rr(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;r<n.length;r++)if((t-=n[r].size)<0)return r}function ir(e,t,n,r){null==t&&(t=e.doc.first),null==n&&(n=e.doc.first+e.doc.size),r=r||0;var i,o,l,s,a=e.display;r&&n<a.viewTo&&(null==a.updateLineNumbers||a.updateLineNumbers>t)&&(a.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=a.viewTo?Nt&&Vt(e.doc,t)<a.viewTo&&lr(e):n<=a.viewFrom?Nt&&Kt(e.doc,n+r)>a.viewFrom?lr(e):(a.viewFrom+=r,a.viewTo+=r):t<=a.viewFrom&&n>=a.viewTo?lr(e):t<=a.viewFrom?(i=sr(e,n,n+r,1))?(a.view=a.view.slice(i.index),a.viewFrom=i.lineN,a.viewTo+=r):lr(e):n>=a.viewTo?(o=sr(e,t,t,-1))?(a.view=a.view.slice(0,o.index),a.viewTo=o.lineN):lr(e):(l=sr(e,t,t,-1),s=sr(e,n,n+r,1),l&&s?(a.view=a.view.slice(0,l.index).concat(on(e,l.lineN,s.lineN)).concat(a.view.slice(s.index)),a.viewTo+=r):lr(e));var u=a.externalMeasured;u&&(n<u.lineN?u.lineN+=r:t<u.lineN+u.size&&(a.externalMeasured=null))}function or(e,t,n){e.curOp.viewChanged=!0;var r,i,o=e.display,l=e.display.externalMeasured;l&&t>=l.lineN&&t<l.lineN+l.size&&(o.externalMeasured=null),t<o.viewFrom||t>=o.viewTo||(null==(r=o.view[rr(e,t)]).node||-1==B(i=r.changes||(r.changes=[]),n)&&i.push(n))}function lr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function sr(e,t,n,r){var i,o=rr(e,t),l=e.display.view;if(!Nt||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var s=e.display.viewFrom,a=0;a<o;a++)s+=l[a].size;if(s!=t){if(0<r){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,n+=i}for(;Vt(e.doc,n)!=n;){if(o==(r<0?0:l.length-1))return null;n+=r*l[o-(r<0?1:0)].size,o+=r}return{index:o,lineN:n}}function ar(e){for(var t=e.display.view,n=0,r=0;r<t.length;r++){var i=t[r];i.hidden||i.node&&!i.changes||++n}return n}function ur(e){e.display.input.showSelection(e.display.input.prepareSelection())}function cr(e,t){void 0===t&&(t=!0);for(var n,r,i=e.doc,o={},l=o.cursors=document.createDocumentFragment(),s=o.selection=document.createDocumentFragment(),a=0;a<i.sel.ranges.length;a++){!t&&a==i.sel.primIndex||((n=i.sel.ranges[a]).from().line>=e.display.viewTo||n.to().line<e.display.viewFrom||(((r=n.empty())||e.options.showCursorWhenSelecting)&&hr(e,n.head,l),r||function(l,e,t){var n=l.display,r=l.doc,i=document.createDocumentFragment(),o=Cn(l.display),T=o.left,M=Math.max(n.sizerWidth,Ln(l)-n.sizer.offsetLeft)-o.right,N="ltr"==r.direction;function A(e,t,n,r){t<0&&(t=0),t=Math.round(t),r=Math.round(r),i.appendChild(O("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==n?M-e:n)+"px;\n height: "+(r-t)+"px"))}function s(n,y,b){var w,x,o=Qe(r,n),C=o.text.length;function S(e,t){return Un(l,lt(n,e),"div",o,t)}function L(e,t,n){var r=_n(l,o,null,e),i="ltr"==t==("after"==n)?"left":"right";return S("after"==n?r.begin:r.end-(/\s/.test(o.text.charAt(r.end-1))?2:1),i)[i]}var k=ye(o,r.direction);return function(e,t,n,r){if(!e)return r(t,n,"ltr",0);for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<n&&l.to>t||t==n&&l.to==t)&&(r(Math.max(l.from,t),Math.min(l.to,n),1==l.level?"rtl":"ltr",o),i=!0)}i||r(t,n,"ltr")}(k,y||0,null==b?C:b,function(e,t,n,r){var i,o,l,s,a,u,c,h="ltr"==n,d=S(e,h?"left":"right"),f=S(t-1,h?"right":"left"),p=null==y&&0==e,g=null==b&&t==C,m=0==r,v=!k||r==k.length-1;f.top-d.top<=3?(i=(N?g:p)&&v,o=(N?p:g)&&m?T:(h?d:f).left,l=i?M:(h?f:d).right,A(o,d.top,l-o,d.bottom)):(c=h?(s=N&&p&&m?T:d.left,a=N?M:L(e,n,"before"),u=N?T:L(t,n,"after"),N&&g&&v?M:f.right):(s=N?L(e,n,"before"):T,a=!N&&p&&m?M:d.right,u=!N&&g&&v?T:f.left,N?L(t,n,"after"):M),A(s,d.top,a-s,d.bottom),d.bottom<f.top&&A(T,d.bottom,null,f.top),A(u,f.top,c-u,f.bottom)),(!w||dr(d,w)<0)&&(w=d),dr(f,w)<0&&(w=f),(!x||dr(d,x)<0)&&(x=d),dr(f,x)<0&&(x=f)}),{start:w,end:x}}var a=e.from(),u=e.to();{var c,h,d,f,p;a.line==u.line?s(a.line,a.ch,u.ch):(c=Qe(r,a.line),h=Qe(r,u.line),d=Ut(c)==Ut(h),f=s(a.line,a.ch,d?c.text.length+1:null).end,p=s(u.line,d?0:null,u.ch).start,d&&(f.top<p.top-2?(A(f.right,f.top,null,f.bottom),A(T,p.top,p.left,p.bottom)):A(f.right,f.top,p.left-f.right,f.bottom)),f.bottom<p.top&&A(T,f.bottom,null,p.top))}t.appendChild(i)}(e,n,s)))}return o}function hr(e,t,n){var r,i=Vn(e,t,"div",null,null,!e.options.singleCursorHeightPerLine),o=n.appendChild(O("div"," ","CodeMirror-cursor"));o.style.left=i.left+"px",o.style.top=i.top+"px",o.style.height=Math.max(0,i.bottom-i.top)*e.options.cursorHeight+"px",i.other&&((r=n.appendChild(O("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"))).style.display="",r.style.left=i.other.left+"px",r.style.top=i.other.top+"px",r.style.height=.85*(i.other.bottom-i.other.top)+"px")}function dr(e,t){return e.top-t.top||e.left-t.left}function fr(e){var t,n;e.state.focused&&(t=e.display,clearInterval(t.blinker),n=!0,t.cursorDiv.style.visibility="",0<e.options.cursorBlinkRate?t.blinker=setInterval(function(){e.hasFocus()||vr(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden"))}function pr(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||mr(e))}function gr(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&vr(e))},100)}function mr(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(Se(e,"focus",e,t),e.state.focused=!0,H(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),v&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),fr(e))}function vr(e,t){e.state.delayingBlurEvent||(e.state.focused&&(Se(e,"blur",e,t),e.state.focused=!1,T(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function yr(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=0;r<t.view.length;r++){var i,o,l=t.view[r],s=e.options.lineWrapping,a=void 0,u=0;if(!l.hidden){L&&x<8?(a=(i=l.node.offsetTop+l.node.offsetHeight)-n,n=i):(a=(o=l.node.getBoundingClientRect()).bottom-o.top,!s&&l.text.firstChild&&(u=l.text.firstChild.getBoundingClientRect().right-o.left-1));var c,h=l.line.height-a;if((.005<h||h<-.005)&&(tt(l.line,a),br(l.line),l.rest))for(var d=0;d<l.rest.length;d++)br(l.rest[d]);u>e.display.sizerWidth&&((c=Math.ceil(u/Zn(e.display)))>e.display.maxLineLength&&(e.display.maxLineLength=c,e.display.maxLine=l.line,e.display.maxLineChanged=!0))}}}function br(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t){var n=e.widgets[t],r=n.node.parentNode;r&&(n.height=r.offsetHeight)}}function wr(e,t,n){var r,i,o=n&&null!=n.top?Math.max(0,n.top):e.scroller.scrollTop,o=Math.floor(o-wn(e)),l=n&&null!=n.bottom?n.bottom:o+e.wrapper.clientHeight,s=rt(t,o),a=rt(t,l);return n&&n.ensure&&(r=n.ensure.from.line,i=n.ensure.to.line,r<s?a=rt(t,Xt(Qe(t,s=r))+e.wrapper.clientHeight):Math.min(i,t.lastLine())>=a&&(s=rt(t,Xt(Qe(t,i))-e.wrapper.clientHeight),a=i)),{from:s,to:Math.max(a,s+1)}}function xr(e,t){var n=e.display,r=qn(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:n.scroller.scrollTop,o=kn(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s,a=e.doc.height+xn(n),u=t.top<r,c=t.bottom>a-r;t.top<i?l.scrollTop=u?0:t.top:t.bottom>i+o&&((s=Math.min(t.top,(c?a:t.bottom)-o))!=i&&(l.scrollTop=s));var h=e.options.fixedGutter?0:n.gutters.offsetWidth,d=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-h,f=Ln(e)-n.gutters.offsetWidth,p=t.right-t.left>f;return p&&(t.right=t.left+f),t.left<10?l.scrollLeft=0:t.left<d?l.scrollLeft=Math.max(0,t.left+h-(p?0:10)):t.right>f+d-3&&(l.scrollLeft=t.right+(p?0:10)-f),l}function Cr(e,t){null!=t&&(kr(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function Sr(e){kr(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function Lr(e,t,n){null==t&&null==n||kr(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function kr(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Tr(e,Kn(e,t.from),Kn(e,t.to),t.margin))}function Tr(e,t,n,r){var i=xr(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});Lr(e,i.scrollLeft,i.scrollTop)}function Mr(e,t){Math.abs(e.doc.scrollTop-t)<2||(g||$r(e,{top:t}),Nr(e,t,!0),g&&$r(e),Kr(e,100))}function Nr(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),e.display.scroller.scrollTop==t&&!n||(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Ar(e,t,n,r){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,Qr(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Or(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+xn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+Sn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}function Dr(e,t,n){this.cm=n;var r=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");r.tabIndex=i.tabIndex=-1,e(r),e(i),we(r,"scroll",function(){r.clientHeight&&t(r.scrollTop,"vertical")}),we(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,L&&x<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}Dr.prototype.update=function(e){var t,n,r=e.scrollWidth>e.clientWidth+1,i=e.scrollHeight>e.clientHeight+1,o=e.nativeBarWidth;return i?(this.vert.style.display="block",this.vert.style.bottom=r?o+"px":"0",t=e.viewHeight-(r?o:0),this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+t)+"px"):(this.vert.style.display="",this.vert.firstChild.style.height="0"),r?(this.horiz.style.display="block",this.horiz.style.right=i?o+"px":"0",this.horiz.style.left=e.barLeft+"px",n=e.viewWidth-e.barLeft-(i?o:0),this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+n)+"px"):(this.horiz.style.display="",this.horiz.firstChild.style.width="0"),!this.checkedZeroWidth&&0<e.clientHeight&&(0==o&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:i?o:0,bottom:r?o:0}},Dr.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},Dr.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},Dr.prototype.zeroWidthHack=function(){var e=y&&!s?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new z,this.disableVert=new z},Dr.prototype.enableZeroWidthBar=function(n,r,i){n.style.pointerEvents="auto",r.set(1e3,function e(){var t=n.getBoundingClientRect();("vert"==i?document.elementFromPoint(t.right-1,(t.top+t.bottom)/2):document.elementFromPoint((t.right+t.left)/2,t.bottom-1))!=n?n.style.pointerEvents="none":r.set(1e3,e)})},Dr.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};function Wr(){}function Hr(e,t){t=t||Or(e);var n=e.display.barWidth,r=e.display.barHeight;Fr(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&yr(e),Fr(e,Or(e)),n=e.display.barWidth,r=e.display.barHeight}function Fr(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}Wr.prototype.update=function(){return{bottom:0,right:0}},Wr.prototype.setScrollLeft=function(){},Wr.prototype.setScrollTop=function(){},Wr.prototype.clear=function(){};var Er={native:Dr,null:Wr};function Pr(n){n.display.scrollbars&&(n.display.scrollbars.clear(),n.display.scrollbars.addClass&&T(n.display.wrapper,n.display.scrollbars.addClass)),n.display.scrollbars=new Er[n.options.scrollbarStyle](function(e){n.display.wrapper.insertBefore(e,n.display.scrollbarFiller),we(e,"mousedown",function(){n.state.focused&&setTimeout(function(){return n.display.input.focus()},0)}),e.setAttribute("cm-not-content","true")},function(e,t){("horizontal"==t?Ar:Mr)(n,e)},n),n.display.scrollbars.addClass&&H(n.display.wrapper,n.display.scrollbars.addClass)}var Ir=0;function Rr(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Ir},t=e.curOp,ln?ln.ops.push(t):t.ownsGroup=ln={ops:[t],delayedCallbacks:[]}}function zr(e){var t=e.curOp;t&&sn(t,function(e){for(var t=0;t<e.ops.length;t++)e.ops[t].cm.curOp=null;!function(e){for(var t=e.ops,n=0;n<t.length;n++)!function(e){var t=e.cm,n=t.display;(function(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=Sn(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=Sn(e)+"px",t.scrollbarsClipped=!0)})(t),e.updateMaxLine&&_t(t);e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<n.viewFrom||e.scrollToPos.to.line>=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new Xr(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}(t[n]);for(var r=0;r<t.length;r++)!function(e){e.updatedDisplay=e.mustUpdate&&Yr(e.cm,e.update)}(t[r]);for(var i=0;i<t.length;i++)!function(e){var t=e.cm,n=t.display;e.updatedDisplay&&yr(t);e.barMeasure=Or(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Mn(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Sn(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Ln(t)));(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}(t[i]);for(var o=0;o<t.length;o++)!function(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&Ar(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1);var n=e.focus&&e.focus==W();e.preparedSelection&&t.display.input.showSelection(e.preparedSelection,n);!e.updatedDisplay&&e.startHeight==t.doc.height||Hr(t,e.barMeasure);e.updatedDisplay&&Zr(t,e.barMeasure);e.selectionChanged&&fr(t);t.state.focused&&e.updateInput&&t.display.input.reset(e.typing);n&&pr(e.cm)}(t[o]);for(var l=0;l<t.length;l++)!function(e){var t=e.cm,n=t.display,r=t.doc;e.updatedDisplay&&_r(t,e.update);null==n.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(n.wheelStartX=n.wheelStartY=null);null!=e.scrollTop&&Nr(t,e.scrollTop,e.forceScroll);null!=e.scrollLeft&&Ar(t,e.scrollLeft,!0,!0);{var i;e.scrollToPos&&(i=function(e,t,n,r){null==r&&(r=0),e.options.lineWrapping||t!=n||(n="before"==(t=t.ch?lt(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?lt(t.line,t.ch+1,"before"):t);for(var i=0;i<5;i++){var o,l=!1,s=Vn(e,t),a=n&&n!=t?Vn(e,n):s,u=xr(e,o={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-r,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+r}),c=e.doc.scrollTop,h=e.doc.scrollLeft;if(null!=u.scrollTop&&(Mr(e,u.scrollTop),1<Math.abs(e.doc.scrollTop-c)&&(l=!0)),null!=u.scrollLeft&&(Ar(e,u.scrollLeft),1<Math.abs(e.doc.scrollLeft-h)&&(l=!0)),!l)break}return o}(t,ft(r,e.scrollToPos.from),ft(r,e.scrollToPos.to),e.scrollToPos.margin),function(e,t){var n,r,i,o;Le(e,"scrollCursorIntoView")||(r=(n=e.display).sizer.getBoundingClientRect(),i=null,t.top+r.top<0?i=!0:t.bottom+r.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null==i||u||(o=O("div","​",null,"position: absolute;\n top: "+(t.top-n.viewOffset-wn(e.display))+"px;\n height: "+(t.bottom-t.top+Sn(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;"),e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)))}(t,i))}var o=e.maybeHiddenMarkers,l=e.maybeUnhiddenMarkers;if(o)for(var s=0;s<o.length;++s)o[s].lines.length||Se(o[s],"hide");if(l)for(var a=0;a<l.length;++a)l[a].lines.length&&Se(l[a],"unhide");n.wrapper.offsetHeight&&(r.scrollTop=t.display.scroller.scrollTop);e.changeObjs&&Se(t,"changes",t,e.changeObjs);e.update&&e.update.finish()}(t[l])}(e)})}function Br(e,t){if(e.curOp)return t();Rr(e);try{return t()}finally{zr(e)}}function Gr(e,t){return function(){if(e.curOp)return t.apply(e,arguments);Rr(e);try{return t.apply(e,arguments)}finally{zr(e)}}}function Ur(e){return function(){if(this.curOp)return e.apply(this,arguments);Rr(this);try{return e.apply(this,arguments)}finally{zr(this)}}}function Vr(t){return function(){var e=this.cm;if(!e||e.curOp)return t.apply(this,arguments);Rr(e);try{return t.apply(this,arguments)}finally{zr(e)}}}function Kr(e,t){e.doc.highlightFrontier<e.display.viewTo&&e.state.highlight.set(t,P(jr,e))}function jr(a){var u,c,h,d=a.doc;d.highlightFrontier>=a.display.viewTo||(u=+new Date+a.options.workTime,c=bt(a,d.highlightFrontier),h=[],d.iter(c.line,Math.min(d.first+d.size,a.display.viewTo+500),function(e){if(c.line>=a.display.viewFrom){var t=e.styles,n=e.text.length>a.options.maxHighlightLength?_e(d.mode,c.state):null,r=vt(a,e,c,!0);n&&(c.state=n),e.styles=r.styles;var i=e.styleClasses,o=r.classes;o?e.styleClasses=o:i&&(e.styleClasses=null);for(var l=!t||t.length!=e.styles.length||i!=o&&(!i||!o||i.bgClass!=o.bgClass||i.textClass!=o.textClass),s=0;!l&&s<t.length;++s)l=t[s]!=e.styles[s];l&&h.push(c.line),e.stateAfter=c.save(),c.nextLine()}else e.text.length<=a.options.maxHighlightLength&&wt(a,e.text,c),e.stateAfter=c.line%5==0?c.save():null,c.nextLine();if(+new Date>u)return Kr(a,a.options.workDelay),!0}),d.highlightFrontier=c.line,d.modeFrontier=Math.max(d.modeFrontier,c.line),h.length&&Br(a,function(){for(var e=0;e<h.length;e++)or(a,h[e],"text")}))}var Xr=function(e,t,n){var r=e.display;this.viewport=t,this.visible=wr(r,e.doc,t),this.editorIsHidden=!r.wrapper.offsetWidth,this.wrapperHeight=r.wrapper.clientHeight,this.wrapperWidth=r.wrapper.clientWidth,this.oldDisplayWidth=Ln(e),this.force=n,this.dims=Qn(e),this.events=[]};function Yr(e,t){var n=e.display,r=e.doc;if(t.editorIsHidden)return lr(e),!1;if(!t.force&&t.visible.from>=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==ar(e))return!1;Jr(e)&&(lr(e),t.dims=Qn(e));var i=r.first+r.size,o=Math.max(t.visible.from-e.options.viewportMargin,r.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);n.viewFrom<o&&o-n.viewFrom<20&&(o=Math.max(r.first,n.viewFrom)),n.viewTo>l&&n.viewTo-l<20&&(l=Math.min(i,n.viewTo)),Nt&&(o=Vt(e.doc,o),l=Kt(e.doc,l));var s,a,u,c,h=o!=n.viewFrom||l!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;a=o,u=l,0==(c=(s=e).display).view.length||a>=c.viewTo||u<=c.viewFrom?(c.view=on(s,a,u),c.viewFrom=a):(c.viewFrom>a?c.view=on(s,a,c.viewFrom).concat(c.view):c.viewFrom<a&&(c.view=c.view.slice(rr(s,a))),c.viewFrom=a,c.viewTo<u?c.view=c.view.concat(on(s,c.viewTo,u)):c.viewTo>u&&(c.view=c.view.slice(0,rr(s,u)))),c.viewTo=u,n.viewOffset=Xt(Qe(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var d=ar(e);if(!h&&0==d&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var f,p,g,m=function(e){if(e.hasFocus())return null;var t=W();if(!t||!D(e.display.lineDiv,t))return null;var n,r={activeElt:t};return!window.getSelection||(n=window.getSelection()).anchorNode&&n.extend&&D(e.display.lineDiv,n.anchorNode)&&(r.anchorNode=n.anchorNode,r.anchorOffset=n.anchorOffset,r.focusNode=n.focusNode,r.focusOffset=n.focusOffset),r}(e);return 4<d&&(n.lineDiv.style.display="none"),function(n,e,t){var r=n.display,i=n.options.lineNumbers,o=r.lineDiv,l=o.firstChild;function s(e){var t=e.nextSibling;return v&&y&&n.display.currentWheelTarget==e?e.style.display="none":e.parentNode.removeChild(e),t}for(var a=r.view,u=r.viewFrom,c=0;c<a.length;c++){var h=a[c];if(!h.hidden)if(h.node&&h.node.parentNode==o){for(;l!=h.node;)l=s(l);var d=i&&null!=e&&e<=u&&h.lineNumber;h.changes&&(-1<B(h.changes,"gutter")&&(d=!1),hn(n,h,u,t)),d&&(M(h.lineNumber),h.lineNumber.appendChild(document.createTextNode(ot(n.options,u)))),l=h.node.nextSibling}else{var f=function(e,t,n,r){var i=fn(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),pn(e,t),gn(e,t,n,r),mn(e,t,r),t.node}(n,h,u,t);o.insertBefore(f,l)}u+=h.size}for(;l;)l=s(l)}(e,n.updateLineNumbers,t.dims),4<d&&(n.lineDiv.style.display=""),n.renderedView=n.view,(f=m)&&f.activeElt&&f.activeElt!=W()&&(f.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(f.activeElt.nodeName)&&f.anchorNode&&D(document.body,f.anchorNode)&&D(document.body,f.focusNode)&&(p=window.getSelection(),(g=document.createRange()).setEnd(f.anchorNode,f.anchorOffset),g.collapse(!1),p.removeAllRanges(),p.addRange(g),p.extend(f.focusNode,f.focusOffset))),M(n.cursorDiv),M(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,h&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,Kr(e,400)),!(n.updateLineNumbers=null)}function _r(e,t){for(var n=t.viewport,r=!0;;r=!1){if(r&&e.options.lineWrapping&&t.oldDisplayWidth!=Ln(e))r&&(t.visible=wr(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+xn(e.display)-kn(e),n.top)}),t.visible=wr(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!Yr(e,t))break;yr(e);var i=Or(e);ur(e),Hr(e,i),Zr(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function $r(e,t){var n,r=new Xr(e,t);Yr(e,r)&&(yr(e),_r(e,r),n=Or(e),ur(e),Hr(e,n),Zr(e,n),r.finish())}function qr(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function Zr(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Sn(e)+"px"}function Qr(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=Jn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=r+"px",l=0;l<n.length;l++)if(!n[l].hidden){e.options.fixedGutter&&(n[l].gutter&&(n[l].gutter.style.left=o),n[l].gutterBackground&&(n[l].gutterBackground.style.left=o));var s=n[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=r+i+"px")}}function Jr(e){if(e.options.lineNumbers){var t=e.doc,n=ot(e.options,t.first+t.size-1),r=e.display;if(n.length!=r.lineNumChars){var i=r.measure.appendChild(O("div",[O("div",n)],"CodeMirror-linenumber CodeMirror-gutter-elt")),o=i.firstChild.offsetWidth,l=i.offsetWidth-o;return r.lineGutter.style.width="",r.lineNumInnerWidth=Math.max(o,r.lineGutter.offsetWidth-l)+1,r.lineNumWidth=r.lineNumInnerWidth+l,r.lineNumChars=r.lineNumInnerWidth?n.length:-1,r.lineGutter.style.width=r.lineNumWidth+"px",qr(e.display),1}}}function ei(e,t){for(var n=[],r=!1,i=0;i<e.length;i++){var o=e[i],l=null;if("string"!=typeof o&&(l=o.style,o=o.className),"CodeMirror-linenumbers"==o){if(!t)continue;r=!0}n.push({className:o,style:l})}return t&&!r&&n.push({className:"CodeMirror-linenumbers",style:null}),n}function ti(e){var t=e.gutters,n=e.gutterSpecs;M(t),e.lineGutter=null;for(var r=0;r<n.length;++r){var i=n[r],o=i.className,l=i.style,s=t.appendChild(O("div",null,"CodeMirror-gutter "+o));l&&(s.style.cssText=l),"CodeMirror-linenumbers"==o&&((e.lineGutter=s).style.width=(e.lineNumWidth||1)+"px")}t.style.display=n.length?"":"none",qr(e)}function ni(e){ti(e.display),ir(e),Qr(e)}function ri(e,t,n,r){var i=this;this.input=n,i.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),i.scrollbarFiller.setAttribute("cm-not-content","true"),i.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),i.gutterFiller.setAttribute("cm-not-content","true"),i.lineDiv=A("div",null,"CodeMirror-code"),i.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),i.cursorDiv=O("div",null,"CodeMirror-cursors"),i.measure=O("div",null,"CodeMirror-measure"),i.lineMeasure=O("div",null,"CodeMirror-measure"),i.lineSpace=A("div",[i.measure,i.lineMeasure,i.selectionDiv,i.cursorDiv,i.lineDiv],null,"position: relative; outline: none");var o=A("div",[i.lineSpace],"CodeMirror-lines");i.mover=O("div",[o],null,"position: relative"),i.sizer=O("div",[i.mover],"CodeMirror-sizer"),i.sizerWidth=null,i.heightForcer=O("div",null,null,"position: absolute; height: "+G+"px; width: 1px;"),i.gutters=O("div",null,"CodeMirror-gutters"),i.lineGutter=null,i.scroller=O("div",[i.sizer,i.heightForcer,i.gutters],"CodeMirror-scroll"),i.scroller.setAttribute("tabIndex","-1"),i.wrapper=O("div",[i.scrollbarFiller,i.gutterFiller,i.scroller],"CodeMirror"),L&&x<8&&(i.gutters.style.zIndex=-1,i.scroller.style.paddingRight=0),v||g&&d||(i.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(i.wrapper):e(i.wrapper)),i.viewFrom=i.viewTo=t.first,i.reportedViewFrom=i.reportedViewTo=t.first,i.view=[],i.renderedView=null,i.externalMeasured=null,i.viewOffset=0,i.lastWrapHeight=i.lastWrapWidth=0,i.updateLineNumbers=null,i.nativeBarWidth=i.barHeight=i.barWidth=0,i.scrollbarsClipped=!1,i.lineNumWidth=i.lineNumInnerWidth=i.lineNumChars=null,i.alignWidgets=!1,i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.maxLine=null,i.maxLineLength=0,i.maxLineChanged=!1,i.wheelDX=i.wheelDY=i.wheelStartX=i.wheelStartY=null,i.shift=!1,i.selForContextMenu=null,i.activeTouch=null,i.gutterSpecs=ei(r.gutters,r.lineNumbers),ti(i),n.init(i)}Xr.prototype.signal=function(e,t){Te(e,t)&&this.events.push(arguments)},Xr.prototype.finish=function(){for(var e=0;e<this.events.length;e++)Se.apply(null,this.events[e])};var ii=0,oi=null;function li(e){var t=e.wheelDeltaX,n=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==n&&e.detail&&e.axis==e.VERTICAL_AXIS?n=e.detail:null==n&&(n=e.wheelDelta),{x:t,y:n}}function si(e){var t=li(e);return t.x*=oi,t.y*=oi,t}function ai(e,t){var n,r,i,o=li(t),l=o.x,s=o.y,a=e.display,u=a.scroller,c=u.scrollWidth>u.clientWidth,h=u.scrollHeight>u.clientHeight;if(l&&c||s&&h){if(s&&y&&v)e:for(var d=t.target,f=a.view;d!=u;d=d.parentNode)for(var p=0;p<f.length;p++)if(f[p].node==d){e.display.currentWheelTarget=d;break e}if(l&&!g&&!m&&null!=oi)return s&&h&&Mr(e,Math.max(0,u.scrollTop+s*oi)),Ar(e,Math.max(0,u.scrollLeft+l*oi)),(!s||s&&h)&&Ne(t),void(a.wheelStartX=null);s&&null!=oi&&(n=s*oi,i=(r=e.doc.scrollTop)+a.wrapper.clientHeight,n<0?r=Math.max(0,r+n-50):i=Math.min(e.doc.height,i+n+50),$r(e,{top:r,bottom:i})),ii<20&&(null==a.wheelStartX?(a.wheelStartX=u.scrollLeft,a.wheelStartY=u.scrollTop,a.wheelDX=l,a.wheelDY=s,setTimeout(function(){var e,t,n;null!=a.wheelStartX&&(e=u.scrollLeft-a.wheelStartX,n=(t=u.scrollTop-a.wheelStartY)&&a.wheelDY&&t/a.wheelDY||e&&a.wheelDX&&e/a.wheelDX,a.wheelStartX=a.wheelStartY=null,n&&(oi=(oi*ii+n)/(ii+1),++ii))},200)):(a.wheelDX+=l,a.wheelDY+=s))}}L?oi=-.53:g?oi=15:l?oi=-.7:c&&(oi=-1/3);var ui=function(e,t){this.ranges=e,this.primIndex=t};ui.prototype.primary=function(){return this.ranges[this.primIndex]},ui.prototype.equals=function(e){if(e==this)return!0;if(e.primIndex!=this.primIndex||e.ranges.length!=this.ranges.length)return!1;for(var t=0;t<this.ranges.length;t++){var n=this.ranges[t],r=e.ranges[t];if(!at(n.anchor,r.anchor)||!at(n.head,r.head))return!1}return!0},ui.prototype.deepCopy=function(){for(var e=[],t=0;t<this.ranges.length;t++)e[t]=new ci(ut(this.ranges[t].anchor),ut(this.ranges[t].head));return new ui(e,this.primIndex)},ui.prototype.somethingSelected=function(){for(var e=0;e<this.ranges.length;e++)if(!this.ranges[e].empty())return!0;return!1},ui.prototype.contains=function(e,t){t=t||e;for(var n=0;n<this.ranges.length;n++){var r=this.ranges[n];if(0<=st(t,r.from())&&st(e,r.to())<=0)return n}return-1};var ci=function(e,t){this.anchor=e,this.head=t};function hi(e,t,n){var r=e&&e.options.selectionsMayTouch,i=t[n];t.sort(function(e,t){return st(e.from(),t.from())}),n=B(t,i);for(var o=1;o<t.length;o++){var l,s,a,u=t[o],c=t[o-1],h=st(c.to(),u.from());(r&&!u.empty()?0<h:0<=h)&&(l=ht(c.from(),u.from()),s=ct(c.to(),u.to()),a=c.empty()?u.from()==u.head:c.from()==c.head,o<=n&&--n,t.splice(--o,2,new ci(a?s:l,a?l:s)))}return new ui(t,n)}function di(e,t){return new ui([new ci(e,t||e)],0)}function fi(e){return e.text?lt(e.from.line+e.text.length-1,$(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function pi(e,t){if(st(e,t.from)<0)return e;if(st(e,t.to)<=0)return fi(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=fi(t).ch-t.to.ch),lt(n,r)}function gi(e,t){for(var n=[],r=0;r<e.sel.ranges.length;r++){var i=e.sel.ranges[r];n.push(new ci(pi(i.anchor,t),pi(i.head,t)))}return hi(e.cm,n,e.sel.primIndex)}function mi(e,t,n){return e.line==t.line?lt(n.line,e.ch-t.ch+n.ch):lt(n.line+(e.line-t.line),e.ch)}function vi(e){e.doc.mode=je(e.options,e.doc.modeOption),yi(e)}function yi(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.modeFrontier=e.doc.highlightFrontier=e.doc.first,Kr(e,100),e.state.modeGen++,e.curOp&&ir(e)}function bi(e,t){return 0==t.from.ch&&0==t.to.ch&&""==$(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function wi(e,r,t,i){function o(e){return t?t[e]:null}function n(e,t,n){!function(e,t,n,r){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),Ht(e),Ft(e,n);var i=r?r(e):1;i!=e.height&&tt(e,i)}(e,t,n,i),un(e,"change",e,r)}function l(e,t){for(var n=[],r=e;r<t;++r)n.push(new $t(d[r],o(r),i));return n}var s,a,u,c=r.from,h=r.to,d=r.text,f=Qe(e,c.line),p=Qe(e,h.line),g=$(d),m=o(d.length-1),v=h.line-c.line;r.full?(e.insert(0,l(0,d.length)),e.remove(d.length,e.size-d.length)):bi(e,r)?(s=l(0,d.length-1),n(p,p.text,m),v&&e.remove(c.line,v),s.length&&e.insert(c.line,s)):f==p?1==d.length?n(f,f.text.slice(0,c.ch)+g+f.text.slice(h.ch),m):((a=l(1,d.length-1)).push(new $t(g+f.text.slice(h.ch),m,i)),n(f,f.text.slice(0,c.ch)+d[0],o(0)),e.insert(c.line+1,a)):1==d.length?(n(f,f.text.slice(0,c.ch)+d[0]+p.text.slice(h.ch),o(0)),e.remove(c.line+1,v)):(n(f,f.text.slice(0,c.ch)+d[0],o(0)),n(p,g+p.text.slice(h.ch),m),u=l(1,d.length-1),1<v&&e.remove(c.line+1,v-1),e.insert(c.line+1,u)),un(e,"change",e,r)}function xi(e,s,a){!function e(t,n,r){if(t.linked)for(var i=0;i<t.linked.length;++i){var o,l=t.linked[i];l.doc!=n&&(o=r&&l.sharedHist,a&&!o||(s(l.doc,o),e(l.doc,t,o)))}}(e,null,!0)}function Ci(e,t){if(t.cm)throw new Error("This document is already in use.");tr((e.doc=t).cm=e),vi(e),Si(e),e.options.lineWrapping||_t(e),e.options.mode=t.modeOption,ir(e)}function Si(e){("rtl"==e.doc.direction?H:T)(e.display.lineDiv,"CodeMirror-rtl")}function Li(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function ki(e,t){var n={from:ut(t.from),to:fi(t),text:Je(e,t.from,t.to)};return Oi(e,n,t.from.line,t.to.line+1),xi(e,function(e){return Oi(e,n,t.from.line,t.to.line+1),0},!0),n}function Ti(e){for(;e.length;){if(!$(e).ranges)break;e.pop()}}function Mi(e,t,n,r){var i=e.history;i.undone.length=0;var o,l,s,a=+new Date;if((i.lastOp==r||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>a-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=(s=i).lastOp==r?(Ti(s.done),$(s.done)):s.done.length&&!$(s.done).ranges?$(s.done):1<s.done.length&&!s.done[s.done.length-2].ranges?(s.done.pop(),$(s.done)):void 0))l=$(o.changes),0==st(t.from,t.to)&&0==st(t.from,l.to)?l.to=fi(t):o.changes.push(ki(e,t));else{var u=$(i.done);for(u&&u.ranges||Ai(e.sel,i.done),o={changes:[ki(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(n),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=a,i.lastOp=i.lastSelOp=r,i.lastOrigin=i.lastSelOrigin=t.origin,l||Se(e,"historyAdded")}function Ni(e,t,n,r){var i,o,l,s,a,u=e.history,c=r&&r.origin;n==u.lastSelOp||c&&u.lastSelOrigin==c&&(u.lastModTime==u.lastSelTime&&u.lastOrigin==c||(i=e,o=c,l=$(u.done),s=t,"*"==(a=o.charAt(0))||"+"==a&&l.ranges.length==s.ranges.length&&l.somethingSelected()==s.somethingSelected()&&new Date-i.history.lastSelTime<=(i.cm?i.cm.options.historyEventDelay:500)))?u.done[u.done.length-1]=t:Ai(t,u.done),u.lastSelTime=+new Date,u.lastSelOrigin=c,u.lastSelOp=n,r&&!1!==r.clearRedo&&Ti(u.undone)}function Ai(e,t){var n=$(t);n&&n.ranges&&n.equals(e)||t.push(e)}function Oi(t,n,e,r){var i=n["spans_"+t.id],o=0;t.iter(Math.max(t.first,e),Math.min(t.first+t.size,r),function(e){e.markedSpans&&((i=i||(n["spans_"+t.id]={}))[o]=e.markedSpans),++o})}function Di(e,t){var n=t["spans_"+e.id];if(!n)return null;for(var r=[],i=0;i<t.text.length;++i)r.push(function(e){if(!e)return null;for(var t,n=0;n<e.length;++n)e[n].marker.explicitlyCleared?t=t||e.slice(0,n):t&&t.push(e[n]);return t?t.length?t:null:e}(n[i]));return r}function Wi(e,t){var n=Di(e,t),r=Dt(e,t);if(!n)return r;if(!r)return n;for(var i=0;i<n.length;++i){var o=n[i],l=r[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(n[i]=l)}return n}function Hi(e,t,n){for(var r=[],i=0;i<e.length;++i){var o=e[i];if(o.ranges)r.push(n?ui.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];r.push({changes:s});for(var a=0;a<l.length;++a){var u=l[a],c=void 0;if(s.push({from:u.from,to:u.to,text:u.text}),t)for(var h in u)(c=h.match(/^spans_(\d+)$/))&&-1<B(t,Number(c[1]))&&($(s)[h]=u[h],delete u[h])}}}return r}function Fi(e,t,n,r){if(r){var i,o=e.anchor;return n&&((i=st(t,o)<0)!=st(n,o)<0?(o=t,t=n):i!=st(t,n)<0&&(t=n)),new ci(o,t)}return new ci(n||t,t)}function Ei(e,t,n,r,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),Bi(e,new ui([Fi(e.sel.primary(),t,n,i)],0),r)}function Pi(e,t,n){for(var r=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o<e.sel.ranges.length;o++)r[o]=Fi(e.sel.ranges[o],t[o],null,i);Bi(e,hi(e.cm,r,e.sel.primIndex),n)}function Ii(e,t,n,r){var i=e.sel.ranges.slice(0);i[t]=n,Bi(e,hi(e.cm,i,e.sel.primIndex),r)}function Ri(e,t,n,r){Bi(e,di(t,n),r)}function zi(e,t,n){var r=e.history.done,i=$(r);i&&i.ranges?Gi(e,r[r.length-1]=t,n):Bi(e,t,n)}function Bi(e,t,n){Gi(e,t,n),Ni(e,e.sel,e.cm?e.cm.curOp.id:NaN,n)}function Gi(e,t,n){var r,i,o,l;(Te(e,"beforeSelectionChange")||e.cm&&Te(e.cm,"beforeSelectionChange"))&&(r=e,o=n,l={ranges:(i=t).ranges,update:function(e){this.ranges=[];for(var t=0;t<e.length;t++)this.ranges[t]=new ci(ft(r,e[t].anchor),ft(r,e[t].head))},origin:o&&o.origin},Se(r,"beforeSelectionChange",r,l),r.cm&&Se(r.cm,"beforeSelectionChange",r.cm,l),t=l.ranges!=i.ranges?hi(r.cm,l.ranges,l.ranges.length-1):i);var s=n&&n.bias||(st(t.primary().head,e.sel.primary().head)<0?-1:1);Ui(e,Ki(e,t,s,!0)),n&&!1===n.scroll||!e.cm||Sr(e.cm)}function Ui(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=1,e.cm.curOp.selectionChanged=!0,ke(e.cm)),un(e,"cursorActivity",e))}function Vi(e){Ui(e,Ki(e,e.sel,null,!1))}function Ki(e,t,n,r){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=t.ranges.length==e.sel.ranges.length&&e.sel.ranges[o],a=Xi(e,l.anchor,s&&s.anchor,n,r),u=Xi(e,l.head,s&&s.head,n,r);!i&&a==l.anchor&&u==l.head||((i=i||t.ranges.slice(0,o))[o]=new ci(a,u))}return i?hi(e.cm,i,t.primIndex):t}function ji(e,t,n,r,i){var o=Qe(e,t.line);if(o.markedSpans)for(var l=0;l<o.markedSpans.length;++l){var s=o.markedSpans[l],a=s.marker,u="selectLeft"in a?!a.selectLeft:a.inclusiveLeft,c="selectRight"in a?!a.selectRight:a.inclusiveRight;if((null==s.from||(u?s.from<=t.ch:s.from<t.ch))&&(null==s.to||(c?s.to>=t.ch:s.to>t.ch))){if(i&&(Se(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(n){var h=a.find(r<0?1:-1),d=void 0;if((r<0?c:u)&&(h=Yi(e,h,-r,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(d=st(h,n))&&(r<0?d<0:0<d))return ji(e,h,t,r,i)}var f=a.find(r<0?-1:1);return(r<0?u:c)&&(f=Yi(e,f,r,f.line==t.line?o:null)),f?ji(e,f,t,r,i):null}}return t}function Xi(e,t,n,r,i){var o=r||1,l=ji(e,t,n,o,i)||!i&&ji(e,t,n,o,!0)||ji(e,t,n,-o,i)||!i&&ji(e,t,n,-o,!0);return l||(e.cantEdit=!0,lt(e.first,0))}function Yi(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?ft(e,lt(t.line-1)):null:0<n&&t.ch==(r||Qe(e,t.line)).text.length?t.line<e.first+e.size-1?lt(t.line+1,0):null:new lt(t.line,t.ch+n)}function _i(e){e.setSelection(lt(e.firstLine(),0),lt(e.lastLine()),V)}function $i(i,e,t){var o={canceled:!1,from:e.from,to:e.to,text:e.text,origin:e.origin,cancel:function(){return o.canceled=!0}};return t&&(o.update=function(e,t,n,r){e&&(o.from=ft(i,e)),t&&(o.to=ft(i,t)),n&&(o.text=n),void 0!==r&&(o.origin=r)}),Se(i,"beforeChange",i,o),i.cm&&Se(i.cm,"beforeChange",i.cm,o),o.canceled?(i.cm&&(i.cm.curOp.updateInput=2),null):{from:o.from,to:o.to,text:o.text,origin:o.origin}}function qi(e,t,n){if(e.cm){if(!e.cm.curOp)return Gr(e.cm,qi)(e,t,n);if(e.cm.state.suppressEdits)return}if(!(Te(e,"beforeChange")||e.cm&&Te(e.cm,"beforeChange"))||(t=$i(e,t,!0))){var r=Mt&&!n&&function(e,t,n){var r=null;if(e.iter(t.line,n.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var n=e.markedSpans[t].marker;!n.readOnly||r&&-1!=B(r,n)||(r=r||[]).push(n)}}),!r)return null;for(var i=[{from:t,to:n}],o=0;o<r.length;++o)for(var l=r[o],s=l.find(0),a=0;a<i.length;++a){var u,c,h,d=i[a];st(d.to,s.from)<0||0<st(d.from,s.to)||(u=[a,1],c=st(d.from,s.from),h=st(d.to,s.to),(c<0||!l.inclusiveLeft&&!c)&&u.push({from:d.from,to:s.from}),(0<h||!l.inclusiveRight&&!h)&&u.push({from:s.to,to:d.to}),i.splice.apply(i,u),a+=u.length-3)}return i}(e,t.from,t.to);if(r)for(var i=r.length-1;0<=i;--i)Zi(e,{from:r[i].from,to:r[i].to,text:i?[""]:t.text,origin:t.origin});else Zi(e,t)}}function Zi(e,n){var t,r;1==n.text.length&&""==n.text[0]&&0==st(n.from,n.to)||(t=gi(e,n),Mi(e,n,t,e.cm?e.cm.curOp.id:NaN),eo(e,n,t,Dt(e,n)),r=[],xi(e,function(e,t){t||-1!=B(r,e.history)||(io(e.history,n),r.push(e.history)),eo(e,n,null,Dt(e,n))}))}function Qi(i,o,e){var t=i.cm&&i.cm.state.suppressEdits;if(!t||e){for(var l,n=i.history,r=i.sel,s="undo"==o?n.done:n.undone,a="undo"==o?n.undone:n.done,u=0;u<s.length&&(l=s[u],e?!l.ranges||l.equals(i.sel):l.ranges);u++);if(u!=s.length){for(n.lastOrigin=n.lastSelOrigin=null;;){if(!(l=s.pop()).ranges){if(t)return void s.push(l);break}if(Ai(l,a),e&&!l.equals(i.sel))return void Bi(i,l,{clearRedo:!1});r=l}var c=[];Ai(r,a),a.push({changes:c,generation:n.generation}),n.generation=l.generation||++n.maxGeneration;for(var h=Te(i,"beforeChange")||i.cm&&Te(i.cm,"beforeChange"),d=l.changes.length-1;0<=d;--d){var f=function(e){var n=l.changes[e];if(n.origin=o,h&&!$i(i,n,!1))return s.length=0,{};c.push(ki(i,n));var t=e?gi(i,n):$(s);eo(i,n,t,Wi(i,n)),!e&&i.cm&&i.cm.scrollIntoView({from:n.from,to:fi(n)});var r=[];xi(i,function(e,t){t||-1!=B(r,e.history)||(io(e.history,n),r.push(e.history)),eo(e,n,null,Wi(e,n))})}(d);if(f)return f.v}}}}function Ji(e,t){if(0!=t&&(e.first+=t,e.sel=new ui(q(e.sel.ranges,function(e){return new ci(lt(e.anchor.line+t,e.anchor.ch),lt(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){ir(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;r<n.viewTo;r++)or(e.cm,r,"gutter")}}function eo(e,t,n,r){if(e.cm&&!e.cm.curOp)return Gr(e.cm,eo)(e,t,n,r);var i,o;t.to.line<e.first?Ji(e,t.text.length-1-(t.to.line-t.from.line)):t.from.line>e.lastLine()||(t.from.line<e.first&&(Ji(e,i=t.text.length-1-(e.first-t.from.line)),t={from:lt(e.first,0),to:lt(t.to.line+i,t.to.ch),text:[$(t.text)],origin:t.origin}),o=e.lastLine(),t.to.line>o&&(t={from:t.from,to:lt(o,Qe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Je(e,t.from,t.to),n=n||gi(e,t),e.cm?function(e,t,n){var r=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=nt(Ut(Qe(r,o.line))),r.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0}));-1<r.sel.contains(t.from,t.to)&&ke(e);wi(r,t,n,er(e)),e.options.lineWrapping||(r.iter(a,o.line+t.text.length,function(e){var t=Yt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontier<t-10)){for(var n=e.first,r=t-1;n<r;r--){var i=Qe(e,r).stateAfter;if(i&&(!(i instanceof gt)||r+i.lookAhead<t)){n=r+1;break}}e.highlightFrontier=Math.min(e.highlightFrontier,n)}})(r,o.line),Kr(e,400);var u=t.text.length-(l.line-o.line)-1;t.full?ir(e):o.line!=l.line||1!=t.text.length||bi(e.doc,t)?ir(e,o.line,l.line+1,u):or(e,o.line,"text");var c=Te(e,"changes"),h=Te(e,"change");{var d;(h||c)&&(d={from:o,to:l,text:t.text,removed:t.removed,origin:t.origin},h&&un(e,"change",e,d),c&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(d))}e.display.selForContextMenu=null}(e.cm,t,r):wi(e,t,r),Gi(e,n,V),e.cantEdit&&Xi(e,lt(e.firstLine(),0))&&(e.cantEdit=!1))}function to(e,t,n,r,i){var o;st(r=r||n,n)<0&&(n=(o=[r,n])[0],r=o[1]),"string"==typeof t&&(t=e.splitLines(t)),qi(e,{from:n,to:r,text:t,origin:i})}function no(e,t,n,r){n<e.line?e.line+=r:t<e.line&&(e.line=t,e.ch=0)}function ro(e,t,n,r){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||((o=e[i]=o.deepCopy()).copied=!0);for(var s=0;s<o.ranges.length;s++)no(o.ranges[s].anchor,t,n,r),no(o.ranges[s].head,t,n,r)}else{for(var a=0;a<o.changes.length;++a){var u=o.changes[a];if(n<u.from.line)u.from=lt(u.from.line+r,u.from.ch),u.to=lt(u.to.line+r,u.to.ch);else if(t<=u.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function io(e,t){var n=t.from.line,r=t.to.line,i=t.text.length-(r-n)-1;ro(e.done,n,r,i),ro(e.undone,n,r,i)}function oo(e,t,n,r){var i=t,o=t;return"number"==typeof t?o=Qe(e,dt(e,t)):i=nt(t),null==i?null:(r(o,i)&&e.cm&&or(e.cm,i,n),o)}function lo(e){this.lines=e,this.parent=null;for(var t=0,n=0;n<e.length;++n)e[n].parent=this,t+=e[n].height;this.height=t}function so(e){this.children=e;for(var t=0,n=0,r=0;r<e.length;++r){var i=e[r];t+=i.chunkSize(),n+=i.height,i.parent=this}this.size=t,this.height=n,this.parent=null}ci.prototype.from=function(){return ht(this.anchor,this.head)},ci.prototype.to=function(){return ct(this.anchor,this.head)},ci.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch},lo.prototype={chunkSize:function(){return this.lines.length},removeInner:function(e,t){for(var n,r=e,i=e+t;r<i;++r){var o=this.lines[r];this.height-=o.height,(n=o).parent=null,Ht(n),un(o,"delete")}this.lines.splice(e,t)},collapse:function(e){e.push.apply(e,this.lines)},insertInner:function(e,t,n){this.height+=n,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var r=0;r<t.length;++r)t[r].parent=this},iterN:function(e,t,n){for(var r=e+t;e<r;++e)if(n(this.lines[e]))return!0}},so.prototype={chunkSize:function(){return this.size},removeInner:function(e,t){this.size-=t;for(var n,r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e),s=i.height;if(i.removeInner(e,l),this.height-=s-i.height,o==l&&(this.children.splice(r--,1),i.parent=null),0==(t-=l))break;e=0}else e-=o}this.size-t<25&&(1<this.children.length||!(this.children[0]instanceof lo))&&(n=[],this.collapse(n),this.children=[new lo(n)],this.children[0].parent=this)},collapse:function(e){for(var t=0;t<this.children.length;++t)this.children[t].collapse(e)},insertInner:function(e,t,n){this.size+=t.length,this.height+=n;for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<=o){if(i.insertInner(e,t,n),i.lines&&50<i.lines.length){for(var l=i.lines.length%25+25,s=l;s<i.lines.length;){var a=new lo(i.lines.slice(s,s+=25));i.height-=a.height,this.children.splice(++r,0,a),a.parent=this}i.lines=i.lines.slice(0,l),this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(!(this.children.length<=10)){var e=this;do{var t,n,r=new so(e.children.splice(e.children.length-5,5));e.parent?(e.size-=r.size,e.height-=r.height,t=B(e.parent.children,e),e.parent.children.splice(t+1,0,r)):(((n=new so(e.children)).parent=e).children=[n,r],e=n),r.parent=e.parent}while(10<e.children.length);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e);if(i.iterN(e,l,n))return!0;if(0==(t-=l))break;e=0}else e-=o}}};function ao(e,t,n){if(n)for(var r in n)n.hasOwnProperty(r)&&(this[r]=n[r]);this.doc=e,this.node=t}function uo(e,t,n){Xt(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&Cr(e,n)}ao.prototype.clear=function(){var e=this.doc.cm,t=this.line.widgets,n=this.line,r=nt(n);if(null!=r&&t){for(var i=0;i<t.length;++i)t[i]==this&&t.splice(i--,1);t.length||(n.widgets=null);var o=yn(this);tt(n,Math.max(0,n.height-o)),e&&(Br(e,function(){uo(e,n,-o),or(e,r,"widget")}),un(e,"lineWidgetCleared",e,this,r))}},ao.prototype.changed=function(){var e=this,t=this.height,n=this.doc.cm,r=this.line;this.height=null;var i=yn(this)-t;i&&(jt(this.doc,r)||tt(r,r.height+i),n&&Br(n,function(){n.curOp.forceUpdate=!0,uo(n,r,i),un(n,"lineWidgetChanged",n,e,nt(r))}))},Me(ao);var co=0,ho=function(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++co};function fo(t,r,i,e,n){if(e&&e.shared)return function(e,n,r,i,o){(i=I(i)).shared=!1;var l=[fo(e,n,r,i,o)],s=l[0],a=i.widgetNode;return xi(e,function(e){a&&(i.widgetNode=a.cloneNode(!0)),l.push(fo(e,ft(e,n),ft(e,r),i,o));for(var t=0;t<e.linked.length;++t)if(e.linked[t].isParent)return;s=$(l)}),new po(l,s)}(t,r,i,e,n);if(t.cm&&!t.cm.curOp)return Gr(t.cm,fo)(t,r,i,e,n);var o=new ho(t,n),l=st(r,i);if(e&&I(e,o,!1),0<l||0==l&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),e.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),e.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Gt(t,r.line,r,i,o)||r.line!=i.line&&Gt(t,i.line,r,i,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Nt=!0}o.addToHistory&&Mi(t,{from:r,to:i,origin:"markText"},t.sel,NaN);var s,a=r.line,u=t.cm;if(t.iter(a,i.line+1,function(e){var t,n;u&&o.collapsed&&!u.options.lineWrapping&&Ut(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=r.line&&tt(e,0),t=e,n=new At(o,a==r.line?r.ch:null,a==i.line?i.ch:null),t.markedSpans=t.markedSpans?t.markedSpans.concat([n]):[n],n.marker.attachLine(t),++a}),o.collapsed&&t.iter(r.line,i.line+1,function(e){jt(t,e)&&tt(e,0)}),o.clearOnEnter&&we(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(Mt=!0,(t.history.done.length||t.history.undone.length)&&t.clearHistory()),o.collapsed&&(o.id=++co,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)ir(u,r.line,i.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=r.line;c<=i.line;c++)or(u,c,"text");o.atomic&&Vi(u.doc),un(u,"markerAdded",u,o)}return o}ho.prototype.clear=function(){if(!this.explicitlyCleared){var e,t=this.doc.cm,n=t&&!t.curOp;n&&Rr(t),!Te(this,"clear")||(e=this.find())&&un(this,"clear",e.from,e.to);for(var r=null,i=null,o=0;o<this.lines.length;++o){var l=this.lines[o],s=Ot(l.markedSpans,this);t&&!this.collapsed?or(t,nt(l),"text"):t&&(null!=s.to&&(i=nt(l)),null!=s.from&&(r=nt(l))),l.markedSpans=function(e,t){for(var n,r=0;r<e.length;++r)e[r]!=t&&(n=n||[]).push(e[r]);return n}(l.markedSpans,s),null==s.from&&this.collapsed&&!jt(this.doc,l)&&t&&tt(l,qn(t.display))}if(t&&this.collapsed&&!t.options.lineWrapping)for(var a=0;a<this.lines.length;++a){var u=Ut(this.lines[a]),c=Yt(u);c>t.display.maxLineLength&&(t.display.maxLine=u,t.display.maxLineLength=c,t.display.maxLineChanged=!0)}null!=r&&t&&this.collapsed&&ir(t,r,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,t&&Vi(t.doc)),t&&un(t,"markerCleared",t,this,r,i),n&&zr(t),this.parent&&this.parent.clear()}},ho.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i<this.lines.length;++i){var o=this.lines[i],l=Ot(o.markedSpans,this);if(null!=l.from&&(n=lt(t?o:nt(o),l.from),-1==e))return n;if(null!=l.to&&(r=lt(t?o:nt(o),l.to),1==e))return r}return n&&{from:n,to:r}},ho.prototype.changed=function(){var o=this,l=this.find(-1,!0),s=this,a=this.doc.cm;l&&a&&Br(a,function(){var e,t,n=l.line,r=nt(l.line),i=Nn(a,r);i&&(Fn(i),a.curOp.selectionChanged=a.curOp.forceUpdate=!0),a.curOp.updateMaxLine=!0,jt(s.doc,n)||null==s.height||(e=s.height,s.height=null,(t=yn(s)-e)&&tt(n,n.height+t)),un(a,"markerChanged",a,o)})},ho.prototype.attachLine=function(e){var t;!this.lines.length&&this.doc.cm&&((t=this.doc.cm.curOp).maybeHiddenMarkers&&-1!=B(t.maybeHiddenMarkers,this)||(t.maybeUnhiddenMarkers||(t.maybeUnhiddenMarkers=[])).push(this)),this.lines.push(e)},ho.prototype.detachLine=function(e){var t;this.lines.splice(B(this.lines,e),1),!this.lines.length&&this.doc.cm&&((t=this.doc.cm.curOp).maybeHiddenMarkers||(t.maybeHiddenMarkers=[])).push(this)},Me(ho);var po=function(e,t){this.markers=e,this.primary=t;for(var n=0;n<e.length;++n)e[n].parent=this};function go(e){return e.findMarks(lt(e.first,0),e.clipPos(lt(e.lastLine())),function(e){return e.parent})}po.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var e=0;e<this.markers.length;++e)this.markers[e].clear();un(this,"clear")}},po.prototype.find=function(e,t){return this.primary.find(e,t)},Me(po);var mo=0,vo=function(e,t,n,r,i){if(!(this instanceof vo))return new vo(e,t,n,r,i);null==n&&(n=0),so.call(this,[new lo([new $t("",null)])]),this.first=n,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1;var o=lt(this.modeFrontier=this.highlightFrontier=n,0);this.sel=di(o),this.history=new Li(null),this.id=++mo,this.modeOption=t,this.lineSep=r,this.direction="rtl"==i?"rtl":"ltr",this.extend=!1,"string"==typeof e&&(e=this.splitLines(e)),wi(this,{from:o,to:o,text:e}),Bi(this,di(o),V)};vo.prototype=Q(so.prototype,{constructor:vo,iter:function(e,t,n){n?this.iterN(e-this.first,t-e,n):this.iterN(this.first,this.first+this.size,e)},insert:function(e,t){for(var n=0,r=0;r<t.length;++r)n+=t[r].height;this.insertInner(e-this.first,t,n)},remove:function(e,t){this.removeInner(e-this.first,t)},getValue:function(e){var t=et(this,this.first,this.first+this.size);return!1===e?t:t.join(e||this.lineSeparator())},setValue:Vr(function(e){var t=lt(this.first,0),n=this.first+this.size-1;qi(this,{from:t,to:lt(n,Qe(this,n).text.length),text:this.splitLines(e),origin:"setValue",full:!0},!0),this.cm&&Lr(this.cm,0,0),Bi(this,di(t),V)}),replaceRange:function(e,t,n,r){to(this,e,t=ft(this,t),n=n?ft(this,n):t,r)},getRange:function(e,t,n){var r=Je(this,ft(this,e),ft(this,t));return!1===n?r:r.join(n||this.lineSeparator())},getLine:function(e){var t=this.getLineHandle(e);return t&&t.text},getLineHandle:function(e){if(it(this,e))return Qe(this,e)},getLineNumber:nt,getLineHandleVisualStart:function(e){return"number"==typeof e&&(e=Qe(this,e)),Ut(e)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(e){return ft(this,e)},getCursor:function(e){var t=this.sel.primary(),n=null==e||"head"==e?t.head:"anchor"==e?t.anchor:"end"==e||"to"==e||!1===e?t.to():t.from();return n},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Vr(function(e,t,n){Ri(this,ft(this,"number"==typeof e?lt(e,t||0):e),null,n)}),setSelection:Vr(function(e,t,n){Ri(this,ft(this,e),ft(this,t||e),n)}),extendSelection:Vr(function(e,t,n){Ei(this,ft(this,e),t&&ft(this,t),n)}),extendSelections:Vr(function(e,t){Pi(this,pt(this,e),t)}),extendSelectionsBy:Vr(function(e,t){Pi(this,pt(this,q(this.sel.ranges,e)),t)}),setSelections:Vr(function(e,t,n){if(e.length){for(var r=[],i=0;i<e.length;i++)r[i]=new ci(ft(this,e[i].anchor),ft(this,e[i].head));null==t&&(t=Math.min(e.length-1,this.sel.primIndex)),Bi(this,hi(this.cm,r,t),n)}}),addSelection:Vr(function(e,t,n){var r=this.sel.ranges.slice(0);r.push(new ci(ft(this,e),ft(this,t||e))),Bi(this,hi(this.cm,r,r.length-1),n)}),getSelection:function(e){for(var t=this.sel.ranges,n=0;n<t.length;n++)var r=Je(this,t[n].from(),t[n].to()),i=i?i.concat(r):r;return!1===e?i:i.join(e||this.lineSeparator())},getSelections:function(e){for(var t=[],n=this.sel.ranges,r=0;r<n.length;r++){var i=Je(this,n[r].from(),n[r].to());!1!==e&&(i=i.join(e||this.lineSeparator())),t[r]=i}return t},replaceSelection:function(e,t,n){for(var r=[],i=0;i<this.sel.ranges.length;i++)r[i]=e;this.replaceSelections(r,t,n||"+input")},replaceSelections:Vr(function(e,t,n){for(var r=[],i=this.sel,o=0;o<i.ranges.length;o++){var l=i.ranges[o];r[o]={from:l.from(),to:l.to(),text:this.splitLines(e[o]),origin:n}}for(var s=t&&"end"!=t&&function(e,t,n){for(var r=[],i=h=lt(e.first,0),o=0;o<t.length;o++){var l,s,a=t[o],u=mi(a.from,h,i),c=mi(fi(a),h,i),h=a.to,i=c;"around"==n?(s=st((l=e.sel.ranges[o]).head,l.anchor)<0,r[o]=new ci(s?c:u,s?u:c)):r[o]=new ci(u,u)}return new ui(r,e.sel.primIndex)}(this,r,t),a=r.length-1;0<=a;a--)qi(this,r[a]);s?zi(this,s):this.cm&&Sr(this.cm)}),undo:Vr(function(){Qi(this,"undo")}),redo:Vr(function(){Qi(this,"redo")}),undoSelection:Vr(function(){Qi(this,"undo",!0)}),redoSelection:Vr(function(){Qi(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r<e.done.length;r++)e.done[r].ranges||++t;for(var i=0;i<e.undone.length;i++)e.undone[i].ranges||++n;return{undo:t,redo:n}},clearHistory:function(){var t=this;this.history=new Li(this.history.maxGeneration),xi(this,function(e){return e.history=t.history},!0)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(e){return e&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(e){return this.history.generation==(e||this.cleanGeneration)},getHistory:function(){return{done:Hi(this.history.done),undone:Hi(this.history.undone)}},setHistory:function(e){var t=this.history=new Li(this.history.maxGeneration);t.done=Hi(e.done.slice(0),null,!0),t.undone=Hi(e.undone.slice(0),null,!0)},setGutterMarker:Vr(function(e,n,r){return oo(this,e,"gutter",function(e){var t=e.gutterMarkers||(e.gutterMarkers={});return!(t[n]=r)&&ne(t)&&(e.gutterMarkers=null),1})}),clearGutter:Vr(function(t){var n=this;this.iter(function(e){e.gutterMarkers&&e.gutterMarkers[t]&&oo(n,e,"gutter",function(){return e.gutterMarkers[t]=null,ne(e.gutterMarkers)&&(e.gutterMarkers=null),1})})}),lineInfo:function(e){var t;if("number"==typeof e){if(!it(this,e))return null;if(!(e=Qe(this,t=e)))return null}else if(null==(t=nt(e)))return null;return{line:t,handle:e,text:e.text,gutterMarkers:e.gutterMarkers,textClass:e.textClass,bgClass:e.bgClass,wrapClass:e.wrapClass,widgets:e.widgets}},addLineClass:Vr(function(e,n,r){return oo(this,e,"gutter"==n?"gutter":"class",function(e){var t="text"==n?"textClass":"background"==n?"bgClass":"gutter"==n?"gutterClass":"wrapClass";if(e[t]){if(S(r).test(e[t]))return;e[t]+=" "+r}else e[t]=r;return 1})}),removeLineClass:Vr(function(e,o,l){return oo(this,e,"gutter"==o?"gutter":"class",function(e){var t="text"==o?"textClass":"background"==o?"bgClass":"gutter"==o?"gutterClass":"wrapClass",n=e[t];if(n){if(null==l)e[t]=null;else{var r=n.match(S(l));if(!r)return;var i=r.index+r[0].length;e[t]=n.slice(0,r.index)+(r.index&&i!=n.length?" ":"")+n.slice(i)||null}return 1}})}),addLineWidget:Vr(function(e,t,n){return i=e,o=new ao(r=this,t,n),(l=r.cm)&&o.noHScroll&&(l.display.alignWidgets=!0),oo(r,i,"widget",function(e){var t,n=e.widgets||(e.widgets=[]);return null==o.insertAt?n.push(o):n.splice(Math.min(n.length,Math.max(0,o.insertAt)),0,o),o.line=e,l&&!jt(r,e)&&(t=Xt(e)<r.scrollTop,tt(e,e.height+yn(o)),t&&Cr(l,o.height),l.curOp.forceUpdate=!0),1}),l&&un(l,"lineWidgetAdded",l,o,"number"==typeof i?i:nt(i)),o;var r,i,o,l}),removeLineWidget:function(e){e.clear()},markText:function(e,t,n){return fo(this,ft(this,e),ft(this,t),n,n&&n.type||"range")},setBookmark:function(e,t){var n={replacedWith:t&&(null==t.nodeType?t.widget:t),insertLeft:t&&t.insertLeft,clearWhenEmpty:!1,shared:t&&t.shared,handleMouseEvents:t&&t.handleMouseEvents};return fo(this,e=ft(this,e),e,n,"bookmark")},findMarksAt:function(e){var t=[],n=Qe(this,(e=ft(this,e)).line).markedSpans;if(n)for(var r=0;r<n.length;++r){var i=n[r];(null==i.from||i.from<=e.ch)&&(null==i.to||i.to>=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(i,o,l){i=ft(this,i),o=ft(this,o);var s=[],a=i.line;return this.iter(i.line,o.line+1,function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;n++){var r=t[n];null!=r.to&&a==i.line&&i.ch>=r.to||null==r.from&&a!=i.line||null!=r.from&&a==o.line&&r.from>=o.ch||l&&!l(r.marker)||s.push(r.marker.parent||r.marker)}++a}),s},getAllMarks:function(){var r=[];return this.iter(function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;++n)null!=t[n].from&&r.push(t[n].marker)}),r},posFromIndex:function(n){var r,i=this.first,o=this.lineSeparator().length;return this.iter(function(e){var t=e.text.length+o;if(n<t)return r=n,!0;n-=t,++i}),ft(this,lt(i,r))},indexFromPos:function(e){var t=(e=ft(this,e)).ch;if(e.line<this.first||e.ch<0)return 0;var n=this.lineSeparator().length;return this.iter(this.first,e.line,function(e){t+=e.text.length+n}),t},copy:function(e){var t=new vo(et(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft,t.sel=this.sel,t.extend=!1,e&&(t.history.undoDepth=this.history.undoDepth,t.setHistory(this.getHistory())),t},linkedDoc:function(e){e=e||{};var t=this.first,n=this.first+this.size;null!=e.from&&e.from>t&&(t=e.from),null!=e.to&&e.to<n&&(n=e.to);var r=new vo(et(this,t,n),e.mode||this.modeOption,t,this.lineSep,this.direction);return e.sharedHist&&(r.history=this.history),(this.linked||(this.linked=[])).push({doc:r,sharedHist:e.sharedHist}),r.linked=[{doc:this,isParent:!0,sharedHist:e.sharedHist}],function(e,t){for(var n=0;n<t.length;n++){var r,i=t[n],o=i.find(),l=e.clipPos(o.from),s=e.clipPos(o.to);st(l,s)&&(r=fo(e,l,s,i.primary,i.primary.type),i.markers.push(r),r.parent=i)}}(r,go(this)),r},unlinkDoc:function(e){if(e instanceof pl&&(e=e.doc),this.linked)for(var t=0;t<this.linked.length;++t){if(this.linked[t].doc==e){this.linked.splice(t,1),e.unlinkDoc(this),function(o){for(var e=0;e<o.length;e++)!function(e){var t=o[e],n=[t.primary.doc];xi(t.primary.doc,function(e){return n.push(e)});for(var r=0;r<t.markers.length;r++){var i=t.markers[r];-1==B(n,i.doc)&&(i.parent=null,t.markers.splice(r--,1))}}(e)}(go(this));break}}var n;e.history==this.history&&(n=[e.id],xi(e,function(e){return n.push(e.id)},!0),e.history=new Li(null),e.history.done=Hi(this.history.done,n),e.history.undone=Hi(this.history.undone,n))},iterLinkedDocs:function(e){xi(this,e)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(e){return this.lineSep?e.split(this.lineSep):Re(e)},lineSeparator:function(){return this.lineSep||"\n"},setDirection:Vr(function(e){var t;"rtl"!=e&&(e="ltr"),e!=this.direction&&(this.direction=e,this.iter(function(e){return e.order=null}),this.cm&&Br(t=this.cm,function(){Si(t),ir(t)}))})}),vo.prototype.eachLine=vo.prototype.iter;var yo=0;function bo(e){var r=this;if(wo(r),!Le(r,e)&&!bn(r.display,e)){Ne(e),L&&(yo=+new Date);var t=nr(r,e,!0),n=e.dataTransfer.files;if(t&&!r.isReadOnly())if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),l=0,s=function(){++l==i&&Gr(r,function(){var e={from:t=ft(r.doc,t),to:t,text:r.doc.splitLines(o.filter(function(e){return null!=e}).join(r.doc.lineSeparator())),origin:"paste"};qi(r.doc,e),zi(r.doc,di(ft(r.doc,t),ft(r.doc,fi(e))))})()},a=0;a<n.length;a++)!function(e,t){var n;r.options.allowDropFileTypes&&-1==B(r.options.allowDropFileTypes,e.type)?s():((n=new FileReader).onerror=s,n.onload=function(){var e=n.result;/[\x00-\x08\x0e-\x1f]{2}/.test(e)||(o[t]=e),s()},n.readAsText(e))}(n[a],a);else{if(r.state.draggingText&&-1<r.doc.sel.contains(t))return r.state.draggingText(e),void setTimeout(function(){return r.display.input.focus()},20);try{var u,c=e.dataTransfer.getData("Text");if(c){if(r.state.draggingText&&!r.state.draggingText.copy&&(u=r.listSelections()),Gi(r.doc,di(t,t)),u)for(var h=0;h<u.length;++h)to(r.doc,"",u[h].anchor,u[h].head,"drag");r.replaceSelection(c,"around","paste"),r.display.input.focus()}}catch(e){}}}}function wo(e){e.display.dragCursor&&(e.display.lineSpace.removeChild(e.display.dragCursor),e.display.dragCursor=null)}function xo(t){if(document.getElementsByClassName){for(var e=document.getElementsByClassName("CodeMirror"),n=[],r=0;r<e.length;r++){var i=e[r].CodeMirror;i&&n.push(i)}n.length&&n[0].operation(function(){for(var e=0;e<n.length;e++)t(n[e])})}}var Co=!1;function So(){var e;Co||(we(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,xo(Lo)},100))}),we(window,"blur",function(){return xo(vr)}),Co=!0)}function Lo(e){var t=e.display;t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize()}for(var ko={3:"Pause",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",145:"ScrollLock",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",224:"Mod",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"},To=0;To<10;To++)ko[To+48]=ko[To+96]=String(To);for(var Mo=65;Mo<=90;Mo++)ko[Mo]=String.fromCharCode(Mo);for(var No=1;No<=12;No++)ko[No+111]=ko[No+63235]="F"+No;var Ao={};function Oo(e){var t,n,r,i,o=e.split(/-(?!$)/);e=o[o.length-1];for(var l=0;l<o.length-1;l++){var s=o[l];if(/^(cmd|meta|m)$/i.test(s))i=!0;else if(/^a(lt)?$/i.test(s))t=!0;else if(/^(c|ctrl|control)$/i.test(s))n=!0;else{if(!/^s(hift)?$/i.test(s))throw new Error("Unrecognized modifier name: "+s);r=!0}}return t&&(e="Alt-"+e),n&&(e="Ctrl-"+e),i&&(e="Cmd-"+e),r&&(e="Shift-"+e),e}function Do(e){var t={};for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];if(/^(name|fallthrough|(de|at)tach)$/.test(n))continue;if("..."==r){delete e[n];continue}for(var i=q(n.split(" "),Oo),o=0;o<i.length;o++){var l=void 0,s=void 0,l=o==i.length-1?(s=i.join(" "),r):(s=i.slice(0,o+1).join(" "),"..."),a=t[s];if(a){if(a!=l)throw new Error("Inconsistent bindings for "+s)}else t[s]=l}delete e[n]}for(var u in t)e[u]=t[u];return e}function Wo(e,t,n,r){var i=(t=Po(t)).call?t.call(e,r):t[e];if(!1===i)return"nothing";if("..."===i)return"multi";if(null!=i&&n(i))return"handled";if(t.fallthrough){if("[object Array]"!=Object.prototype.toString.call(t.fallthrough))return Wo(e,t.fallthrough,n,r);for(var o=0;o<t.fallthrough.length;o++){var l=Wo(e,t.fallthrough[o],n,r);if(l)return l}}}function Ho(e){var t="string"==typeof e?e:ko[e.keyCode];return"Ctrl"==t||"Alt"==t||"Shift"==t||"Mod"==t}function Fo(e,t,n){var r=e;return t.altKey&&"Alt"!=r&&(e="Alt-"+e),(w?t.metaKey:t.ctrlKey)&&"Ctrl"!=r&&(e="Ctrl-"+e),(w?t.ctrlKey:t.metaKey)&&"Mod"!=r&&(e="Cmd-"+e),!n&&t.shiftKey&&"Shift"!=r&&(e="Shift-"+e),e}function Eo(e,t){if(m&&34==e.keyCode&&e.char)return!1;var n=ko[e.keyCode];return null!=n&&!e.altGraphKey&&(3==e.keyCode&&e.code&&(n=e.code),Fo(n,e,t))}function Po(e){return"string"==typeof e?Ao[e]:e}function Io(t,e){for(var n=t.doc.sel.ranges,r=[],i=0;i<n.length;i++){for(var o=e(n[i]);r.length&&st(o.from,$(r).to)<=0;){var l=r.pop();if(st(l.from,o.from)<0){o.from=l.from;break}}r.push(o)}Br(t,function(){for(var e=r.length-1;0<=e;e--)to(t.doc,"",r[e].from,r[e].to,"+delete");Sr(t)})}function Ro(e,t,n){var r=oe(e.text,t+n,n);return r<0||r>e.text.length?null:r}function zo(e,t,n){var r=Ro(e,t.ch,n);return null==r?null:new lt(t.line,r,n<0?"after":"before")}function Bo(e,t,n,r,i){if(e){"rtl"==t.doc.direction&&(i=-i);var o=ye(n,t.doc.direction);if(o){var l,s,a,u=i<0?$(o):o[0],c=i<0==(1==u.level)?"after":"before";return 0<u.level||"rtl"==t.doc.direction?(l=An(t,n),s=i<0?n.text.length-1:0,a=On(t,l,s).top,s=le(function(e){return On(t,l,e).top==a},i<0==(1==u.level)?u.from:u.to-1,s),"before"==c&&(s=Ro(n,s,1))):s=i<0?u.to:u.from,new lt(r,s,c)}}return new lt(r,i<0?n.text.length:0,i<0?"before":"after")}function Go(t,n,s,e){var a=ye(n,t.doc.direction);if(!a)return zo(n,s,e);s.ch>=n.text.length?(s.ch=n.text.length,s.sticky="before"):s.ch<=0&&(s.ch=0,s.sticky="after");var r=ae(a,s.ch,s.sticky),i=a[r];if("ltr"==t.doc.direction&&i.level%2==0&&(0<e?i.to>s.ch:i.from<s.ch))return zo(n,s,e);function u(e,t){return Ro(n,e instanceof lt?e.ch:e,t)}function o(e){return t.options.lineWrapping?(l=l||An(t,n),_n(t,n,l,e)):{begin:0,end:n.text.length}}var l,c=o("before"==s.sticky?u(s,-1):s.ch);if("rtl"==t.doc.direction||1==i.level){var h=1==i.level==e<0,d=u(s,h?1:-1);if(null!=d&&(h?d<=i.to&&d<=c.end:d>=i.from&&d>=c.begin)){var f=h?"before":"after";return new lt(s.line,d,f)}}function p(e,t,n){for(var r=function(e,t){return t?new lt(s.line,u(e,1),"before"):new lt(s.line,e,"after")};0<=e&&e<a.length;e+=t){var i=a[e],o=0<t==(1!=i.level),l=o?n.begin:u(n.end,-1);if(i.from<=l&&l<i.to)return r(l,o);if(l=o?i.from:u(i.to,-1),n.begin<=l&&l<n.end)return r(l,o)}}var g=p(r+e,e,c);if(g)return g;var m=0<e?c.end:u(c.begin,-1);return null==m||0<e&&m==n.text.length||!(g=p(0<e?0:a.length-1,e,o(m)))?null:g}Ao.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Ao.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Ao.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Ao.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Ao.default=y?Ao.macDefault:Ao.pcDefault;var Uo={selectAll:_i,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),V)},killLine:function(n){return Io(n,function(e){if(e.empty()){var t=Qe(n.doc,e.head.line).text.length;return e.head.ch==t&&e.head.line<n.lastLine()?{from:e.head,to:lt(e.head.line+1,0)}:{from:e.head,to:lt(e.head.line,t)}}return{from:e.from(),to:e.to()}})},deleteLine:function(t){return Io(t,function(e){return{from:lt(e.from().line,0),to:ft(t.doc,lt(e.to().line+1,0))}})},delLineLeft:function(e){return Io(e,function(e){return{from:lt(e.from().line,0),to:e.from()}})},delWrappedLineLeft:function(n){return Io(n,function(e){var t=n.charCoords(e.head,"div").top+5;return{from:n.coordsChar({left:0,top:t},"div"),to:e.from()}})},delWrappedLineRight:function(r){return Io(r,function(e){var t=r.charCoords(e.head,"div").top+5,n=r.coordsChar({left:r.display.lineDiv.offsetWidth+100,top:t},"div");return{from:e.from(),to:n}})},undo:function(e){return e.undo()},redo:function(e){return e.redo()},undoSelection:function(e){return e.undoSelection()},redoSelection:function(e){return e.redoSelection()},goDocStart:function(e){return e.extendSelection(lt(e.firstLine(),0))},goDocEnd:function(e){return e.extendSelection(lt(e.lastLine()))},goLineStart:function(t){return t.extendSelectionsBy(function(e){return Vo(t,e.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(t){return t.extendSelectionsBy(function(e){return Ko(t,e.head)},{origin:"+move",bias:1})},goLineEnd:function(t){return t.extendSelectionsBy(function(e){return function(e,t){var n=Qe(e.doc,t),r=function(e){for(var t;t=Bt(e);)e=t.find(1,!0).line;return e}(n);r!=n&&(t=nt(r));return Bo(!0,e,n,t,-1)}(t,e.head.line)},{origin:"+move",bias:-1})},goLineRight:function(n){return n.extendSelectionsBy(function(e){var t=n.cursorCoords(e.head,"div").top+5;return n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:t},"div")},j)},goLineLeft:function(n){return n.extendSelectionsBy(function(e){var t=n.cursorCoords(e.head,"div").top+5;return n.coordsChar({left:0,top:t},"div")},j)},goLineLeftSmart:function(r){return r.extendSelectionsBy(function(e){var t=r.cursorCoords(e.head,"div").top+5,n=r.coordsChar({left:0,top:t},"div");return n.ch<r.getLine(n.line).search(/\S/)?Ko(r,e.head):n},j)},goLineUp:function(e){return e.moveV(-1,"line")},goLineDown:function(e){return e.moveV(1,"line")},goPageUp:function(e){return e.moveV(-1,"page")},goPageDown:function(e){return e.moveV(1,"page")},goCharLeft:function(e){return e.moveH(-1,"char")},goCharRight:function(e){return e.moveH(1,"char")},goColumnLeft:function(e){return e.moveH(-1,"column")},goColumnRight:function(e){return e.moveH(1,"column")},goWordLeft:function(e){return e.moveH(-1,"word")},goGroupRight:function(e){return e.moveH(1,"group")},goGroupLeft:function(e){return e.moveH(-1,"group")},goWordRight:function(e){return e.moveH(1,"word")},delCharBefore:function(e){return e.deleteH(-1,"codepoint")},delCharAfter:function(e){return e.deleteH(1,"char")},delWordBefore:function(e){return e.deleteH(-1,"word")},delWordAfter:function(e){return e.deleteH(1,"word")},delGroupBefore:function(e){return e.deleteH(-1,"group")},delGroupAfter:function(e){return e.deleteH(1,"group")},indentAuto:function(e){return e.indentSelection("smart")},indentMore:function(e){return e.indentSelection("add")},indentLess:function(e){return e.indentSelection("subtract")},insertTab:function(e){return e.replaceSelection("\t")},insertSoftTab:function(e){for(var t=[],n=e.listSelections(),r=e.options.tabSize,i=0;i<n.length;i++){var o=n[i].from(),l=R(e.getLine(o.line),o.ch,r);t.push(_(r-l%r))}e.replaceSelections(t)},defaultTab:function(e){e.somethingSelected()?e.indentSelection("add"):e.execCommand("insertTab")},transposeChars:function(l){return Br(l,function(){for(var e,t,n,r=l.listSelections(),i=[],o=0;o<r.length;o++){r[o].empty()&&(e=r[o].head,(t=Qe(l.doc,e.line).text)&&(e.ch==t.length&&(e=new lt(e.line,e.ch-1)),0<e.ch?(e=new lt(e.line,e.ch+1),l.replaceRange(t.charAt(e.ch-1)+t.charAt(e.ch-2),lt(e.line,e.ch-2),e,"+transpose")):e.line>l.doc.first&&((n=Qe(l.doc,e.line-1).text)&&(e=new lt(e.line,1),l.replaceRange(t.charAt(0)+l.doc.lineSeparator()+n.charAt(n.length-1),lt(e.line-1,n.length-1),e,"+transpose")))),i.push(new ci(e,e)))}l.setSelections(i)})},newlineAndIndent:function(r){return Br(r,function(){for(var e=r.listSelections(),t=e.length-1;0<=t;t--)r.replaceRange(r.doc.lineSeparator(),e[t].anchor,e[t].head,"+input");e=r.listSelections();for(var n=0;n<e.length;n++)r.indentLine(e[n].from().line,null,!0);Sr(r)})},openLine:function(e){return e.replaceSelection("\n","start")},toggleOverwrite:function(e){return e.toggleOverwrite()}};function Vo(e,t){var n=Qe(e.doc,t),r=Ut(n);return r!=n&&(t=nt(r)),Bo(!0,e,r,t,1)}function Ko(e,t){var n=Vo(e,t.line),r=Qe(e.doc,n.line),i=ye(r,e.doc.direction);if(i&&0!=i[0].level)return n;var o=Math.max(n.ch,r.text.search(/\S/)),l=t.line==n.line&&t.ch<=o&&t.ch;return lt(n.line,l?0:o,n.sticky)}function jo(e,t,n){if("string"==typeof t&&!(t=Uo[t]))return!1;e.display.input.ensurePolled();var r=e.display.shift,i=!1;try{e.isReadOnly()&&(e.state.suppressEdits=!0),n&&(e.display.shift=!1),i=t(e)!=U}finally{e.display.shift=r,e.state.suppressEdits=!1}return i}var Xo=new z;function Yo(e,t,n,r){var i=e.state.keySeq;if(i){if(Ho(t))return"handled";if(/\'$/.test(t)?e.state.keySeq=null:Xo.set(50,function(){e.state.keySeq==i&&(e.state.keySeq=null,e.display.input.reset())}),_o(e,i+" "+t,n,r))return!0}return _o(e,t,n,r)}function _o(e,t,n,r){var i=function(e,t,n){for(var r=0;r<e.state.keyMaps.length;r++){var i=Wo(t,e.state.keyMaps[r],n,e);if(i)return i}return e.options.extraKeys&&Wo(t,e.options.extraKeys,n,e)||Wo(t,e.options.keyMap,n,e)}(e,t,r);return"multi"==i&&(e.state.keySeq=t),"handled"==i&&un(e,"keyHandled",e,t,n),"handled"!=i&&"multi"!=i||(Ne(n),fr(e)),!!i}function $o(t,e){var n=Eo(e,!0);return!!n&&(e.shiftKey&&!t.state.keySeq?Yo(t,"Shift-"+n,e,function(e){return jo(t,e,!0)})||Yo(t,n,e,function(e){if("string"==typeof e?/^go[A-Z]/.test(e):e.motion)return jo(t,e)}):Yo(t,n,e,function(e){return jo(t,e)}))}var qo=null;function Zo(e){var t,n,r,i=this;function o(e){18!=e.keyCode&&e.altKey||(T(r,"CodeMirror-crosshair"),Ce(document,"keyup",o),Ce(document,"mouseover",o))}e.target&&e.target!=i.display.input.getField()||(i.curOp.focus=W(),Le(i,e)||(L&&x<11&&27==e.keyCode&&(e.returnValue=!1),t=e.keyCode,i.display.shift=16==t||e.shiftKey,n=$o(i,e),m&&(qo=n?t:null,!n&&88==t&&!Be&&(y?e.metaKey:e.ctrlKey)&&i.replaceSelection("",null,"cut")),g&&!y&&!n&&46==t&&e.shiftKey&&!e.ctrlKey&&document.execCommand&&document.execCommand("cut"),18!=t||/\bCodeMirror-crosshair\b/.test(i.display.lineDiv.className)||(H(r=i.display.lineDiv,"CodeMirror-crosshair"),we(document,"keyup",o),we(document,"mouseover",o))))}function Qo(e){16==e.keyCode&&(this.doc.sel.shift=!1),Le(this,e)}function Jo(e){var t=this;if(!(e.target&&e.target!=t.display.input.getField()||bn(t.display,e)||Le(t,e)||e.ctrlKey&&!e.altKey||y&&e.metaKey)){var n,r,i=e.keyCode,o=e.charCode;if(m&&i==qo)return qo=null,void Ne(e);m&&(!e.which||e.which<10)&&$o(t,e)||"\b"!=(n=String.fromCharCode(null==o?i:o))&&(Yo(r=t,"'"+n+"'",e,function(e){return jo(r,e,!0)})||t.display.input.onKeyPress(e))}}var el,tl,nl=function(e,t,n){this.time=e,this.pos=t,this.button=n};function rl(e){var t,n,r,i,o,l,s=this,a=s.display;Le(s,e)||a.activeTouch&&a.input.supportsTouch()||(a.input.ensurePolled(),a.shift=e.shiftKey,bn(a,e)?v||(a.scroller.draggable=!1,setTimeout(function(){return a.scroller.draggable=!0},100)):ll(s,e)||(t=nr(s,e),n=He(e),r=t?(i=t,o=n,l=+new Date,tl&&tl.compare(l,i,o)?(el=tl=null,"triple"):el&&el.compare(l,i,o)?(tl=new nl(l,i,o),el=null,"double"):(el=new nl(l,i,o),tl=null,"single")):"single",window.focus(),1==n&&s.state.selectingText&&s.state.selectingText(e),t&&function(n,e,r,t,i){var o="Click";"double"==t?o="Double"+o:"triple"==t&&(o="Triple"+o);return Yo(n,Fo(o=(1==e?"Left":2==e?"Middle":"Right")+o,i),i,function(e){if("string"==typeof e&&(e=Uo[e]),!e)return!1;var t=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),t=e(n,r)!=U}finally{n.state.suppressEdits=!1}return t})}(s,n,t,r,e)||(1==n?t?function(e,t,n,r){L?setTimeout(P(pr,e),0):e.curOp.focus=W();var i,o=function(e,t,n){var r=e.getOption("configureMouse"),i=r?r(e,t,n):{};{var o;null==i.unit&&(o=f?n.shiftKey&&n.metaKey:n.altKey,i.unit=o?"rectangle":"single"==t?"char":"double"==t?"word":"line")}null!=i.extend&&!e.doc.extend||(i.extend=e.doc.extend||n.shiftKey);null==i.addNew&&(i.addNew=y?n.metaKey:n.ctrlKey);null==i.moveOnDrag&&(i.moveOnDrag=!(y?n.altKey:n.ctrlKey));return i}(e,n,r),l=e.doc.sel;(e.options.dragDrop&&Pe&&!e.isReadOnly()&&"single"==n&&-1<(i=l.contains(t))&&(st((i=l.ranges[i]).from(),t)<0||0<t.xRel)&&(0<st(i.to(),t)||t.xRel<0)?function(t,n,r,i){var o=t.display,l=!1,s=Gr(t,function(e){v&&(o.scroller.draggable=!1),t.state.draggingText=!1,t.state.delayingBlurEvent&&(t.hasFocus()?t.state.delayingBlurEvent=!1:gr(t)),Ce(o.wrapper.ownerDocument,"mouseup",s),Ce(o.wrapper.ownerDocument,"mousemove",a),Ce(o.scroller,"dragstart",u),Ce(o.scroller,"drop",s),l||(Ne(e),i.addNew||Ei(t.doc,r,null,null,i.extend),v&&!c||L&&9==x?setTimeout(function(){o.wrapper.ownerDocument.body.focus({preventScroll:!0}),o.input.focus()},20):o.input.focus())}),a=function(e){l=l||10<=Math.abs(n.clientX-e.clientX)+Math.abs(n.clientY-e.clientY)},u=function(){return l=!0};v&&(o.scroller.draggable=!0);(t.state.draggingText=s).copy=!i.moveOnDrag,we(o.wrapper.ownerDocument,"mouseup",s),we(o.wrapper.ownerDocument,"mousemove",a),we(o.scroller,"dragstart",u),we(o.scroller,"drop",s),t.state.delayingBlurEvent=!0,setTimeout(function(){return o.input.focus()},20),o.scroller.dragDrop&&o.scroller.dragDrop()}:function(m,e,v,y){L&&gr(m);var l=m.display,b=m.doc;Ne(e);var w,x,C=b.sel,t=C.ranges;y.addNew&&!y.extend?(x=b.sel.contains(v),w=-1<x?t[x]:new ci(v,v)):(w=b.sel.primary(),x=b.sel.primIndex);{var n;"rectangle"==y.unit?(y.addNew||(w=new ci(v,v)),v=nr(m,e,!0,!0),x=-1):(n=il(m,v,y.unit),w=y.extend?Fi(w,n.anchor,n.head,y.extend):n)}y.addNew?-1==x?(x=t.length,Bi(b,hi(m,t.concat([w]),x),{scroll:!1,origin:"*mouse"})):1<t.length&&t[x].empty()&&"char"==y.unit&&!y.extend?(Bi(b,hi(m,t.slice(0,x).concat(t.slice(x+1)),0),{scroll:!1,origin:"*mouse"}),C=b.sel):Ii(b,x,w,K):(Bi(b,new ui([w],x=0),K),C=b.sel);var S=v;function s(e){if(0!=st(S,e))if(S=e,"rectangle"==y.unit){for(var t=[],n=m.options.tabSize,r=R(Qe(b,v.line).text,v.ch,n),i=R(Qe(b,e.line).text,e.ch,n),o=Math.min(r,i),l=Math.max(r,i),s=Math.min(v.line,e.line),a=Math.min(m.lastLine(),Math.max(v.line,e.line));s<=a;s++){var u=Qe(b,s).text,c=X(u,o,n);o==l?t.push(new ci(lt(s,c),lt(s,c))):u.length>c&&t.push(new ci(lt(s,c),lt(s,X(u,l,n))))}t.length||t.push(new ci(v,v)),Bi(b,hi(m,C.ranges.slice(0,x).concat(t),x),{origin:"*mouse",scroll:!1}),m.scrollIntoView(e)}else{var h,d=w,f=il(m,e,y.unit),p=d.anchor,p=0<st(f.anchor,p)?(h=f.head,ht(d.from(),f.anchor)):(h=f.anchor,ct(d.to(),f.head)),g=C.ranges.slice(0);g[x]=function(e,t){var n=t.anchor,r=t.head,i=Qe(e.doc,n.line);if(0==st(n,r)&&n.sticky==r.sticky)return t;var o=ye(i);if(!o)return t;var l=ae(o,n.ch,n.sticky),s=o[l];if(s.from!=n.ch&&s.to!=n.ch)return t;var a,u=l+(s.from==n.ch==(1!=s.level)?0:1);if(0==u||u==o.length)return t;{var c,h;a=r.line!=n.line?0<(r.line-n.line)*("ltr"==e.doc.direction?1:-1):(c=ae(o,r.ch,r.sticky),h=c-l||(r.ch-n.ch)*(1==s.level?-1:1),c==u-1||c==u?h<0:0<h)}var d=o[u+(a?-1:0)],f=a==(1==d.level),p=f?d.from:d.to,g=f?"after":"before";return n.ch==p&&n.sticky==g?t:new ci(new lt(n.line,p,g),r)}(m,new ci(ft(b,p),h)),Bi(b,hi(m,g,x),K)}}var a=l.wrapper.getBoundingClientRect(),u=0;function r(e){m.state.selectingText=!1,u=1/0,e&&(Ne(e),l.input.focus()),Ce(l.wrapper.ownerDocument,"mousemove",i),Ce(l.wrapper.ownerDocument,"mouseup",o),b.history.lastSelOrigin=null}var i=Gr(m,function(e){(0!==e.buttons&&He(e)?function e(t){var n,r,i=++u,o=nr(m,t,!0,"rectangle"==y.unit);o&&(0!=st(o,S)?(m.curOp.focus=W(),s(o),n=wr(l,b),(o.line>=n.to||o.line<n.from)&&setTimeout(Gr(m,function(){u==i&&e(t)}),150)):(r=t.clientY<a.top?-20:t.clientY>a.bottom?20:0)&&setTimeout(Gr(m,function(){u==i&&(l.scroller.scrollTop+=r,e(t))}),50))}:r)(e)}),o=Gr(m,r);m.state.selectingText=o,we(l.wrapper.ownerDocument,"mousemove",i),we(l.wrapper.ownerDocument,"mouseup",o)})(e,r,t,o)}(s,t,r,e):We(e)==a.scroller&&Ne(e):2==n?(t&&Ei(s.doc,t),setTimeout(function(){return a.input.focus()},20)):3==n&&(C?s.display.input.onContextMenu(e):gr(s)))))}function il(e,t,n){if("char"==n)return new ci(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new ci(lt(t.line,0),ft(e.doc,lt(t.line+1,0)));var r=n(e,t);return new ci(r.from,r.to)}function ol(e,t,n,r){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(e){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&&Ne(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!Te(e,n))return Oe(t);o-=s.top-l.viewOffset;for(var a=0;a<e.display.gutterSpecs.length;++a){var u=l.gutters.childNodes[a];if(u&&u.getBoundingClientRect().right>=i)return Se(e,n,e,rt(e.doc,o),e.display.gutterSpecs[a].className,t),Oe(t)}}function ll(e,t){return ol(e,t,"gutterClick",!0)}function sl(e,t){var n,r;bn(e.display,t)||(r=t,Te(n=e,"gutterContextMenu")&&ol(n,r,"gutterContextMenu",!1))||Le(e,t,"contextmenu")||C||e.display.input.onContextMenu(t)}function al(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),Pn(e)}nl.prototype.compare=function(e,t,n){return this.time+400>e&&0==st(t,this.pos)&&n==this.button};var ul={toString:function(){return"CodeMirror.Init"}},cl={},hl={};function dl(e,t,n){var r,i;!t!=!(n&&n!=ul)&&(r=e.display.dragFunctions,(i=t?we:Ce)(e.display.scroller,"dragstart",r.start),i(e.display.scroller,"dragenter",r.enter),i(e.display.scroller,"dragover",r.over),i(e.display.scroller,"dragleave",r.leave),i(e.display.scroller,"drop",r.drop))}function fl(e){e.options.lineWrapping?(H(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(T(e.display.wrapper,"CodeMirror-wrap"),_t(e)),tr(e),ir(e),Pn(e),setTimeout(function(){return Hr(e)},100)}function pl(e,t){var n=this;if(!(this instanceof pl))return new pl(e,t);this.options=t=t?I(t):{},I(cl,t,!1);var r=t.value;"string"==typeof r?r=new vo(r,t.mode,null,t.lineSeparator,t.direction):t.mode&&(r.modeOption=t.mode),this.doc=r;var i=new pl.inputStyles[t.inputStyle](this),o=this.display=new ri(e,r,i,t);for(var l in al(o.wrapper.CodeMirror=this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Pr(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new z,keySeq:null,specialChars:null},t.autofocus&&!d&&o.input.focus(),L&&x<11&&setTimeout(function(){return n.display.input.reset(!0)},20),function(i){var o=i.display;we(o.scroller,"mousedown",Gr(i,rl)),we(o.scroller,"dblclick",L&&x<11?Gr(i,function(e){var t,n;Le(i,e)||(!(t=nr(i,e))||ll(i,e)||bn(i.display,e)||(Ne(e),n=i.findWordAt(t),Ei(i.doc,n.anchor,n.head)))}):function(e){return Le(i,e)||Ne(e)});we(o.scroller,"contextmenu",function(e){return sl(i,e)}),we(o.input.getField(),"contextmenu",function(e){o.scroller.contains(e.target)||sl(i,e)});var n,r={end:0};function l(){o.activeTouch&&(n=setTimeout(function(){return o.activeTouch=null},1e3),(r=o.activeTouch).end=+new Date)}function s(e,t){if(null==t.left)return 1;var n=t.left-e.left,r=t.top-e.top;return 400<n*n+r*r}we(o.scroller,"touchstart",function(e){var t;Le(i,e)||function(e){if(1==e.touches.length){var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}}(e)||ll(i,e)||(o.input.ensurePolled(),clearTimeout(n),t=+new Date,o.activeTouch={start:t,moved:!1,prev:t-r.end<=300?r:null},1==e.touches.length&&(o.activeTouch.left=e.touches[0].pageX,o.activeTouch.top=e.touches[0].pageY))}),we(o.scroller,"touchmove",function(){o.activeTouch&&(o.activeTouch.moved=!0)}),we(o.scroller,"touchend",function(e){var t,n,r=o.activeTouch;r&&!bn(o,e)&&null!=r.left&&!r.moved&&new Date-r.start<300&&(t=i.coordsChar(o.activeTouch,"page"),n=!r.prev||s(r,r.prev)?new ci(t,t):!r.prev.prev||s(r,r.prev.prev)?i.findWordAt(t):new ci(lt(t.line,0),ft(i.doc,lt(t.line+1,0))),i.setSelection(n.anchor,n.head),i.focus(),Ne(e)),l()}),we(o.scroller,"touchcancel",l),we(o.scroller,"scroll",function(){o.scroller.clientHeight&&(Mr(i,o.scroller.scrollTop),Ar(i,o.scroller.scrollLeft,!0),Se(i,"scroll",i))}),we(o.scroller,"mousewheel",function(e){return ai(i,e)}),we(o.scroller,"DOMMouseScroll",function(e){return ai(i,e)}),we(o.wrapper,"scroll",function(){return o.wrapper.scrollTop=o.wrapper.scrollLeft=0}),o.dragFunctions={enter:function(e){Le(i,e)||De(e)},over:function(e){var t,n,r;Le(i,e)||((r=nr(t=i,e))&&(hr(t,r,n=document.createDocumentFragment()),t.display.dragCursor||(t.display.dragCursor=O("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),t.display.lineSpace.insertBefore(t.display.dragCursor,t.display.cursorDiv)),N(t.display.dragCursor,n)),De(e))},start:function(e){return t=i,n=e,void(L&&(!t.state.draggingText||new Date-yo<100)?De(n):Le(t,n)||bn(t.display,n)||(n.dataTransfer.setData("Text",t.getSelection()),n.dataTransfer.effectAllowed="copyMove",n.dataTransfer.setDragImage&&!c&&((r=O("img",null,null,"position: fixed; left: 0; top: 0;")).src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",m&&(r.width=r.height=1,t.display.wrapper.appendChild(r),r._top=r.offsetTop),n.dataTransfer.setDragImage(r,0,0),m&&r.parentNode.removeChild(r))));var t,n,r},drop:Gr(i,bo),leave:function(e){Le(i,e)||wo(i)}};var e=o.input.getField();we(e,"keyup",function(e){return Qo.call(i,e)}),we(e,"keydown",Gr(i,Zo)),we(e,"keypress",Gr(i,Jo)),we(e,"focus",function(e){return mr(i,e)}),we(e,"blur",function(e){return vr(i,e)})}(this),So(),Rr(this),this.curOp.forceUpdate=!0,Ci(this,r),t.autofocus&&!d||this.hasFocus()?setTimeout(function(){n.hasFocus()&&!n.state.focused&&mr(n)},20):vr(this),hl)hl.hasOwnProperty(l)&&hl[l](this,t[l],ul);Jr(this),t.finishInit&&t.finishInit(this);for(var s=0;s<gl.length;++s)gl[s](this);zr(this),v&&t.lineWrapping&&"optimizelegibility"==getComputedStyle(o.lineDiv).textRendering&&(o.lineDiv.style.textRendering="auto")}pl.defaults=cl,pl.optionHandlers=hl;var gl=[];function ml(e,t,n,r){var i,o=e.doc;null==n&&(n="add"),"smart"==n&&(o.mode.indent?i=bt(e,t).state:n="prev");var l=e.options.tabSize,s=Qe(o,t),a=R(s.text,null,l);s.stateAfter&&(s.stateAfter=null);var u,c=s.text.match(/^\s*/)[0];if(r||/\S/.test(s.text)){if("smart"==n&&((u=o.mode.indent(i,s.text.slice(c.length),s.text))==U||150<u)){if(!r)return;n="prev"}}else u=0,n="not";"prev"==n?u=t>o.first?R(Qe(o,t-1).text,null,l):0:"add"==n?u=a+e.options.indentUnit:"subtract"==n?u=a-e.options.indentUnit:"number"==typeof n&&(u=a+n),u=Math.max(0,u);var h="",d=0;if(e.options.indentWithTabs)for(var f=Math.floor(u/l);f;--f)d+=l,h+="\t";if(d<u&&(h+=_(u-d)),h!=c)return to(o,h,lt(t,0),lt(t,c.length),"+input"),!(s.stateAfter=null);for(var p=0;p<o.sel.ranges.length;p++){var g=o.sel.ranges[p];if(g.head.line==t&&g.head.ch<c.length){var m=lt(t,c.length);Ii(o,p,new ci(m,m));break}}}pl.defineInitHook=function(e){return gl.push(e)};var vl=null;function yl(e){vl=e}function bl(e,t,n,r,i){var o=e.doc;e.display.shift=!1,r=r||o.sel;var l=new Date-200,s="paste"==i||e.state.pasteIncoming>l,a=Re(t),u=null;if(s&&1<r.ranges.length)if(vl&&vl.text.join("\n")==t){if(r.ranges.length%vl.text.length==0){u=[];for(var c=0;c<vl.text.length;c++)u.push(o.splitLines(vl.text[c]))}}else a.length==r.ranges.length&&e.options.pasteLinesPerSelection&&(u=q(a,function(e){return[e]}));for(var h=e.curOp.updateInput,d=r.ranges.length-1;0<=d;d--){var f=r.ranges[d],p=f.from(),g=f.to();f.empty()&&(n&&0<n?p=lt(p.line,p.ch-n):e.state.overwrite&&!s?g=lt(g.line,Math.min(Qe(o,g.line).text.length,g.ch+$(a).length)):s&&vl&&vl.lineWise&&vl.text.join("\n")==a.join("\n")&&(p=g=lt(p.line,0)));var m={from:p,to:g,text:u?u[d%u.length]:a,origin:i||(s?"paste":e.state.cutIncoming>l?"cut":"+input")};qi(e.doc,m),un(e,"inputRead",e,m)}t&&!s&&xl(e,t),Sr(e),e.curOp.updateInput<2&&(e.curOp.updateInput=h),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function wl(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");return n&&(e.preventDefault(),t.isReadOnly()||t.options.disableInput||Br(t,function(){return bl(t,n,0,null,"paste")}),1)}function xl(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;0<=r;r--){var i=n.ranges[r];if(!(100<i.head.ch||r&&n.ranges[r-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s<o.electricChars.length;s++)if(-1<t.indexOf(o.electricChars.charAt(s))){l=ml(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Qe(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=ml(e,i.head.line,"smart"));l&&un(e,"electricInput",e,i.head.line)}}}function Cl(e){for(var t=[],n=[],r=0;r<e.doc.sel.ranges.length;r++){var i=e.doc.sel.ranges[r].head.line,o={anchor:lt(i,0),head:lt(i+1,0)};n.push(o),t.push(e.getRange(o.anchor,o.head))}return{text:t,ranges:n}}function Sl(e,t,n,r){e.setAttribute("autocorrect",n?"":"off"),e.setAttribute("autocapitalize",r?"":"off"),e.setAttribute("spellcheck",!!t)}function Ll(){var e=O("textarea",null,null,"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"),t=O("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return v?e.style.width="1000px":e.setAttribute("wrap","off"),a&&(e.style.border="1px solid black"),Sl(e),t}function kl(i,o,l,s,a){var e=o,t=l,u=Qe(i,o.line),c=a&&"rtl"==i.direction?-l:l;function n(e){var t,n,r;if(null==(n="codepoint"==s?(t=u.text.charCodeAt(o.ch+(0<s?0:-1)),isNaN(t)?null:new lt(o.line,Math.max(0,Math.min(u.text.length,o.ch+l*(55296<=t&&t<56320?2:1))),-l)):a?Go(i.cm,u,o,l):zo(u,o,l))){if(e||(r=o.line+c)<i.first||r>=i.first+i.size||(o=new lt(r,o.ch,o.sticky),!(u=Qe(i,r))))return;o=Bo(a,i.cm,u,o.line,c)}else o=n;return 1}if("char"==s||"codepoint"==s)n();else if("column"==s)n(!0);else if("word"==s||"group"==s)for(var r=null,h="group"==s,d=i.cm&&i.cm.getHelper(o,"wordChars"),f=!0;!(l<0)||n(!f);f=!1){var p=u.text.charAt(o.ch)||"\n",g=te(p,d)?"w":h&&"\n"==p?"n":!h||/\s/.test(p)?null:"p";if(!h||f||g||(g="s"),r&&r!=g){l<0&&(l=1,n(),o.sticky="after");break}if(g&&(r=g),0<l&&!n(!f))break}var m=Xi(i,o,e,t,!0);return at(e,m)&&(m.hitSide=!0),m}function Tl(e,t,n,r){var i,o,l,s,a=e.doc,u=t.left;for("page"==r?(i=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),o=Math.max(i-.5*qn(e.display),3),l=(0<n?t.bottom:t.top)+n*o):"line"==r&&(l=0<n?t.bottom+3:t.top-3);(s=Xn(e,u,l)).outside;){if(n<0?l<=0:l>=a.height){s.hitSide=!0;break}l+=5*n}return s}function Ml(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new z,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null}function Nl(e,t){var n=Nn(e,t.line);if(!n||n.hidden)return null;var r=Qe(e.doc,t.line),i=Tn(n,r,t.line),o=ye(r,e.doc.direction),l="left";o&&(l=ae(o,t.ch)%2?"right":"left");var s=Hn(i.map,t.ch,l);return s.offset="right"==s.collapse?s.end:s.start,s}function Al(e,t){return t&&(e.bad=!0),e}function Ol(e,t,n){var r;if(t==e.display.lineDiv){if(!(r=e.display.lineDiv.childNodes[n]))return Al(e.clipPos(lt(e.display.viewTo-1)),!0);t=null,n=0}else for(r=t;;r=r.parentNode){if(!r||r==e.display.lineDiv)return null;if(r.parentNode&&r.parentNode==e.display.lineDiv)break}for(var i=0;i<e.display.view.length;i++){var o=e.display.view[i];if(o.node==r)return function(u,e,t){var n=u.text.firstChild,r=!1;if(!e||!D(n,e))return Al(lt(nt(u.line),0),!0);if(e==n&&(r=!0,e=n.childNodes[t],t=0,!e)){var i=u.rest?$(u.rest):u.line;return Al(lt(nt(i),i.text.length),r)}var o=3==e.nodeType?e:null,l=e;o||1!=e.childNodes.length||3!=e.firstChild.nodeType||(o=e.firstChild,t=t&&o.nodeValue.length);for(;l.parentNode!=n;)l=l.parentNode;var c=u.measure,h=c.maps;function s(e,t,n){for(var r=-1;r<(h?h.length:0);r++)for(var i=r<0?c.map:h[r],o=0;o<i.length;o+=3){var l=i[o+2];if(l==e||l==t){var s=nt(r<0?u.line:u.rest[r]),a=i[o]+n;return(n<0||l!=e)&&(a=i[o+(n?1:0)]),lt(s,a)}}}var a=s(o,l,t);if(a)return Al(a,r);for(var d=l.nextSibling,f=o?o.nodeValue.length-t:0;d;d=d.nextSibling){if(a=s(d,d.firstChild,0))return Al(lt(a.line,a.ch-f),r);f+=d.textContent.length}for(var p=l.previousSibling,g=t;p;p=p.previousSibling){if(a=s(p,p.firstChild,-1))return Al(lt(a.line,a.ch+g),r);g+=p.textContent.length}}(o,t,n)}}Ml.prototype.init=function(e){var t=this,l=this,s=l.cm,a=l.div=e.lineDiv;function u(e){for(var t=e.target;t;t=t.parentNode){if(t==a)return 1;if(/\bCodeMirror-(?:line)?widget\b/.test(t.className))break}}function n(e){if(u(e)&&!Le(s,e)){if(s.somethingSelected())yl({lineWise:!1,text:s.getSelections()}),"cut"==e.type&&s.replaceSelection("",null,"cut");else{if(!s.options.lineWiseCopyCut)return;var t=Cl(s);yl({lineWise:!0,text:t.text}),"cut"==e.type&&s.operation(function(){s.setSelections(t.ranges,0,V),s.replaceSelection("",null,"cut")})}if(e.clipboardData){e.clipboardData.clearData();var n=vl.text.join("\n");if(e.clipboardData.setData("Text",n),e.clipboardData.getData("Text")==n)return void e.preventDefault()}var r=Ll(),i=r.firstChild;s.display.lineSpace.insertBefore(r,s.display.lineSpace.firstChild),i.value=vl.text.join("\n");var o=document.activeElement;E(i),setTimeout(function(){s.display.lineSpace.removeChild(r),o.focus(),o==a&&l.showPrimarySelection()},50)}}Sl(a,s.options.spellcheck,s.options.autocorrect,s.options.autocapitalize),we(a,"paste",function(e){!u(e)||Le(s,e)||wl(e,s)||x<=11&&setTimeout(Gr(s,function(){return t.updateFromDOM()}),20)}),we(a,"compositionstart",function(e){t.composing={data:e.data,done:!1}}),we(a,"compositionupdate",function(e){t.composing||(t.composing={data:e.data,done:!1})}),we(a,"compositionend",function(e){t.composing&&(e.data!=t.composing.data&&t.readFromDOMSoon(),t.composing.done=!0)}),we(a,"touchstart",function(){return l.forceCompositionEnd()}),we(a,"input",function(){t.composing||t.readFromDOMSoon()}),we(a,"copy",n),we(a,"cut",n)},Ml.prototype.screenReaderLabelChanged=function(e){e?this.div.setAttribute("aria-label",e):this.div.removeAttribute("aria-label")},Ml.prototype.prepareSelection=function(){var e=cr(this.cm,!1);return e.focus=document.activeElement==this.div,e},Ml.prototype.showSelection=function(e,t){e&&this.cm.display.view.length&&((e.focus||t)&&this.showPrimarySelection(),this.showMultipleSelections(e))},Ml.prototype.getSelection=function(){return this.cm.display.wrapper.ownerDocument.getSelection()},Ml.prototype.showPrimarySelection=function(){var e=this.getSelection(),t=this.cm,n=t.doc.sel.primary(),r=n.from(),i=n.to();if(t.display.viewTo==t.display.viewFrom||r.line>=t.display.viewTo||i.line<t.display.viewFrom)e.removeAllRanges();else{var o=Ol(t,e.anchorNode,e.anchorOffset),l=Ol(t,e.focusNode,e.focusOffset);if(!o||o.bad||!l||l.bad||0!=st(ht(o,l),r)||0!=st(ct(o,l),i)){var s,a,u=t.display.view,c=r.line>=t.display.viewFrom&&Nl(t,r)||{node:u[0].measure.map[2],offset:0},h=i.line<t.display.viewTo&&Nl(t,i);if(h||(h={node:(a=(s=u[u.length-1].measure).maps?s.maps[s.maps.length-1]:s.map)[a.length-1],offset:a[a.length-2]-a[a.length-3]}),c&&h){var d,f=e.rangeCount&&e.getRangeAt(0);try{d=k(c.node,c.offset,h.offset,h.node)}catch(e){}d&&(!g&&t.state.focused?(e.collapse(c.node,c.offset),d.collapsed||(e.removeAllRanges(),e.addRange(d))):(e.removeAllRanges(),e.addRange(d)),f&&null==e.anchorNode?e.addRange(f):g&&this.startGracePeriod()),this.rememberSelection()}else e.removeAllRanges()}}},Ml.prototype.startGracePeriod=function(){var e=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){e.gracePeriod=!1,e.selectionChanged()&&e.cm.operation(function(){return e.cm.curOp.selectionChanged=!0})},20)},Ml.prototype.showMultipleSelections=function(e){N(this.cm.display.cursorDiv,e.cursors),N(this.cm.display.selectionDiv,e.selection)},Ml.prototype.rememberSelection=function(){var e=this.getSelection();this.lastAnchorNode=e.anchorNode,this.lastAnchorOffset=e.anchorOffset,this.lastFocusNode=e.focusNode,this.lastFocusOffset=e.focusOffset},Ml.prototype.selectionInEditor=function(){var e=this.getSelection();if(!e.rangeCount)return!1;var t=e.getRangeAt(0).commonAncestorContainer;return D(this.div,t)},Ml.prototype.focus=function(){"nocursor"!=this.cm.options.readOnly&&(this.selectionInEditor()&&document.activeElement==this.div||this.showSelection(this.prepareSelection(),!0),this.div.focus())},Ml.prototype.blur=function(){this.div.blur()},Ml.prototype.getField=function(){return this.div},Ml.prototype.supportsTouch=function(){return!0},Ml.prototype.receivedFocus=function(){var t=this;this.selectionInEditor()?this.pollSelection():Br(this.cm,function(){return t.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,function e(){t.cm.state.focused&&(t.pollSelection(),t.polling.set(t.cm.options.pollInterval,e))})},Ml.prototype.selectionChanged=function(){var e=this.getSelection();return e.anchorNode!=this.lastAnchorNode||e.anchorOffset!=this.lastAnchorOffset||e.focusNode!=this.lastFocusNode||e.focusOffset!=this.lastFocusOffset},Ml.prototype.pollSelection=function(){if(null==this.readDOMTimeout&&!this.gracePeriod&&this.selectionChanged()){var e,t,n=this.getSelection(),r=this.cm;if(h&&l&&this.cm.display.gutterSpecs.length&&function(e){for(var t=e;t;t=t.parentNode)if(/CodeMirror-gutter-wrapper/.test(t.className))return!0;return!1}(n.anchorNode))return this.cm.triggerOnKeyDown({type:"keydown",keyCode:8,preventDefault:Math.abs}),this.blur(),void this.focus();this.composing||(this.rememberSelection(),e=Ol(r,n.anchorNode,n.anchorOffset),t=Ol(r,n.focusNode,n.focusOffset),e&&t&&Br(r,function(){Bi(r.doc,di(e,t),V),(e.bad||t.bad)&&(r.curOp.selectionChanged=!0)}))}},Ml.prototype.pollContent=function(){null!=this.readDOMTimeout&&(clearTimeout(this.readDOMTimeout),this.readDOMTimeout=null);var e,t,n,r=this.cm,i=r.display,o=r.doc.sel.primary(),l=o.from(),s=o.to();if(0==l.ch&&l.line>r.firstLine()&&(l=lt(l.line-1,Qe(r.doc,l.line-1).length)),s.ch==Qe(r.doc,s.line).text.length&&s.line<r.lastLine()&&(s=lt(s.line+1,0)),l.line<i.viewFrom||s.line>i.viewTo-1)return!1;n=l.line==i.viewFrom||0==(e=rr(r,l.line))?(t=nt(i.view[0].line),i.view[0].node):(t=nt(i.view[e].line),i.view[e-1].node.nextSibling);var a,u=rr(r,s.line),c=u==i.view.length-1?(a=i.viewTo-1,i.lineDiv.lastChild):(a=nt(i.view[u+1].line)-1,i.view[u+1].node.previousSibling);if(!n)return!1;for(var h=r.doc.splitLines(function(u,e,t,c,h){var n="",d=!1,f=u.doc.lineSeparator(),p=!1;function g(){d&&(n+=f,p&&(n+=f),d=p=!1)}function m(e){e&&(g(),n+=e)}for(;!function e(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)return void m(n);var r,i=t.getAttribute("cm-marker");if(i){var o=u.findMarks(lt(c,0),lt(h+1,0),(a=+i,function(e){return e.id==a}));return void(o.length&&(r=o[0].find(0))&&m(Je(u.doc,r.from,r.to).join(f)))}if("false"==t.getAttribute("contenteditable"))return;var l=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;l&&g();for(var s=0;s<t.childNodes.length;s++)e(t.childNodes[s]);/^(pre|p)$/i.test(t.nodeName)&&(p=!0),l&&(d=!0)}else 3==t.nodeType&&m(t.nodeValue.replace(/\u200b/g,"").replace(/\u00a0/g," "));var a}(e),e!=t;)e=e.nextSibling,p=!1;return n}(r,n,c,t,a)),d=Je(r.doc,lt(t,0),lt(a,Qe(r.doc,a).text.length));1<h.length&&1<d.length;)if($(h)==$(d))h.pop(),d.pop(),a--;else{if(h[0]!=d[0])break;h.shift(),d.shift(),t++}for(var f=0,p=0,g=h[0],m=d[0],v=Math.min(g.length,m.length);f<v&&g.charCodeAt(f)==m.charCodeAt(f);)++f;for(var y=$(h),b=$(d),w=Math.min(y.length-(1==h.length?f:0),b.length-(1==d.length?f:0));p<w&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)++p;if(1==h.length&&1==d.length&&t==l.line)for(;f&&f>l.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)f--,p++;h[h.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),h[0]=h[0].slice(f).replace(/\u200b+$/,"");var x=lt(t,f),C=lt(a,d.length?$(d).length-p:0);return 1<h.length||h[0]||st(x,C)?(to(r.doc,h,x,C,"+input"),!0):void 0},Ml.prototype.ensurePolled=function(){this.forceCompositionEnd()},Ml.prototype.reset=function(){this.forceCompositionEnd()},Ml.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Ml.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},Ml.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||Br(this.cm,function(){return ir(e.cm)})},Ml.prototype.setUneditable=function(e){e.contentEditable="false"},Ml.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Gr(this.cm,bl)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Ml.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Ml.prototype.onContextMenu=function(){},Ml.prototype.resetPosition=function(){},Ml.prototype.needsContentAttribute=!0;function Dl(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new z,this.hasSelection=!1,this.composing=null}var Wl,Hl,Fl,El,Pl;function Il(e,t,r,n){Wl.defaults[e]=t,r&&(Hl[e]=n?function(e,t,n){n!=ul&&r(e,t,n)}:r)}Dl.prototype.init=function(n){var e=this,r=this,i=this.cm;this.createField(n);var o=this.textarea;function t(e){if(!Le(i,e)){if(i.somethingSelected())yl({lineWise:!1,text:i.getSelections()});else{if(!i.options.lineWiseCopyCut)return;var t=Cl(i);yl({lineWise:!0,text:t.text}),"cut"==e.type?i.setSelections(t.ranges,null,V):(r.prevInput="",o.value=t.text.join("\n"),E(o))}"cut"==e.type&&(i.state.cutIncoming=+new Date)}}n.wrapper.insertBefore(this.wrapper,n.wrapper.firstChild),a&&(o.style.width="0px"),we(o,"input",function(){L&&9<=x&&e.hasSelection&&(e.hasSelection=null),r.poll()}),we(o,"paste",function(e){Le(i,e)||wl(e,i)||(i.state.pasteIncoming=+new Date,r.fastPoll())}),we(o,"cut",t),we(o,"copy",t),we(n.scroller,"paste",function(e){if(!bn(n,e)&&!Le(i,e)){if(!o.dispatchEvent)return i.state.pasteIncoming=+new Date,void r.focus();var t=new Event("paste");t.clipboardData=e.clipboardData,o.dispatchEvent(t)}}),we(n.lineSpace,"selectstart",function(e){bn(n,e)||Ne(e)}),we(o,"compositionstart",function(){var e=i.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:i.markText(e,i.getCursor("to"),{className:"CodeMirror-composing"})}}),we(o,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},Dl.prototype.createField=function(e){this.wrapper=Ll(),this.textarea=this.wrapper.firstChild},Dl.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},Dl.prototype.prepareSelection=function(){var e,t,n,r=this.cm,i=r.display,o=r.doc,l=cr(r);return r.options.moveInputWithCursor&&(e=Vn(r,o.sel.primary().head,"div"),t=i.wrapper.getBoundingClientRect(),n=i.lineDiv.getBoundingClientRect(),l.teTop=Math.max(0,Math.min(i.wrapper.clientHeight-10,e.top+n.top-t.top)),l.teLeft=Math.max(0,Math.min(i.wrapper.clientWidth-10,e.left+n.left-t.left))),l},Dl.prototype.showSelection=function(e){var t=this.cm.display;N(t.cursorDiv,e.cursors),N(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Dl.prototype.reset=function(e){var t,n;this.contextMenuPending||this.composing||((t=this.cm).somethingSelected()?(this.prevInput="",n=t.getSelection(),this.textarea.value=n,t.state.focused&&E(this.textarea),L&&9<=x&&(this.hasSelection=n)):e||(this.prevInput=this.textarea.value="",L&&9<=x&&(this.hasSelection=null)))},Dl.prototype.getField=function(){return this.textarea},Dl.prototype.supportsTouch=function(){return!1},Dl.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!d||W()!=this.textarea))try{this.textarea.focus()}catch(e){}},Dl.prototype.blur=function(){this.textarea.blur()},Dl.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Dl.prototype.receivedFocus=function(){this.slowPoll()},Dl.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},Dl.prototype.fastPoll=function(){var t=!1,n=this;n.pollingFast=!0,n.polling.set(20,function e(){n.poll()||t?(n.pollingFast=!1,n.slowPoll()):(t=!0,n.polling.set(60,e))})},Dl.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||ze(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=n.value;if(i==r&&!t.somethingSelected())return!1;if(L&&9<=x&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||r||(r="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var l=0,s=Math.min(r.length,i.length);l<s&&r.charCodeAt(l)==i.charCodeAt(l);)++l;return Br(t,function(){bl(t,i.slice(l),r.length-l,null,e.composing?"*compose":null),1e3<i.length||-1<i.indexOf("\n")?n.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},Dl.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Dl.prototype.onKeyPress=function(){L&&9<=x&&(this.hasSelection=null),this.fastPoll()},Dl.prototype.onContextMenu=function(e){var n=this,r=n.cm,i=r.display,o=n.textarea;n.contextMenuPending&&n.contextMenuPending();var l,s,t,a,u,c=nr(r,e),h=i.scroller.scrollTop;function d(){var e,t;null!=o.selectionStart&&(t="​"+((e=r.somethingSelected())?o.value:""),o.value="⇚",o.value=t,n.prevInput=e?"":"​",o.selectionStart=1,o.selectionEnd=t.length,i.selForContextMenu=r.doc.sel)}function f(){var e,t;n.contextMenuPending==f&&(n.contextMenuPending=!1,n.wrapper.style.cssText=s,o.style.cssText=l,L&&x<9&&i.scrollbars.setScrollTop(i.scroller.scrollTop=h),null!=o.selectionStart&&((!L||L&&x<9)&&d(),e=0,t=function(){i.selForContextMenu==r.doc.sel&&0==o.selectionStart&&0<o.selectionEnd&&"​"==n.prevInput?Gr(r,_i)(r):e++<10?i.detectingSelectAll=setTimeout(t,500):(i.selForContextMenu=null,i.input.reset())},i.detectingSelectAll=setTimeout(t,200)))}c&&!m&&(r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(c)&&Gr(r,Bi)(r.doc,di(c),V),l=o.style.cssText,s=n.wrapper.style.cssText,t=n.wrapper.offsetParent.getBoundingClientRect(),n.wrapper.style.cssText="position: static",o.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-t.top-5)+"px; left: "+(e.clientX-t.left-5)+"px;\n z-index: 1000; background: "+(L?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",v&&(a=window.scrollY),i.input.focus(),v&&window.scrollTo(null,a),i.input.reset(),r.somethingSelected()||(o.value=n.prevInput=" "),n.contextMenuPending=f,i.selForContextMenu=r.doc.sel,clearTimeout(i.detectingSelectAll),L&&9<=x&&d(),C?(De(e),u=function(){Ce(window,"mouseup",u),setTimeout(f,20)},we(window,"mouseup",u)):setTimeout(f,50))},Dl.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},Dl.prototype.setUneditable=function(){},Dl.prototype.needsContentAttribute=!1,Hl=(Wl=pl).optionHandlers,Wl.defineOption=Il,Wl.Init=ul,Il("value","",function(e,t){return e.setValue(t)},!0),Il("mode",null,function(e,t){e.doc.modeOption=t,vi(e)},!0),Il("indentUnit",2,vi,!0),Il("indentWithTabs",!1),Il("smartIndent",!0),Il("tabSize",4,function(e){yi(e),Pn(e),ir(e)},!0),Il("lineSeparator",null,function(e,r){if(e.doc.lineSep=r){var i=[],o=e.doc.first;e.doc.iter(function(e){for(var t=0;;){var n=e.text.indexOf(r,t);if(-1==n)break;t=n+r.length,i.push(lt(o,n))}o++});for(var t=i.length-1;0<=t;t--)to(e.doc,r,i[t],lt(i[t].line,i[t].ch+r.length))}}),Il("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=ul&&e.refresh()}),Il("specialCharPlaceholder",en,function(e){return e.refresh()},!0),Il("electricChars",!0),Il("inputStyle",d?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),Il("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),Il("autocorrect",!1,function(e,t){return e.getInputField().autocorrect=t},!0),Il("autocapitalize",!1,function(e,t){return e.getInputField().autocapitalize=t},!0),Il("rtlMoveVisually",!p),Il("wholeLineUpdateBefore",!0),Il("theme","default",function(e){al(e),ni(e)},!0),Il("keyMap","default",function(e,t,n){var r=Po(t),i=n!=ul&&Po(n);i&&i.detach&&i.detach(e,r),r.attach&&r.attach(e,i||null)}),Il("extraKeys",null),Il("configureMouse",null),Il("lineWrapping",!1,fl,!0),Il("gutters",[],function(e,t){e.display.gutterSpecs=ei(t,e.options.lineNumbers),ni(e)},!0),Il("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?Jn(e.display)+"px":"0",e.refresh()},!0),Il("coverGutterNextToScrollbar",!1,function(e){return Hr(e)},!0),Il("scrollbarStyle","native",function(e){Pr(e),Hr(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),Il("lineNumbers",!1,function(e,t){e.display.gutterSpecs=ei(e.options.gutters,t),ni(e)},!0),Il("firstLineNumber",1,ni,!0),Il("lineNumberFormatter",function(e){return e},ni,!0),Il("showCursorWhenSelecting",!1,ur,!0),Il("resetSelectionOnContextMenu",!0),Il("lineWiseCopyCut",!0),Il("pasteLinesPerSelection",!0),Il("selectionsMayTouch",!1),Il("readOnly",!1,function(e,t){"nocursor"==t&&(vr(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),Il("screenReaderLabel",null,function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)}),Il("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),Il("dragDrop",!0,dl),Il("allowDropFileTypes",null),Il("cursorBlinkRate",530),Il("cursorScrollMargin",0),Il("cursorHeight",1,ur,!0),Il("singleCursorHeightPerLine",!0,ur,!0),Il("workTime",100),Il("workDelay",100),Il("flattenSpans",!0,yi,!0),Il("addModeClass",!1,yi,!0),Il("pollInterval",100),Il("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),Il("historyEventDelay",1250),Il("viewportMargin",10,function(e){return e.refresh()},!0),Il("maxHighlightLength",1e4,yi,!0),Il("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),Il("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),Il("autofocus",null),Il("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0),Il("phrases",null),El=(Fl=pl).optionHandlers,Pl=Fl.helpers={},Fl.prototype={constructor:Fl,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,t){var n=this.options,r=n[e];n[e]==t&&"mode"!=e||(n[e]=t,El.hasOwnProperty(e)&&Gr(this,El[e])(this,t,r),Se(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Po(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,n=0;n<t.length;++n)if(t[n]==e||t[n].name==e)return t.splice(n,1),!0},addOverlay:Ur(function(e,t){var n=e.token?e:Fl.getMode(this.options,e);if(n.startState)throw new Error("Overlays may not be stateful.");!function(e,t,n){for(var r=0,i=n(t);r<e.length&&n(e[r])<=i;)r++;e.splice(r,0,t)}(this.state.overlays,{mode:n,modeSpec:e,opaque:t&&t.opaque,priority:t&&t.priority||0},function(e){return e.priority}),this.state.modeGen++,ir(this)}),removeOverlay:Ur(function(e){for(var t=this.state.overlays,n=0;n<t.length;++n){var r=t[n].modeSpec;if(r==e||"string"==typeof e&&r.name==e)return t.splice(n,1),this.state.modeGen++,void ir(this)}}),indentLine:Ur(function(e,t,n){"string"!=typeof t&&"number"!=typeof t&&(t=null==t?this.options.smartIndent?"smart":"prev":t?"add":"subtract"),it(this.doc,e)&&ml(this,e,t,n)}),indentSelection:Ur(function(e){for(var t=this.doc.sel.ranges,n=-1,r=0;r<t.length;r++){var i=t[r];if(i.empty())i.head.line>n&&(ml(this,i.head.line,e,!0),n=i.head.line,r==this.doc.sel.primIndex&&Sr(this));else{for(var o=i.from(),l=i.to(),s=Math.max(n,o.line),n=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1,a=s;a<n;++a)ml(this,a,e);var u=this.doc.sel.ranges;0==o.ch&&t.length==u.length&&0<u[r].from().ch&&Ii(this.doc,r,new ci(o,u[r].to()),V)}}}),getTokenAt:function(e,t){return Lt(this,e,t)},getLineTokens:function(e,t){return Lt(this,lt(e),t,!0)},getTokenTypeAt:function(e){e=ft(this.doc,e);var t,n=yt(this,Qe(this.doc,e.line)),r=0,i=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var l=r+i>>1;if((l?n[2*l-1]:0)>=o)i=l;else{if(!(n[2*l+1]<o)){t=n[2*l+2];break}r=1+l}}var s=t?t.indexOf("overlay "):-1;return s<0?t:0==s?null:t.slice(0,s-1)},getModeAt:function(e){var t=this.doc.mode;return t.innerMode?Fl.innerMode(t,this.getTokenAt(e).state).mode:t},getHelper:function(e,t){return this.getHelpers(e,t)[0]},getHelpers:function(e,t){var n=[];if(!Pl.hasOwnProperty(t))return n;var r=Pl[t],i=this.getModeAt(e);if("string"==typeof i[t])r[i[t]]&&n.push(r[i[t]]);else if(i[t])for(var o=0;o<i[t].length;o++){var l=r[i[t][o]];l&&n.push(l)}else i.helperType&&r[i.helperType]?n.push(r[i.helperType]):r[i.name]&&n.push(r[i.name]);for(var s=0;s<r._global.length;s++){var a=r._global[s];a.pred(i,this)&&-1==B(n,a.val)&&n.push(a.val)}return n},getStateAfter:function(e,t){var n=this.doc;return bt(this,(e=dt(n,null==e?n.first+n.size-1:e))+1,t).state},cursorCoords:function(e,t){var n=this.doc.sel.primary(),r=null==e?n.head:"object"==typeof e?ft(this.doc,e):e?n.from():n.to();return Vn(this,r,t||"page")},charCoords:function(e,t){return Un(this,ft(this.doc,e),t||"page")},coordsChar:function(e,t){return Xn(this,(e=Gn(this,e,t||"page")).left,e.top)},lineAtHeight:function(e,t){return e=Gn(this,{top:e,left:0},t||"page").top,rt(this.doc,e+this.display.viewOffset)},heightAtLine:function(e,t,n){var r,i=!1,o="number"==typeof e?(r=this.doc.first+this.doc.size-1,e<this.doc.first?e=this.doc.first:r<e&&(e=r,i=!0),Qe(this.doc,e)):e;return Bn(this,o,{top:0,left:0},t||"page",n||i).top+(i?this.doc.height-Xt(o):0)},defaultTextHeight:function(){return qn(this.display)},defaultCharWidth:function(){return Zn(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,i){var o,l,s,a,u,c=this.display,h=(e=Vn(this,ft(this.doc,e))).bottom,d=e.left;t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),c.sizer.appendChild(t),"over"==r?h=e.top:"above"!=r&&"near"!=r||(o=Math.max(c.wrapper.clientHeight,this.doc.height),l=Math.max(c.sizer.clientWidth,c.lineSpace.clientWidth),("above"==r||e.bottom+t.offsetHeight>o)&&e.top>t.offsetHeight?h=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=o&&(h=e.bottom),d+t.offsetWidth>l&&(d=l-t.offsetWidth)),t.style.top=h+"px",t.style.left=t.style.right="","right"==i?(d=c.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?d=0:"middle"==i&&(d=(c.sizer.clientWidth-t.offsetWidth)/2),t.style.left=d+"px"),n&&(s=this,a={left:d,top:h,right:d+t.offsetWidth,bottom:h+t.offsetHeight},null!=(u=xr(s,a)).scrollTop&&Mr(s,u.scrollTop),null!=u.scrollLeft&&Ar(s,u.scrollLeft))},triggerOnKeyDown:Ur(Zo),triggerOnKeyPress:Ur(Jo),triggerOnKeyUp:Qo,triggerOnMouseDown:Ur(rl),execCommand:function(e){if(Uo.hasOwnProperty(e))return Uo[e].call(null,this)},triggerElectric:Ur(function(e){xl(this,e)}),findPosH:function(e,t,n,r){var i=1;t<0&&(i=-1,t=-t);for(var o=ft(this.doc,e),l=0;l<t&&!(o=kl(this.doc,o,i,n,r)).hitSide;++l);return o},moveH:Ur(function(t,n){var r=this;this.extendSelectionsBy(function(e){return r.display.shift||r.doc.extend||e.empty()?kl(r.doc,e.head,t,n,r.options.rtlMoveVisually):t<0?e.from():e.to()},j)}),deleteH:Ur(function(n,r){var e=this.doc.sel,i=this.doc;e.somethingSelected()?i.replaceSelection("",null,"+delete"):Io(this,function(e){var t=kl(i,e.head,n,r,!1);return n<0?{from:t,to:e.head}:{from:e.head,to:t}})}),findPosV:function(e,t,n,r){var i=1,o=r;t<0&&(i=-1,t=-t);for(var l=ft(this.doc,e),s=0;s<t;++s){var a=Vn(this,l,"div");if(null==o?o=a.left:a.left=o,(l=Tl(this,a,i,n)).hitSide)break}return l},moveV:Ur(function(r,i){var o=this,l=this.doc,s=[],a=!this.display.shift&&!l.extend&&l.sel.somethingSelected();if(l.extendSelectionsBy(function(e){if(a)return r<0?e.from():e.to();var t=Vn(o,e.head,"div");null!=e.goalColumn&&(t.left=e.goalColumn),s.push(t.left);var n=Tl(o,t,r,i);return"page"==i&&e==l.sel.primary()&&Cr(o,Un(o,n,"div").top-t.top),n},j),s.length)for(var e=0;e<l.sel.ranges.length;e++)l.sel.ranges[e].goalColumn=s[e]}),findWordAt:function(e){var t=Qe(this.doc,e.line).text,n=e.ch,r=e.ch;if(t){var i=this.getHelper(e,"wordChars");"before"!=e.sticky&&r!=t.length||!n?++r:--n;for(var o=t.charAt(n),l=te(o,i)?function(e){return te(e,i)}:/\s/.test(o)?function(e){return/\s/.test(e)}:function(e){return!/\s/.test(e)&&!te(e)};0<n&&l(t.charAt(n-1));)--n;for(;r<t.length&&l(t.charAt(r));)++r}return new ci(lt(e.line,n),lt(e.line,r))},toggleOverwrite:function(e){null!=e&&e==this.state.overwrite||(((this.state.overwrite=!this.state.overwrite)?H:T)(this.display.cursorDiv,"CodeMirror-overwrite"),Se(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==W()},isReadOnly:function(){return!(!this.options.readOnly&&!this.doc.cantEdit)},scrollTo:Ur(function(e,t){Lr(this,e,t)}),getScrollInfo:function(){var e=this.display.scroller;return{left:e.scrollLeft,top:e.scrollTop,height:e.scrollHeight-Sn(this)-this.display.barHeight,width:e.scrollWidth-Sn(this)-this.display.barWidth,clientHeight:kn(this),clientWidth:Ln(this)}},scrollIntoView:Ur(function(e,t){var n,r;null==e?(e={from:this.doc.sel.primary().head,to:null},null==t&&(t=this.options.cursorScrollMargin)):"number"==typeof e?e={from:lt(e,0),to:null}:null==e.from&&(e={from:e,to:null}),e.to||(e.to=e.from),e.margin=t||0,null!=e.from.line?(r=e,kr(n=this),n.curOp.scrollToPos=r):Tr(this,e.from,e.to,e.margin)}),setSize:Ur(function(e,t){function n(e){return"number"==typeof e||/^\d+$/.test(String(e))?e+"px":e}var r=this;null!=e&&(this.display.wrapper.style.width=n(e)),null!=t&&(this.display.wrapper.style.height=n(t)),this.options.lineWrapping&&En(this);var i=this.display.viewFrom;this.doc.iter(i,this.display.viewTo,function(e){if(e.widgets)for(var t=0;t<e.widgets.length;t++)if(e.widgets[t].noHScroll){or(r,i,"widget");break}++i}),this.curOp.forceUpdate=!0,Se(this,"refresh",this)}),operation:function(e){return Br(this,e)},startOperation:function(){return Rr(this)},endOperation:function(){return zr(this)},refresh:Ur(function(){var e=this.display.cachedTextHeight;ir(this),this.curOp.forceUpdate=!0,Pn(this),Lr(this,this.doc.scrollLeft,this.doc.scrollTop),qr(this.display),(null==e||.5<Math.abs(e-qn(this.display))||this.options.lineWrapping)&&tr(this),Se(this,"refresh",this)}),swapDoc:Ur(function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Ci(this,e),Pn(this),this.display.input.reset(),Lr(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,un(this,"swapDoc",this,t),t}),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Me(Fl),Fl.registerHelper=function(e,t,n){Pl.hasOwnProperty(e)||(Pl[e]=Fl[e]={_global:[]}),Pl[e][t]=n},Fl.registerGlobalHelper=function(e,t,n,r){Fl.registerHelper(e,t,r),Pl[e]._global.push({pred:n,val:r})};var Rl,zl="iter insert remove copy getEditor constructor".split(" ");for(var Bl in vo.prototype)vo.prototype.hasOwnProperty(Bl)&&B(zl,Bl)<0&&(pl.prototype[Bl]=function(e){return function(){return e.apply(this.doc,arguments)}}(vo.prototype[Bl]));return Me(vo),pl.inputStyles={textarea:Dl,contenteditable:Ml},pl.defineMode=function(e){pl.defaults.mode||"null"==e||(pl.defaults.mode=e),function(e,t){2<arguments.length&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ue[e]=t}.apply(this,arguments)},pl.defineMIME=function(e,t){Ve[e]=t},pl.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),pl.defineMIME("text/plain","null"),pl.defineExtension=function(e,t){pl.prototype[e]=t},pl.defineDocExtension=function(e,t){vo.prototype[e]=t},pl.fromTextArea=function(t,n){var e;function r(){t.value=s.getValue()}if((n=n?I(n):{}).value=t.value,!n.tabindex&&t.tabIndex&&(n.tabindex=t.tabIndex),!n.placeholder&&t.placeholder&&(n.placeholder=t.placeholder),null==n.autofocus&&(e=W(),n.autofocus=e==t||null!=t.getAttribute("autofocus")&&e==document.body),t.form&&(we(t.form,"submit",r),!n.leaveSubmitMethodAlone)){var i=t.form,o=i.submit;try{var l=i.submit=function(){r(),i.submit=o,i.submit(),i.submit=l}}catch(e){}}n.finishInit=function(e){e.save=r,e.getTextArea=function(){return t},e.toTextArea=function(){e.toTextArea=isNaN,r(),t.parentNode.removeChild(e.getWrapperElement()),t.style.display="",t.form&&(Ce(t.form,"submit",r),n.leaveSubmitMethodAlone||"function"!=typeof t.form.submit||(t.form.submit=o))}},t.style.display="none";var s=pl(function(e){return t.parentNode.insertBefore(e,t.nextSibling)},n);return s},(Rl=pl).off=Ce,Rl.on=we,Rl.wheelEventPixels=si,Rl.Doc=vo,Rl.splitLines=Re,Rl.countColumn=R,Rl.findColumn=X,Rl.isWordChar=ee,Rl.Pass=U,Rl.signal=Se,Rl.Line=$t,Rl.changeEnd=fi,Rl.scrollbarModel=Er,Rl.Pos=lt,Rl.cmpPos=st,Rl.modes=Ue,Rl.mimeModes=Ve,Rl.resolveMode=Ke,Rl.getMode=je,Rl.modeExtensions=Xe,Rl.extendMode=Ye,Rl.copyState=_e,Rl.startState=qe,Rl.innerMode=$e,Rl.commands=Uo,Rl.keyMap=Ao,Rl.keyName=Eo,Rl.isModifierKey=Ho,Rl.lookupKey=Wo,Rl.normalizeKeyMap=Do,Rl.StringStream=Ze,Rl.SharedTextMarker=po,Rl.TextMarker=ho,Rl.LineWidget=ao,Rl.e_preventDefault=Ne,Rl.e_stopPropagation=Ae,Rl.e_stop=De,Rl.addClass=H,Rl.contains=D,Rl.rmClass=T,Rl.keyNames=ko,pl.version="5.58.3",pl}); From 4079f7231044161e5e033030c7b0e1ac19109b1f Mon Sep 17 00:00:00 2001 From: Saq Imtiaz <saq.imtiaz@gmail.com> Date: Tue, 1 Dec 2020 19:14:07 +0100 Subject: [PATCH 102/124] Fix typo in x-listops.js (#5171) --- core/modules/filters/x-listops.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/modules/filters/x-listops.js b/core/modules/filters/x-listops.js index eeda70c4a..cb8c031a2 100644 --- a/core/modules/filters/x-listops.js +++ b/core/modules/filters/x-listops.js @@ -206,7 +206,7 @@ Extended filter operators to manipulate the current list. if(operands.length > 1) { results.splice(resultsIndex,1,operands[nextOperandIndex]); } else { - results.splice(resultsIndex,1,); + results.splice(resultsIndex,1); } } else { results.push(operands[0]); @@ -232,4 +232,4 @@ Extended filter operators to manipulate the current list. return cycleValueInArray(results,operands,step); } -})(); \ No newline at end of file +})(); From c3055f92a96ac369d034872035f02aa7300b59fc Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Tue, 1 Dec 2020 21:55:22 +0100 Subject: [PATCH 103/124] Don't minify codemirror.js (#5173) --- .../tiddlywiki/codemirror/files/codemirror.js | 9798 ++++++++++++++++- 1 file changed, 9797 insertions(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/codemirror/files/codemirror.js b/plugins/tiddlywiki/codemirror/files/codemirror.js index 0c80808ae..0436a9968 100755 --- a/plugins/tiddlywiki/codemirror/files/codemirror.js +++ b/plugins/tiddlywiki/codemirror/files/codemirror.js @@ -1 +1,9797 @@ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,g=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),r=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),i=/Edge\/(\d+)/.exec(e),L=n||r||i,x=L&&(n?document.documentMode||6:+(i||r)[1]),v=!i&&/WebKit\//.test(e),o=v&&/Qt\/\d+\.\d+/.test(e),l=!i&&/Chrome\//.test(e),m=/Opera\//.test(e),c=/Apple Computer/.test(navigator.vendor),s=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),u=/PhantomJS/.test(e),a=!i&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),h=/Android/.test(e),d=a||h||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),y=a||/Mac/.test(t),f=/\bCrOS\b/.test(e),p=/win/i.test(t),b=m&&e.match(/Version\/(\d*\.\d*)/);(b=b&&Number(b[1]))&&15<=b&&(v=!(m=!1));var w=y&&(o||m&&(null==b||b<12.11)),C=g||L&&9<=x;function S(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var k,T=function(e,t){var n,r=e.className,i=S(t).exec(r);i&&(n=r.slice(i.index+i[0].length),e.className=r.slice(0,i.index)+(n?i[1]+n:""))};function M(e){for(var t=e.childNodes.length;0<t;--t)e.removeChild(e.firstChild);return e}function N(e,t){return M(e).appendChild(t)}function O(e,t,n,r){var i=document.createElement(e);if(n&&(i.className=n),r&&(i.style.cssText=r),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function A(e,t,n,r){var i=O(e,t,n,r);return i.setAttribute("role","presentation"),i}function D(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do{if(11==t.nodeType&&(t=t.host),t==e)return!0}while(t=t.parentNode)}function W(){var t;try{t=document.activeElement}catch(e){t=document.body||null}for(;t&&t.shadowRoot&&t.shadowRoot.activeElement;)t=t.shadowRoot.activeElement;return t}function H(e,t){var n=e.className;S(t).test(n)||(e.className+=(n?" ":"")+t)}function F(e,t){for(var n=e.split(" "),r=0;r<n.length;r++)n[r]&&!S(n[r]).test(t)&&(t+=" "+n[r]);return t}k=document.createRange?function(e,t,n,r){var i=document.createRange();return i.setEnd(r||e,n),i.setStart(e,t),i}:function(e,t,n){var r=document.body.createTextRange();try{r.moveToElementText(e.parentNode)}catch(e){return r}return r.collapse(!0),r.moveEnd("character",n),r.moveStart("character",t),r};var E=function(e){e.select()};function P(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function I(e,t,n){for(var r in t=t||{},e)!e.hasOwnProperty(r)||!1===n&&t.hasOwnProperty(r)||(t[r]=e[r]);return t}function R(e,t,n,r,i){null==t&&-1==(t=e.search(/[^\s\u00a0]/))&&(t=e.length);for(var o=r||0,l=i||0;;){var s=e.indexOf("\t",o);if(s<0||t<=s)return l+(t-o);l+=s-o,l+=n-l%n,o=s+1}}a?E=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:L&&(E=function(e){try{e.select()}catch(e){}});var z=function(){this.id=null,this.f=null,this.time=0,this.handler=P(this.onTimeout,this)};function B(e,t){for(var n=0;n<e.length;++n)if(e[n]==t)return n;return-1}z.prototype.onTimeout=function(e){e.id=0,e.time<=+new Date?e.f():setTimeout(e.handler,e.time-new Date)},z.prototype.set=function(e,t){this.f=t;var n=+new Date+e;(!this.id||n<this.time)&&(clearTimeout(this.id),this.id=setTimeout(this.handler,e),this.time=n)};var G=50,U={toString:function(){return"CodeMirror.Pass"}},V={scroll:!1},K={origin:"*mouse"},j={origin:"+move"};function X(e,t,n){for(var r=0,i=0;;){var o=e.indexOf("\t",r);-1==o&&(o=e.length);var l=o-r;if(o==e.length||t<=i+l)return r+Math.min(l,t-i);if(i+=o-r,r=o+1,t<=(i+=n-i%n))return r}}var Y=[""];function _(e){for(;Y.length<=e;)Y.push($(Y)+" ");return Y[e]}function $(e){return e[e.length-1]}function q(e,t){for(var n=[],r=0;r<e.length;r++)n[r]=t(e[r],r);return n}function Z(){}function Q(e,t){var n=Object.create?Object.create(e):(Z.prototype=e,new Z);return t&&I(t,n),n}var J=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function ee(e){return/\w/.test(e)||"€"<e&&(e.toUpperCase()!=e.toLowerCase()||J.test(e))}function te(e,t){return t?!!(-1<t.source.indexOf("\\w")&&ee(e))||t.test(e):ee(e)}function ne(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return;return 1}var re=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ie(e){return 768<=e.charCodeAt(0)&&re.test(e)}function oe(e,t,n){for(;(n<0?0<t:t<e.length)&&ie(e.charAt(t));)t+=n;return t}function le(e,t,n){for(var r=n<t?-1:1;;){if(t==n)return t;var i=(t+n)/2,o=r<0?Math.ceil(i):Math.floor(i);if(o==t)return e(o)?t:n;e(o)?n=o:t=o+r}}var se=null;function ae(e,t,n){var r;se=null;for(var i=0;i<e.length;++i){var o=e[i];if(o.from<t&&o.to>t)return i;o.to==t&&(o.from!=o.to&&"before"==n?r=i:se=i),o.from==t&&(o.from!=o.to&&"before"!=n?r=i:se=i)}return null!=r?r:se}var ue,ce,he,de,fe,pe,ge,me=(ue="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",ce="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111",he=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,de=/[stwN]/,fe=/[LRr]/,pe=/[Lb1n]/,ge=/[1n]/,function(e,t){var n="ltr"==t?"L":"R";if(0==e.length||"ltr"==t&&!he.test(e))return!1;for(var r,i=e.length,o=[],l=0;l<i;++l)o.push((r=e.charCodeAt(l))<=247?ue.charAt(r):1424<=r&&r<=1524?"R":1536<=r&&r<=1785?ce.charAt(r-1536):1774<=r&&r<=2220?"r":8192<=r&&r<=8203?"w":8204==r?"b":"L");for(var s=0,a=n;s<i;++s){var u=o[s];"m"==u?o[s]=a:a=u}for(var c=0,h=n;c<i;++c){var d=o[c];"1"==d&&"r"==h?o[c]="n":fe.test(d)&&"r"==(h=d)&&(o[c]="R")}for(var f=1,p=o[0];f<i-1;++f){var g=o[f];"+"==g&&"1"==p&&"1"==o[f+1]?o[f]="1":","!=g||p!=o[f+1]||"1"!=p&&"n"!=p||(o[f]=p),p=g}for(var m=0;m<i;++m){var v=o[m];if(","==v)o[m]="N";else if("%"==v){for(var y=void 0,y=m+1;y<i&&"%"==o[y];++y);for(var b=m&&"!"==o[m-1]||y<i&&"1"==o[y]?"1":"N",w=m;w<y;++w)o[w]=b;m=y-1}}for(var x=0,C=n;x<i;++x){var S=o[x];"L"==C&&"1"==S?o[x]="L":fe.test(S)&&(C=S)}for(var L=0;L<i;++L)if(de.test(o[L])){for(var k=void 0,k=L+1;k<i&&de.test(o[k]);++k);for(var T="L"==(L?o[L-1]:n),M=T==("L"==(k<i?o[k]:n))?T?"L":"R":n,N=L;N<k;++N)o[N]=M;L=k-1}for(var A,O=[],D=0;D<i;)if(pe.test(o[D])){var W=D;for(++D;D<i&&pe.test(o[D]);++D);O.push(new ve(0,W,D))}else{var H=D,F=O.length,E="rtl"==t?1:0;for(++D;D<i&&"L"!=o[D];++D);for(var P=H;P<D;)if(ge.test(o[P])){H<P&&(O.splice(F,0,new ve(1,H,P)),F+=E);var I=P;for(++P;P<D&&ge.test(o[P]);++P);O.splice(F,0,new ve(2,I,P)),F+=E,H=P}else++P;H<D&&O.splice(F,0,new ve(1,H,D))}return"ltr"==t&&(1==O[0].level&&(A=e.match(/^\s+/))&&(O[0].from=A[0].length,O.unshift(new ve(0,0,A[0].length))),1==$(O).level&&(A=e.match(/\s+$/))&&($(O).to-=A[0].length,O.push(new ve(0,i-A[0].length,i)))),"rtl"==t?O.reverse():O});function ve(e,t,n){this.level=e,this.from=t,this.to=n}function ye(e,t){var n=e.order;return null==n&&(n=e.order=me(e.text,t)),n}var be=[],we=function(e,t,n){var r;e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):(r=e._handlers||(e._handlers={}))[t]=(r[t]||be).concat(n)};function xe(e,t){return e._handlers&&e._handlers[t]||be}function Ce(e,t,n){var r,i,o;e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):!(i=(r=e._handlers)&&r[t])||-1<(o=B(i,n))&&(r[t]=i.slice(0,o).concat(i.slice(o+1)))}function Se(e,t){var n=xe(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),i=0;i<n.length;++i)n[i].apply(null,r)}function Le(e,t,n){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),Se(e,n||t.type,e,t),Oe(t)||t.codemirrorIgnore}function ke(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var n=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),r=0;r<t.length;++r)-1==B(n,t[r])&&n.push(t[r])}function Te(e,t){return 0<xe(e,t).length}function Me(e){e.prototype.on=function(e,t){we(this,e,t)},e.prototype.off=function(e,t){Ce(this,e,t)}}function Ne(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Ae(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Oe(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function De(e){Ne(e),Ae(e)}function We(e){return e.target||e.srcElement}function He(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),y&&e.ctrlKey&&1==t&&(t=3),t}var Fe,Ee,Pe=function(){if(L&&x<9)return!1;var e=O("div");return"draggable"in e||"dragDrop"in e}();var Ie,Re=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(n.push(o.slice(0,l)),t+=l+1):(n.push(o),t=i+1)}return n}:function(e){return e.split(/\r\n?|\n/)},ze=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Be="oncopy"in(Ie=O("div"))||(Ie.setAttribute("oncopy","return;"),"function"==typeof Ie.oncopy),Ge=null;var Ue={},Ve={};function Ke(e){if("string"==typeof e&&Ve.hasOwnProperty(e))e=Ve[e];else if(e&&"string"==typeof e.name&&Ve.hasOwnProperty(e.name)){var t=Ve[e.name];"string"==typeof t&&(t={name:t}),(e=Q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Ke("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Ke("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function je(e,t){t=Ke(t);var n=Ue[t.name];if(!n)return je(e,"text/plain");var r=n(e,t);if(Xe.hasOwnProperty(t.name)){var i=Xe[t.name];for(var o in i)i.hasOwnProperty(o)&&(r.hasOwnProperty(o)&&(r["_"+o]=r[o]),r[o]=i[o])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)r[l]=t.modeProps[l];return r}var Xe={};function Ye(e,t){I(t,Xe.hasOwnProperty(e)?Xe[e]:Xe[e]={})}function _e(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n={};for(var r in t){var i=t[r];i instanceof Array&&(i=i.concat([])),n[r]=i}return n}function $e(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function qe(e,t,n){return!e.startState||e.startState(t,n)}var Ze=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};function Qe(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var i=n.children[r],o=i.chunkSize();if(t<o){n=i;break}t-=o}return n.lines[t]}function Je(e,n,r){var i=[],o=n.line;return e.iter(n.line,r.line+1,function(e){var t=e.text;o==r.line&&(t=t.slice(0,r.ch)),o==n.line&&(t=t.slice(n.ch)),i.push(t),++o}),i}function et(e,t,n){var r=[];return e.iter(t,n,function(e){r.push(e.text)}),r}function tt(e,t){var n=t-e.height;if(n)for(var r=e;r;r=r.parent)r.height+=n}function nt(e){if(null==e.parent)return null;for(var t=e.parent,n=B(t.lines,e),r=t.parent;r;r=(t=r).parent)for(var i=0;r.children[i]!=t;++i)n+=r.children[i].chunkSize();return n+t.first}function rt(e,t){var n=e.first;e:do{for(var r=0;r<e.children.length;++r){var i=e.children[r],o=i.height;if(t<o){e=i;continue e}t-=o,n+=i.chunkSize()}return n}while(!e.lines);for(var l=0;l<e.lines.length;++l){var s=e.lines[l].height;if(t<s)break;t-=s}return n+l}function it(e,t){return t>=e.first&&t<e.first+e.size}function ot(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function lt(e,t,n){if(void 0===n&&(n=null),!(this instanceof lt))return new lt(e,t,n);this.line=e,this.ch=t,this.sticky=n}function st(e,t){return e.line-t.line||e.ch-t.ch}function at(e,t){return e.sticky==t.sticky&&0==st(e,t)}function ut(e){return lt(e.line,e.ch)}function ct(e,t){return st(e,t)<0?t:e}function ht(e,t){return st(e,t)<0?e:t}function dt(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function ft(e,t){if(t.line<e.first)return lt(e.first,0);var n,r,i,o=e.first+e.size-1;return t.line>o?lt(o,Qe(e,o).text.length):(r=Qe(e,(n=t).line).text.length,null==(i=n.ch)||r<i?lt(n.line,r):i<0?lt(n.line,0):n)}function pt(e,t){for(var n=[],r=0;r<t.length;r++)n[r]=ft(e,t[r]);return n}Ze.prototype.eol=function(){return this.pos>=this.string.length},Ze.prototype.sol=function(){return this.pos==this.lineStart},Ze.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},Ze.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},Ze.prototype.eat=function(e){var t=this.string.charAt(this.pos),n="string"==typeof e?t==e:t&&(e.test?e.test(t):e(t));if(n)return++this.pos,t},Ze.prototype.eatWhile=function(e){for(var t=this.pos;this.eat(e););return this.pos>t},Ze.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},Ze.prototype.skipToEnd=function(){this.pos=this.string.length},Ze.prototype.skipTo=function(e){var t=this.string.indexOf(e,this.pos);if(-1<t)return this.pos=t,!0},Ze.prototype.backUp=function(e){this.pos-=e},Ze.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=R(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},Ze.prototype.indentation=function(){return R(this.string,null,this.tabSize)-(this.lineStart?R(this.string,this.lineStart,this.tabSize):0)},Ze.prototype.match=function(e,t,n){if("string"!=typeof e){var r=this.string.slice(this.pos).match(e);return r&&0<r.index?null:(r&&!1!==t&&(this.pos+=r[0].length),r)}function i(e){return n?e.toLowerCase():e}if(i(this.string.substr(this.pos,e.length))==i(e))return!1!==t&&(this.pos+=e.length),!0},Ze.prototype.current=function(){return this.string.slice(this.start,this.pos)},Ze.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},Ze.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},Ze.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var gt=function(e,t){this.state=e,this.lookAhead=t},mt=function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1};function vt(t,n,r,e){var a=[t.state.modeGen],i={};Tt(t,n.text,t.doc.mode,r,function(e,t){return a.push(e,t)},i,e);for(var u=r.state,o=0;o<t.state.overlays.length;++o)!function(e){r.baseTokens=a;var o=t.state.overlays[e],l=1,s=0;r.state=!0,Tt(t,n.text,o.mode,r,function(e,t){for(var n=l;s<e;){var r=a[l];e<r&&a.splice(l,1,e,a[l+1],r),l+=2,s=Math.min(e,r)}if(t)if(o.opaque)a.splice(n,l-n,e,"overlay "+t),l=n+2;else for(;n<l;n+=2){var i=a[n+1];a[n+1]=(i?i+" ":"")+"overlay "+t}},i),r.state=u,r.baseTokens=null,r.baseTokenPos=1}(o);return{styles:a,classes:i.bgClass||i.textClass?i:null}}function yt(e,t,n){var r,i,o;return t.styles&&t.styles[0]==e.state.modeGen||(r=bt(e,nt(t)),i=t.text.length>e.options.maxHighlightLength&&_e(e.doc.mode,r.state),o=vt(e,t,r),i&&(r.state=i),t.stateAfter=r.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))),t.styles}function bt(n,r,e){var t=n.doc,i=n.display;if(!t.mode.startState)return new mt(t,!0,r);var o=function(e,t,n){for(var r,i,o=e.doc,l=n?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;l<s;--s){if(s<=o.first)return o.first;var a=Qe(o,s-1),u=a.stateAfter;if(u&&(!n||s+(u instanceof gt?u.lookAhead:0)<=o.modeFrontier))return s;var c=R(a.text,null,e.options.tabSize);(null==i||c<r)&&(i=s-1,r=c)}return i}(n,r,e),l=o>t.first&&Qe(t,o-1).stateAfter,s=l?mt.fromSaved(t,l,o):new mt(t,qe(t.mode),o);return t.iter(o,r,function(e){wt(n,e.text,s);var t=s.line;e.stateAfter=t==r-1||t%5==0||t>=i.viewFrom&&t<i.viewTo?s.save():null,s.nextLine()}),e&&(t.modeFrontier=s.line),s}function wt(e,t,n,r){var i=e.doc.mode,o=new Ze(t,e.options.tabSize,n);for(o.start=o.pos=r||0,""==t&&xt(i,n.state);!o.eol();)Ct(i,o,n.state),o.start=o.pos}function xt(e,t){if(e.blankLine)return e.blankLine(t);if(e.innerMode){var n=$e(e,t);return n.mode.blankLine?n.mode.blankLine(n.state):void 0}}function Ct(e,t,n,r){for(var i=0;i<10;i++){r&&(r[0]=$e(e,n).mode);var o=e.token(t,n);if(t.pos>t.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}mt.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},mt.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},mt.prototype.nextLine=function(){this.line++,0<this.maxLookAhead&&this.maxLookAhead--},mt.fromSaved=function(e,t,n){return t instanceof gt?new mt(e,_e(e.mode,t.state),n,t.lookAhead):new mt(e,_e(e.mode,t),n)},mt.prototype.save=function(e){var t=!1!==e?_e(this.doc.mode,this.state):this.state;return 0<this.maxLookAhead?new gt(t,this.maxLookAhead):t};var St=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function Lt(e,t,n,r){var i,o,l=e.doc,s=l.mode,a=Qe(l,(t=ft(l,t)).line),u=bt(e,t.line,n),c=new Ze(a.text,e.options.tabSize,u);for(r&&(o=[]);(r||c.pos<t.ch)&&!c.eol();)c.start=c.pos,i=Ct(s,c,u.state),r&&o.push(new St(c,i,_e(l.mode,u.state)));return r?o:new St(c,i,u.state)}function kt(e,t){if(e)for(;;){var n=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!n)break;e=e.slice(0,n.index)+e.slice(n.index+n[0].length);var r=n[1]?"bgClass":"textClass";null==t[r]?t[r]=n[2]:new RegExp("(?:^|\\s)"+n[2]+"(?:$|\\s)").test(t[r])||(t[r]+=" "+n[2])}return e}function Tt(e,t,n,r,i,o,l){var s=n.flattenSpans;null==s&&(s=e.options.flattenSpans);var a=0,u=null,c=new Ze(t,e.options.tabSize,r),h=e.options.addModeClass&&[null];for(""==t&&kt(xt(n,r.state),o);!c.eol();){var d,f=c.pos>e.options.maxHighlightLength?(s=!1,l&&wt(e,t,r,c.pos),c.pos=t.length,null):kt(Ct(n,c,r.state,h),o);if(!h||(d=h[0].name)&&(f="m-"+(f?d+" "+f:d)),!s||u!=f){for(;a<c.start;)i(a=Math.min(c.start,a+5e3),u);u=f}c.start=c.pos}for(;a<c.pos;){var p=Math.min(c.pos,a+5e3);i(p,u),a=p}}var Mt=!1,Nt=!1;function At(e,t,n){this.marker=e,this.from=t,this.to=n}function Ot(e,t){if(e)for(var n=0;n<e.length;++n){var r=e[n];if(r.marker==t)return r}}function Dt(e,t){if(t.full)return null;var n=it(e,t.from.line)&&Qe(e,t.from.line).markedSpans,r=it(e,t.to.line)&&Qe(e,t.to.line).markedSpans;if(!n&&!r)return null;var i=t.from.ch,o=t.to.ch,l=0==st(t.from,t.to),s=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t))&&(l.from!=t||"bookmark"!=s.type||n&&l.marker.insertLeft)||(o=null==l.to||(s.inclusiveRight?l.to>=t:l.to>t),(r=r||[]).push(new At(s,l.from,o?null:l.to)))}return r}(n,i,l),a=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.to||(s.inclusiveRight?l.to>=t:l.to>t))&&(l.from!=t||"bookmark"!=s.type||n&&!l.marker.insertLeft)||(o=null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t),(r=r||[]).push(new At(s,o?null:l.from-t,null==l.to?null:l.to-t)))}return r}(r,o,l),u=1==t.text.length,c=$(t.text).length+(u?i:0);if(s)for(var h=0;h<s.length;++h){var d,f=s[h];null==f.to&&((d=Ot(a,f.marker))?u&&(f.to=null==d.to?null:d.to+c):f.to=i)}if(a)for(var p=0;p<a.length;++p){var g=a[p];null!=g.to&&(g.to+=c),null==g.from?Ot(s,g.marker)||(g.from=c,u&&(s=s||[]).push(g)):(g.from+=c,u&&(s=s||[]).push(g))}s=s&&Wt(s),a&&a!=s&&(a=Wt(a));var m=[s];if(!u){var v,y=t.text.length-2;if(0<y&&s)for(var b=0;b<s.length;++b)null==s[b].to&&(v=v||[]).push(new At(s[b].marker,null,null));for(var w=0;w<y;++w)m.push(v);m.push(a)}return m}function Wt(e){for(var t=0;t<e.length;++t){var n=e[t];null!=n.from&&n.from==n.to&&!1!==n.marker.clearWhenEmpty&&e.splice(t--,1)}return e.length?e:null}function Ht(e){var t=e.markedSpans;if(t){for(var n=0;n<t.length;++n)t[n].marker.detachLine(e);e.markedSpans=null}}function Ft(e,t){if(t){for(var n=0;n<t.length;++n)t[n].marker.attachLine(e);e.markedSpans=t}}function Et(e){return e.inclusiveLeft?-1:0}function Pt(e){return e.inclusiveRight?1:0}function It(e,t){var n=e.lines.length-t.lines.length;if(0!=n)return n;var r=e.find(),i=t.find(),o=st(r.from,i.from)||Et(e)-Et(t);if(o)return-o;var l=st(r.to,i.to)||Pt(e)-Pt(t);return l||t.id-e.id}function Rt(e,t){var n,r=Nt&&e.markedSpans;if(r)for(var i=void 0,o=0;o<r.length;++o)(i=r[o]).marker.collapsed&&null==(t?i.from:i.to)&&(!n||It(n,i.marker)<0)&&(n=i.marker);return n}function zt(e){return Rt(e,!0)}function Bt(e){return Rt(e,!1)}function Gt(e,t,n,r,i){var o=Qe(e,t),l=Nt&&o.markedSpans;if(l)for(var s=0;s<l.length;++s){var a=l[s];if(a.marker.collapsed){var u=a.marker.find(0),c=st(u.from,n)||Et(a.marker)-Et(i),h=st(u.to,r)||Pt(a.marker)-Pt(i);if(!(0<=c&&h<=0||c<=0&&0<=h)&&(c<=0&&(a.marker.inclusiveRight&&i.inclusiveLeft?0<=st(u.to,n):0<st(u.to,n))||0<=c&&(a.marker.inclusiveRight&&i.inclusiveLeft?st(u.from,r)<=0:st(u.from,r)<0)))return 1}}}function Ut(e){for(var t;t=zt(e);)e=t.find(-1,!0).line;return e}function Vt(e,t){var n=Qe(e,t),r=Ut(n);return n==r?t:nt(r)}function Kt(e,t){if(t>e.lastLine())return t;var n,r=Qe(e,t);if(!jt(e,r))return t;for(;n=Bt(r);)r=n.find(1,!0).line;return nt(r)+1}function jt(e,t){var n=Nt&&t.markedSpans;if(n)for(var r=void 0,i=0;i<n.length;++i)if((r=n[i]).marker.collapsed){if(null==r.from)return!0;if(!r.marker.widgetNode&&0==r.from&&r.marker.inclusiveLeft&&function e(t,n,r){if(null==r.to){var i=r.marker.find(1,!0);return e(t,i.line,Ot(i.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==n.text.length)return!0;for(var o=void 0,l=0;l<n.markedSpans.length;++l)if((o=n.markedSpans[l]).marker.collapsed&&!o.marker.widgetNode&&o.from==r.to&&(null==o.to||o.to!=r.from)&&(o.marker.inclusiveLeft||r.marker.inclusiveRight)&&e(t,n,o))return!0}(e,t,r))return!0}}function Xt(e){for(var t=0,n=(e=Ut(e)).parent,r=0;r<n.lines.length;++r){var i=n.lines[r];if(i==e)break;t+=i.height}for(var o=n.parent;o;o=(n=o).parent)for(var l=0;l<o.children.length;++l){var s=o.children[l];if(s==n)break;t+=s.height}return t}function Yt(e){if(0==e.height)return 0;for(var t,n=e.text.length,r=e;t=zt(r);){var i=t.find(0,!0),r=i.from.line;n+=i.from.ch-i.to.ch}for(r=e;t=Bt(r);){var o=t.find(0,!0);n-=r.text.length-o.from.ch,n+=(r=o.to.line).text.length-o.to.ch}return n}function _t(e){var n=e.display,t=e.doc;n.maxLine=Qe(t,t.first),n.maxLineLength=Yt(n.maxLine),n.maxLineChanged=!0,t.iter(function(e){var t=Yt(e);t>n.maxLineLength&&(n.maxLineLength=t,n.maxLine=e)})}var $t=function(e,t,n){this.text=e,Ft(this,t),this.height=n?n(this):1};$t.prototype.lineNo=function(){return nt(this)},Me($t);var qt={},Zt={};function Qt(e,t){if(!e||/^\s*$/.test(e))return null;var n=t.addModeClass?Zt:qt;return n[e]||(n[e]=e.replace(/\S+/g,"cm-$&"))}function Jt(e,t){var n=A("span",null,null,v?"padding-right: .1px":null),r={pre:A("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i,o=0;o<=(t.rest?t.rest.length:0);o++){var l=o?t.rest[o-1]:t.line,s=void 0;r.pos=0,r.addToken=tn,function(e){if(null!=Ee)return Ee;var t=N(e,document.createTextNode("AخA")),n=k(t,0,1).getBoundingClientRect(),r=k(t,1,2).getBoundingClientRect();return M(e),n&&n.left!=n.right&&(Ee=r.right-n.right<3)}(e.display.measure)&&(s=ye(l,e.doc.direction))&&(r.addToken=function(h,d){return function(e,t,n,r,i,o,l){n=n?n+" cm-force-border":"cm-force-border";for(var s=e.pos,a=s+t.length;;){for(var u=void 0,c=0;c<d.length&&!((u=d[c]).to>s&&u.from<=s);c++);if(u.to>=a)return h(e,t,n,r,i,o,l);h(e,t.slice(0,u.to-s),n,r,null,o,l),r=null,t=t.slice(u.to-s),s=u.to}}}(r.addToken,s)),r.map=[],function(e,t,n){var r=e.markedSpans,i=e.text,o=0;if(!r){for(var l=1;l<n.length;l+=2)t.addToken(t,i.slice(o,o=n[l]),Qt(n[l+1],t.cm.options));return}for(var s,a,u,c,h,d,f,p=i.length,g=0,m=1,v="",y=0;;){if(y==g){u=c=h=a="",d=f=null,y=1/0;for(var b=[],w=void 0,x=0;x<r.length;++x){var C=r[x],S=C.marker;if("bookmark"==S.type&&C.from==g&&S.widgetNode)b.push(S);else if(C.from<=g&&(null==C.to||C.to>g||S.collapsed&&C.to==g&&C.from==g)){if(null!=C.to&&C.to!=g&&y>C.to&&(y=C.to,c=""),S.className&&(u+=" "+S.className),S.css&&(a=(a?a+";":"")+S.css),S.startStyle&&C.from==g&&(h+=" "+S.startStyle),S.endStyle&&C.to==y&&(w=w||[]).push(S.endStyle,C.to),S.title&&((f=f||{}).title=S.title),S.attributes)for(var L in S.attributes)(f=f||{})[L]=S.attributes[L];S.collapsed&&(!d||It(d.marker,S)<0)&&(d=C)}else C.from>g&&y>C.from&&(y=C.from)}if(w)for(var k=0;k<w.length;k+=2)w[k+1]==y&&(c+=" "+w[k]);if(!d||d.from==g)for(var T=0;T<b.length;++T)nn(t,0,b[T]);if(d&&(d.from||0)==g){if(nn(t,(null==d.to?p+1:d.to)-g,d.marker,null==d.from),null==d.to)return;d.to==g&&(d=!1)}}if(p<=g)break;for(var M=Math.min(p,y);;){if(v){var N,A=g+v.length;if(d||(N=M<A?v.slice(0,M-g):v,t.addToken(t,N,s?s+u:u,h,g+N.length==y?c:"",a,f)),M<=A){v=v.slice(M-g),g=M;break}g=A,h=""}v=i.slice(o,o=n[m++]),s=Qt(n[m++],t.cm.options)}}}(l,r,yt(e,l,t!=e.display.externalMeasured&&nt(l))),l.styleClasses&&(l.styleClasses.bgClass&&(r.bgClass=F(l.styleClasses.bgClass,r.bgClass||"")),l.styleClasses.textClass&&(r.textClass=F(l.styleClasses.textClass,r.textClass||""))),0==r.map.length&&r.map.push(0,0,r.content.appendChild(function(e){var t;null==Fe&&(t=O("span","​"),N(e,O("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(Fe=t.offsetWidth<=1&&2<t.offsetHeight&&!(L&&x<8)));var n=Fe?O("span","​"):O("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return n.setAttribute("cm-text",""),n}(e.display.measure))),0==o?(t.measure.map=r.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(r.map),(t.measure.caches||(t.measure.caches=[])).push({}))}return v&&(i=r.content.lastChild,(/\bcm-tab\b/.test(i.className)||i.querySelector&&i.querySelector(".cm-tab"))&&(r.content.className="cm-tab-wrap-hack")),Se(e,"renderLine",e,t.line,r.pre),r.pre.className&&(r.textClass=F(r.pre.className,r.textClass||"")),r}function en(e){var t=O("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function tn(e,t,n,r,i,o,l){if(t){var s,a=e.splitSpaces?function(e,t){if(1<e.length&&!/ /.test(e))return e;for(var n=t,r="",i=0;i<e.length;i++){var o=e.charAt(i);" "!=o||!n||i!=e.length-1&&32!=e.charCodeAt(i+1)||(o=" "),r+=o,n=" "==o}return r}(t,e.trailingSpace):t,u=e.cm.state.specialChars,c=!1;if(u.test(t)){s=document.createDocumentFragment();for(var h=0;;){u.lastIndex=h;var d,f=u.exec(t),p=f?f.index-h:t.length-h;if(p&&(d=document.createTextNode(a.slice(h,h+p)),L&&x<9?s.appendChild(O("span",[d])):s.appendChild(d),e.map.push(e.pos,e.pos+p,d),e.col+=p,e.pos+=p),!f)break;h+=1+p;var g,m,v=void 0;"\t"==f[0]?(m=(g=e.cm.options.tabSize)-e.col%g,(v=s.appendChild(O("span",_(m),"cm-tab"))).setAttribute("role","presentation"),v.setAttribute("cm-text","\t"),e.col+=m):("\r"==f[0]||"\n"==f[0]?(v=s.appendChild(O("span","\r"==f[0]?"␍":"␤","cm-invalidchar"))).setAttribute("cm-text",f[0]):((v=e.cm.options.specialCharPlaceholder(f[0])).setAttribute("cm-text",f[0]),L&&x<9?s.appendChild(O("span",[v])):s.appendChild(v)),e.col+=1),e.map.push(e.pos,e.pos+1,v),e.pos++}}else e.col+=t.length,s=document.createTextNode(a),e.map.push(e.pos,e.pos+t.length,s),L&&x<9&&(c=!0),e.pos+=t.length;if(e.trailingSpace=32==a.charCodeAt(t.length-1),n||r||i||c||o||l){var y=n||"";r&&(y+=r),i&&(y+=i);var b=O("span",[s],y,o);if(l)for(var w in l)l.hasOwnProperty(w)&&"style"!=w&&"class"!=w&&b.setAttribute(w,l[w]);return e.content.appendChild(b)}e.content.appendChild(s)}}function nn(e,t,n,r){var i=!r&&n.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!r&&e.cm.display.input.needsContentAttribute&&(i=i||e.content.appendChild(document.createElement("span"))).setAttribute("cm-marker",n.id),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function rn(e,t,n){this.line=t,this.rest=function(e){for(var t,n;t=Bt(e);)e=t.find(1,!0).line,(n=n||[]).push(e);return n}(t),this.size=this.rest?nt($(this.rest))-n+1:1,this.node=this.text=null,this.hidden=jt(e,t)}function on(e,t,n){for(var r=[],i=t;i<n;i=l){var o=new rn(e.doc,Qe(e.doc,i),i),l=i+o.size;r.push(o)}return r}var ln=null;function sn(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n<t.length;n++)t[n].call(null);for(var r=0;r<e.ops.length;r++){var i=e.ops[r];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++].call(null,i.cm)}}while(n<t.length)}(n)}finally{ln=null,t(n)}}var an=null;function un(e,t){var n=xe(e,t);if(n.length){var r,i=Array.prototype.slice.call(arguments,2);ln?r=ln.delayedCallbacks:an?r=an:(r=an=[],setTimeout(cn,0));for(var o=0;o<n.length;++o)!function(e){r.push(function(){return n[e].apply(null,i)})}(o)}}function cn(){var e=an;an=null;for(var t=0;t<e.length;++t)e[t]()}function hn(e,t,n,r){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?function(e,t){var n=t.text.className,r=fn(e,t);t.text==t.node&&(t.node=r.pre);t.text.parentNode.replaceChild(r.pre,t.text),t.text=r.pre,r.bgClass!=t.bgClass||r.textClass!=t.textClass?(t.bgClass=r.bgClass,t.textClass=r.textClass,pn(e,t)):n&&(t.text.className=n)}(e,t):"gutter"==o?gn(e,t,n,r):"class"==o?pn(e,t):"widget"==o&&function(e,t,n){t.alignable&&(t.alignable=null);for(var r=S("CodeMirror-linewidget"),i=t.node.firstChild,o=void 0;i;i=o)o=i.nextSibling,r.test(i.className)&&t.node.removeChild(i);mn(e,t,n)}(e,t,r)}t.changes=null}function dn(e){return e.node==e.text&&(e.node=O("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),L&&x<8&&(e.node.style.zIndex=2)),e.node}function fn(e,t){var n=e.display.externalMeasured;return n&&n.line==t.line?(e.display.externalMeasured=null,t.measure=n.measure,n.built):Jt(e,t)}function pn(e,t){var n,r,i,o;n=e,(o=(r=t).bgClass?r.bgClass+" "+(r.line.bgClass||""):r.line.bgClass)&&(o+=" CodeMirror-linebackground"),r.background?o?r.background.className=o:(r.background.parentNode.removeChild(r.background),r.background=null):o&&(i=dn(r),r.background=i.insertBefore(O("div",null,o),i.firstChild),n.display.input.setUneditable(r.background)),t.line.wrapClass?dn(t).className=t.line.wrapClass:t.node!=t.text&&(t.node.className="");var l=t.textClass?t.textClass+" "+(t.line.textClass||""):t.line.textClass;t.text.className=l||""}function gn(e,t,n,r){var i;t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null),t.gutterBackground&&(t.node.removeChild(t.gutterBackground),t.gutterBackground=null),t.line.gutterClass&&(i=dn(t),t.gutterBackground=O("div",null,"CodeMirror-gutter-background "+t.line.gutterClass,"left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px; width: "+r.gutterTotalWidth+"px"),e.display.input.setUneditable(t.gutterBackground),i.insertBefore(t.gutterBackground,t.text));var o=t.line.gutterMarkers;if(e.options.lineNumbers||o){var l=dn(t),s=t.gutter=O("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px");if(e.display.input.setUneditable(s),l.insertBefore(s,t.text),t.line.gutterClass&&(s.className+=" "+t.line.gutterClass),!e.options.lineNumbers||o&&o["CodeMirror-linenumbers"]||(t.lineNumber=s.appendChild(O("div",ot(e.options,n),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+r.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),o)for(var a=0;a<e.display.gutterSpecs.length;++a){var u=e.display.gutterSpecs[a].className,c=o.hasOwnProperty(u)&&o[u];c&&s.appendChild(O("div",[c],"CodeMirror-gutter-elt","left: "+r.gutterLeft[u]+"px; width: "+r.gutterWidth[u]+"px"))}}}function mn(e,t,n){if(vn(e,t.line,t,n,!0),t.rest)for(var r=0;r<t.rest.length;r++)vn(e,t.rest[r],t,n,!1)}function vn(e,t,n,r,i){if(t.widgets)for(var o=dn(n),l=0,s=t.widgets;l<s.length;++l){var a=s[l],u=O("div",[a.node],"CodeMirror-linewidget"+(a.className?" "+a.className:""));a.handleMouseEvents||u.setAttribute("cm-ignore-events","true"),function(e,t,n,r){{var i;e.noHScroll&&((n.alignable||(n.alignable=[])).push(t),i=r.wrapperWidth,t.style.left=r.fixedPos+"px",e.coverGutter||(i-=r.gutterTotalWidth,t.style.paddingLeft=r.gutterTotalWidth+"px"),t.style.width=i+"px")}e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-r.gutterTotalWidth+"px"))}(a,u,n,r),e.display.input.setUneditable(u),i&&a.above?o.insertBefore(u,n.gutter||n.text):o.appendChild(u),un(a,"redraw")}}function yn(e){if(null!=e.height)return e.height;var t,n=e.doc.cm;return n?(D(document.body,e.node)||(t="position: relative;",e.coverGutter&&(t+="margin-left: -"+n.display.gutters.offsetWidth+"px;"),e.noHScroll&&(t+="width: "+n.display.wrapper.clientWidth+"px;"),N(n.display.measure,O("div",[e.node],null,t))),e.height=e.node.parentNode.offsetHeight):0}function bn(e,t){for(var n=We(t);n!=e.wrapper;n=n.parentNode)if(!n||1==n.nodeType&&"true"==n.getAttribute("cm-ignore-events")||n.parentNode==e.sizer&&n!=e.mover)return 1}function wn(e){return e.lineSpace.offsetTop}function xn(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function Cn(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=N(e.measure,O("pre","x","CodeMirror-line-like")),n=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,r={left:parseInt(n.paddingLeft),right:parseInt(n.paddingRight)};return isNaN(r.left)||isNaN(r.right)||(e.cachedPaddingH=r),r}function Sn(e){return G-e.display.nativeBarWidth}function Ln(e){return e.display.scroller.clientWidth-Sn(e)-e.display.barWidth}function kn(e){return e.display.scroller.clientHeight-Sn(e)-e.display.barHeight}function Tn(e,t,n){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var r=0;r<e.rest.length;r++)if(e.rest[r]==t)return{map:e.measure.maps[r],cache:e.measure.caches[r]};for(var i=0;i<e.rest.length;i++)if(nt(e.rest[i])>n)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Mn(e,t,n,r){return On(e,An(e,t),n,r)}function Nn(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[rr(e,t)];var n=e.display.externalMeasured;return n&&t>=n.lineN&&t<n.lineN+n.size?n:void 0}function An(e,t){var n=nt(t),r=Nn(e,n);r&&!r.text?r=null:r&&r.changes&&(hn(e,r,n,Qn(e)),e.curOp.forceUpdate=!0);var i=Tn(r=r||function(e,t){var n=nt(t=Ut(t)),r=e.display.externalMeasured=new rn(e.doc,t,n);r.lineN=n;var i=r.built=Jt(e,r);return r.text=i.pre,N(e.display.lineMeasure,i.pre),r}(e,t),t,n);return{line:t,view:r,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function On(e,t,n,r,i){t.before&&(n=-1);var o,l=n+(r||"");return t.cache.hasOwnProperty(l)?o=t.cache[l]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||(function(e,t,n){var r=e.options.lineWrapping,i=r&&Ln(e);if(!t.measure.heights||r&&t.measure.width!=i){var o=t.measure.heights=[];if(r){t.measure.width=i;for(var l=t.text.firstChild.getClientRects(),s=0;s<l.length-1;s++){var a=l[s],u=l[s+1];2<Math.abs(a.bottom-u.bottom)&&o.push((a.bottom+u.top)/2-n.top)}}o.push(n.bottom-n.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,n,r){var i,o,l=Hn(t.map,n,r),s=l.node,a=l.start,u=l.end,c=l.collapse;if(3==s.nodeType){for(var h=0;h<4;h++){for(;a&&ie(t.line.text.charAt(l.coverStart+a));)--a;for(;l.coverStart+u<l.coverEnd&&ie(t.line.text.charAt(l.coverStart+u));)++u;if((i=L&&x<9&&0==a&&u==l.coverEnd-l.coverStart?s.parentNode.getBoundingClientRect():function(e,t){var n=Wn;if("left"==t)for(var r=0;r<e.length&&(n=e[r]).left==n.right;r++);else for(var i=e.length-1;0<=i&&(n=e[i]).left==n.right;i--);return n}(k(s,a,u).getClientRects(),r)).left||i.right||0==a)break;u=a,--a,c="right"}L&&x<11&&(i=function(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!function(e){if(null!=Ge)return Ge;var t=N(e,O("span","x")),n=t.getBoundingClientRect(),r=k(t,0,1).getBoundingClientRect();return Ge=1<Math.abs(n.left-r.left)}(e))return t;var n=screen.logicalXDPI/screen.deviceXDPI,r=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*n,right:t.right*n,top:t.top*r,bottom:t.bottom*r}}(e.display.measure,i))}else 0<a&&(c=r="right"),i=e.options.lineWrapping&&1<(o=s.getClientRects()).length?o["right"==r?o.length-1:0]:s.getBoundingClientRect();{var d;!(L&&x<9)||a||i&&(i.left||i.right)||(d=s.parentNode.getClientRects()[0],i=d?{left:d.left,right:d.left+Zn(e.display),top:d.top,bottom:d.bottom}:Wn)}for(var f=i.top-t.rect.top,p=i.bottom-t.rect.top,g=(f+p)/2,m=t.view.measure.heights,v=0;v<m.length-1&&!(g<m[v]);v++);var y=v?m[v-1]:0,b=m[v],w={left:("right"==c?i.right:i.left)-t.rect.left,right:("left"==c?i.left:i.right)-t.rect.left,top:y,bottom:b};i.left||i.right||(w.bogus=!0);e.options.singleCursorHeightPerLine||(w.rtop=f,w.rbottom=p);return w}(e,t,n,r)).bogus||(t.cache[l]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}var Dn,Wn={left:0,right:0,top:0,bottom:0};function Hn(e,t,n){for(var r,i,o,l,s,a,u=0;u<e.length;u+=3)if(s=e[u],a=e[u+1],t<s?(i=0,o=1,l="left"):t<a?o=(i=t-s)+1:(u==e.length-3||t==a&&e[u+3]>t)&&(i=(o=a-s)-1,a<=t&&(l="right")),null!=i){if(r=e[u+2],s==a&&n==(r.insertLeft?"left":"right")&&(l=n),"left"==n&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)r=e[2+(u-=3)],l="left";if("right"==n&&i==a-s)for(;u<e.length-3&&e[u+3]==e[u+4]&&!e[u+5].insertLeft;)r=e[(u+=3)+2],l="right";break}return{node:r,start:i,end:o,collapse:l,coverStart:s,coverEnd:a}}function Fn(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function En(e){e.display.externalMeasure=null,M(e.display.lineMeasure);for(var t=0;t<e.display.view.length;t++)Fn(e.display.view[t])}function Pn(e){En(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function In(){return l&&h?-(document.body.getBoundingClientRect().left-parseInt(getComputedStyle(document.body).marginLeft)):window.pageXOffset||(document.documentElement||document.body).scrollLeft}function Rn(){return l&&h?-(document.body.getBoundingClientRect().top-parseInt(getComputedStyle(document.body).marginTop)):window.pageYOffset||(document.documentElement||document.body).scrollTop}function zn(e){var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;++n)e.widgets[n].above&&(t+=yn(e.widgets[n]));return t}function Bn(e,t,n,r,i){var o;if(i||(o=zn(t),n.top+=o,n.bottom+=o),"line"==r)return n;r=r||"local";var l,s,a=Xt(t);return"local"==r?a+=wn(e.display):a-=e.display.viewOffset,"page"!=r&&"window"!=r||(a+=(l=e.display.lineSpace.getBoundingClientRect()).top+("window"==r?0:Rn()),s=l.left+("window"==r?0:In()),n.left+=s,n.right+=s),n.top+=a,n.bottom+=a,n}function Gn(e,t,n){if("div"==n)return t;var r,i=t.left,o=t.top;"page"==n?(i-=In(),o-=Rn()):"local"!=n&&n||(i+=(r=e.display.sizer.getBoundingClientRect()).left,o+=r.top);var l=e.display.lineSpace.getBoundingClientRect();return{left:i-l.left,top:o-l.top}}function Un(e,t,n,r,i){return Bn(e,r=r||Qe(e.doc,t.line),Mn(e,r,t.ch,i),n)}function Vn(r,e,i,o,l,s){function a(e,t){var n=On(r,l,e,t?"right":"left",s);return t?n.left=n.right:n.right=n.left,Bn(r,o,n,i)}o=o||Qe(r.doc,e.line),l=l||An(r,o);var u=ye(o,r.doc.direction),t=e.ch,n=e.sticky;if(t>=o.text.length?(t=o.text.length,n="before"):t<=0&&(t=0,n="after"),!u)return a("before"==n?t-1:t,"before"==n);function c(e,t,n){return a(n?e-1:e,1==u[t].level!=n)}var h=ae(u,t,n),d=se,f=c(t,h,"before"==n);return null!=d&&(f.other=c(t,d,"before"!=n)),f}function Kn(e,t){var n=0;t=ft(e.doc,t),e.options.lineWrapping||(n=Zn(e.display)*t.ch);var r=Qe(e.doc,t.line),i=Xt(r)+wn(e.display);return{left:n,right:n,top:i,bottom:i+r.height}}function jn(e,t,n,r,i){var o=lt(e,t,n);return o.xRel=i,r&&(o.outside=r),o}function Xn(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return jn(r.first,0,null,-1,-1);var i=rt(r,n),o=r.first+r.size-1;if(o<i)return jn(r.first+r.size-1,Qe(r,o).text.length,null,1,1);t<0&&(t=0);for(var l=Qe(r,i);;){var s=function(n,e,t,r,i){i-=Xt(e);var o=An(n,e),l=zn(e),s=0,a=e.text.length,u=!0,c=ye(e,n.doc.direction);{var h;c&&(h=(n.options.lineWrapping?function(e,t,n,r,i,o,l){var s=Yn(e,t,r,l),a=s.begin,u=s.end;/\s/.test(t.text.charAt(u-1))&&u--;for(var c=null,h=null,d=0;d<i.length;d++){var f,p,g,m=i[d];m.from>=u||m.to<=a||(f=1!=m.level,p=On(e,r,f?Math.min(u,m.to)-1:Math.max(a,m.from)).right,g=p<o?o-p+1e9:p-o,(!c||g<h)&&(c=m,h=g))}c=c||i[i.length-1];c.from<a&&(c={from:a,to:c.to,level:c.level});c.to>u&&(c={from:c.from,to:u,level:c.level});return c}:function(r,i,o,l,s,a,u){var e=le(function(e){var t=s[e],n=1!=t.level;return $n(Vn(r,lt(o,n?t.to:t.from,n?"before":"after"),"line",i,l),a,u,!0)},0,s.length-1),t=s[e];{var n,c;0<e&&(n=1!=t.level,$n(c=Vn(r,lt(o,n?t.from:t.to,n?"after":"before"),"line",i,l),a,u,!0)&&c.top>u&&(t=s[e-1]))}return t})(n,e,t,o,c,r,i),u=1!=h.level,s=u?h.from:h.to-1,a=u?h.to:h.from-1)}var d,f,p=null,g=null,m=le(function(e){var t=On(n,o,e);return t.top+=l,t.bottom+=l,$n(t,r,i,!1)&&(t.top<=i&&t.left<=r&&(p=e,g=t),1)},s,a),v=!1;{var y,b,w;g?(y=r-g.left<g.right-r,m=p+((b=y==u)?0:1),f=b?"after":"before",d=y?g.left:g.right):(u||m!=a&&m!=s||m++,f=0==m||m!=e.text.length&&On(n,o,m-(u?1:0)).bottom+l<=i==u?"after":"before",w=Vn(n,lt(t,m,f),"line",e,o),d=w.left,v=i<w.top?-1:i>=w.bottom?1:0)}return m=oe(e.text,m,1),jn(t,m,f,v,r-d)}(e,l,i,t,n),a=function(e,t){var n,r=Nt&&e.markedSpans;if(r)for(var i=0;i<r.length;++i){var o=r[i];o.marker.collapsed&&(null==o.from||o.from<t)&&(null==o.to||o.to>t)&&(!n||It(n,o.marker)<0)&&(n=o.marker)}return n}(l,s.ch+(0<s.xRel||0<s.outside?1:0));if(!a)return s;var u=a.find(1);if(u.line==i)return u;l=Qe(r,i=u.line)}}function Yn(t,e,n,r){r-=zn(e);var i=e.text.length,o=le(function(e){return On(t,n,e-1).bottom<=r},i,0);return{begin:o,end:i=le(function(e){return On(t,n,e).top>r},o,i)}}function _n(e,t,n,r){return Yn(e,t,n=n||An(e,t),Bn(e,t,On(e,n,r),"line").top)}function $n(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function qn(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Dn){Dn=O("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Dn.appendChild(document.createTextNode("x")),Dn.appendChild(O("br"));Dn.appendChild(document.createTextNode("x"))}N(e.measure,Dn);var n=Dn.offsetHeight/50;return 3<n&&(e.cachedTextHeight=n),M(e.measure),n||1}function Zn(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=O("span","xxxxxxxxxx"),n=O("pre",[t],"CodeMirror-line-like");N(e.measure,n);var r=t.getBoundingClientRect(),i=(r.right-r.left)/10;return 2<i&&(e.cachedCharWidth=i),i||10}function Qn(e){for(var t=e.display,n={},r={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;n[s]=o.offsetLeft+o.clientLeft+i,r[s]=o.clientWidth}return{fixedPos:Jn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function Jn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function er(r){var i=qn(r.display),o=r.options.lineWrapping,l=o&&Math.max(5,r.display.scroller.clientWidth/Zn(r.display)-3);return function(e){if(jt(r.doc,e))return 0;var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;n++)e.widgets[n].height&&(t+=e.widgets[n].height);return o?t+(Math.ceil(e.text.length/l)||1)*i:t+i}}function tr(e){var t=e.doc,n=er(e);t.iter(function(e){var t=n(e);t!=e.height&&tt(e,t)})}function nr(e,t,n,r){var i=e.display;if(!n&&"true"==We(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(e){return null}var a,u,c=Xn(e,o,l);return r&&0<c.xRel&&(a=Qe(e.doc,c.line).text).length==c.ch&&(u=R(a,a.length,e.options.tabSize)-a.length,c=lt(c.line,Math.max(0,Math.round((o-Cn(e.display).left)/Zn(e.display))-u))),c}function rr(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;r<n.length;r++)if((t-=n[r].size)<0)return r}function ir(e,t,n,r){null==t&&(t=e.doc.first),null==n&&(n=e.doc.first+e.doc.size),r=r||0;var i,o,l,s,a=e.display;r&&n<a.viewTo&&(null==a.updateLineNumbers||a.updateLineNumbers>t)&&(a.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=a.viewTo?Nt&&Vt(e.doc,t)<a.viewTo&&lr(e):n<=a.viewFrom?Nt&&Kt(e.doc,n+r)>a.viewFrom?lr(e):(a.viewFrom+=r,a.viewTo+=r):t<=a.viewFrom&&n>=a.viewTo?lr(e):t<=a.viewFrom?(i=sr(e,n,n+r,1))?(a.view=a.view.slice(i.index),a.viewFrom=i.lineN,a.viewTo+=r):lr(e):n>=a.viewTo?(o=sr(e,t,t,-1))?(a.view=a.view.slice(0,o.index),a.viewTo=o.lineN):lr(e):(l=sr(e,t,t,-1),s=sr(e,n,n+r,1),l&&s?(a.view=a.view.slice(0,l.index).concat(on(e,l.lineN,s.lineN)).concat(a.view.slice(s.index)),a.viewTo+=r):lr(e));var u=a.externalMeasured;u&&(n<u.lineN?u.lineN+=r:t<u.lineN+u.size&&(a.externalMeasured=null))}function or(e,t,n){e.curOp.viewChanged=!0;var r,i,o=e.display,l=e.display.externalMeasured;l&&t>=l.lineN&&t<l.lineN+l.size&&(o.externalMeasured=null),t<o.viewFrom||t>=o.viewTo||(null==(r=o.view[rr(e,t)]).node||-1==B(i=r.changes||(r.changes=[]),n)&&i.push(n))}function lr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function sr(e,t,n,r){var i,o=rr(e,t),l=e.display.view;if(!Nt||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var s=e.display.viewFrom,a=0;a<o;a++)s+=l[a].size;if(s!=t){if(0<r){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,n+=i}for(;Vt(e.doc,n)!=n;){if(o==(r<0?0:l.length-1))return null;n+=r*l[o-(r<0?1:0)].size,o+=r}return{index:o,lineN:n}}function ar(e){for(var t=e.display.view,n=0,r=0;r<t.length;r++){var i=t[r];i.hidden||i.node&&!i.changes||++n}return n}function ur(e){e.display.input.showSelection(e.display.input.prepareSelection())}function cr(e,t){void 0===t&&(t=!0);for(var n,r,i=e.doc,o={},l=o.cursors=document.createDocumentFragment(),s=o.selection=document.createDocumentFragment(),a=0;a<i.sel.ranges.length;a++){!t&&a==i.sel.primIndex||((n=i.sel.ranges[a]).from().line>=e.display.viewTo||n.to().line<e.display.viewFrom||(((r=n.empty())||e.options.showCursorWhenSelecting)&&hr(e,n.head,l),r||function(l,e,t){var n=l.display,r=l.doc,i=document.createDocumentFragment(),o=Cn(l.display),T=o.left,M=Math.max(n.sizerWidth,Ln(l)-n.sizer.offsetLeft)-o.right,N="ltr"==r.direction;function A(e,t,n,r){t<0&&(t=0),t=Math.round(t),r=Math.round(r),i.appendChild(O("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==n?M-e:n)+"px;\n height: "+(r-t)+"px"))}function s(n,y,b){var w,x,o=Qe(r,n),C=o.text.length;function S(e,t){return Un(l,lt(n,e),"div",o,t)}function L(e,t,n){var r=_n(l,o,null,e),i="ltr"==t==("after"==n)?"left":"right";return S("after"==n?r.begin:r.end-(/\s/.test(o.text.charAt(r.end-1))?2:1),i)[i]}var k=ye(o,r.direction);return function(e,t,n,r){if(!e)return r(t,n,"ltr",0);for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<n&&l.to>t||t==n&&l.to==t)&&(r(Math.max(l.from,t),Math.min(l.to,n),1==l.level?"rtl":"ltr",o),i=!0)}i||r(t,n,"ltr")}(k,y||0,null==b?C:b,function(e,t,n,r){var i,o,l,s,a,u,c,h="ltr"==n,d=S(e,h?"left":"right"),f=S(t-1,h?"right":"left"),p=null==y&&0==e,g=null==b&&t==C,m=0==r,v=!k||r==k.length-1;f.top-d.top<=3?(i=(N?g:p)&&v,o=(N?p:g)&&m?T:(h?d:f).left,l=i?M:(h?f:d).right,A(o,d.top,l-o,d.bottom)):(c=h?(s=N&&p&&m?T:d.left,a=N?M:L(e,n,"before"),u=N?T:L(t,n,"after"),N&&g&&v?M:f.right):(s=N?L(e,n,"before"):T,a=!N&&p&&m?M:d.right,u=!N&&g&&v?T:f.left,N?L(t,n,"after"):M),A(s,d.top,a-s,d.bottom),d.bottom<f.top&&A(T,d.bottom,null,f.top),A(u,f.top,c-u,f.bottom)),(!w||dr(d,w)<0)&&(w=d),dr(f,w)<0&&(w=f),(!x||dr(d,x)<0)&&(x=d),dr(f,x)<0&&(x=f)}),{start:w,end:x}}var a=e.from(),u=e.to();{var c,h,d,f,p;a.line==u.line?s(a.line,a.ch,u.ch):(c=Qe(r,a.line),h=Qe(r,u.line),d=Ut(c)==Ut(h),f=s(a.line,a.ch,d?c.text.length+1:null).end,p=s(u.line,d?0:null,u.ch).start,d&&(f.top<p.top-2?(A(f.right,f.top,null,f.bottom),A(T,p.top,p.left,p.bottom)):A(f.right,f.top,p.left-f.right,f.bottom)),f.bottom<p.top&&A(T,f.bottom,null,p.top))}t.appendChild(i)}(e,n,s)))}return o}function hr(e,t,n){var r,i=Vn(e,t,"div",null,null,!e.options.singleCursorHeightPerLine),o=n.appendChild(O("div"," ","CodeMirror-cursor"));o.style.left=i.left+"px",o.style.top=i.top+"px",o.style.height=Math.max(0,i.bottom-i.top)*e.options.cursorHeight+"px",i.other&&((r=n.appendChild(O("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"))).style.display="",r.style.left=i.other.left+"px",r.style.top=i.other.top+"px",r.style.height=.85*(i.other.bottom-i.other.top)+"px")}function dr(e,t){return e.top-t.top||e.left-t.left}function fr(e){var t,n;e.state.focused&&(t=e.display,clearInterval(t.blinker),n=!0,t.cursorDiv.style.visibility="",0<e.options.cursorBlinkRate?t.blinker=setInterval(function(){e.hasFocus()||vr(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden"))}function pr(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||mr(e))}function gr(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&vr(e))},100)}function mr(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(Se(e,"focus",e,t),e.state.focused=!0,H(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),v&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),fr(e))}function vr(e,t){e.state.delayingBlurEvent||(e.state.focused&&(Se(e,"blur",e,t),e.state.focused=!1,T(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function yr(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=0;r<t.view.length;r++){var i,o,l=t.view[r],s=e.options.lineWrapping,a=void 0,u=0;if(!l.hidden){L&&x<8?(a=(i=l.node.offsetTop+l.node.offsetHeight)-n,n=i):(a=(o=l.node.getBoundingClientRect()).bottom-o.top,!s&&l.text.firstChild&&(u=l.text.firstChild.getBoundingClientRect().right-o.left-1));var c,h=l.line.height-a;if((.005<h||h<-.005)&&(tt(l.line,a),br(l.line),l.rest))for(var d=0;d<l.rest.length;d++)br(l.rest[d]);u>e.display.sizerWidth&&((c=Math.ceil(u/Zn(e.display)))>e.display.maxLineLength&&(e.display.maxLineLength=c,e.display.maxLine=l.line,e.display.maxLineChanged=!0))}}}function br(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t){var n=e.widgets[t],r=n.node.parentNode;r&&(n.height=r.offsetHeight)}}function wr(e,t,n){var r,i,o=n&&null!=n.top?Math.max(0,n.top):e.scroller.scrollTop,o=Math.floor(o-wn(e)),l=n&&null!=n.bottom?n.bottom:o+e.wrapper.clientHeight,s=rt(t,o),a=rt(t,l);return n&&n.ensure&&(r=n.ensure.from.line,i=n.ensure.to.line,r<s?a=rt(t,Xt(Qe(t,s=r))+e.wrapper.clientHeight):Math.min(i,t.lastLine())>=a&&(s=rt(t,Xt(Qe(t,i))-e.wrapper.clientHeight),a=i)),{from:s,to:Math.max(a,s+1)}}function xr(e,t){var n=e.display,r=qn(e.display);t.top<0&&(t.top=0);var i=e.curOp&&null!=e.curOp.scrollTop?e.curOp.scrollTop:n.scroller.scrollTop,o=kn(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s,a=e.doc.height+xn(n),u=t.top<r,c=t.bottom>a-r;t.top<i?l.scrollTop=u?0:t.top:t.bottom>i+o&&((s=Math.min(t.top,(c?a:t.bottom)-o))!=i&&(l.scrollTop=s));var h=e.options.fixedGutter?0:n.gutters.offsetWidth,d=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-h,f=Ln(e)-n.gutters.offsetWidth,p=t.right-t.left>f;return p&&(t.right=t.left+f),t.left<10?l.scrollLeft=0:t.left<d?l.scrollLeft=Math.max(0,t.left+h-(p?0:10)):t.right>f+d-3&&(l.scrollLeft=t.right+(p?0:10)-f),l}function Cr(e,t){null!=t&&(kr(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc.scrollTop:e.curOp.scrollTop)+t)}function Sr(e){kr(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function Lr(e,t,n){null==t&&null==n||kr(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function kr(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Tr(e,Kn(e,t.from),Kn(e,t.to),t.margin))}function Tr(e,t,n,r){var i=xr(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});Lr(e,i.scrollLeft,i.scrollTop)}function Mr(e,t){Math.abs(e.doc.scrollTop-t)<2||(g||$r(e,{top:t}),Nr(e,t,!0),g&&$r(e),Kr(e,100))}function Nr(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),e.display.scroller.scrollTop==t&&!n||(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Ar(e,t,n,r){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,Qr(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Or(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+xn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+Sn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}function Dr(e,t,n){this.cm=n;var r=this.vert=O("div",[O("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=O("div",[O("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");r.tabIndex=i.tabIndex=-1,e(r),e(i),we(r,"scroll",function(){r.clientHeight&&t(r.scrollTop,"vertical")}),we(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,L&&x<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")}Dr.prototype.update=function(e){var t,n,r=e.scrollWidth>e.clientWidth+1,i=e.scrollHeight>e.clientHeight+1,o=e.nativeBarWidth;return i?(this.vert.style.display="block",this.vert.style.bottom=r?o+"px":"0",t=e.viewHeight-(r?o:0),this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+t)+"px"):(this.vert.style.display="",this.vert.firstChild.style.height="0"),r?(this.horiz.style.display="block",this.horiz.style.right=i?o+"px":"0",this.horiz.style.left=e.barLeft+"px",n=e.viewWidth-e.barLeft-(i?o:0),this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+n)+"px"):(this.horiz.style.display="",this.horiz.firstChild.style.width="0"),!this.checkedZeroWidth&&0<e.clientHeight&&(0==o&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:i?o:0,bottom:r?o:0}},Dr.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},Dr.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},Dr.prototype.zeroWidthHack=function(){var e=y&&!s?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new z,this.disableVert=new z},Dr.prototype.enableZeroWidthBar=function(n,r,i){n.style.pointerEvents="auto",r.set(1e3,function e(){var t=n.getBoundingClientRect();("vert"==i?document.elementFromPoint(t.right-1,(t.top+t.bottom)/2):document.elementFromPoint((t.right+t.left)/2,t.bottom-1))!=n?n.style.pointerEvents="none":r.set(1e3,e)})},Dr.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};function Wr(){}function Hr(e,t){t=t||Or(e);var n=e.display.barWidth,r=e.display.barHeight;Fr(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&yr(e),Fr(e,Or(e)),n=e.display.barWidth,r=e.display.barHeight}function Fr(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}Wr.prototype.update=function(){return{bottom:0,right:0}},Wr.prototype.setScrollLeft=function(){},Wr.prototype.setScrollTop=function(){},Wr.prototype.clear=function(){};var Er={native:Dr,null:Wr};function Pr(n){n.display.scrollbars&&(n.display.scrollbars.clear(),n.display.scrollbars.addClass&&T(n.display.wrapper,n.display.scrollbars.addClass)),n.display.scrollbars=new Er[n.options.scrollbarStyle](function(e){n.display.wrapper.insertBefore(e,n.display.scrollbarFiller),we(e,"mousedown",function(){n.state.focused&&setTimeout(function(){return n.display.input.focus()},0)}),e.setAttribute("cm-not-content","true")},function(e,t){("horizontal"==t?Ar:Mr)(n,e)},n),n.display.scrollbars.addClass&&H(n.display.wrapper,n.display.scrollbars.addClass)}var Ir=0;function Rr(e){var t;e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Ir},t=e.curOp,ln?ln.ops.push(t):t.ownsGroup=ln={ops:[t],delayedCallbacks:[]}}function zr(e){var t=e.curOp;t&&sn(t,function(e){for(var t=0;t<e.ops.length;t++)e.ops[t].cm.curOp=null;!function(e){for(var t=e.ops,n=0;n<t.length;n++)!function(e){var t=e.cm,n=t.display;(function(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=Sn(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=Sn(e)+"px",t.scrollbarsClipped=!0)})(t),e.updateMaxLine&&_t(t);e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<n.viewFrom||e.scrollToPos.to.line>=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new Xr(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}(t[n]);for(var r=0;r<t.length;r++)!function(e){e.updatedDisplay=e.mustUpdate&&Yr(e.cm,e.update)}(t[r]);for(var i=0;i<t.length;i++)!function(e){var t=e.cm,n=t.display;e.updatedDisplay&&yr(t);e.barMeasure=Or(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Mn(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+Sn(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-Ln(t)));(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}(t[i]);for(var o=0;o<t.length;o++)!function(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&Ar(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1);var n=e.focus&&e.focus==W();e.preparedSelection&&t.display.input.showSelection(e.preparedSelection,n);!e.updatedDisplay&&e.startHeight==t.doc.height||Hr(t,e.barMeasure);e.updatedDisplay&&Zr(t,e.barMeasure);e.selectionChanged&&fr(t);t.state.focused&&e.updateInput&&t.display.input.reset(e.typing);n&&pr(e.cm)}(t[o]);for(var l=0;l<t.length;l++)!function(e){var t=e.cm,n=t.display,r=t.doc;e.updatedDisplay&&_r(t,e.update);null==n.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(n.wheelStartX=n.wheelStartY=null);null!=e.scrollTop&&Nr(t,e.scrollTop,e.forceScroll);null!=e.scrollLeft&&Ar(t,e.scrollLeft,!0,!0);{var i;e.scrollToPos&&(i=function(e,t,n,r){null==r&&(r=0),e.options.lineWrapping||t!=n||(n="before"==(t=t.ch?lt(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?lt(t.line,t.ch+1,"before"):t);for(var i=0;i<5;i++){var o,l=!1,s=Vn(e,t),a=n&&n!=t?Vn(e,n):s,u=xr(e,o={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-r,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+r}),c=e.doc.scrollTop,h=e.doc.scrollLeft;if(null!=u.scrollTop&&(Mr(e,u.scrollTop),1<Math.abs(e.doc.scrollTop-c)&&(l=!0)),null!=u.scrollLeft&&(Ar(e,u.scrollLeft),1<Math.abs(e.doc.scrollLeft-h)&&(l=!0)),!l)break}return o}(t,ft(r,e.scrollToPos.from),ft(r,e.scrollToPos.to),e.scrollToPos.margin),function(e,t){var n,r,i,o;Le(e,"scrollCursorIntoView")||(r=(n=e.display).sizer.getBoundingClientRect(),i=null,t.top+r.top<0?i=!0:t.bottom+r.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null==i||u||(o=O("div","​",null,"position: absolute;\n top: "+(t.top-n.viewOffset-wn(e.display))+"px;\n height: "+(t.bottom-t.top+Sn(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;"),e.display.lineSpace.appendChild(o),o.scrollIntoView(i),e.display.lineSpace.removeChild(o)))}(t,i))}var o=e.maybeHiddenMarkers,l=e.maybeUnhiddenMarkers;if(o)for(var s=0;s<o.length;++s)o[s].lines.length||Se(o[s],"hide");if(l)for(var a=0;a<l.length;++a)l[a].lines.length&&Se(l[a],"unhide");n.wrapper.offsetHeight&&(r.scrollTop=t.display.scroller.scrollTop);e.changeObjs&&Se(t,"changes",t,e.changeObjs);e.update&&e.update.finish()}(t[l])}(e)})}function Br(e,t){if(e.curOp)return t();Rr(e);try{return t()}finally{zr(e)}}function Gr(e,t){return function(){if(e.curOp)return t.apply(e,arguments);Rr(e);try{return t.apply(e,arguments)}finally{zr(e)}}}function Ur(e){return function(){if(this.curOp)return e.apply(this,arguments);Rr(this);try{return e.apply(this,arguments)}finally{zr(this)}}}function Vr(t){return function(){var e=this.cm;if(!e||e.curOp)return t.apply(this,arguments);Rr(e);try{return t.apply(this,arguments)}finally{zr(e)}}}function Kr(e,t){e.doc.highlightFrontier<e.display.viewTo&&e.state.highlight.set(t,P(jr,e))}function jr(a){var u,c,h,d=a.doc;d.highlightFrontier>=a.display.viewTo||(u=+new Date+a.options.workTime,c=bt(a,d.highlightFrontier),h=[],d.iter(c.line,Math.min(d.first+d.size,a.display.viewTo+500),function(e){if(c.line>=a.display.viewFrom){var t=e.styles,n=e.text.length>a.options.maxHighlightLength?_e(d.mode,c.state):null,r=vt(a,e,c,!0);n&&(c.state=n),e.styles=r.styles;var i=e.styleClasses,o=r.classes;o?e.styleClasses=o:i&&(e.styleClasses=null);for(var l=!t||t.length!=e.styles.length||i!=o&&(!i||!o||i.bgClass!=o.bgClass||i.textClass!=o.textClass),s=0;!l&&s<t.length;++s)l=t[s]!=e.styles[s];l&&h.push(c.line),e.stateAfter=c.save(),c.nextLine()}else e.text.length<=a.options.maxHighlightLength&&wt(a,e.text,c),e.stateAfter=c.line%5==0?c.save():null,c.nextLine();if(+new Date>u)return Kr(a,a.options.workDelay),!0}),d.highlightFrontier=c.line,d.modeFrontier=Math.max(d.modeFrontier,c.line),h.length&&Br(a,function(){for(var e=0;e<h.length;e++)or(a,h[e],"text")}))}var Xr=function(e,t,n){var r=e.display;this.viewport=t,this.visible=wr(r,e.doc,t),this.editorIsHidden=!r.wrapper.offsetWidth,this.wrapperHeight=r.wrapper.clientHeight,this.wrapperWidth=r.wrapper.clientWidth,this.oldDisplayWidth=Ln(e),this.force=n,this.dims=Qn(e),this.events=[]};function Yr(e,t){var n=e.display,r=e.doc;if(t.editorIsHidden)return lr(e),!1;if(!t.force&&t.visible.from>=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==ar(e))return!1;Jr(e)&&(lr(e),t.dims=Qn(e));var i=r.first+r.size,o=Math.max(t.visible.from-e.options.viewportMargin,r.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);n.viewFrom<o&&o-n.viewFrom<20&&(o=Math.max(r.first,n.viewFrom)),n.viewTo>l&&n.viewTo-l<20&&(l=Math.min(i,n.viewTo)),Nt&&(o=Vt(e.doc,o),l=Kt(e.doc,l));var s,a,u,c,h=o!=n.viewFrom||l!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;a=o,u=l,0==(c=(s=e).display).view.length||a>=c.viewTo||u<=c.viewFrom?(c.view=on(s,a,u),c.viewFrom=a):(c.viewFrom>a?c.view=on(s,a,c.viewFrom).concat(c.view):c.viewFrom<a&&(c.view=c.view.slice(rr(s,a))),c.viewFrom=a,c.viewTo<u?c.view=c.view.concat(on(s,c.viewTo,u)):c.viewTo>u&&(c.view=c.view.slice(0,rr(s,u)))),c.viewTo=u,n.viewOffset=Xt(Qe(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";var d=ar(e);if(!h&&0==d&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;var f,p,g,m=function(e){if(e.hasFocus())return null;var t=W();if(!t||!D(e.display.lineDiv,t))return null;var n,r={activeElt:t};return!window.getSelection||(n=window.getSelection()).anchorNode&&n.extend&&D(e.display.lineDiv,n.anchorNode)&&(r.anchorNode=n.anchorNode,r.anchorOffset=n.anchorOffset,r.focusNode=n.focusNode,r.focusOffset=n.focusOffset),r}(e);return 4<d&&(n.lineDiv.style.display="none"),function(n,e,t){var r=n.display,i=n.options.lineNumbers,o=r.lineDiv,l=o.firstChild;function s(e){var t=e.nextSibling;return v&&y&&n.display.currentWheelTarget==e?e.style.display="none":e.parentNode.removeChild(e),t}for(var a=r.view,u=r.viewFrom,c=0;c<a.length;c++){var h=a[c];if(!h.hidden)if(h.node&&h.node.parentNode==o){for(;l!=h.node;)l=s(l);var d=i&&null!=e&&e<=u&&h.lineNumber;h.changes&&(-1<B(h.changes,"gutter")&&(d=!1),hn(n,h,u,t)),d&&(M(h.lineNumber),h.lineNumber.appendChild(document.createTextNode(ot(n.options,u)))),l=h.node.nextSibling}else{var f=function(e,t,n,r){var i=fn(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),pn(e,t),gn(e,t,n,r),mn(e,t,r),t.node}(n,h,u,t);o.insertBefore(f,l)}u+=h.size}for(;l;)l=s(l)}(e,n.updateLineNumbers,t.dims),4<d&&(n.lineDiv.style.display=""),n.renderedView=n.view,(f=m)&&f.activeElt&&f.activeElt!=W()&&(f.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(f.activeElt.nodeName)&&f.anchorNode&&D(document.body,f.anchorNode)&&D(document.body,f.focusNode)&&(p=window.getSelection(),(g=document.createRange()).setEnd(f.anchorNode,f.anchorOffset),g.collapse(!1),p.removeAllRanges(),p.addRange(g),p.extend(f.focusNode,f.focusOffset))),M(n.cursorDiv),M(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,h&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,Kr(e,400)),!(n.updateLineNumbers=null)}function _r(e,t){for(var n=t.viewport,r=!0;;r=!1){if(r&&e.options.lineWrapping&&t.oldDisplayWidth!=Ln(e))r&&(t.visible=wr(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+xn(e.display)-kn(e),n.top)}),t.visible=wr(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!Yr(e,t))break;yr(e);var i=Or(e);ur(e),Hr(e,i),Zr(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function $r(e,t){var n,r=new Xr(e,t);Yr(e,r)&&(yr(e),_r(e,r),n=Or(e),ur(e),Hr(e,n),Zr(e,n),r.finish())}function qr(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function Zr(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+Sn(e)+"px"}function Qr(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=Jn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=r+"px",l=0;l<n.length;l++)if(!n[l].hidden){e.options.fixedGutter&&(n[l].gutter&&(n[l].gutter.style.left=o),n[l].gutterBackground&&(n[l].gutterBackground.style.left=o));var s=n[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=r+i+"px")}}function Jr(e){if(e.options.lineNumbers){var t=e.doc,n=ot(e.options,t.first+t.size-1),r=e.display;if(n.length!=r.lineNumChars){var i=r.measure.appendChild(O("div",[O("div",n)],"CodeMirror-linenumber CodeMirror-gutter-elt")),o=i.firstChild.offsetWidth,l=i.offsetWidth-o;return r.lineGutter.style.width="",r.lineNumInnerWidth=Math.max(o,r.lineGutter.offsetWidth-l)+1,r.lineNumWidth=r.lineNumInnerWidth+l,r.lineNumChars=r.lineNumInnerWidth?n.length:-1,r.lineGutter.style.width=r.lineNumWidth+"px",qr(e.display),1}}}function ei(e,t){for(var n=[],r=!1,i=0;i<e.length;i++){var o=e[i],l=null;if("string"!=typeof o&&(l=o.style,o=o.className),"CodeMirror-linenumbers"==o){if(!t)continue;r=!0}n.push({className:o,style:l})}return t&&!r&&n.push({className:"CodeMirror-linenumbers",style:null}),n}function ti(e){var t=e.gutters,n=e.gutterSpecs;M(t),e.lineGutter=null;for(var r=0;r<n.length;++r){var i=n[r],o=i.className,l=i.style,s=t.appendChild(O("div",null,"CodeMirror-gutter "+o));l&&(s.style.cssText=l),"CodeMirror-linenumbers"==o&&((e.lineGutter=s).style.width=(e.lineNumWidth||1)+"px")}t.style.display=n.length?"":"none",qr(e)}function ni(e){ti(e.display),ir(e),Qr(e)}function ri(e,t,n,r){var i=this;this.input=n,i.scrollbarFiller=O("div",null,"CodeMirror-scrollbar-filler"),i.scrollbarFiller.setAttribute("cm-not-content","true"),i.gutterFiller=O("div",null,"CodeMirror-gutter-filler"),i.gutterFiller.setAttribute("cm-not-content","true"),i.lineDiv=A("div",null,"CodeMirror-code"),i.selectionDiv=O("div",null,null,"position: relative; z-index: 1"),i.cursorDiv=O("div",null,"CodeMirror-cursors"),i.measure=O("div",null,"CodeMirror-measure"),i.lineMeasure=O("div",null,"CodeMirror-measure"),i.lineSpace=A("div",[i.measure,i.lineMeasure,i.selectionDiv,i.cursorDiv,i.lineDiv],null,"position: relative; outline: none");var o=A("div",[i.lineSpace],"CodeMirror-lines");i.mover=O("div",[o],null,"position: relative"),i.sizer=O("div",[i.mover],"CodeMirror-sizer"),i.sizerWidth=null,i.heightForcer=O("div",null,null,"position: absolute; height: "+G+"px; width: 1px;"),i.gutters=O("div",null,"CodeMirror-gutters"),i.lineGutter=null,i.scroller=O("div",[i.sizer,i.heightForcer,i.gutters],"CodeMirror-scroll"),i.scroller.setAttribute("tabIndex","-1"),i.wrapper=O("div",[i.scrollbarFiller,i.gutterFiller,i.scroller],"CodeMirror"),L&&x<8&&(i.gutters.style.zIndex=-1,i.scroller.style.paddingRight=0),v||g&&d||(i.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(i.wrapper):e(i.wrapper)),i.viewFrom=i.viewTo=t.first,i.reportedViewFrom=i.reportedViewTo=t.first,i.view=[],i.renderedView=null,i.externalMeasured=null,i.viewOffset=0,i.lastWrapHeight=i.lastWrapWidth=0,i.updateLineNumbers=null,i.nativeBarWidth=i.barHeight=i.barWidth=0,i.scrollbarsClipped=!1,i.lineNumWidth=i.lineNumInnerWidth=i.lineNumChars=null,i.alignWidgets=!1,i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.maxLine=null,i.maxLineLength=0,i.maxLineChanged=!1,i.wheelDX=i.wheelDY=i.wheelStartX=i.wheelStartY=null,i.shift=!1,i.selForContextMenu=null,i.activeTouch=null,i.gutterSpecs=ei(r.gutters,r.lineNumbers),ti(i),n.init(i)}Xr.prototype.signal=function(e,t){Te(e,t)&&this.events.push(arguments)},Xr.prototype.finish=function(){for(var e=0;e<this.events.length;e++)Se.apply(null,this.events[e])};var ii=0,oi=null;function li(e){var t=e.wheelDeltaX,n=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==n&&e.detail&&e.axis==e.VERTICAL_AXIS?n=e.detail:null==n&&(n=e.wheelDelta),{x:t,y:n}}function si(e){var t=li(e);return t.x*=oi,t.y*=oi,t}function ai(e,t){var n,r,i,o=li(t),l=o.x,s=o.y,a=e.display,u=a.scroller,c=u.scrollWidth>u.clientWidth,h=u.scrollHeight>u.clientHeight;if(l&&c||s&&h){if(s&&y&&v)e:for(var d=t.target,f=a.view;d!=u;d=d.parentNode)for(var p=0;p<f.length;p++)if(f[p].node==d){e.display.currentWheelTarget=d;break e}if(l&&!g&&!m&&null!=oi)return s&&h&&Mr(e,Math.max(0,u.scrollTop+s*oi)),Ar(e,Math.max(0,u.scrollLeft+l*oi)),(!s||s&&h)&&Ne(t),void(a.wheelStartX=null);s&&null!=oi&&(n=s*oi,i=(r=e.doc.scrollTop)+a.wrapper.clientHeight,n<0?r=Math.max(0,r+n-50):i=Math.min(e.doc.height,i+n+50),$r(e,{top:r,bottom:i})),ii<20&&(null==a.wheelStartX?(a.wheelStartX=u.scrollLeft,a.wheelStartY=u.scrollTop,a.wheelDX=l,a.wheelDY=s,setTimeout(function(){var e,t,n;null!=a.wheelStartX&&(e=u.scrollLeft-a.wheelStartX,n=(t=u.scrollTop-a.wheelStartY)&&a.wheelDY&&t/a.wheelDY||e&&a.wheelDX&&e/a.wheelDX,a.wheelStartX=a.wheelStartY=null,n&&(oi=(oi*ii+n)/(ii+1),++ii))},200)):(a.wheelDX+=l,a.wheelDY+=s))}}L?oi=-.53:g?oi=15:l?oi=-.7:c&&(oi=-1/3);var ui=function(e,t){this.ranges=e,this.primIndex=t};ui.prototype.primary=function(){return this.ranges[this.primIndex]},ui.prototype.equals=function(e){if(e==this)return!0;if(e.primIndex!=this.primIndex||e.ranges.length!=this.ranges.length)return!1;for(var t=0;t<this.ranges.length;t++){var n=this.ranges[t],r=e.ranges[t];if(!at(n.anchor,r.anchor)||!at(n.head,r.head))return!1}return!0},ui.prototype.deepCopy=function(){for(var e=[],t=0;t<this.ranges.length;t++)e[t]=new ci(ut(this.ranges[t].anchor),ut(this.ranges[t].head));return new ui(e,this.primIndex)},ui.prototype.somethingSelected=function(){for(var e=0;e<this.ranges.length;e++)if(!this.ranges[e].empty())return!0;return!1},ui.prototype.contains=function(e,t){t=t||e;for(var n=0;n<this.ranges.length;n++){var r=this.ranges[n];if(0<=st(t,r.from())&&st(e,r.to())<=0)return n}return-1};var ci=function(e,t){this.anchor=e,this.head=t};function hi(e,t,n){var r=e&&e.options.selectionsMayTouch,i=t[n];t.sort(function(e,t){return st(e.from(),t.from())}),n=B(t,i);for(var o=1;o<t.length;o++){var l,s,a,u=t[o],c=t[o-1],h=st(c.to(),u.from());(r&&!u.empty()?0<h:0<=h)&&(l=ht(c.from(),u.from()),s=ct(c.to(),u.to()),a=c.empty()?u.from()==u.head:c.from()==c.head,o<=n&&--n,t.splice(--o,2,new ci(a?s:l,a?l:s)))}return new ui(t,n)}function di(e,t){return new ui([new ci(e,t||e)],0)}function fi(e){return e.text?lt(e.from.line+e.text.length-1,$(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function pi(e,t){if(st(e,t.from)<0)return e;if(st(e,t.to)<=0)return fi(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=fi(t).ch-t.to.ch),lt(n,r)}function gi(e,t){for(var n=[],r=0;r<e.sel.ranges.length;r++){var i=e.sel.ranges[r];n.push(new ci(pi(i.anchor,t),pi(i.head,t)))}return hi(e.cm,n,e.sel.primIndex)}function mi(e,t,n){return e.line==t.line?lt(n.line,e.ch-t.ch+n.ch):lt(n.line+(e.line-t.line),e.ch)}function vi(e){e.doc.mode=je(e.options,e.doc.modeOption),yi(e)}function yi(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.modeFrontier=e.doc.highlightFrontier=e.doc.first,Kr(e,100),e.state.modeGen++,e.curOp&&ir(e)}function bi(e,t){return 0==t.from.ch&&0==t.to.ch&&""==$(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function wi(e,r,t,i){function o(e){return t?t[e]:null}function n(e,t,n){!function(e,t,n,r){e.text=t,e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null),null!=e.order&&(e.order=null),Ht(e),Ft(e,n);var i=r?r(e):1;i!=e.height&&tt(e,i)}(e,t,n,i),un(e,"change",e,r)}function l(e,t){for(var n=[],r=e;r<t;++r)n.push(new $t(d[r],o(r),i));return n}var s,a,u,c=r.from,h=r.to,d=r.text,f=Qe(e,c.line),p=Qe(e,h.line),g=$(d),m=o(d.length-1),v=h.line-c.line;r.full?(e.insert(0,l(0,d.length)),e.remove(d.length,e.size-d.length)):bi(e,r)?(s=l(0,d.length-1),n(p,p.text,m),v&&e.remove(c.line,v),s.length&&e.insert(c.line,s)):f==p?1==d.length?n(f,f.text.slice(0,c.ch)+g+f.text.slice(h.ch),m):((a=l(1,d.length-1)).push(new $t(g+f.text.slice(h.ch),m,i)),n(f,f.text.slice(0,c.ch)+d[0],o(0)),e.insert(c.line+1,a)):1==d.length?(n(f,f.text.slice(0,c.ch)+d[0]+p.text.slice(h.ch),o(0)),e.remove(c.line+1,v)):(n(f,f.text.slice(0,c.ch)+d[0],o(0)),n(p,g+p.text.slice(h.ch),m),u=l(1,d.length-1),1<v&&e.remove(c.line+1,v-1),e.insert(c.line+1,u)),un(e,"change",e,r)}function xi(e,s,a){!function e(t,n,r){if(t.linked)for(var i=0;i<t.linked.length;++i){var o,l=t.linked[i];l.doc!=n&&(o=r&&l.sharedHist,a&&!o||(s(l.doc,o),e(l.doc,t,o)))}}(e,null,!0)}function Ci(e,t){if(t.cm)throw new Error("This document is already in use.");tr((e.doc=t).cm=e),vi(e),Si(e),e.options.lineWrapping||_t(e),e.options.mode=t.modeOption,ir(e)}function Si(e){("rtl"==e.doc.direction?H:T)(e.display.lineDiv,"CodeMirror-rtl")}function Li(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function ki(e,t){var n={from:ut(t.from),to:fi(t),text:Je(e,t.from,t.to)};return Oi(e,n,t.from.line,t.to.line+1),xi(e,function(e){return Oi(e,n,t.from.line,t.to.line+1),0},!0),n}function Ti(e){for(;e.length;){if(!$(e).ranges)break;e.pop()}}function Mi(e,t,n,r){var i=e.history;i.undone.length=0;var o,l,s,a=+new Date;if((i.lastOp==r||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>a-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=(s=i).lastOp==r?(Ti(s.done),$(s.done)):s.done.length&&!$(s.done).ranges?$(s.done):1<s.done.length&&!s.done[s.done.length-2].ranges?(s.done.pop(),$(s.done)):void 0))l=$(o.changes),0==st(t.from,t.to)&&0==st(t.from,l.to)?l.to=fi(t):o.changes.push(ki(e,t));else{var u=$(i.done);for(u&&u.ranges||Ai(e.sel,i.done),o={changes:[ki(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(n),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=a,i.lastOp=i.lastSelOp=r,i.lastOrigin=i.lastSelOrigin=t.origin,l||Se(e,"historyAdded")}function Ni(e,t,n,r){var i,o,l,s,a,u=e.history,c=r&&r.origin;n==u.lastSelOp||c&&u.lastSelOrigin==c&&(u.lastModTime==u.lastSelTime&&u.lastOrigin==c||(i=e,o=c,l=$(u.done),s=t,"*"==(a=o.charAt(0))||"+"==a&&l.ranges.length==s.ranges.length&&l.somethingSelected()==s.somethingSelected()&&new Date-i.history.lastSelTime<=(i.cm?i.cm.options.historyEventDelay:500)))?u.done[u.done.length-1]=t:Ai(t,u.done),u.lastSelTime=+new Date,u.lastSelOrigin=c,u.lastSelOp=n,r&&!1!==r.clearRedo&&Ti(u.undone)}function Ai(e,t){var n=$(t);n&&n.ranges&&n.equals(e)||t.push(e)}function Oi(t,n,e,r){var i=n["spans_"+t.id],o=0;t.iter(Math.max(t.first,e),Math.min(t.first+t.size,r),function(e){e.markedSpans&&((i=i||(n["spans_"+t.id]={}))[o]=e.markedSpans),++o})}function Di(e,t){var n=t["spans_"+e.id];if(!n)return null;for(var r=[],i=0;i<t.text.length;++i)r.push(function(e){if(!e)return null;for(var t,n=0;n<e.length;++n)e[n].marker.explicitlyCleared?t=t||e.slice(0,n):t&&t.push(e[n]);return t?t.length?t:null:e}(n[i]));return r}function Wi(e,t){var n=Di(e,t),r=Dt(e,t);if(!n)return r;if(!r)return n;for(var i=0;i<n.length;++i){var o=n[i],l=r[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(n[i]=l)}return n}function Hi(e,t,n){for(var r=[],i=0;i<e.length;++i){var o=e[i];if(o.ranges)r.push(n?ui.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];r.push({changes:s});for(var a=0;a<l.length;++a){var u=l[a],c=void 0;if(s.push({from:u.from,to:u.to,text:u.text}),t)for(var h in u)(c=h.match(/^spans_(\d+)$/))&&-1<B(t,Number(c[1]))&&($(s)[h]=u[h],delete u[h])}}}return r}function Fi(e,t,n,r){if(r){var i,o=e.anchor;return n&&((i=st(t,o)<0)!=st(n,o)<0?(o=t,t=n):i!=st(t,n)<0&&(t=n)),new ci(o,t)}return new ci(n||t,t)}function Ei(e,t,n,r,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),Bi(e,new ui([Fi(e.sel.primary(),t,n,i)],0),r)}function Pi(e,t,n){for(var r=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o<e.sel.ranges.length;o++)r[o]=Fi(e.sel.ranges[o],t[o],null,i);Bi(e,hi(e.cm,r,e.sel.primIndex),n)}function Ii(e,t,n,r){var i=e.sel.ranges.slice(0);i[t]=n,Bi(e,hi(e.cm,i,e.sel.primIndex),r)}function Ri(e,t,n,r){Bi(e,di(t,n),r)}function zi(e,t,n){var r=e.history.done,i=$(r);i&&i.ranges?Gi(e,r[r.length-1]=t,n):Bi(e,t,n)}function Bi(e,t,n){Gi(e,t,n),Ni(e,e.sel,e.cm?e.cm.curOp.id:NaN,n)}function Gi(e,t,n){var r,i,o,l;(Te(e,"beforeSelectionChange")||e.cm&&Te(e.cm,"beforeSelectionChange"))&&(r=e,o=n,l={ranges:(i=t).ranges,update:function(e){this.ranges=[];for(var t=0;t<e.length;t++)this.ranges[t]=new ci(ft(r,e[t].anchor),ft(r,e[t].head))},origin:o&&o.origin},Se(r,"beforeSelectionChange",r,l),r.cm&&Se(r.cm,"beforeSelectionChange",r.cm,l),t=l.ranges!=i.ranges?hi(r.cm,l.ranges,l.ranges.length-1):i);var s=n&&n.bias||(st(t.primary().head,e.sel.primary().head)<0?-1:1);Ui(e,Ki(e,t,s,!0)),n&&!1===n.scroll||!e.cm||Sr(e.cm)}function Ui(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=1,e.cm.curOp.selectionChanged=!0,ke(e.cm)),un(e,"cursorActivity",e))}function Vi(e){Ui(e,Ki(e,e.sel,null,!1))}function Ki(e,t,n,r){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=t.ranges.length==e.sel.ranges.length&&e.sel.ranges[o],a=Xi(e,l.anchor,s&&s.anchor,n,r),u=Xi(e,l.head,s&&s.head,n,r);!i&&a==l.anchor&&u==l.head||((i=i||t.ranges.slice(0,o))[o]=new ci(a,u))}return i?hi(e.cm,i,t.primIndex):t}function ji(e,t,n,r,i){var o=Qe(e,t.line);if(o.markedSpans)for(var l=0;l<o.markedSpans.length;++l){var s=o.markedSpans[l],a=s.marker,u="selectLeft"in a?!a.selectLeft:a.inclusiveLeft,c="selectRight"in a?!a.selectRight:a.inclusiveRight;if((null==s.from||(u?s.from<=t.ch:s.from<t.ch))&&(null==s.to||(c?s.to>=t.ch:s.to>t.ch))){if(i&&(Se(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(!a.atomic)continue;if(n){var h=a.find(r<0?1:-1),d=void 0;if((r<0?c:u)&&(h=Yi(e,h,-r,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(d=st(h,n))&&(r<0?d<0:0<d))return ji(e,h,t,r,i)}var f=a.find(r<0?-1:1);return(r<0?u:c)&&(f=Yi(e,f,r,f.line==t.line?o:null)),f?ji(e,f,t,r,i):null}}return t}function Xi(e,t,n,r,i){var o=r||1,l=ji(e,t,n,o,i)||!i&&ji(e,t,n,o,!0)||ji(e,t,n,-o,i)||!i&&ji(e,t,n,-o,!0);return l||(e.cantEdit=!0,lt(e.first,0))}function Yi(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?ft(e,lt(t.line-1)):null:0<n&&t.ch==(r||Qe(e,t.line)).text.length?t.line<e.first+e.size-1?lt(t.line+1,0):null:new lt(t.line,t.ch+n)}function _i(e){e.setSelection(lt(e.firstLine(),0),lt(e.lastLine()),V)}function $i(i,e,t){var o={canceled:!1,from:e.from,to:e.to,text:e.text,origin:e.origin,cancel:function(){return o.canceled=!0}};return t&&(o.update=function(e,t,n,r){e&&(o.from=ft(i,e)),t&&(o.to=ft(i,t)),n&&(o.text=n),void 0!==r&&(o.origin=r)}),Se(i,"beforeChange",i,o),i.cm&&Se(i.cm,"beforeChange",i.cm,o),o.canceled?(i.cm&&(i.cm.curOp.updateInput=2),null):{from:o.from,to:o.to,text:o.text,origin:o.origin}}function qi(e,t,n){if(e.cm){if(!e.cm.curOp)return Gr(e.cm,qi)(e,t,n);if(e.cm.state.suppressEdits)return}if(!(Te(e,"beforeChange")||e.cm&&Te(e.cm,"beforeChange"))||(t=$i(e,t,!0))){var r=Mt&&!n&&function(e,t,n){var r=null;if(e.iter(t.line,n.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var n=e.markedSpans[t].marker;!n.readOnly||r&&-1!=B(r,n)||(r=r||[]).push(n)}}),!r)return null;for(var i=[{from:t,to:n}],o=0;o<r.length;++o)for(var l=r[o],s=l.find(0),a=0;a<i.length;++a){var u,c,h,d=i[a];st(d.to,s.from)<0||0<st(d.from,s.to)||(u=[a,1],c=st(d.from,s.from),h=st(d.to,s.to),(c<0||!l.inclusiveLeft&&!c)&&u.push({from:d.from,to:s.from}),(0<h||!l.inclusiveRight&&!h)&&u.push({from:s.to,to:d.to}),i.splice.apply(i,u),a+=u.length-3)}return i}(e,t.from,t.to);if(r)for(var i=r.length-1;0<=i;--i)Zi(e,{from:r[i].from,to:r[i].to,text:i?[""]:t.text,origin:t.origin});else Zi(e,t)}}function Zi(e,n){var t,r;1==n.text.length&&""==n.text[0]&&0==st(n.from,n.to)||(t=gi(e,n),Mi(e,n,t,e.cm?e.cm.curOp.id:NaN),eo(e,n,t,Dt(e,n)),r=[],xi(e,function(e,t){t||-1!=B(r,e.history)||(io(e.history,n),r.push(e.history)),eo(e,n,null,Dt(e,n))}))}function Qi(i,o,e){var t=i.cm&&i.cm.state.suppressEdits;if(!t||e){for(var l,n=i.history,r=i.sel,s="undo"==o?n.done:n.undone,a="undo"==o?n.undone:n.done,u=0;u<s.length&&(l=s[u],e?!l.ranges||l.equals(i.sel):l.ranges);u++);if(u!=s.length){for(n.lastOrigin=n.lastSelOrigin=null;;){if(!(l=s.pop()).ranges){if(t)return void s.push(l);break}if(Ai(l,a),e&&!l.equals(i.sel))return void Bi(i,l,{clearRedo:!1});r=l}var c=[];Ai(r,a),a.push({changes:c,generation:n.generation}),n.generation=l.generation||++n.maxGeneration;for(var h=Te(i,"beforeChange")||i.cm&&Te(i.cm,"beforeChange"),d=l.changes.length-1;0<=d;--d){var f=function(e){var n=l.changes[e];if(n.origin=o,h&&!$i(i,n,!1))return s.length=0,{};c.push(ki(i,n));var t=e?gi(i,n):$(s);eo(i,n,t,Wi(i,n)),!e&&i.cm&&i.cm.scrollIntoView({from:n.from,to:fi(n)});var r=[];xi(i,function(e,t){t||-1!=B(r,e.history)||(io(e.history,n),r.push(e.history)),eo(e,n,null,Wi(e,n))})}(d);if(f)return f.v}}}}function Ji(e,t){if(0!=t&&(e.first+=t,e.sel=new ui(q(e.sel.ranges,function(e){return new ci(lt(e.anchor.line+t,e.anchor.ch),lt(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){ir(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;r<n.viewTo;r++)or(e.cm,r,"gutter")}}function eo(e,t,n,r){if(e.cm&&!e.cm.curOp)return Gr(e.cm,eo)(e,t,n,r);var i,o;t.to.line<e.first?Ji(e,t.text.length-1-(t.to.line-t.from.line)):t.from.line>e.lastLine()||(t.from.line<e.first&&(Ji(e,i=t.text.length-1-(e.first-t.from.line)),t={from:lt(e.first,0),to:lt(t.to.line+i,t.to.ch),text:[$(t.text)],origin:t.origin}),o=e.lastLine(),t.to.line>o&&(t={from:t.from,to:lt(o,Qe(e,o).text.length),text:[t.text[0]],origin:t.origin}),t.removed=Je(e,t.from,t.to),n=n||gi(e,t),e.cm?function(e,t,n){var r=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=nt(Ut(Qe(r,o.line))),r.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0}));-1<r.sel.contains(t.from,t.to)&&ke(e);wi(r,t,n,er(e)),e.options.lineWrapping||(r.iter(a,o.line+t.text.length,function(e){var t=Yt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontier<t-10)){for(var n=e.first,r=t-1;n<r;r--){var i=Qe(e,r).stateAfter;if(i&&(!(i instanceof gt)||r+i.lookAhead<t)){n=r+1;break}}e.highlightFrontier=Math.min(e.highlightFrontier,n)}})(r,o.line),Kr(e,400);var u=t.text.length-(l.line-o.line)-1;t.full?ir(e):o.line!=l.line||1!=t.text.length||bi(e.doc,t)?ir(e,o.line,l.line+1,u):or(e,o.line,"text");var c=Te(e,"changes"),h=Te(e,"change");{var d;(h||c)&&(d={from:o,to:l,text:t.text,removed:t.removed,origin:t.origin},h&&un(e,"change",e,d),c&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(d))}e.display.selForContextMenu=null}(e.cm,t,r):wi(e,t,r),Gi(e,n,V),e.cantEdit&&Xi(e,lt(e.firstLine(),0))&&(e.cantEdit=!1))}function to(e,t,n,r,i){var o;st(r=r||n,n)<0&&(n=(o=[r,n])[0],r=o[1]),"string"==typeof t&&(t=e.splitLines(t)),qi(e,{from:n,to:r,text:t,origin:i})}function no(e,t,n,r){n<e.line?e.line+=r:t<e.line&&(e.line=t,e.ch=0)}function ro(e,t,n,r){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||((o=e[i]=o.deepCopy()).copied=!0);for(var s=0;s<o.ranges.length;s++)no(o.ranges[s].anchor,t,n,r),no(o.ranges[s].head,t,n,r)}else{for(var a=0;a<o.changes.length;++a){var u=o.changes[a];if(n<u.from.line)u.from=lt(u.from.line+r,u.from.ch),u.to=lt(u.to.line+r,u.to.ch);else if(t<=u.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function io(e,t){var n=t.from.line,r=t.to.line,i=t.text.length-(r-n)-1;ro(e.done,n,r,i),ro(e.undone,n,r,i)}function oo(e,t,n,r){var i=t,o=t;return"number"==typeof t?o=Qe(e,dt(e,t)):i=nt(t),null==i?null:(r(o,i)&&e.cm&&or(e.cm,i,n),o)}function lo(e){this.lines=e,this.parent=null;for(var t=0,n=0;n<e.length;++n)e[n].parent=this,t+=e[n].height;this.height=t}function so(e){this.children=e;for(var t=0,n=0,r=0;r<e.length;++r){var i=e[r];t+=i.chunkSize(),n+=i.height,i.parent=this}this.size=t,this.height=n,this.parent=null}ci.prototype.from=function(){return ht(this.anchor,this.head)},ci.prototype.to=function(){return ct(this.anchor,this.head)},ci.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch},lo.prototype={chunkSize:function(){return this.lines.length},removeInner:function(e,t){for(var n,r=e,i=e+t;r<i;++r){var o=this.lines[r];this.height-=o.height,(n=o).parent=null,Ht(n),un(o,"delete")}this.lines.splice(e,t)},collapse:function(e){e.push.apply(e,this.lines)},insertInner:function(e,t,n){this.height+=n,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var r=0;r<t.length;++r)t[r].parent=this},iterN:function(e,t,n){for(var r=e+t;e<r;++e)if(n(this.lines[e]))return!0}},so.prototype={chunkSize:function(){return this.size},removeInner:function(e,t){this.size-=t;for(var n,r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e),s=i.height;if(i.removeInner(e,l),this.height-=s-i.height,o==l&&(this.children.splice(r--,1),i.parent=null),0==(t-=l))break;e=0}else e-=o}this.size-t<25&&(1<this.children.length||!(this.children[0]instanceof lo))&&(n=[],this.collapse(n),this.children=[new lo(n)],this.children[0].parent=this)},collapse:function(e){for(var t=0;t<this.children.length;++t)this.children[t].collapse(e)},insertInner:function(e,t,n){this.size+=t.length,this.height+=n;for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<=o){if(i.insertInner(e,t,n),i.lines&&50<i.lines.length){for(var l=i.lines.length%25+25,s=l;s<i.lines.length;){var a=new lo(i.lines.slice(s,s+=25));i.height-=a.height,this.children.splice(++r,0,a),a.parent=this}i.lines=i.lines.slice(0,l),this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(!(this.children.length<=10)){var e=this;do{var t,n,r=new so(e.children.splice(e.children.length-5,5));e.parent?(e.size-=r.size,e.height-=r.height,t=B(e.parent.children,e),e.parent.children.splice(t+1,0,r)):(((n=new so(e.children)).parent=e).children=[n,r],e=n),r.parent=e.parent}while(10<e.children.length);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e);if(i.iterN(e,l,n))return!0;if(0==(t-=l))break;e=0}else e-=o}}};function ao(e,t,n){if(n)for(var r in n)n.hasOwnProperty(r)&&(this[r]=n[r]);this.doc=e,this.node=t}function uo(e,t,n){Xt(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&Cr(e,n)}ao.prototype.clear=function(){var e=this.doc.cm,t=this.line.widgets,n=this.line,r=nt(n);if(null!=r&&t){for(var i=0;i<t.length;++i)t[i]==this&&t.splice(i--,1);t.length||(n.widgets=null);var o=yn(this);tt(n,Math.max(0,n.height-o)),e&&(Br(e,function(){uo(e,n,-o),or(e,r,"widget")}),un(e,"lineWidgetCleared",e,this,r))}},ao.prototype.changed=function(){var e=this,t=this.height,n=this.doc.cm,r=this.line;this.height=null;var i=yn(this)-t;i&&(jt(this.doc,r)||tt(r,r.height+i),n&&Br(n,function(){n.curOp.forceUpdate=!0,uo(n,r,i),un(n,"lineWidgetChanged",n,e,nt(r))}))},Me(ao);var co=0,ho=function(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++co};function fo(t,r,i,e,n){if(e&&e.shared)return function(e,n,r,i,o){(i=I(i)).shared=!1;var l=[fo(e,n,r,i,o)],s=l[0],a=i.widgetNode;return xi(e,function(e){a&&(i.widgetNode=a.cloneNode(!0)),l.push(fo(e,ft(e,n),ft(e,r),i,o));for(var t=0;t<e.linked.length;++t)if(e.linked[t].isParent)return;s=$(l)}),new po(l,s)}(t,r,i,e,n);if(t.cm&&!t.cm.curOp)return Gr(t.cm,fo)(t,r,i,e,n);var o=new ho(t,n),l=st(r,i);if(e&&I(e,o,!1),0<l||0==l&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=A("span",[o.replacedWith],"CodeMirror-widget"),e.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),e.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Gt(t,r.line,r,i,o)||r.line!=i.line&&Gt(t,i.line,r,i,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");Nt=!0}o.addToHistory&&Mi(t,{from:r,to:i,origin:"markText"},t.sel,NaN);var s,a=r.line,u=t.cm;if(t.iter(a,i.line+1,function(e){var t,n;u&&o.collapsed&&!u.options.lineWrapping&&Ut(e)==u.display.maxLine&&(s=!0),o.collapsed&&a!=r.line&&tt(e,0),t=e,n=new At(o,a==r.line?r.ch:null,a==i.line?i.ch:null),t.markedSpans=t.markedSpans?t.markedSpans.concat([n]):[n],n.marker.attachLine(t),++a}),o.collapsed&&t.iter(r.line,i.line+1,function(e){jt(t,e)&&tt(e,0)}),o.clearOnEnter&&we(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(Mt=!0,(t.history.done.length||t.history.undone.length)&&t.clearHistory()),o.collapsed&&(o.id=++co,o.atomic=!0),u){if(s&&(u.curOp.updateMaxLine=!0),o.collapsed)ir(u,r.line,i.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var c=r.line;c<=i.line;c++)or(u,c,"text");o.atomic&&Vi(u.doc),un(u,"markerAdded",u,o)}return o}ho.prototype.clear=function(){if(!this.explicitlyCleared){var e,t=this.doc.cm,n=t&&!t.curOp;n&&Rr(t),!Te(this,"clear")||(e=this.find())&&un(this,"clear",e.from,e.to);for(var r=null,i=null,o=0;o<this.lines.length;++o){var l=this.lines[o],s=Ot(l.markedSpans,this);t&&!this.collapsed?or(t,nt(l),"text"):t&&(null!=s.to&&(i=nt(l)),null!=s.from&&(r=nt(l))),l.markedSpans=function(e,t){for(var n,r=0;r<e.length;++r)e[r]!=t&&(n=n||[]).push(e[r]);return n}(l.markedSpans,s),null==s.from&&this.collapsed&&!jt(this.doc,l)&&t&&tt(l,qn(t.display))}if(t&&this.collapsed&&!t.options.lineWrapping)for(var a=0;a<this.lines.length;++a){var u=Ut(this.lines[a]),c=Yt(u);c>t.display.maxLineLength&&(t.display.maxLine=u,t.display.maxLineLength=c,t.display.maxLineChanged=!0)}null!=r&&t&&this.collapsed&&ir(t,r,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,t&&Vi(t.doc)),t&&un(t,"markerCleared",t,this,r,i),n&&zr(t),this.parent&&this.parent.clear()}},ho.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i<this.lines.length;++i){var o=this.lines[i],l=Ot(o.markedSpans,this);if(null!=l.from&&(n=lt(t?o:nt(o),l.from),-1==e))return n;if(null!=l.to&&(r=lt(t?o:nt(o),l.to),1==e))return r}return n&&{from:n,to:r}},ho.prototype.changed=function(){var o=this,l=this.find(-1,!0),s=this,a=this.doc.cm;l&&a&&Br(a,function(){var e,t,n=l.line,r=nt(l.line),i=Nn(a,r);i&&(Fn(i),a.curOp.selectionChanged=a.curOp.forceUpdate=!0),a.curOp.updateMaxLine=!0,jt(s.doc,n)||null==s.height||(e=s.height,s.height=null,(t=yn(s)-e)&&tt(n,n.height+t)),un(a,"markerChanged",a,o)})},ho.prototype.attachLine=function(e){var t;!this.lines.length&&this.doc.cm&&((t=this.doc.cm.curOp).maybeHiddenMarkers&&-1!=B(t.maybeHiddenMarkers,this)||(t.maybeUnhiddenMarkers||(t.maybeUnhiddenMarkers=[])).push(this)),this.lines.push(e)},ho.prototype.detachLine=function(e){var t;this.lines.splice(B(this.lines,e),1),!this.lines.length&&this.doc.cm&&((t=this.doc.cm.curOp).maybeHiddenMarkers||(t.maybeHiddenMarkers=[])).push(this)},Me(ho);var po=function(e,t){this.markers=e,this.primary=t;for(var n=0;n<e.length;++n)e[n].parent=this};function go(e){return e.findMarks(lt(e.first,0),e.clipPos(lt(e.lastLine())),function(e){return e.parent})}po.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var e=0;e<this.markers.length;++e)this.markers[e].clear();un(this,"clear")}},po.prototype.find=function(e,t){return this.primary.find(e,t)},Me(po);var mo=0,vo=function(e,t,n,r,i){if(!(this instanceof vo))return new vo(e,t,n,r,i);null==n&&(n=0),so.call(this,[new lo([new $t("",null)])]),this.first=n,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1;var o=lt(this.modeFrontier=this.highlightFrontier=n,0);this.sel=di(o),this.history=new Li(null),this.id=++mo,this.modeOption=t,this.lineSep=r,this.direction="rtl"==i?"rtl":"ltr",this.extend=!1,"string"==typeof e&&(e=this.splitLines(e)),wi(this,{from:o,to:o,text:e}),Bi(this,di(o),V)};vo.prototype=Q(so.prototype,{constructor:vo,iter:function(e,t,n){n?this.iterN(e-this.first,t-e,n):this.iterN(this.first,this.first+this.size,e)},insert:function(e,t){for(var n=0,r=0;r<t.length;++r)n+=t[r].height;this.insertInner(e-this.first,t,n)},remove:function(e,t){this.removeInner(e-this.first,t)},getValue:function(e){var t=et(this,this.first,this.first+this.size);return!1===e?t:t.join(e||this.lineSeparator())},setValue:Vr(function(e){var t=lt(this.first,0),n=this.first+this.size-1;qi(this,{from:t,to:lt(n,Qe(this,n).text.length),text:this.splitLines(e),origin:"setValue",full:!0},!0),this.cm&&Lr(this.cm,0,0),Bi(this,di(t),V)}),replaceRange:function(e,t,n,r){to(this,e,t=ft(this,t),n=n?ft(this,n):t,r)},getRange:function(e,t,n){var r=Je(this,ft(this,e),ft(this,t));return!1===n?r:r.join(n||this.lineSeparator())},getLine:function(e){var t=this.getLineHandle(e);return t&&t.text},getLineHandle:function(e){if(it(this,e))return Qe(this,e)},getLineNumber:nt,getLineHandleVisualStart:function(e){return"number"==typeof e&&(e=Qe(this,e)),Ut(e)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(e){return ft(this,e)},getCursor:function(e){var t=this.sel.primary(),n=null==e||"head"==e?t.head:"anchor"==e?t.anchor:"end"==e||"to"==e||!1===e?t.to():t.from();return n},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Vr(function(e,t,n){Ri(this,ft(this,"number"==typeof e?lt(e,t||0):e),null,n)}),setSelection:Vr(function(e,t,n){Ri(this,ft(this,e),ft(this,t||e),n)}),extendSelection:Vr(function(e,t,n){Ei(this,ft(this,e),t&&ft(this,t),n)}),extendSelections:Vr(function(e,t){Pi(this,pt(this,e),t)}),extendSelectionsBy:Vr(function(e,t){Pi(this,pt(this,q(this.sel.ranges,e)),t)}),setSelections:Vr(function(e,t,n){if(e.length){for(var r=[],i=0;i<e.length;i++)r[i]=new ci(ft(this,e[i].anchor),ft(this,e[i].head));null==t&&(t=Math.min(e.length-1,this.sel.primIndex)),Bi(this,hi(this.cm,r,t),n)}}),addSelection:Vr(function(e,t,n){var r=this.sel.ranges.slice(0);r.push(new ci(ft(this,e),ft(this,t||e))),Bi(this,hi(this.cm,r,r.length-1),n)}),getSelection:function(e){for(var t=this.sel.ranges,n=0;n<t.length;n++)var r=Je(this,t[n].from(),t[n].to()),i=i?i.concat(r):r;return!1===e?i:i.join(e||this.lineSeparator())},getSelections:function(e){for(var t=[],n=this.sel.ranges,r=0;r<n.length;r++){var i=Je(this,n[r].from(),n[r].to());!1!==e&&(i=i.join(e||this.lineSeparator())),t[r]=i}return t},replaceSelection:function(e,t,n){for(var r=[],i=0;i<this.sel.ranges.length;i++)r[i]=e;this.replaceSelections(r,t,n||"+input")},replaceSelections:Vr(function(e,t,n){for(var r=[],i=this.sel,o=0;o<i.ranges.length;o++){var l=i.ranges[o];r[o]={from:l.from(),to:l.to(),text:this.splitLines(e[o]),origin:n}}for(var s=t&&"end"!=t&&function(e,t,n){for(var r=[],i=h=lt(e.first,0),o=0;o<t.length;o++){var l,s,a=t[o],u=mi(a.from,h,i),c=mi(fi(a),h,i),h=a.to,i=c;"around"==n?(s=st((l=e.sel.ranges[o]).head,l.anchor)<0,r[o]=new ci(s?c:u,s?u:c)):r[o]=new ci(u,u)}return new ui(r,e.sel.primIndex)}(this,r,t),a=r.length-1;0<=a;a--)qi(this,r[a]);s?zi(this,s):this.cm&&Sr(this.cm)}),undo:Vr(function(){Qi(this,"undo")}),redo:Vr(function(){Qi(this,"redo")}),undoSelection:Vr(function(){Qi(this,"undo",!0)}),redoSelection:Vr(function(){Qi(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r<e.done.length;r++)e.done[r].ranges||++t;for(var i=0;i<e.undone.length;i++)e.undone[i].ranges||++n;return{undo:t,redo:n}},clearHistory:function(){var t=this;this.history=new Li(this.history.maxGeneration),xi(this,function(e){return e.history=t.history},!0)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(e){return e&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(e){return this.history.generation==(e||this.cleanGeneration)},getHistory:function(){return{done:Hi(this.history.done),undone:Hi(this.history.undone)}},setHistory:function(e){var t=this.history=new Li(this.history.maxGeneration);t.done=Hi(e.done.slice(0),null,!0),t.undone=Hi(e.undone.slice(0),null,!0)},setGutterMarker:Vr(function(e,n,r){return oo(this,e,"gutter",function(e){var t=e.gutterMarkers||(e.gutterMarkers={});return!(t[n]=r)&&ne(t)&&(e.gutterMarkers=null),1})}),clearGutter:Vr(function(t){var n=this;this.iter(function(e){e.gutterMarkers&&e.gutterMarkers[t]&&oo(n,e,"gutter",function(){return e.gutterMarkers[t]=null,ne(e.gutterMarkers)&&(e.gutterMarkers=null),1})})}),lineInfo:function(e){var t;if("number"==typeof e){if(!it(this,e))return null;if(!(e=Qe(this,t=e)))return null}else if(null==(t=nt(e)))return null;return{line:t,handle:e,text:e.text,gutterMarkers:e.gutterMarkers,textClass:e.textClass,bgClass:e.bgClass,wrapClass:e.wrapClass,widgets:e.widgets}},addLineClass:Vr(function(e,n,r){return oo(this,e,"gutter"==n?"gutter":"class",function(e){var t="text"==n?"textClass":"background"==n?"bgClass":"gutter"==n?"gutterClass":"wrapClass";if(e[t]){if(S(r).test(e[t]))return;e[t]+=" "+r}else e[t]=r;return 1})}),removeLineClass:Vr(function(e,o,l){return oo(this,e,"gutter"==o?"gutter":"class",function(e){var t="text"==o?"textClass":"background"==o?"bgClass":"gutter"==o?"gutterClass":"wrapClass",n=e[t];if(n){if(null==l)e[t]=null;else{var r=n.match(S(l));if(!r)return;var i=r.index+r[0].length;e[t]=n.slice(0,r.index)+(r.index&&i!=n.length?" ":"")+n.slice(i)||null}return 1}})}),addLineWidget:Vr(function(e,t,n){return i=e,o=new ao(r=this,t,n),(l=r.cm)&&o.noHScroll&&(l.display.alignWidgets=!0),oo(r,i,"widget",function(e){var t,n=e.widgets||(e.widgets=[]);return null==o.insertAt?n.push(o):n.splice(Math.min(n.length,Math.max(0,o.insertAt)),0,o),o.line=e,l&&!jt(r,e)&&(t=Xt(e)<r.scrollTop,tt(e,e.height+yn(o)),t&&Cr(l,o.height),l.curOp.forceUpdate=!0),1}),l&&un(l,"lineWidgetAdded",l,o,"number"==typeof i?i:nt(i)),o;var r,i,o,l}),removeLineWidget:function(e){e.clear()},markText:function(e,t,n){return fo(this,ft(this,e),ft(this,t),n,n&&n.type||"range")},setBookmark:function(e,t){var n={replacedWith:t&&(null==t.nodeType?t.widget:t),insertLeft:t&&t.insertLeft,clearWhenEmpty:!1,shared:t&&t.shared,handleMouseEvents:t&&t.handleMouseEvents};return fo(this,e=ft(this,e),e,n,"bookmark")},findMarksAt:function(e){var t=[],n=Qe(this,(e=ft(this,e)).line).markedSpans;if(n)for(var r=0;r<n.length;++r){var i=n[r];(null==i.from||i.from<=e.ch)&&(null==i.to||i.to>=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(i,o,l){i=ft(this,i),o=ft(this,o);var s=[],a=i.line;return this.iter(i.line,o.line+1,function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;n++){var r=t[n];null!=r.to&&a==i.line&&i.ch>=r.to||null==r.from&&a!=i.line||null!=r.from&&a==o.line&&r.from>=o.ch||l&&!l(r.marker)||s.push(r.marker.parent||r.marker)}++a}),s},getAllMarks:function(){var r=[];return this.iter(function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;++n)null!=t[n].from&&r.push(t[n].marker)}),r},posFromIndex:function(n){var r,i=this.first,o=this.lineSeparator().length;return this.iter(function(e){var t=e.text.length+o;if(n<t)return r=n,!0;n-=t,++i}),ft(this,lt(i,r))},indexFromPos:function(e){var t=(e=ft(this,e)).ch;if(e.line<this.first||e.ch<0)return 0;var n=this.lineSeparator().length;return this.iter(this.first,e.line,function(e){t+=e.text.length+n}),t},copy:function(e){var t=new vo(et(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft,t.sel=this.sel,t.extend=!1,e&&(t.history.undoDepth=this.history.undoDepth,t.setHistory(this.getHistory())),t},linkedDoc:function(e){e=e||{};var t=this.first,n=this.first+this.size;null!=e.from&&e.from>t&&(t=e.from),null!=e.to&&e.to<n&&(n=e.to);var r=new vo(et(this,t,n),e.mode||this.modeOption,t,this.lineSep,this.direction);return e.sharedHist&&(r.history=this.history),(this.linked||(this.linked=[])).push({doc:r,sharedHist:e.sharedHist}),r.linked=[{doc:this,isParent:!0,sharedHist:e.sharedHist}],function(e,t){for(var n=0;n<t.length;n++){var r,i=t[n],o=i.find(),l=e.clipPos(o.from),s=e.clipPos(o.to);st(l,s)&&(r=fo(e,l,s,i.primary,i.primary.type),i.markers.push(r),r.parent=i)}}(r,go(this)),r},unlinkDoc:function(e){if(e instanceof pl&&(e=e.doc),this.linked)for(var t=0;t<this.linked.length;++t){if(this.linked[t].doc==e){this.linked.splice(t,1),e.unlinkDoc(this),function(o){for(var e=0;e<o.length;e++)!function(e){var t=o[e],n=[t.primary.doc];xi(t.primary.doc,function(e){return n.push(e)});for(var r=0;r<t.markers.length;r++){var i=t.markers[r];-1==B(n,i.doc)&&(i.parent=null,t.markers.splice(r--,1))}}(e)}(go(this));break}}var n;e.history==this.history&&(n=[e.id],xi(e,function(e){return n.push(e.id)},!0),e.history=new Li(null),e.history.done=Hi(this.history.done,n),e.history.undone=Hi(this.history.undone,n))},iterLinkedDocs:function(e){xi(this,e)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(e){return this.lineSep?e.split(this.lineSep):Re(e)},lineSeparator:function(){return this.lineSep||"\n"},setDirection:Vr(function(e){var t;"rtl"!=e&&(e="ltr"),e!=this.direction&&(this.direction=e,this.iter(function(e){return e.order=null}),this.cm&&Br(t=this.cm,function(){Si(t),ir(t)}))})}),vo.prototype.eachLine=vo.prototype.iter;var yo=0;function bo(e){var r=this;if(wo(r),!Le(r,e)&&!bn(r.display,e)){Ne(e),L&&(yo=+new Date);var t=nr(r,e,!0),n=e.dataTransfer.files;if(t&&!r.isReadOnly())if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),l=0,s=function(){++l==i&&Gr(r,function(){var e={from:t=ft(r.doc,t),to:t,text:r.doc.splitLines(o.filter(function(e){return null!=e}).join(r.doc.lineSeparator())),origin:"paste"};qi(r.doc,e),zi(r.doc,di(ft(r.doc,t),ft(r.doc,fi(e))))})()},a=0;a<n.length;a++)!function(e,t){var n;r.options.allowDropFileTypes&&-1==B(r.options.allowDropFileTypes,e.type)?s():((n=new FileReader).onerror=s,n.onload=function(){var e=n.result;/[\x00-\x08\x0e-\x1f]{2}/.test(e)||(o[t]=e),s()},n.readAsText(e))}(n[a],a);else{if(r.state.draggingText&&-1<r.doc.sel.contains(t))return r.state.draggingText(e),void setTimeout(function(){return r.display.input.focus()},20);try{var u,c=e.dataTransfer.getData("Text");if(c){if(r.state.draggingText&&!r.state.draggingText.copy&&(u=r.listSelections()),Gi(r.doc,di(t,t)),u)for(var h=0;h<u.length;++h)to(r.doc,"",u[h].anchor,u[h].head,"drag");r.replaceSelection(c,"around","paste"),r.display.input.focus()}}catch(e){}}}}function wo(e){e.display.dragCursor&&(e.display.lineSpace.removeChild(e.display.dragCursor),e.display.dragCursor=null)}function xo(t){if(document.getElementsByClassName){for(var e=document.getElementsByClassName("CodeMirror"),n=[],r=0;r<e.length;r++){var i=e[r].CodeMirror;i&&n.push(i)}n.length&&n[0].operation(function(){for(var e=0;e<n.length;e++)t(n[e])})}}var Co=!1;function So(){var e;Co||(we(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,xo(Lo)},100))}),we(window,"blur",function(){return xo(vr)}),Co=!0)}function Lo(e){var t=e.display;t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize()}for(var ko={3:"Pause",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",145:"ScrollLock",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",224:"Mod",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"},To=0;To<10;To++)ko[To+48]=ko[To+96]=String(To);for(var Mo=65;Mo<=90;Mo++)ko[Mo]=String.fromCharCode(Mo);for(var No=1;No<=12;No++)ko[No+111]=ko[No+63235]="F"+No;var Ao={};function Oo(e){var t,n,r,i,o=e.split(/-(?!$)/);e=o[o.length-1];for(var l=0;l<o.length-1;l++){var s=o[l];if(/^(cmd|meta|m)$/i.test(s))i=!0;else if(/^a(lt)?$/i.test(s))t=!0;else if(/^(c|ctrl|control)$/i.test(s))n=!0;else{if(!/^s(hift)?$/i.test(s))throw new Error("Unrecognized modifier name: "+s);r=!0}}return t&&(e="Alt-"+e),n&&(e="Ctrl-"+e),i&&(e="Cmd-"+e),r&&(e="Shift-"+e),e}function Do(e){var t={};for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];if(/^(name|fallthrough|(de|at)tach)$/.test(n))continue;if("..."==r){delete e[n];continue}for(var i=q(n.split(" "),Oo),o=0;o<i.length;o++){var l=void 0,s=void 0,l=o==i.length-1?(s=i.join(" "),r):(s=i.slice(0,o+1).join(" "),"..."),a=t[s];if(a){if(a!=l)throw new Error("Inconsistent bindings for "+s)}else t[s]=l}delete e[n]}for(var u in t)e[u]=t[u];return e}function Wo(e,t,n,r){var i=(t=Po(t)).call?t.call(e,r):t[e];if(!1===i)return"nothing";if("..."===i)return"multi";if(null!=i&&n(i))return"handled";if(t.fallthrough){if("[object Array]"!=Object.prototype.toString.call(t.fallthrough))return Wo(e,t.fallthrough,n,r);for(var o=0;o<t.fallthrough.length;o++){var l=Wo(e,t.fallthrough[o],n,r);if(l)return l}}}function Ho(e){var t="string"==typeof e?e:ko[e.keyCode];return"Ctrl"==t||"Alt"==t||"Shift"==t||"Mod"==t}function Fo(e,t,n){var r=e;return t.altKey&&"Alt"!=r&&(e="Alt-"+e),(w?t.metaKey:t.ctrlKey)&&"Ctrl"!=r&&(e="Ctrl-"+e),(w?t.ctrlKey:t.metaKey)&&"Mod"!=r&&(e="Cmd-"+e),!n&&t.shiftKey&&"Shift"!=r&&(e="Shift-"+e),e}function Eo(e,t){if(m&&34==e.keyCode&&e.char)return!1;var n=ko[e.keyCode];return null!=n&&!e.altGraphKey&&(3==e.keyCode&&e.code&&(n=e.code),Fo(n,e,t))}function Po(e){return"string"==typeof e?Ao[e]:e}function Io(t,e){for(var n=t.doc.sel.ranges,r=[],i=0;i<n.length;i++){for(var o=e(n[i]);r.length&&st(o.from,$(r).to)<=0;){var l=r.pop();if(st(l.from,o.from)<0){o.from=l.from;break}}r.push(o)}Br(t,function(){for(var e=r.length-1;0<=e;e--)to(t.doc,"",r[e].from,r[e].to,"+delete");Sr(t)})}function Ro(e,t,n){var r=oe(e.text,t+n,n);return r<0||r>e.text.length?null:r}function zo(e,t,n){var r=Ro(e,t.ch,n);return null==r?null:new lt(t.line,r,n<0?"after":"before")}function Bo(e,t,n,r,i){if(e){"rtl"==t.doc.direction&&(i=-i);var o=ye(n,t.doc.direction);if(o){var l,s,a,u=i<0?$(o):o[0],c=i<0==(1==u.level)?"after":"before";return 0<u.level||"rtl"==t.doc.direction?(l=An(t,n),s=i<0?n.text.length-1:0,a=On(t,l,s).top,s=le(function(e){return On(t,l,e).top==a},i<0==(1==u.level)?u.from:u.to-1,s),"before"==c&&(s=Ro(n,s,1))):s=i<0?u.to:u.from,new lt(r,s,c)}}return new lt(r,i<0?n.text.length:0,i<0?"before":"after")}function Go(t,n,s,e){var a=ye(n,t.doc.direction);if(!a)return zo(n,s,e);s.ch>=n.text.length?(s.ch=n.text.length,s.sticky="before"):s.ch<=0&&(s.ch=0,s.sticky="after");var r=ae(a,s.ch,s.sticky),i=a[r];if("ltr"==t.doc.direction&&i.level%2==0&&(0<e?i.to>s.ch:i.from<s.ch))return zo(n,s,e);function u(e,t){return Ro(n,e instanceof lt?e.ch:e,t)}function o(e){return t.options.lineWrapping?(l=l||An(t,n),_n(t,n,l,e)):{begin:0,end:n.text.length}}var l,c=o("before"==s.sticky?u(s,-1):s.ch);if("rtl"==t.doc.direction||1==i.level){var h=1==i.level==e<0,d=u(s,h?1:-1);if(null!=d&&(h?d<=i.to&&d<=c.end:d>=i.from&&d>=c.begin)){var f=h?"before":"after";return new lt(s.line,d,f)}}function p(e,t,n){for(var r=function(e,t){return t?new lt(s.line,u(e,1),"before"):new lt(s.line,e,"after")};0<=e&&e<a.length;e+=t){var i=a[e],o=0<t==(1!=i.level),l=o?n.begin:u(n.end,-1);if(i.from<=l&&l<i.to)return r(l,o);if(l=o?i.from:u(i.to,-1),n.begin<=l&&l<n.end)return r(l,o)}}var g=p(r+e,e,c);if(g)return g;var m=0<e?c.end:u(c.begin,-1);return null==m||0<e&&m==n.text.length||!(g=p(0<e?0:a.length-1,e,o(m)))?null:g}Ao.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Ao.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Ao.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Ao.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Ao.default=y?Ao.macDefault:Ao.pcDefault;var Uo={selectAll:_i,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),V)},killLine:function(n){return Io(n,function(e){if(e.empty()){var t=Qe(n.doc,e.head.line).text.length;return e.head.ch==t&&e.head.line<n.lastLine()?{from:e.head,to:lt(e.head.line+1,0)}:{from:e.head,to:lt(e.head.line,t)}}return{from:e.from(),to:e.to()}})},deleteLine:function(t){return Io(t,function(e){return{from:lt(e.from().line,0),to:ft(t.doc,lt(e.to().line+1,0))}})},delLineLeft:function(e){return Io(e,function(e){return{from:lt(e.from().line,0),to:e.from()}})},delWrappedLineLeft:function(n){return Io(n,function(e){var t=n.charCoords(e.head,"div").top+5;return{from:n.coordsChar({left:0,top:t},"div"),to:e.from()}})},delWrappedLineRight:function(r){return Io(r,function(e){var t=r.charCoords(e.head,"div").top+5,n=r.coordsChar({left:r.display.lineDiv.offsetWidth+100,top:t},"div");return{from:e.from(),to:n}})},undo:function(e){return e.undo()},redo:function(e){return e.redo()},undoSelection:function(e){return e.undoSelection()},redoSelection:function(e){return e.redoSelection()},goDocStart:function(e){return e.extendSelection(lt(e.firstLine(),0))},goDocEnd:function(e){return e.extendSelection(lt(e.lastLine()))},goLineStart:function(t){return t.extendSelectionsBy(function(e){return Vo(t,e.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(t){return t.extendSelectionsBy(function(e){return Ko(t,e.head)},{origin:"+move",bias:1})},goLineEnd:function(t){return t.extendSelectionsBy(function(e){return function(e,t){var n=Qe(e.doc,t),r=function(e){for(var t;t=Bt(e);)e=t.find(1,!0).line;return e}(n);r!=n&&(t=nt(r));return Bo(!0,e,n,t,-1)}(t,e.head.line)},{origin:"+move",bias:-1})},goLineRight:function(n){return n.extendSelectionsBy(function(e){var t=n.cursorCoords(e.head,"div").top+5;return n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:t},"div")},j)},goLineLeft:function(n){return n.extendSelectionsBy(function(e){var t=n.cursorCoords(e.head,"div").top+5;return n.coordsChar({left:0,top:t},"div")},j)},goLineLeftSmart:function(r){return r.extendSelectionsBy(function(e){var t=r.cursorCoords(e.head,"div").top+5,n=r.coordsChar({left:0,top:t},"div");return n.ch<r.getLine(n.line).search(/\S/)?Ko(r,e.head):n},j)},goLineUp:function(e){return e.moveV(-1,"line")},goLineDown:function(e){return e.moveV(1,"line")},goPageUp:function(e){return e.moveV(-1,"page")},goPageDown:function(e){return e.moveV(1,"page")},goCharLeft:function(e){return e.moveH(-1,"char")},goCharRight:function(e){return e.moveH(1,"char")},goColumnLeft:function(e){return e.moveH(-1,"column")},goColumnRight:function(e){return e.moveH(1,"column")},goWordLeft:function(e){return e.moveH(-1,"word")},goGroupRight:function(e){return e.moveH(1,"group")},goGroupLeft:function(e){return e.moveH(-1,"group")},goWordRight:function(e){return e.moveH(1,"word")},delCharBefore:function(e){return e.deleteH(-1,"codepoint")},delCharAfter:function(e){return e.deleteH(1,"char")},delWordBefore:function(e){return e.deleteH(-1,"word")},delWordAfter:function(e){return e.deleteH(1,"word")},delGroupBefore:function(e){return e.deleteH(-1,"group")},delGroupAfter:function(e){return e.deleteH(1,"group")},indentAuto:function(e){return e.indentSelection("smart")},indentMore:function(e){return e.indentSelection("add")},indentLess:function(e){return e.indentSelection("subtract")},insertTab:function(e){return e.replaceSelection("\t")},insertSoftTab:function(e){for(var t=[],n=e.listSelections(),r=e.options.tabSize,i=0;i<n.length;i++){var o=n[i].from(),l=R(e.getLine(o.line),o.ch,r);t.push(_(r-l%r))}e.replaceSelections(t)},defaultTab:function(e){e.somethingSelected()?e.indentSelection("add"):e.execCommand("insertTab")},transposeChars:function(l){return Br(l,function(){for(var e,t,n,r=l.listSelections(),i=[],o=0;o<r.length;o++){r[o].empty()&&(e=r[o].head,(t=Qe(l.doc,e.line).text)&&(e.ch==t.length&&(e=new lt(e.line,e.ch-1)),0<e.ch?(e=new lt(e.line,e.ch+1),l.replaceRange(t.charAt(e.ch-1)+t.charAt(e.ch-2),lt(e.line,e.ch-2),e,"+transpose")):e.line>l.doc.first&&((n=Qe(l.doc,e.line-1).text)&&(e=new lt(e.line,1),l.replaceRange(t.charAt(0)+l.doc.lineSeparator()+n.charAt(n.length-1),lt(e.line-1,n.length-1),e,"+transpose")))),i.push(new ci(e,e)))}l.setSelections(i)})},newlineAndIndent:function(r){return Br(r,function(){for(var e=r.listSelections(),t=e.length-1;0<=t;t--)r.replaceRange(r.doc.lineSeparator(),e[t].anchor,e[t].head,"+input");e=r.listSelections();for(var n=0;n<e.length;n++)r.indentLine(e[n].from().line,null,!0);Sr(r)})},openLine:function(e){return e.replaceSelection("\n","start")},toggleOverwrite:function(e){return e.toggleOverwrite()}};function Vo(e,t){var n=Qe(e.doc,t),r=Ut(n);return r!=n&&(t=nt(r)),Bo(!0,e,r,t,1)}function Ko(e,t){var n=Vo(e,t.line),r=Qe(e.doc,n.line),i=ye(r,e.doc.direction);if(i&&0!=i[0].level)return n;var o=Math.max(n.ch,r.text.search(/\S/)),l=t.line==n.line&&t.ch<=o&&t.ch;return lt(n.line,l?0:o,n.sticky)}function jo(e,t,n){if("string"==typeof t&&!(t=Uo[t]))return!1;e.display.input.ensurePolled();var r=e.display.shift,i=!1;try{e.isReadOnly()&&(e.state.suppressEdits=!0),n&&(e.display.shift=!1),i=t(e)!=U}finally{e.display.shift=r,e.state.suppressEdits=!1}return i}var Xo=new z;function Yo(e,t,n,r){var i=e.state.keySeq;if(i){if(Ho(t))return"handled";if(/\'$/.test(t)?e.state.keySeq=null:Xo.set(50,function(){e.state.keySeq==i&&(e.state.keySeq=null,e.display.input.reset())}),_o(e,i+" "+t,n,r))return!0}return _o(e,t,n,r)}function _o(e,t,n,r){var i=function(e,t,n){for(var r=0;r<e.state.keyMaps.length;r++){var i=Wo(t,e.state.keyMaps[r],n,e);if(i)return i}return e.options.extraKeys&&Wo(t,e.options.extraKeys,n,e)||Wo(t,e.options.keyMap,n,e)}(e,t,r);return"multi"==i&&(e.state.keySeq=t),"handled"==i&&un(e,"keyHandled",e,t,n),"handled"!=i&&"multi"!=i||(Ne(n),fr(e)),!!i}function $o(t,e){var n=Eo(e,!0);return!!n&&(e.shiftKey&&!t.state.keySeq?Yo(t,"Shift-"+n,e,function(e){return jo(t,e,!0)})||Yo(t,n,e,function(e){if("string"==typeof e?/^go[A-Z]/.test(e):e.motion)return jo(t,e)}):Yo(t,n,e,function(e){return jo(t,e)}))}var qo=null;function Zo(e){var t,n,r,i=this;function o(e){18!=e.keyCode&&e.altKey||(T(r,"CodeMirror-crosshair"),Ce(document,"keyup",o),Ce(document,"mouseover",o))}e.target&&e.target!=i.display.input.getField()||(i.curOp.focus=W(),Le(i,e)||(L&&x<11&&27==e.keyCode&&(e.returnValue=!1),t=e.keyCode,i.display.shift=16==t||e.shiftKey,n=$o(i,e),m&&(qo=n?t:null,!n&&88==t&&!Be&&(y?e.metaKey:e.ctrlKey)&&i.replaceSelection("",null,"cut")),g&&!y&&!n&&46==t&&e.shiftKey&&!e.ctrlKey&&document.execCommand&&document.execCommand("cut"),18!=t||/\bCodeMirror-crosshair\b/.test(i.display.lineDiv.className)||(H(r=i.display.lineDiv,"CodeMirror-crosshair"),we(document,"keyup",o),we(document,"mouseover",o))))}function Qo(e){16==e.keyCode&&(this.doc.sel.shift=!1),Le(this,e)}function Jo(e){var t=this;if(!(e.target&&e.target!=t.display.input.getField()||bn(t.display,e)||Le(t,e)||e.ctrlKey&&!e.altKey||y&&e.metaKey)){var n,r,i=e.keyCode,o=e.charCode;if(m&&i==qo)return qo=null,void Ne(e);m&&(!e.which||e.which<10)&&$o(t,e)||"\b"!=(n=String.fromCharCode(null==o?i:o))&&(Yo(r=t,"'"+n+"'",e,function(e){return jo(r,e,!0)})||t.display.input.onKeyPress(e))}}var el,tl,nl=function(e,t,n){this.time=e,this.pos=t,this.button=n};function rl(e){var t,n,r,i,o,l,s=this,a=s.display;Le(s,e)||a.activeTouch&&a.input.supportsTouch()||(a.input.ensurePolled(),a.shift=e.shiftKey,bn(a,e)?v||(a.scroller.draggable=!1,setTimeout(function(){return a.scroller.draggable=!0},100)):ll(s,e)||(t=nr(s,e),n=He(e),r=t?(i=t,o=n,l=+new Date,tl&&tl.compare(l,i,o)?(el=tl=null,"triple"):el&&el.compare(l,i,o)?(tl=new nl(l,i,o),el=null,"double"):(el=new nl(l,i,o),tl=null,"single")):"single",window.focus(),1==n&&s.state.selectingText&&s.state.selectingText(e),t&&function(n,e,r,t,i){var o="Click";"double"==t?o="Double"+o:"triple"==t&&(o="Triple"+o);return Yo(n,Fo(o=(1==e?"Left":2==e?"Middle":"Right")+o,i),i,function(e){if("string"==typeof e&&(e=Uo[e]),!e)return!1;var t=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),t=e(n,r)!=U}finally{n.state.suppressEdits=!1}return t})}(s,n,t,r,e)||(1==n?t?function(e,t,n,r){L?setTimeout(P(pr,e),0):e.curOp.focus=W();var i,o=function(e,t,n){var r=e.getOption("configureMouse"),i=r?r(e,t,n):{};{var o;null==i.unit&&(o=f?n.shiftKey&&n.metaKey:n.altKey,i.unit=o?"rectangle":"single"==t?"char":"double"==t?"word":"line")}null!=i.extend&&!e.doc.extend||(i.extend=e.doc.extend||n.shiftKey);null==i.addNew&&(i.addNew=y?n.metaKey:n.ctrlKey);null==i.moveOnDrag&&(i.moveOnDrag=!(y?n.altKey:n.ctrlKey));return i}(e,n,r),l=e.doc.sel;(e.options.dragDrop&&Pe&&!e.isReadOnly()&&"single"==n&&-1<(i=l.contains(t))&&(st((i=l.ranges[i]).from(),t)<0||0<t.xRel)&&(0<st(i.to(),t)||t.xRel<0)?function(t,n,r,i){var o=t.display,l=!1,s=Gr(t,function(e){v&&(o.scroller.draggable=!1),t.state.draggingText=!1,t.state.delayingBlurEvent&&(t.hasFocus()?t.state.delayingBlurEvent=!1:gr(t)),Ce(o.wrapper.ownerDocument,"mouseup",s),Ce(o.wrapper.ownerDocument,"mousemove",a),Ce(o.scroller,"dragstart",u),Ce(o.scroller,"drop",s),l||(Ne(e),i.addNew||Ei(t.doc,r,null,null,i.extend),v&&!c||L&&9==x?setTimeout(function(){o.wrapper.ownerDocument.body.focus({preventScroll:!0}),o.input.focus()},20):o.input.focus())}),a=function(e){l=l||10<=Math.abs(n.clientX-e.clientX)+Math.abs(n.clientY-e.clientY)},u=function(){return l=!0};v&&(o.scroller.draggable=!0);(t.state.draggingText=s).copy=!i.moveOnDrag,we(o.wrapper.ownerDocument,"mouseup",s),we(o.wrapper.ownerDocument,"mousemove",a),we(o.scroller,"dragstart",u),we(o.scroller,"drop",s),t.state.delayingBlurEvent=!0,setTimeout(function(){return o.input.focus()},20),o.scroller.dragDrop&&o.scroller.dragDrop()}:function(m,e,v,y){L&&gr(m);var l=m.display,b=m.doc;Ne(e);var w,x,C=b.sel,t=C.ranges;y.addNew&&!y.extend?(x=b.sel.contains(v),w=-1<x?t[x]:new ci(v,v)):(w=b.sel.primary(),x=b.sel.primIndex);{var n;"rectangle"==y.unit?(y.addNew||(w=new ci(v,v)),v=nr(m,e,!0,!0),x=-1):(n=il(m,v,y.unit),w=y.extend?Fi(w,n.anchor,n.head,y.extend):n)}y.addNew?-1==x?(x=t.length,Bi(b,hi(m,t.concat([w]),x),{scroll:!1,origin:"*mouse"})):1<t.length&&t[x].empty()&&"char"==y.unit&&!y.extend?(Bi(b,hi(m,t.slice(0,x).concat(t.slice(x+1)),0),{scroll:!1,origin:"*mouse"}),C=b.sel):Ii(b,x,w,K):(Bi(b,new ui([w],x=0),K),C=b.sel);var S=v;function s(e){if(0!=st(S,e))if(S=e,"rectangle"==y.unit){for(var t=[],n=m.options.tabSize,r=R(Qe(b,v.line).text,v.ch,n),i=R(Qe(b,e.line).text,e.ch,n),o=Math.min(r,i),l=Math.max(r,i),s=Math.min(v.line,e.line),a=Math.min(m.lastLine(),Math.max(v.line,e.line));s<=a;s++){var u=Qe(b,s).text,c=X(u,o,n);o==l?t.push(new ci(lt(s,c),lt(s,c))):u.length>c&&t.push(new ci(lt(s,c),lt(s,X(u,l,n))))}t.length||t.push(new ci(v,v)),Bi(b,hi(m,C.ranges.slice(0,x).concat(t),x),{origin:"*mouse",scroll:!1}),m.scrollIntoView(e)}else{var h,d=w,f=il(m,e,y.unit),p=d.anchor,p=0<st(f.anchor,p)?(h=f.head,ht(d.from(),f.anchor)):(h=f.anchor,ct(d.to(),f.head)),g=C.ranges.slice(0);g[x]=function(e,t){var n=t.anchor,r=t.head,i=Qe(e.doc,n.line);if(0==st(n,r)&&n.sticky==r.sticky)return t;var o=ye(i);if(!o)return t;var l=ae(o,n.ch,n.sticky),s=o[l];if(s.from!=n.ch&&s.to!=n.ch)return t;var a,u=l+(s.from==n.ch==(1!=s.level)?0:1);if(0==u||u==o.length)return t;{var c,h;a=r.line!=n.line?0<(r.line-n.line)*("ltr"==e.doc.direction?1:-1):(c=ae(o,r.ch,r.sticky),h=c-l||(r.ch-n.ch)*(1==s.level?-1:1),c==u-1||c==u?h<0:0<h)}var d=o[u+(a?-1:0)],f=a==(1==d.level),p=f?d.from:d.to,g=f?"after":"before";return n.ch==p&&n.sticky==g?t:new ci(new lt(n.line,p,g),r)}(m,new ci(ft(b,p),h)),Bi(b,hi(m,g,x),K)}}var a=l.wrapper.getBoundingClientRect(),u=0;function r(e){m.state.selectingText=!1,u=1/0,e&&(Ne(e),l.input.focus()),Ce(l.wrapper.ownerDocument,"mousemove",i),Ce(l.wrapper.ownerDocument,"mouseup",o),b.history.lastSelOrigin=null}var i=Gr(m,function(e){(0!==e.buttons&&He(e)?function e(t){var n,r,i=++u,o=nr(m,t,!0,"rectangle"==y.unit);o&&(0!=st(o,S)?(m.curOp.focus=W(),s(o),n=wr(l,b),(o.line>=n.to||o.line<n.from)&&setTimeout(Gr(m,function(){u==i&&e(t)}),150)):(r=t.clientY<a.top?-20:t.clientY>a.bottom?20:0)&&setTimeout(Gr(m,function(){u==i&&(l.scroller.scrollTop+=r,e(t))}),50))}:r)(e)}),o=Gr(m,r);m.state.selectingText=o,we(l.wrapper.ownerDocument,"mousemove",i),we(l.wrapper.ownerDocument,"mouseup",o)})(e,r,t,o)}(s,t,r,e):We(e)==a.scroller&&Ne(e):2==n?(t&&Ei(s.doc,t),setTimeout(function(){return a.input.focus()},20)):3==n&&(C?s.display.input.onContextMenu(e):gr(s)))))}function il(e,t,n){if("char"==n)return new ci(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new ci(lt(t.line,0),ft(e.doc,lt(t.line+1,0)));var r=n(e,t);return new ci(r.from,r.to)}function ol(e,t,n,r){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(e){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&&Ne(t);var l=e.display,s=l.lineDiv.getBoundingClientRect();if(o>s.bottom||!Te(e,n))return Oe(t);o-=s.top-l.viewOffset;for(var a=0;a<e.display.gutterSpecs.length;++a){var u=l.gutters.childNodes[a];if(u&&u.getBoundingClientRect().right>=i)return Se(e,n,e,rt(e.doc,o),e.display.gutterSpecs[a].className,t),Oe(t)}}function ll(e,t){return ol(e,t,"gutterClick",!0)}function sl(e,t){var n,r;bn(e.display,t)||(r=t,Te(n=e,"gutterContextMenu")&&ol(n,r,"gutterContextMenu",!1))||Le(e,t,"contextmenu")||C||e.display.input.onContextMenu(t)}function al(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),Pn(e)}nl.prototype.compare=function(e,t,n){return this.time+400>e&&0==st(t,this.pos)&&n==this.button};var ul={toString:function(){return"CodeMirror.Init"}},cl={},hl={};function dl(e,t,n){var r,i;!t!=!(n&&n!=ul)&&(r=e.display.dragFunctions,(i=t?we:Ce)(e.display.scroller,"dragstart",r.start),i(e.display.scroller,"dragenter",r.enter),i(e.display.scroller,"dragover",r.over),i(e.display.scroller,"dragleave",r.leave),i(e.display.scroller,"drop",r.drop))}function fl(e){e.options.lineWrapping?(H(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(T(e.display.wrapper,"CodeMirror-wrap"),_t(e)),tr(e),ir(e),Pn(e),setTimeout(function(){return Hr(e)},100)}function pl(e,t){var n=this;if(!(this instanceof pl))return new pl(e,t);this.options=t=t?I(t):{},I(cl,t,!1);var r=t.value;"string"==typeof r?r=new vo(r,t.mode,null,t.lineSeparator,t.direction):t.mode&&(r.modeOption=t.mode),this.doc=r;var i=new pl.inputStyles[t.inputStyle](this),o=this.display=new ri(e,r,i,t);for(var l in al(o.wrapper.CodeMirror=this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Pr(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new z,keySeq:null,specialChars:null},t.autofocus&&!d&&o.input.focus(),L&&x<11&&setTimeout(function(){return n.display.input.reset(!0)},20),function(i){var o=i.display;we(o.scroller,"mousedown",Gr(i,rl)),we(o.scroller,"dblclick",L&&x<11?Gr(i,function(e){var t,n;Le(i,e)||(!(t=nr(i,e))||ll(i,e)||bn(i.display,e)||(Ne(e),n=i.findWordAt(t),Ei(i.doc,n.anchor,n.head)))}):function(e){return Le(i,e)||Ne(e)});we(o.scroller,"contextmenu",function(e){return sl(i,e)}),we(o.input.getField(),"contextmenu",function(e){o.scroller.contains(e.target)||sl(i,e)});var n,r={end:0};function l(){o.activeTouch&&(n=setTimeout(function(){return o.activeTouch=null},1e3),(r=o.activeTouch).end=+new Date)}function s(e,t){if(null==t.left)return 1;var n=t.left-e.left,r=t.top-e.top;return 400<n*n+r*r}we(o.scroller,"touchstart",function(e){var t;Le(i,e)||function(e){if(1==e.touches.length){var t=e.touches[0];return t.radiusX<=1&&t.radiusY<=1}}(e)||ll(i,e)||(o.input.ensurePolled(),clearTimeout(n),t=+new Date,o.activeTouch={start:t,moved:!1,prev:t-r.end<=300?r:null},1==e.touches.length&&(o.activeTouch.left=e.touches[0].pageX,o.activeTouch.top=e.touches[0].pageY))}),we(o.scroller,"touchmove",function(){o.activeTouch&&(o.activeTouch.moved=!0)}),we(o.scroller,"touchend",function(e){var t,n,r=o.activeTouch;r&&!bn(o,e)&&null!=r.left&&!r.moved&&new Date-r.start<300&&(t=i.coordsChar(o.activeTouch,"page"),n=!r.prev||s(r,r.prev)?new ci(t,t):!r.prev.prev||s(r,r.prev.prev)?i.findWordAt(t):new ci(lt(t.line,0),ft(i.doc,lt(t.line+1,0))),i.setSelection(n.anchor,n.head),i.focus(),Ne(e)),l()}),we(o.scroller,"touchcancel",l),we(o.scroller,"scroll",function(){o.scroller.clientHeight&&(Mr(i,o.scroller.scrollTop),Ar(i,o.scroller.scrollLeft,!0),Se(i,"scroll",i))}),we(o.scroller,"mousewheel",function(e){return ai(i,e)}),we(o.scroller,"DOMMouseScroll",function(e){return ai(i,e)}),we(o.wrapper,"scroll",function(){return o.wrapper.scrollTop=o.wrapper.scrollLeft=0}),o.dragFunctions={enter:function(e){Le(i,e)||De(e)},over:function(e){var t,n,r;Le(i,e)||((r=nr(t=i,e))&&(hr(t,r,n=document.createDocumentFragment()),t.display.dragCursor||(t.display.dragCursor=O("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),t.display.lineSpace.insertBefore(t.display.dragCursor,t.display.cursorDiv)),N(t.display.dragCursor,n)),De(e))},start:function(e){return t=i,n=e,void(L&&(!t.state.draggingText||new Date-yo<100)?De(n):Le(t,n)||bn(t.display,n)||(n.dataTransfer.setData("Text",t.getSelection()),n.dataTransfer.effectAllowed="copyMove",n.dataTransfer.setDragImage&&!c&&((r=O("img",null,null,"position: fixed; left: 0; top: 0;")).src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",m&&(r.width=r.height=1,t.display.wrapper.appendChild(r),r._top=r.offsetTop),n.dataTransfer.setDragImage(r,0,0),m&&r.parentNode.removeChild(r))));var t,n,r},drop:Gr(i,bo),leave:function(e){Le(i,e)||wo(i)}};var e=o.input.getField();we(e,"keyup",function(e){return Qo.call(i,e)}),we(e,"keydown",Gr(i,Zo)),we(e,"keypress",Gr(i,Jo)),we(e,"focus",function(e){return mr(i,e)}),we(e,"blur",function(e){return vr(i,e)})}(this),So(),Rr(this),this.curOp.forceUpdate=!0,Ci(this,r),t.autofocus&&!d||this.hasFocus()?setTimeout(function(){n.hasFocus()&&!n.state.focused&&mr(n)},20):vr(this),hl)hl.hasOwnProperty(l)&&hl[l](this,t[l],ul);Jr(this),t.finishInit&&t.finishInit(this);for(var s=0;s<gl.length;++s)gl[s](this);zr(this),v&&t.lineWrapping&&"optimizelegibility"==getComputedStyle(o.lineDiv).textRendering&&(o.lineDiv.style.textRendering="auto")}pl.defaults=cl,pl.optionHandlers=hl;var gl=[];function ml(e,t,n,r){var i,o=e.doc;null==n&&(n="add"),"smart"==n&&(o.mode.indent?i=bt(e,t).state:n="prev");var l=e.options.tabSize,s=Qe(o,t),a=R(s.text,null,l);s.stateAfter&&(s.stateAfter=null);var u,c=s.text.match(/^\s*/)[0];if(r||/\S/.test(s.text)){if("smart"==n&&((u=o.mode.indent(i,s.text.slice(c.length),s.text))==U||150<u)){if(!r)return;n="prev"}}else u=0,n="not";"prev"==n?u=t>o.first?R(Qe(o,t-1).text,null,l):0:"add"==n?u=a+e.options.indentUnit:"subtract"==n?u=a-e.options.indentUnit:"number"==typeof n&&(u=a+n),u=Math.max(0,u);var h="",d=0;if(e.options.indentWithTabs)for(var f=Math.floor(u/l);f;--f)d+=l,h+="\t";if(d<u&&(h+=_(u-d)),h!=c)return to(o,h,lt(t,0),lt(t,c.length),"+input"),!(s.stateAfter=null);for(var p=0;p<o.sel.ranges.length;p++){var g=o.sel.ranges[p];if(g.head.line==t&&g.head.ch<c.length){var m=lt(t,c.length);Ii(o,p,new ci(m,m));break}}}pl.defineInitHook=function(e){return gl.push(e)};var vl=null;function yl(e){vl=e}function bl(e,t,n,r,i){var o=e.doc;e.display.shift=!1,r=r||o.sel;var l=new Date-200,s="paste"==i||e.state.pasteIncoming>l,a=Re(t),u=null;if(s&&1<r.ranges.length)if(vl&&vl.text.join("\n")==t){if(r.ranges.length%vl.text.length==0){u=[];for(var c=0;c<vl.text.length;c++)u.push(o.splitLines(vl.text[c]))}}else a.length==r.ranges.length&&e.options.pasteLinesPerSelection&&(u=q(a,function(e){return[e]}));for(var h=e.curOp.updateInput,d=r.ranges.length-1;0<=d;d--){var f=r.ranges[d],p=f.from(),g=f.to();f.empty()&&(n&&0<n?p=lt(p.line,p.ch-n):e.state.overwrite&&!s?g=lt(g.line,Math.min(Qe(o,g.line).text.length,g.ch+$(a).length)):s&&vl&&vl.lineWise&&vl.text.join("\n")==a.join("\n")&&(p=g=lt(p.line,0)));var m={from:p,to:g,text:u?u[d%u.length]:a,origin:i||(s?"paste":e.state.cutIncoming>l?"cut":"+input")};qi(e.doc,m),un(e,"inputRead",e,m)}t&&!s&&xl(e,t),Sr(e),e.curOp.updateInput<2&&(e.curOp.updateInput=h),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function wl(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");return n&&(e.preventDefault(),t.isReadOnly()||t.options.disableInput||Br(t,function(){return bl(t,n,0,null,"paste")}),1)}function xl(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;0<=r;r--){var i=n.ranges[r];if(!(100<i.head.ch||r&&n.ranges[r-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s<o.electricChars.length;s++)if(-1<t.indexOf(o.electricChars.charAt(s))){l=ml(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test(Qe(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=ml(e,i.head.line,"smart"));l&&un(e,"electricInput",e,i.head.line)}}}function Cl(e){for(var t=[],n=[],r=0;r<e.doc.sel.ranges.length;r++){var i=e.doc.sel.ranges[r].head.line,o={anchor:lt(i,0),head:lt(i+1,0)};n.push(o),t.push(e.getRange(o.anchor,o.head))}return{text:t,ranges:n}}function Sl(e,t,n,r){e.setAttribute("autocorrect",n?"":"off"),e.setAttribute("autocapitalize",r?"":"off"),e.setAttribute("spellcheck",!!t)}function Ll(){var e=O("textarea",null,null,"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"),t=O("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return v?e.style.width="1000px":e.setAttribute("wrap","off"),a&&(e.style.border="1px solid black"),Sl(e),t}function kl(i,o,l,s,a){var e=o,t=l,u=Qe(i,o.line),c=a&&"rtl"==i.direction?-l:l;function n(e){var t,n,r;if(null==(n="codepoint"==s?(t=u.text.charCodeAt(o.ch+(0<s?0:-1)),isNaN(t)?null:new lt(o.line,Math.max(0,Math.min(u.text.length,o.ch+l*(55296<=t&&t<56320?2:1))),-l)):a?Go(i.cm,u,o,l):zo(u,o,l))){if(e||(r=o.line+c)<i.first||r>=i.first+i.size||(o=new lt(r,o.ch,o.sticky),!(u=Qe(i,r))))return;o=Bo(a,i.cm,u,o.line,c)}else o=n;return 1}if("char"==s||"codepoint"==s)n();else if("column"==s)n(!0);else if("word"==s||"group"==s)for(var r=null,h="group"==s,d=i.cm&&i.cm.getHelper(o,"wordChars"),f=!0;!(l<0)||n(!f);f=!1){var p=u.text.charAt(o.ch)||"\n",g=te(p,d)?"w":h&&"\n"==p?"n":!h||/\s/.test(p)?null:"p";if(!h||f||g||(g="s"),r&&r!=g){l<0&&(l=1,n(),o.sticky="after");break}if(g&&(r=g),0<l&&!n(!f))break}var m=Xi(i,o,e,t,!0);return at(e,m)&&(m.hitSide=!0),m}function Tl(e,t,n,r){var i,o,l,s,a=e.doc,u=t.left;for("page"==r?(i=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),o=Math.max(i-.5*qn(e.display),3),l=(0<n?t.bottom:t.top)+n*o):"line"==r&&(l=0<n?t.bottom+3:t.top-3);(s=Xn(e,u,l)).outside;){if(n<0?l<=0:l>=a.height){s.hitSide=!0;break}l+=5*n}return s}function Ml(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new z,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null}function Nl(e,t){var n=Nn(e,t.line);if(!n||n.hidden)return null;var r=Qe(e.doc,t.line),i=Tn(n,r,t.line),o=ye(r,e.doc.direction),l="left";o&&(l=ae(o,t.ch)%2?"right":"left");var s=Hn(i.map,t.ch,l);return s.offset="right"==s.collapse?s.end:s.start,s}function Al(e,t){return t&&(e.bad=!0),e}function Ol(e,t,n){var r;if(t==e.display.lineDiv){if(!(r=e.display.lineDiv.childNodes[n]))return Al(e.clipPos(lt(e.display.viewTo-1)),!0);t=null,n=0}else for(r=t;;r=r.parentNode){if(!r||r==e.display.lineDiv)return null;if(r.parentNode&&r.parentNode==e.display.lineDiv)break}for(var i=0;i<e.display.view.length;i++){var o=e.display.view[i];if(o.node==r)return function(u,e,t){var n=u.text.firstChild,r=!1;if(!e||!D(n,e))return Al(lt(nt(u.line),0),!0);if(e==n&&(r=!0,e=n.childNodes[t],t=0,!e)){var i=u.rest?$(u.rest):u.line;return Al(lt(nt(i),i.text.length),r)}var o=3==e.nodeType?e:null,l=e;o||1!=e.childNodes.length||3!=e.firstChild.nodeType||(o=e.firstChild,t=t&&o.nodeValue.length);for(;l.parentNode!=n;)l=l.parentNode;var c=u.measure,h=c.maps;function s(e,t,n){for(var r=-1;r<(h?h.length:0);r++)for(var i=r<0?c.map:h[r],o=0;o<i.length;o+=3){var l=i[o+2];if(l==e||l==t){var s=nt(r<0?u.line:u.rest[r]),a=i[o]+n;return(n<0||l!=e)&&(a=i[o+(n?1:0)]),lt(s,a)}}}var a=s(o,l,t);if(a)return Al(a,r);for(var d=l.nextSibling,f=o?o.nodeValue.length-t:0;d;d=d.nextSibling){if(a=s(d,d.firstChild,0))return Al(lt(a.line,a.ch-f),r);f+=d.textContent.length}for(var p=l.previousSibling,g=t;p;p=p.previousSibling){if(a=s(p,p.firstChild,-1))return Al(lt(a.line,a.ch+g),r);g+=p.textContent.length}}(o,t,n)}}Ml.prototype.init=function(e){var t=this,l=this,s=l.cm,a=l.div=e.lineDiv;function u(e){for(var t=e.target;t;t=t.parentNode){if(t==a)return 1;if(/\bCodeMirror-(?:line)?widget\b/.test(t.className))break}}function n(e){if(u(e)&&!Le(s,e)){if(s.somethingSelected())yl({lineWise:!1,text:s.getSelections()}),"cut"==e.type&&s.replaceSelection("",null,"cut");else{if(!s.options.lineWiseCopyCut)return;var t=Cl(s);yl({lineWise:!0,text:t.text}),"cut"==e.type&&s.operation(function(){s.setSelections(t.ranges,0,V),s.replaceSelection("",null,"cut")})}if(e.clipboardData){e.clipboardData.clearData();var n=vl.text.join("\n");if(e.clipboardData.setData("Text",n),e.clipboardData.getData("Text")==n)return void e.preventDefault()}var r=Ll(),i=r.firstChild;s.display.lineSpace.insertBefore(r,s.display.lineSpace.firstChild),i.value=vl.text.join("\n");var o=document.activeElement;E(i),setTimeout(function(){s.display.lineSpace.removeChild(r),o.focus(),o==a&&l.showPrimarySelection()},50)}}Sl(a,s.options.spellcheck,s.options.autocorrect,s.options.autocapitalize),we(a,"paste",function(e){!u(e)||Le(s,e)||wl(e,s)||x<=11&&setTimeout(Gr(s,function(){return t.updateFromDOM()}),20)}),we(a,"compositionstart",function(e){t.composing={data:e.data,done:!1}}),we(a,"compositionupdate",function(e){t.composing||(t.composing={data:e.data,done:!1})}),we(a,"compositionend",function(e){t.composing&&(e.data!=t.composing.data&&t.readFromDOMSoon(),t.composing.done=!0)}),we(a,"touchstart",function(){return l.forceCompositionEnd()}),we(a,"input",function(){t.composing||t.readFromDOMSoon()}),we(a,"copy",n),we(a,"cut",n)},Ml.prototype.screenReaderLabelChanged=function(e){e?this.div.setAttribute("aria-label",e):this.div.removeAttribute("aria-label")},Ml.prototype.prepareSelection=function(){var e=cr(this.cm,!1);return e.focus=document.activeElement==this.div,e},Ml.prototype.showSelection=function(e,t){e&&this.cm.display.view.length&&((e.focus||t)&&this.showPrimarySelection(),this.showMultipleSelections(e))},Ml.prototype.getSelection=function(){return this.cm.display.wrapper.ownerDocument.getSelection()},Ml.prototype.showPrimarySelection=function(){var e=this.getSelection(),t=this.cm,n=t.doc.sel.primary(),r=n.from(),i=n.to();if(t.display.viewTo==t.display.viewFrom||r.line>=t.display.viewTo||i.line<t.display.viewFrom)e.removeAllRanges();else{var o=Ol(t,e.anchorNode,e.anchorOffset),l=Ol(t,e.focusNode,e.focusOffset);if(!o||o.bad||!l||l.bad||0!=st(ht(o,l),r)||0!=st(ct(o,l),i)){var s,a,u=t.display.view,c=r.line>=t.display.viewFrom&&Nl(t,r)||{node:u[0].measure.map[2],offset:0},h=i.line<t.display.viewTo&&Nl(t,i);if(h||(h={node:(a=(s=u[u.length-1].measure).maps?s.maps[s.maps.length-1]:s.map)[a.length-1],offset:a[a.length-2]-a[a.length-3]}),c&&h){var d,f=e.rangeCount&&e.getRangeAt(0);try{d=k(c.node,c.offset,h.offset,h.node)}catch(e){}d&&(!g&&t.state.focused?(e.collapse(c.node,c.offset),d.collapsed||(e.removeAllRanges(),e.addRange(d))):(e.removeAllRanges(),e.addRange(d)),f&&null==e.anchorNode?e.addRange(f):g&&this.startGracePeriod()),this.rememberSelection()}else e.removeAllRanges()}}},Ml.prototype.startGracePeriod=function(){var e=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){e.gracePeriod=!1,e.selectionChanged()&&e.cm.operation(function(){return e.cm.curOp.selectionChanged=!0})},20)},Ml.prototype.showMultipleSelections=function(e){N(this.cm.display.cursorDiv,e.cursors),N(this.cm.display.selectionDiv,e.selection)},Ml.prototype.rememberSelection=function(){var e=this.getSelection();this.lastAnchorNode=e.anchorNode,this.lastAnchorOffset=e.anchorOffset,this.lastFocusNode=e.focusNode,this.lastFocusOffset=e.focusOffset},Ml.prototype.selectionInEditor=function(){var e=this.getSelection();if(!e.rangeCount)return!1;var t=e.getRangeAt(0).commonAncestorContainer;return D(this.div,t)},Ml.prototype.focus=function(){"nocursor"!=this.cm.options.readOnly&&(this.selectionInEditor()&&document.activeElement==this.div||this.showSelection(this.prepareSelection(),!0),this.div.focus())},Ml.prototype.blur=function(){this.div.blur()},Ml.prototype.getField=function(){return this.div},Ml.prototype.supportsTouch=function(){return!0},Ml.prototype.receivedFocus=function(){var t=this;this.selectionInEditor()?this.pollSelection():Br(this.cm,function(){return t.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,function e(){t.cm.state.focused&&(t.pollSelection(),t.polling.set(t.cm.options.pollInterval,e))})},Ml.prototype.selectionChanged=function(){var e=this.getSelection();return e.anchorNode!=this.lastAnchorNode||e.anchorOffset!=this.lastAnchorOffset||e.focusNode!=this.lastFocusNode||e.focusOffset!=this.lastFocusOffset},Ml.prototype.pollSelection=function(){if(null==this.readDOMTimeout&&!this.gracePeriod&&this.selectionChanged()){var e,t,n=this.getSelection(),r=this.cm;if(h&&l&&this.cm.display.gutterSpecs.length&&function(e){for(var t=e;t;t=t.parentNode)if(/CodeMirror-gutter-wrapper/.test(t.className))return!0;return!1}(n.anchorNode))return this.cm.triggerOnKeyDown({type:"keydown",keyCode:8,preventDefault:Math.abs}),this.blur(),void this.focus();this.composing||(this.rememberSelection(),e=Ol(r,n.anchorNode,n.anchorOffset),t=Ol(r,n.focusNode,n.focusOffset),e&&t&&Br(r,function(){Bi(r.doc,di(e,t),V),(e.bad||t.bad)&&(r.curOp.selectionChanged=!0)}))}},Ml.prototype.pollContent=function(){null!=this.readDOMTimeout&&(clearTimeout(this.readDOMTimeout),this.readDOMTimeout=null);var e,t,n,r=this.cm,i=r.display,o=r.doc.sel.primary(),l=o.from(),s=o.to();if(0==l.ch&&l.line>r.firstLine()&&(l=lt(l.line-1,Qe(r.doc,l.line-1).length)),s.ch==Qe(r.doc,s.line).text.length&&s.line<r.lastLine()&&(s=lt(s.line+1,0)),l.line<i.viewFrom||s.line>i.viewTo-1)return!1;n=l.line==i.viewFrom||0==(e=rr(r,l.line))?(t=nt(i.view[0].line),i.view[0].node):(t=nt(i.view[e].line),i.view[e-1].node.nextSibling);var a,u=rr(r,s.line),c=u==i.view.length-1?(a=i.viewTo-1,i.lineDiv.lastChild):(a=nt(i.view[u+1].line)-1,i.view[u+1].node.previousSibling);if(!n)return!1;for(var h=r.doc.splitLines(function(u,e,t,c,h){var n="",d=!1,f=u.doc.lineSeparator(),p=!1;function g(){d&&(n+=f,p&&(n+=f),d=p=!1)}function m(e){e&&(g(),n+=e)}for(;!function e(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)return void m(n);var r,i=t.getAttribute("cm-marker");if(i){var o=u.findMarks(lt(c,0),lt(h+1,0),(a=+i,function(e){return e.id==a}));return void(o.length&&(r=o[0].find(0))&&m(Je(u.doc,r.from,r.to).join(f)))}if("false"==t.getAttribute("contenteditable"))return;var l=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(!/^br$/i.test(t.nodeName)&&0==t.textContent.length)return;l&&g();for(var s=0;s<t.childNodes.length;s++)e(t.childNodes[s]);/^(pre|p)$/i.test(t.nodeName)&&(p=!0),l&&(d=!0)}else 3==t.nodeType&&m(t.nodeValue.replace(/\u200b/g,"").replace(/\u00a0/g," "));var a}(e),e!=t;)e=e.nextSibling,p=!1;return n}(r,n,c,t,a)),d=Je(r.doc,lt(t,0),lt(a,Qe(r.doc,a).text.length));1<h.length&&1<d.length;)if($(h)==$(d))h.pop(),d.pop(),a--;else{if(h[0]!=d[0])break;h.shift(),d.shift(),t++}for(var f=0,p=0,g=h[0],m=d[0],v=Math.min(g.length,m.length);f<v&&g.charCodeAt(f)==m.charCodeAt(f);)++f;for(var y=$(h),b=$(d),w=Math.min(y.length-(1==h.length?f:0),b.length-(1==d.length?f:0));p<w&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)++p;if(1==h.length&&1==d.length&&t==l.line)for(;f&&f>l.ch&&y.charCodeAt(y.length-p-1)==b.charCodeAt(b.length-p-1);)f--,p++;h[h.length-1]=y.slice(0,y.length-p).replace(/^\u200b+/,""),h[0]=h[0].slice(f).replace(/\u200b+$/,"");var x=lt(t,f),C=lt(a,d.length?$(d).length-p:0);return 1<h.length||h[0]||st(x,C)?(to(r.doc,h,x,C,"+input"),!0):void 0},Ml.prototype.ensurePolled=function(){this.forceCompositionEnd()},Ml.prototype.reset=function(){this.forceCompositionEnd()},Ml.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},Ml.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},Ml.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||Br(this.cm,function(){return ir(e.cm)})},Ml.prototype.setUneditable=function(e){e.contentEditable="false"},Ml.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Gr(this.cm,bl)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},Ml.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},Ml.prototype.onContextMenu=function(){},Ml.prototype.resetPosition=function(){},Ml.prototype.needsContentAttribute=!0;function Dl(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new z,this.hasSelection=!1,this.composing=null}var Wl,Hl,Fl,El,Pl;function Il(e,t,r,n){Wl.defaults[e]=t,r&&(Hl[e]=n?function(e,t,n){n!=ul&&r(e,t,n)}:r)}Dl.prototype.init=function(n){var e=this,r=this,i=this.cm;this.createField(n);var o=this.textarea;function t(e){if(!Le(i,e)){if(i.somethingSelected())yl({lineWise:!1,text:i.getSelections()});else{if(!i.options.lineWiseCopyCut)return;var t=Cl(i);yl({lineWise:!0,text:t.text}),"cut"==e.type?i.setSelections(t.ranges,null,V):(r.prevInput="",o.value=t.text.join("\n"),E(o))}"cut"==e.type&&(i.state.cutIncoming=+new Date)}}n.wrapper.insertBefore(this.wrapper,n.wrapper.firstChild),a&&(o.style.width="0px"),we(o,"input",function(){L&&9<=x&&e.hasSelection&&(e.hasSelection=null),r.poll()}),we(o,"paste",function(e){Le(i,e)||wl(e,i)||(i.state.pasteIncoming=+new Date,r.fastPoll())}),we(o,"cut",t),we(o,"copy",t),we(n.scroller,"paste",function(e){if(!bn(n,e)&&!Le(i,e)){if(!o.dispatchEvent)return i.state.pasteIncoming=+new Date,void r.focus();var t=new Event("paste");t.clipboardData=e.clipboardData,o.dispatchEvent(t)}}),we(n.lineSpace,"selectstart",function(e){bn(n,e)||Ne(e)}),we(o,"compositionstart",function(){var e=i.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:i.markText(e,i.getCursor("to"),{className:"CodeMirror-composing"})}}),we(o,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},Dl.prototype.createField=function(e){this.wrapper=Ll(),this.textarea=this.wrapper.firstChild},Dl.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},Dl.prototype.prepareSelection=function(){var e,t,n,r=this.cm,i=r.display,o=r.doc,l=cr(r);return r.options.moveInputWithCursor&&(e=Vn(r,o.sel.primary().head,"div"),t=i.wrapper.getBoundingClientRect(),n=i.lineDiv.getBoundingClientRect(),l.teTop=Math.max(0,Math.min(i.wrapper.clientHeight-10,e.top+n.top-t.top)),l.teLeft=Math.max(0,Math.min(i.wrapper.clientWidth-10,e.left+n.left-t.left))),l},Dl.prototype.showSelection=function(e){var t=this.cm.display;N(t.cursorDiv,e.cursors),N(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},Dl.prototype.reset=function(e){var t,n;this.contextMenuPending||this.composing||((t=this.cm).somethingSelected()?(this.prevInput="",n=t.getSelection(),this.textarea.value=n,t.state.focused&&E(this.textarea),L&&9<=x&&(this.hasSelection=n)):e||(this.prevInput=this.textarea.value="",L&&9<=x&&(this.hasSelection=null)))},Dl.prototype.getField=function(){return this.textarea},Dl.prototype.supportsTouch=function(){return!1},Dl.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!d||W()!=this.textarea))try{this.textarea.focus()}catch(e){}},Dl.prototype.blur=function(){this.textarea.blur()},Dl.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},Dl.prototype.receivedFocus=function(){this.slowPoll()},Dl.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},Dl.prototype.fastPoll=function(){var t=!1,n=this;n.pollingFast=!0,n.polling.set(20,function e(){n.poll()||t?(n.pollingFast=!1,n.slowPoll()):(t=!0,n.polling.set(60,e))})},Dl.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||ze(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=n.value;if(i==r&&!t.somethingSelected())return!1;if(L&&9<=x&&this.hasSelection===i||y&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||r||(r="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var l=0,s=Math.min(r.length,i.length);l<s&&r.charCodeAt(l)==i.charCodeAt(l);)++l;return Br(t,function(){bl(t,i.slice(l),r.length-l,null,e.composing?"*compose":null),1e3<i.length||-1<i.indexOf("\n")?n.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},Dl.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},Dl.prototype.onKeyPress=function(){L&&9<=x&&(this.hasSelection=null),this.fastPoll()},Dl.prototype.onContextMenu=function(e){var n=this,r=n.cm,i=r.display,o=n.textarea;n.contextMenuPending&&n.contextMenuPending();var l,s,t,a,u,c=nr(r,e),h=i.scroller.scrollTop;function d(){var e,t;null!=o.selectionStart&&(t="​"+((e=r.somethingSelected())?o.value:""),o.value="⇚",o.value=t,n.prevInput=e?"":"​",o.selectionStart=1,o.selectionEnd=t.length,i.selForContextMenu=r.doc.sel)}function f(){var e,t;n.contextMenuPending==f&&(n.contextMenuPending=!1,n.wrapper.style.cssText=s,o.style.cssText=l,L&&x<9&&i.scrollbars.setScrollTop(i.scroller.scrollTop=h),null!=o.selectionStart&&((!L||L&&x<9)&&d(),e=0,t=function(){i.selForContextMenu==r.doc.sel&&0==o.selectionStart&&0<o.selectionEnd&&"​"==n.prevInput?Gr(r,_i)(r):e++<10?i.detectingSelectAll=setTimeout(t,500):(i.selForContextMenu=null,i.input.reset())},i.detectingSelectAll=setTimeout(t,200)))}c&&!m&&(r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(c)&&Gr(r,Bi)(r.doc,di(c),V),l=o.style.cssText,s=n.wrapper.style.cssText,t=n.wrapper.offsetParent.getBoundingClientRect(),n.wrapper.style.cssText="position: static",o.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-t.top-5)+"px; left: "+(e.clientX-t.left-5)+"px;\n z-index: 1000; background: "+(L?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",v&&(a=window.scrollY),i.input.focus(),v&&window.scrollTo(null,a),i.input.reset(),r.somethingSelected()||(o.value=n.prevInput=" "),n.contextMenuPending=f,i.selForContextMenu=r.doc.sel,clearTimeout(i.detectingSelectAll),L&&9<=x&&d(),C?(De(e),u=function(){Ce(window,"mouseup",u),setTimeout(f,20)},we(window,"mouseup",u)):setTimeout(f,50))},Dl.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},Dl.prototype.setUneditable=function(){},Dl.prototype.needsContentAttribute=!1,Hl=(Wl=pl).optionHandlers,Wl.defineOption=Il,Wl.Init=ul,Il("value","",function(e,t){return e.setValue(t)},!0),Il("mode",null,function(e,t){e.doc.modeOption=t,vi(e)},!0),Il("indentUnit",2,vi,!0),Il("indentWithTabs",!1),Il("smartIndent",!0),Il("tabSize",4,function(e){yi(e),Pn(e),ir(e)},!0),Il("lineSeparator",null,function(e,r){if(e.doc.lineSep=r){var i=[],o=e.doc.first;e.doc.iter(function(e){for(var t=0;;){var n=e.text.indexOf(r,t);if(-1==n)break;t=n+r.length,i.push(lt(o,n))}o++});for(var t=i.length-1;0<=t;t--)to(e.doc,r,i[t],lt(i[t].line,i[t].ch+r.length))}}),Il("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=ul&&e.refresh()}),Il("specialCharPlaceholder",en,function(e){return e.refresh()},!0),Il("electricChars",!0),Il("inputStyle",d?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),Il("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),Il("autocorrect",!1,function(e,t){return e.getInputField().autocorrect=t},!0),Il("autocapitalize",!1,function(e,t){return e.getInputField().autocapitalize=t},!0),Il("rtlMoveVisually",!p),Il("wholeLineUpdateBefore",!0),Il("theme","default",function(e){al(e),ni(e)},!0),Il("keyMap","default",function(e,t,n){var r=Po(t),i=n!=ul&&Po(n);i&&i.detach&&i.detach(e,r),r.attach&&r.attach(e,i||null)}),Il("extraKeys",null),Il("configureMouse",null),Il("lineWrapping",!1,fl,!0),Il("gutters",[],function(e,t){e.display.gutterSpecs=ei(t,e.options.lineNumbers),ni(e)},!0),Il("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?Jn(e.display)+"px":"0",e.refresh()},!0),Il("coverGutterNextToScrollbar",!1,function(e){return Hr(e)},!0),Il("scrollbarStyle","native",function(e){Pr(e),Hr(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),Il("lineNumbers",!1,function(e,t){e.display.gutterSpecs=ei(e.options.gutters,t),ni(e)},!0),Il("firstLineNumber",1,ni,!0),Il("lineNumberFormatter",function(e){return e},ni,!0),Il("showCursorWhenSelecting",!1,ur,!0),Il("resetSelectionOnContextMenu",!0),Il("lineWiseCopyCut",!0),Il("pasteLinesPerSelection",!0),Il("selectionsMayTouch",!1),Il("readOnly",!1,function(e,t){"nocursor"==t&&(vr(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),Il("screenReaderLabel",null,function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)}),Il("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),Il("dragDrop",!0,dl),Il("allowDropFileTypes",null),Il("cursorBlinkRate",530),Il("cursorScrollMargin",0),Il("cursorHeight",1,ur,!0),Il("singleCursorHeightPerLine",!0,ur,!0),Il("workTime",100),Il("workDelay",100),Il("flattenSpans",!0,yi,!0),Il("addModeClass",!1,yi,!0),Il("pollInterval",100),Il("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),Il("historyEventDelay",1250),Il("viewportMargin",10,function(e){return e.refresh()},!0),Il("maxHighlightLength",1e4,yi,!0),Il("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),Il("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),Il("autofocus",null),Il("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0),Il("phrases",null),El=(Fl=pl).optionHandlers,Pl=Fl.helpers={},Fl.prototype={constructor:Fl,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,t){var n=this.options,r=n[e];n[e]==t&&"mode"!=e||(n[e]=t,El.hasOwnProperty(e)&&Gr(this,El[e])(this,t,r),Se(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Po(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,n=0;n<t.length;++n)if(t[n]==e||t[n].name==e)return t.splice(n,1),!0},addOverlay:Ur(function(e,t){var n=e.token?e:Fl.getMode(this.options,e);if(n.startState)throw new Error("Overlays may not be stateful.");!function(e,t,n){for(var r=0,i=n(t);r<e.length&&n(e[r])<=i;)r++;e.splice(r,0,t)}(this.state.overlays,{mode:n,modeSpec:e,opaque:t&&t.opaque,priority:t&&t.priority||0},function(e){return e.priority}),this.state.modeGen++,ir(this)}),removeOverlay:Ur(function(e){for(var t=this.state.overlays,n=0;n<t.length;++n){var r=t[n].modeSpec;if(r==e||"string"==typeof e&&r.name==e)return t.splice(n,1),this.state.modeGen++,void ir(this)}}),indentLine:Ur(function(e,t,n){"string"!=typeof t&&"number"!=typeof t&&(t=null==t?this.options.smartIndent?"smart":"prev":t?"add":"subtract"),it(this.doc,e)&&ml(this,e,t,n)}),indentSelection:Ur(function(e){for(var t=this.doc.sel.ranges,n=-1,r=0;r<t.length;r++){var i=t[r];if(i.empty())i.head.line>n&&(ml(this,i.head.line,e,!0),n=i.head.line,r==this.doc.sel.primIndex&&Sr(this));else{for(var o=i.from(),l=i.to(),s=Math.max(n,o.line),n=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1,a=s;a<n;++a)ml(this,a,e);var u=this.doc.sel.ranges;0==o.ch&&t.length==u.length&&0<u[r].from().ch&&Ii(this.doc,r,new ci(o,u[r].to()),V)}}}),getTokenAt:function(e,t){return Lt(this,e,t)},getLineTokens:function(e,t){return Lt(this,lt(e),t,!0)},getTokenTypeAt:function(e){e=ft(this.doc,e);var t,n=yt(this,Qe(this.doc,e.line)),r=0,i=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var l=r+i>>1;if((l?n[2*l-1]:0)>=o)i=l;else{if(!(n[2*l+1]<o)){t=n[2*l+2];break}r=1+l}}var s=t?t.indexOf("overlay "):-1;return s<0?t:0==s?null:t.slice(0,s-1)},getModeAt:function(e){var t=this.doc.mode;return t.innerMode?Fl.innerMode(t,this.getTokenAt(e).state).mode:t},getHelper:function(e,t){return this.getHelpers(e,t)[0]},getHelpers:function(e,t){var n=[];if(!Pl.hasOwnProperty(t))return n;var r=Pl[t],i=this.getModeAt(e);if("string"==typeof i[t])r[i[t]]&&n.push(r[i[t]]);else if(i[t])for(var o=0;o<i[t].length;o++){var l=r[i[t][o]];l&&n.push(l)}else i.helperType&&r[i.helperType]?n.push(r[i.helperType]):r[i.name]&&n.push(r[i.name]);for(var s=0;s<r._global.length;s++){var a=r._global[s];a.pred(i,this)&&-1==B(n,a.val)&&n.push(a.val)}return n},getStateAfter:function(e,t){var n=this.doc;return bt(this,(e=dt(n,null==e?n.first+n.size-1:e))+1,t).state},cursorCoords:function(e,t){var n=this.doc.sel.primary(),r=null==e?n.head:"object"==typeof e?ft(this.doc,e):e?n.from():n.to();return Vn(this,r,t||"page")},charCoords:function(e,t){return Un(this,ft(this.doc,e),t||"page")},coordsChar:function(e,t){return Xn(this,(e=Gn(this,e,t||"page")).left,e.top)},lineAtHeight:function(e,t){return e=Gn(this,{top:e,left:0},t||"page").top,rt(this.doc,e+this.display.viewOffset)},heightAtLine:function(e,t,n){var r,i=!1,o="number"==typeof e?(r=this.doc.first+this.doc.size-1,e<this.doc.first?e=this.doc.first:r<e&&(e=r,i=!0),Qe(this.doc,e)):e;return Bn(this,o,{top:0,left:0},t||"page",n||i).top+(i?this.doc.height-Xt(o):0)},defaultTextHeight:function(){return qn(this.display)},defaultCharWidth:function(){return Zn(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,i){var o,l,s,a,u,c=this.display,h=(e=Vn(this,ft(this.doc,e))).bottom,d=e.left;t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),c.sizer.appendChild(t),"over"==r?h=e.top:"above"!=r&&"near"!=r||(o=Math.max(c.wrapper.clientHeight,this.doc.height),l=Math.max(c.sizer.clientWidth,c.lineSpace.clientWidth),("above"==r||e.bottom+t.offsetHeight>o)&&e.top>t.offsetHeight?h=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=o&&(h=e.bottom),d+t.offsetWidth>l&&(d=l-t.offsetWidth)),t.style.top=h+"px",t.style.left=t.style.right="","right"==i?(d=c.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?d=0:"middle"==i&&(d=(c.sizer.clientWidth-t.offsetWidth)/2),t.style.left=d+"px"),n&&(s=this,a={left:d,top:h,right:d+t.offsetWidth,bottom:h+t.offsetHeight},null!=(u=xr(s,a)).scrollTop&&Mr(s,u.scrollTop),null!=u.scrollLeft&&Ar(s,u.scrollLeft))},triggerOnKeyDown:Ur(Zo),triggerOnKeyPress:Ur(Jo),triggerOnKeyUp:Qo,triggerOnMouseDown:Ur(rl),execCommand:function(e){if(Uo.hasOwnProperty(e))return Uo[e].call(null,this)},triggerElectric:Ur(function(e){xl(this,e)}),findPosH:function(e,t,n,r){var i=1;t<0&&(i=-1,t=-t);for(var o=ft(this.doc,e),l=0;l<t&&!(o=kl(this.doc,o,i,n,r)).hitSide;++l);return o},moveH:Ur(function(t,n){var r=this;this.extendSelectionsBy(function(e){return r.display.shift||r.doc.extend||e.empty()?kl(r.doc,e.head,t,n,r.options.rtlMoveVisually):t<0?e.from():e.to()},j)}),deleteH:Ur(function(n,r){var e=this.doc.sel,i=this.doc;e.somethingSelected()?i.replaceSelection("",null,"+delete"):Io(this,function(e){var t=kl(i,e.head,n,r,!1);return n<0?{from:t,to:e.head}:{from:e.head,to:t}})}),findPosV:function(e,t,n,r){var i=1,o=r;t<0&&(i=-1,t=-t);for(var l=ft(this.doc,e),s=0;s<t;++s){var a=Vn(this,l,"div");if(null==o?o=a.left:a.left=o,(l=Tl(this,a,i,n)).hitSide)break}return l},moveV:Ur(function(r,i){var o=this,l=this.doc,s=[],a=!this.display.shift&&!l.extend&&l.sel.somethingSelected();if(l.extendSelectionsBy(function(e){if(a)return r<0?e.from():e.to();var t=Vn(o,e.head,"div");null!=e.goalColumn&&(t.left=e.goalColumn),s.push(t.left);var n=Tl(o,t,r,i);return"page"==i&&e==l.sel.primary()&&Cr(o,Un(o,n,"div").top-t.top),n},j),s.length)for(var e=0;e<l.sel.ranges.length;e++)l.sel.ranges[e].goalColumn=s[e]}),findWordAt:function(e){var t=Qe(this.doc,e.line).text,n=e.ch,r=e.ch;if(t){var i=this.getHelper(e,"wordChars");"before"!=e.sticky&&r!=t.length||!n?++r:--n;for(var o=t.charAt(n),l=te(o,i)?function(e){return te(e,i)}:/\s/.test(o)?function(e){return/\s/.test(e)}:function(e){return!/\s/.test(e)&&!te(e)};0<n&&l(t.charAt(n-1));)--n;for(;r<t.length&&l(t.charAt(r));)++r}return new ci(lt(e.line,n),lt(e.line,r))},toggleOverwrite:function(e){null!=e&&e==this.state.overwrite||(((this.state.overwrite=!this.state.overwrite)?H:T)(this.display.cursorDiv,"CodeMirror-overwrite"),Se(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==W()},isReadOnly:function(){return!(!this.options.readOnly&&!this.doc.cantEdit)},scrollTo:Ur(function(e,t){Lr(this,e,t)}),getScrollInfo:function(){var e=this.display.scroller;return{left:e.scrollLeft,top:e.scrollTop,height:e.scrollHeight-Sn(this)-this.display.barHeight,width:e.scrollWidth-Sn(this)-this.display.barWidth,clientHeight:kn(this),clientWidth:Ln(this)}},scrollIntoView:Ur(function(e,t){var n,r;null==e?(e={from:this.doc.sel.primary().head,to:null},null==t&&(t=this.options.cursorScrollMargin)):"number"==typeof e?e={from:lt(e,0),to:null}:null==e.from&&(e={from:e,to:null}),e.to||(e.to=e.from),e.margin=t||0,null!=e.from.line?(r=e,kr(n=this),n.curOp.scrollToPos=r):Tr(this,e.from,e.to,e.margin)}),setSize:Ur(function(e,t){function n(e){return"number"==typeof e||/^\d+$/.test(String(e))?e+"px":e}var r=this;null!=e&&(this.display.wrapper.style.width=n(e)),null!=t&&(this.display.wrapper.style.height=n(t)),this.options.lineWrapping&&En(this);var i=this.display.viewFrom;this.doc.iter(i,this.display.viewTo,function(e){if(e.widgets)for(var t=0;t<e.widgets.length;t++)if(e.widgets[t].noHScroll){or(r,i,"widget");break}++i}),this.curOp.forceUpdate=!0,Se(this,"refresh",this)}),operation:function(e){return Br(this,e)},startOperation:function(){return Rr(this)},endOperation:function(){return zr(this)},refresh:Ur(function(){var e=this.display.cachedTextHeight;ir(this),this.curOp.forceUpdate=!0,Pn(this),Lr(this,this.doc.scrollLeft,this.doc.scrollTop),qr(this.display),(null==e||.5<Math.abs(e-qn(this.display))||this.options.lineWrapping)&&tr(this),Se(this,"refresh",this)}),swapDoc:Ur(function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),Ci(this,e),Pn(this),this.display.input.reset(),Lr(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,un(this,"swapDoc",this,t),t}),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},Me(Fl),Fl.registerHelper=function(e,t,n){Pl.hasOwnProperty(e)||(Pl[e]=Fl[e]={_global:[]}),Pl[e][t]=n},Fl.registerGlobalHelper=function(e,t,n,r){Fl.registerHelper(e,t,r),Pl[e]._global.push({pred:n,val:r})};var Rl,zl="iter insert remove copy getEditor constructor".split(" ");for(var Bl in vo.prototype)vo.prototype.hasOwnProperty(Bl)&&B(zl,Bl)<0&&(pl.prototype[Bl]=function(e){return function(){return e.apply(this.doc,arguments)}}(vo.prototype[Bl]));return Me(vo),pl.inputStyles={textarea:Dl,contenteditable:Ml},pl.defineMode=function(e){pl.defaults.mode||"null"==e||(pl.defaults.mode=e),function(e,t){2<arguments.length&&(t.dependencies=Array.prototype.slice.call(arguments,2)),Ue[e]=t}.apply(this,arguments)},pl.defineMIME=function(e,t){Ve[e]=t},pl.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),pl.defineMIME("text/plain","null"),pl.defineExtension=function(e,t){pl.prototype[e]=t},pl.defineDocExtension=function(e,t){vo.prototype[e]=t},pl.fromTextArea=function(t,n){var e;function r(){t.value=s.getValue()}if((n=n?I(n):{}).value=t.value,!n.tabindex&&t.tabIndex&&(n.tabindex=t.tabIndex),!n.placeholder&&t.placeholder&&(n.placeholder=t.placeholder),null==n.autofocus&&(e=W(),n.autofocus=e==t||null!=t.getAttribute("autofocus")&&e==document.body),t.form&&(we(t.form,"submit",r),!n.leaveSubmitMethodAlone)){var i=t.form,o=i.submit;try{var l=i.submit=function(){r(),i.submit=o,i.submit(),i.submit=l}}catch(e){}}n.finishInit=function(e){e.save=r,e.getTextArea=function(){return t},e.toTextArea=function(){e.toTextArea=isNaN,r(),t.parentNode.removeChild(e.getWrapperElement()),t.style.display="",t.form&&(Ce(t.form,"submit",r),n.leaveSubmitMethodAlone||"function"!=typeof t.form.submit||(t.form.submit=o))}},t.style.display="none";var s=pl(function(e){return t.parentNode.insertBefore(e,t.nextSibling)},n);return s},(Rl=pl).off=Ce,Rl.on=we,Rl.wheelEventPixels=si,Rl.Doc=vo,Rl.splitLines=Re,Rl.countColumn=R,Rl.findColumn=X,Rl.isWordChar=ee,Rl.Pass=U,Rl.signal=Se,Rl.Line=$t,Rl.changeEnd=fi,Rl.scrollbarModel=Er,Rl.Pos=lt,Rl.cmpPos=st,Rl.modes=Ue,Rl.mimeModes=Ve,Rl.resolveMode=Ke,Rl.getMode=je,Rl.modeExtensions=Xe,Rl.extendMode=Ye,Rl.copyState=_e,Rl.startState=qe,Rl.innerMode=$e,Rl.commands=Uo,Rl.keyMap=Ao,Rl.keyName=Eo,Rl.isModifierKey=Ho,Rl.lookupKey=Wo,Rl.normalizeKeyMap=Do,Rl.StringStream=Ze,Rl.SharedTextMarker=po,Rl.TextMarker=ho,Rl.LineWidget=ao,Rl.e_preventDefault=Ne,Rl.e_stopPropagation=Ae,Rl.e_stop=De,Rl.addClass=H,Rl.contains=D,Rl.rmClass=T,Rl.keyNames=ko,pl.version="5.58.3",pl}); +// CodeMirror, copyright (c) by Marijn Haverbeke and others +// Distributed under an MIT license: https://codemirror.net/LICENSE + +// This is CodeMirror (https://codemirror.net), a code editor +// implemented in JavaScript on top of the browser's DOM. +// +// You can find some technical background for some of the code below +// at http://marijnhaverbeke.nl/blog/#cm-internals . + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + (global = global || self, global.CodeMirror = factory()); +}(this, (function () { 'use strict'; + + // Kludges for bugs and behavior differences that can't be feature + // detected are enabled based on userAgent etc sniffing. + var userAgent = navigator.userAgent; + var platform = navigator.platform; + + var gecko = /gecko\/\d/i.test(userAgent); + var ie_upto10 = /MSIE \d/.test(userAgent); + var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); + var edge = /Edge\/(\d+)/.exec(userAgent); + var ie = ie_upto10 || ie_11up || edge; + var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]); + var webkit = !edge && /WebKit\//.test(userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); + var chrome = !edge && /Chrome\//.test(userAgent); + var presto = /Opera\//.test(userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); + var phantom = /PhantomJS/.test(userAgent); + + var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); + var android = /Android/.test(userAgent); + // This is woefully incomplete. Suggestions for alternative methods welcome. + var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); + var mac = ios || /Mac/.test(platform); + var chromeOS = /\bCrOS\b/.test(userAgent); + var windows = /win/i.test(platform); + + var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); + if (presto_version) { presto_version = Number(presto_version[1]); } + if (presto_version && presto_version >= 15) { presto = false; webkit = true; } + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); + var captureRightClick = gecko || (ie && ie_version >= 9); + + function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } + + var rmClass = function(node, cls) { + var current = node.className; + var match = classTest(cls).exec(current); + if (match) { + var after = current.slice(match.index + match[0].length); + node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); + } + }; + + function removeChildren(e) { + for (var count = e.childNodes.length; count > 0; --count) + { e.removeChild(e.firstChild); } + return e + } + + function removeChildrenAndAdd(parent, e) { + return removeChildren(parent).appendChild(e) + } + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) { e.className = className; } + if (style) { e.style.cssText = style; } + if (typeof content == "string") { e.appendChild(document.createTextNode(content)); } + else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } } + return e + } + // wrapper for elt, which removes the elt from the accessibility tree + function eltP(tag, content, className, style) { + var e = elt(tag, content, className, style); + e.setAttribute("role", "presentation"); + return e + } + + var range; + if (document.createRange) { range = function(node, start, end, endNode) { + var r = document.createRange(); + r.setEnd(endNode || node, end); + r.setStart(node, start); + return r + }; } + else { range = function(node, start, end) { + var r = document.body.createTextRange(); + try { r.moveToElementText(node.parentNode); } + catch(e) { return r } + r.collapse(true); + r.moveEnd("character", end); + r.moveStart("character", start); + return r + }; } + + function contains(parent, child) { + if (child.nodeType == 3) // Android browser always returns false when child is a textnode + { child = child.parentNode; } + if (parent.contains) + { return parent.contains(child) } + do { + if (child.nodeType == 11) { child = child.host; } + if (child == parent) { return true } + } while (child = child.parentNode) + } + + function activeElt() { + // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. + // IE < 10 will throw when accessed while the page is loading or in an iframe. + // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. + var activeElement; + try { + activeElement = document.activeElement; + } catch(e) { + activeElement = document.body || null; + } + while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) + { activeElement = activeElement.shadowRoot.activeElement; } + return activeElement + } + + function addClass(node, cls) { + var current = node.className; + if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; } + } + function joinClasses(a, b) { + var as = a.split(" "); + for (var i = 0; i < as.length; i++) + { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } } + return b + } + + var selectInput = function(node) { node.select(); }; + if (ios) // Mobile Safari apparently has a bug where select() is broken. + { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; } + else if (ie) // Suppress mysterious IE10 errors + { selectInput = function(node) { try { node.select(); } catch(_e) {} }; } + + function bind(f) { + var args = Array.prototype.slice.call(arguments, 1); + return function(){return f.apply(null, args)} + } + + function copyObj(obj, target, overwrite) { + if (!target) { target = {}; } + for (var prop in obj) + { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) + { target[prop] = obj[prop]; } } + return target + } + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize, startIndex, startValue) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) { end = string.length; } + } + for (var i = startIndex || 0, n = startValue || 0;;) { + var nextTab = string.indexOf("\t", i); + if (nextTab < 0 || nextTab >= end) + { return n + (end - i) } + n += nextTab - i; + n += tabSize - (n % tabSize); + i = nextTab + 1; + } + } + + var Delayed = function() { + this.id = null; + this.f = null; + this.time = 0; + this.handler = bind(this.onTimeout, this); + }; + Delayed.prototype.onTimeout = function (self) { + self.id = 0; + if (self.time <= +new Date) { + self.f(); + } else { + setTimeout(self.handler, self.time - +new Date); + } + }; + Delayed.prototype.set = function (ms, f) { + this.f = f; + var time = +new Date + ms; + if (!this.id || time < this.time) { + clearTimeout(this.id); + this.id = setTimeout(this.handler, ms); + this.time = time; + } + }; + + function indexOf(array, elt) { + for (var i = 0; i < array.length; ++i) + { if (array[i] == elt) { return i } } + return -1 + } + + // Number of pixels added to scroller and sizer to hide scrollbar + var scrollerGap = 50; + + // Returned or thrown by various protocols to signal 'I'm not + // handling this'. + var Pass = {toString: function(){return "CodeMirror.Pass"}}; + + // Reused option objects for setSelection & friends + var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; + + // The inverse of countColumn -- find the offset that corresponds to + // a particular column. + function findColumn(string, goal, tabSize) { + for (var pos = 0, col = 0;;) { + var nextTab = string.indexOf("\t", pos); + if (nextTab == -1) { nextTab = string.length; } + var skipped = nextTab - pos; + if (nextTab == string.length || col + skipped >= goal) + { return pos + Math.min(skipped, goal - col) } + col += nextTab - pos; + col += tabSize - (col % tabSize); + pos = nextTab + 1; + if (col >= goal) { return pos } + } + } + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + { spaceStrs.push(lst(spaceStrs) + " "); } + return spaceStrs[n] + } + + function lst(arr) { return arr[arr.length-1] } + + function map(array, f) { + var out = []; + for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); } + return out + } + + function insertSorted(array, value, score) { + var pos = 0, priority = score(value); + while (pos < array.length && score(array[pos]) <= priority) { pos++; } + array.splice(pos, 0, value); + } + + function nothing() {} + + function createObj(base, props) { + var inst; + if (Object.create) { + inst = Object.create(base); + } else { + nothing.prototype = base; + inst = new nothing(); + } + if (props) { copyObj(props, inst); } + return inst + } + + var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; + function isWordCharBasic(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) + } + function isWordChar(ch, helper) { + if (!helper) { return isWordCharBasic(ch) } + if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } + return helper.test(ch) + } + + function isEmpty(obj) { + for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } + return true + } + + // Extending unicode characters. A series of a non-extending char + + // any number of extending chars is treated as a single unit as far + // as editing and measuring is concerned. This is not fully correct, + // since some scripts/fonts/browsers also treat other configurations + // of code points as a group. + var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; + function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } + + // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. + function skipExtendingChars(str, pos, dir) { + while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; } + return pos + } + + // Returns the value from the range [`from`; `to`] that satisfies + // `pred` and is closest to `from`. Assumes that at least `to` + // satisfies `pred`. Supports `from` being greater than `to`. + function findFirst(pred, from, to) { + // At any point we are certain `to` satisfies `pred`, don't know + // whether `from` does. + var dir = from > to ? -1 : 1; + for (;;) { + if (from == to) { return from } + var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF); + if (mid == from) { return pred(mid) ? from : to } + if (pred(mid)) { to = mid; } + else { from = mid + dir; } + } + } + + // BIDI HELPERS + + function iterateBidiSections(order, from, to, f) { + if (!order) { return f(from, to, "ltr", 0) } + var found = false; + for (var i = 0; i < order.length; ++i) { + var part = order[i]; + if (part.from < to && part.to > from || from == to && part.to == from) { + f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i); + found = true; + } + } + if (!found) { f(from, to, "ltr"); } + } + + var bidiOther = null; + function getBidiPartAt(order, ch, sticky) { + var found; + bidiOther = null; + for (var i = 0; i < order.length; ++i) { + var cur = order[i]; + if (cur.from < ch && cur.to > ch) { return i } + if (cur.to == ch) { + if (cur.from != cur.to && sticky == "before") { found = i; } + else { bidiOther = i; } + } + if (cur.from == ch) { + if (cur.from != cur.to && sticky != "before") { found = i; } + else { bidiOther = i; } + } + } + return found != null ? found : bidiOther + } + + // Bidirectional ordering algorithm + // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm + // that this (partially) implements. + + // One-char codes used for character types: + // L (L): Left-to-Right + // R (R): Right-to-Left + // r (AL): Right-to-Left Arabic + // 1 (EN): European Number + // + (ES): European Number Separator + // % (ET): European Number Terminator + // n (AN): Arabic Number + // , (CS): Common Number Separator + // m (NSM): Non-Spacing Mark + // b (BN): Boundary Neutral + // s (B): Paragraph Separator + // t (S): Segment Separator + // w (WS): Whitespace + // N (ON): Other Neutrals + + // Returns null if characters are ordered as they appear + // (left-to-right), or an array of sections ({from, to, level} + // objects) in the order in which they occur visually. + var bidiOrdering = (function() { + // Character types for codepoints 0 to 0xff + var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; + // Character types for codepoints 0x600 to 0x6f9 + var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"; + function charType(code) { + if (code <= 0xf7) { return lowTypes.charAt(code) } + else if (0x590 <= code && code <= 0x5f4) { return "R" } + else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } + else if (0x6ee <= code && code <= 0x8ac) { return "r" } + else if (0x2000 <= code && code <= 0x200b) { return "w" } + else if (code == 0x200c) { return "b" } + else { return "L" } + } + + var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; + var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; + + function BidiSpan(level, from, to) { + this.level = level; + this.from = from; this.to = to; + } + + return function(str, direction) { + var outerType = direction == "ltr" ? "L" : "R"; + + if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } + var len = str.length, types = []; + for (var i = 0; i < len; ++i) + { types.push(charType(str.charCodeAt(i))); } + + // W1. Examine each non-spacing mark (NSM) in the level run, and + // change the type of the NSM to the type of the previous + // character. If the NSM is at the start of the level run, it will + // get the type of sor. + for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { + var type = types[i$1]; + if (type == "m") { types[i$1] = prev; } + else { prev = type; } + } + + // W2. Search backwards from each instance of a European number + // until the first strong type (R, L, AL, or sor) is found. If an + // AL is found, change the type of the European number to Arabic + // number. + // W3. Change all ALs to R. + for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { + var type$1 = types[i$2]; + if (type$1 == "1" && cur == "r") { types[i$2] = "n"; } + else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } } + } + + // W4. A single European separator between two European numbers + // changes to a European number. A single common separator between + // two numbers of the same type changes to that type. + for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { + var type$2 = types[i$3]; + if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; } + else if (type$2 == "," && prev$1 == types[i$3+1] && + (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; } + prev$1 = type$2; + } + + // W5. A sequence of European terminators adjacent to European + // numbers changes to all European numbers. + // W6. Otherwise, separators and terminators change to Other + // Neutral. + for (var i$4 = 0; i$4 < len; ++i$4) { + var type$3 = types[i$4]; + if (type$3 == ",") { types[i$4] = "N"; } + else if (type$3 == "%") { + var end = (void 0); + for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} + var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; + for (var j = i$4; j < end; ++j) { types[j] = replace; } + i$4 = end - 1; + } + } + + // W7. Search backwards from each instance of a European number + // until the first strong type (R, L, or sor) is found. If an L is + // found, then change the type of the European number to L. + for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { + var type$4 = types[i$5]; + if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; } + else if (isStrong.test(type$4)) { cur$1 = type$4; } + } + + // N1. A sequence of neutrals takes the direction of the + // surrounding strong text if the text on both sides has the same + // direction. European and Arabic numbers act as if they were R in + // terms of their influence on neutrals. Start-of-level-run (sor) + // and end-of-level-run (eor) are used at level run boundaries. + // N2. Any remaining neutrals take the embedding direction. + for (var i$6 = 0; i$6 < len; ++i$6) { + if (isNeutral.test(types[i$6])) { + var end$1 = (void 0); + for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} + var before = (i$6 ? types[i$6-1] : outerType) == "L"; + var after = (end$1 < len ? types[end$1] : outerType) == "L"; + var replace$1 = before == after ? (before ? "L" : "R") : outerType; + for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; } + i$6 = end$1 - 1; + } + } + + // Here we depart from the documented algorithm, in order to avoid + // building up an actual levels array. Since there are only three + // levels (0, 1, 2) in an implementation that doesn't take + // explicit embedding into account, we can build up the order on + // the fly, without following the level-based algorithm. + var order = [], m; + for (var i$7 = 0; i$7 < len;) { + if (countsAsLeft.test(types[i$7])) { + var start = i$7; + for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} + order.push(new BidiSpan(0, start, i$7)); + } else { + var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0; + for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} + for (var j$2 = pos; j$2 < i$7;) { + if (countsAsNum.test(types[j$2])) { + if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; } + var nstart = j$2; + for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} + order.splice(at, 0, new BidiSpan(2, nstart, j$2)); + at += isRTL; + pos = j$2; + } else { ++j$2; } + } + if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); } + } + } + if (direction == "ltr") { + if (order[0].level == 1 && (m = str.match(/^\s+/))) { + order[0].from = m[0].length; + order.unshift(new BidiSpan(0, 0, m[0].length)); + } + if (lst(order).level == 1 && (m = str.match(/\s+$/))) { + lst(order).to -= m[0].length; + order.push(new BidiSpan(0, len - m[0].length, len)); + } + } + + return direction == "rtl" ? order.reverse() : order + } + })(); + + // Get the bidi ordering for the given line (and cache it). Returns + // false for lines that are fully left-to-right, and an array of + // BidiSpan objects otherwise. + function getOrder(line, direction) { + var order = line.order; + if (order == null) { order = line.order = bidiOrdering(line.text, direction); } + return order + } + + // EVENT HANDLING + + // Lightweight event framework. on/off also work on DOM nodes, + // registering native DOM handlers. + + var noHandlers = []; + + var on = function(emitter, type, f) { + if (emitter.addEventListener) { + emitter.addEventListener(type, f, false); + } else if (emitter.attachEvent) { + emitter.attachEvent("on" + type, f); + } else { + var map = emitter._handlers || (emitter._handlers = {}); + map[type] = (map[type] || noHandlers).concat(f); + } + }; + + function getHandlers(emitter, type) { + return emitter._handlers && emitter._handlers[type] || noHandlers + } + + function off(emitter, type, f) { + if (emitter.removeEventListener) { + emitter.removeEventListener(type, f, false); + } else if (emitter.detachEvent) { + emitter.detachEvent("on" + type, f); + } else { + var map = emitter._handlers, arr = map && map[type]; + if (arr) { + var index = indexOf(arr, f); + if (index > -1) + { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); } + } + } + } + + function signal(emitter, type /*, values...*/) { + var handlers = getHandlers(emitter, type); + if (!handlers.length) { return } + var args = Array.prototype.slice.call(arguments, 2); + for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); } + } + + // The DOM events that CodeMirror handles can be overridden by + // registering a (non-DOM) handler on the editor for the event name, + // and preventDefault-ing the event in that handler. + function signalDOMEvent(cm, e, override) { + if (typeof e == "string") + { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; } + signal(cm, override || e.type, cm, e); + return e_defaultPrevented(e) || e.codemirrorIgnore + } + + function signalCursorActivity(cm) { + var arr = cm._handlers && cm._handlers.cursorActivity; + if (!arr) { return } + var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); + for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) + { set.push(arr[i]); } } + } + + function hasHandler(emitter, type) { + return getHandlers(emitter, type).length > 0 + } + + // Add on and off methods to a constructor's prototype, to make + // registering events on such objects more convenient. + function eventMixin(ctor) { + ctor.prototype.on = function(type, f) {on(this, type, f);}; + ctor.prototype.off = function(type, f) {off(this, type, f);}; + } + + // Due to the fact that we still support jurassic IE versions, some + // compatibility wrappers are needed. + + function e_preventDefault(e) { + if (e.preventDefault) { e.preventDefault(); } + else { e.returnValue = false; } + } + function e_stopPropagation(e) { + if (e.stopPropagation) { e.stopPropagation(); } + else { e.cancelBubble = true; } + } + function e_defaultPrevented(e) { + return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} + + function e_target(e) {return e.target || e.srcElement} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) { b = 1; } + else if (e.button & 2) { b = 3; } + else if (e.button & 4) { b = 2; } + } + if (mac && e.ctrlKey && b == 1) { b = 3; } + return b + } + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie && ie_version < 9) { return false } + var div = elt('div'); + return "draggable" in div || "dragDrop" in div + }(); + + var zwspSupported; + function zeroWidthElement(measure) { + if (zwspSupported == null) { + var test = elt("span", "\u200b"); + removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); + if (measure.firstChild.offsetHeight != 0) + { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); } + } + var node = zwspSupported ? elt("span", "\u200b") : + elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); + node.setAttribute("cm-text", ""); + return node + } + + // Feature-detect IE's crummy client rect reporting for bidi text + var badBidiRects; + function hasBadBidiRects(measure) { + if (badBidiRects != null) { return badBidiRects } + var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); + var r0 = range(txt, 0, 1).getBoundingClientRect(); + var r1 = range(txt, 1, 2).getBoundingClientRect(); + removeChildren(measure); + if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) + return badBidiRects = (r1.right - r0.right < 3) + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) { nl = string.length; } + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result + } : function (string) { return string.split(/\r\n?|\n/); }; + + var hasSelection = window.getSelection ? function (te) { + try { return te.selectionStart != te.selectionEnd } + catch(e) { return false } + } : function (te) { + var range; + try {range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) { return false } + return range.compareEndPoints("StartToEnd", range) != 0 + }; + + var hasCopyEvent = (function () { + var e = elt("div"); + if ("oncopy" in e) { return true } + e.setAttribute("oncopy", "return;"); + return typeof e.oncopy == "function" + })(); + + var badZoomedRects = null; + function hasBadZoomedRects(measure) { + if (badZoomedRects != null) { return badZoomedRects } + var node = removeChildrenAndAdd(measure, elt("span", "x")); + var normal = node.getBoundingClientRect(); + var fromRange = range(node, 0, 1).getBoundingClientRect(); + return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 + } + + // Known modes, by name and by MIME + var modes = {}, mimeModes = {}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + function defineMode(name, mode) { + if (arguments.length > 2) + { mode.dependencies = Array.prototype.slice.call(arguments, 2); } + modes[name] = mode; + } + + function defineMIME(mime, spec) { + mimeModes[mime] = spec; + } + + // Given a MIME type, a {name, ...options} config object, or a name + // string, return a mode config object. + function resolveMode(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { + spec = mimeModes[spec]; + } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { + var found = mimeModes[spec.name]; + if (typeof found == "string") { found = {name: found}; } + spec = createObj(found, spec); + spec.name = found.name; + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { + return resolveMode("application/xml") + } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { + return resolveMode("application/json") + } + if (typeof spec == "string") { return {name: spec} } + else { return spec || {name: "null"} } + } + + // Given a mode spec (anything that resolveMode accepts), find and + // initialize an actual mode object. + function getMode(options, spec) { + spec = resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) { return getMode(options, "text/plain") } + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) { continue } + if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; } + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + if (spec.helperType) { modeObj.helperType = spec.helperType; } + if (spec.modeProps) { for (var prop$1 in spec.modeProps) + { modeObj[prop$1] = spec.modeProps[prop$1]; } } + + return modeObj + } + + // This can be used to attach properties to mode objects from + // outside the actual mode definition. + var modeExtensions = {}; + function extendMode(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + copyObj(properties, exts); + } + + function copyState(mode, state) { + if (state === true) { return state } + if (mode.copyState) { return mode.copyState(state) } + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) { val = val.concat([]); } + nstate[n] = val; + } + return nstate + } + + // Given a mode and a state (for that mode), find the inner mode and + // state at the position that the state refers to. + function innerMode(mode, state) { + var info; + while (mode.innerMode) { + info = mode.innerMode(state); + if (!info || info.mode == mode) { break } + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state} + } + + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true + } + + // STRING STREAM + + // Fed to the mode parsers, provides helper functions to make + // parsers more succinct. + + var StringStream = function(string, tabSize, lineOracle) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + this.lastColumnPos = this.lastColumnValue = 0; + this.lineStart = 0; + this.lineOracle = lineOracle; + }; + + StringStream.prototype.eol = function () {return this.pos >= this.string.length}; + StringStream.prototype.sol = function () {return this.pos == this.lineStart}; + StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; + StringStream.prototype.next = function () { + if (this.pos < this.string.length) + { return this.string.charAt(this.pos++) } + }; + StringStream.prototype.eat = function (match) { + var ch = this.string.charAt(this.pos); + var ok; + if (typeof match == "string") { ok = ch == match; } + else { ok = ch && (match.test ? match.test(ch) : match(ch)); } + if (ok) {++this.pos; return ch} + }; + StringStream.prototype.eatWhile = function (match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start + }; + StringStream.prototype.eatSpace = function () { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; } + return this.pos > start + }; + StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;}; + StringStream.prototype.skipTo = function (ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true} + }; + StringStream.prototype.backUp = function (n) {this.pos -= n;}; + StringStream.prototype.column = function () { + if (this.lastColumnPos < this.start) { + this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); + this.lastColumnPos = this.start; + } + return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.indentation = function () { + return countColumn(this.string, null, this.tabSize) - + (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) + }; + StringStream.prototype.match = function (pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }; + var substr = this.string.substr(this.pos, pattern.length); + if (cased(substr) == cased(pattern)) { + if (consume !== false) { this.pos += pattern.length; } + return true + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) { return null } + if (match && consume !== false) { this.pos += match[0].length; } + return match + } + }; + StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; + StringStream.prototype.hideFirstChars = function (n, inner) { + this.lineStart += n; + try { return inner() } + finally { this.lineStart -= n; } + }; + StringStream.prototype.lookAhead = function (n) { + var oracle = this.lineOracle; + return oracle && oracle.lookAhead(n) + }; + StringStream.prototype.baseToken = function () { + var oracle = this.lineOracle; + return oracle && oracle.baseToken(this.pos) + }; + + // Find the line object corresponding to the given line number. + function getLine(doc, n) { + n -= doc.first; + if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } + var chunk = doc; + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break } + n -= sz; + } + } + return chunk.lines[n] + } + + // Get the part of a document between two positions, as an array of + // strings. + function getBetween(doc, start, end) { + var out = [], n = start.line; + doc.iter(start.line, end.line + 1, function (line) { + var text = line.text; + if (n == end.line) { text = text.slice(0, end.ch); } + if (n == start.line) { text = text.slice(start.ch); } + out.push(text); + ++n; + }); + return out + } + // Get the lines between from and to, as array of strings. + function getLines(doc, from, to) { + var out = []; + doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value + return out + } + + // Update the height of a line, propagating the height change + // upwards to parent nodes. + function updateLineHeight(line, height) { + var diff = height - line.height; + if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } + } + + // Given a line object, find its line number by walking up through + // its parent links. + function lineNo(line) { + if (line.parent == null) { return null } + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0;; ++i) { + if (chunk.children[i] == cur) { break } + no += chunk.children[i].chunkSize(); + } + } + return no + cur.first + } + + // Find the line at the given vertical position, using the height + // information in the document tree. + function lineAtHeight(chunk, h) { + var n = chunk.first; + outer: do { + for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { + var child = chunk.children[i$1], ch = child.height; + if (h < ch) { chunk = child; continue outer } + h -= ch; + n += child.chunkSize(); + } + return n + } while (!chunk.lines) + var i = 0; + for (; i < chunk.lines.length; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) { break } + h -= lh; + } + return n + i + } + + function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} + + function lineNumberFor(options, i) { + return String(options.lineNumberFormatter(i + options.firstLineNumber)) + } + + // A Pos instance represents a position within the text. + function Pos(line, ch, sticky) { + if ( sticky === void 0 ) sticky = null; + + if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } + this.line = line; + this.ch = ch; + this.sticky = sticky; + } + + // Compare two positions, return 0 if they are the same, a negative + // number when a is less, and a positive number otherwise. + function cmp(a, b) { return a.line - b.line || a.ch - b.ch } + + function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } + + function copyPos(x) {return Pos(x.line, x.ch)} + function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } + function minPos(a, b) { return cmp(a, b) < 0 ? a : b } + + // Most of the external API clips given positions to make sure they + // actually exist within the document. + function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} + function clipPos(doc, pos) { + if (pos.line < doc.first) { return Pos(doc.first, 0) } + var last = doc.first + doc.size - 1; + if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } + return clipToLen(pos, getLine(doc, pos.line).text.length) + } + function clipToLen(pos, linelen) { + var ch = pos.ch; + if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } + else if (ch < 0) { return Pos(pos.line, 0) } + else { return pos } + } + function clipPosArray(doc, array) { + var out = []; + for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } + return out + } + + var SavedContext = function(state, lookAhead) { + this.state = state; + this.lookAhead = lookAhead; + }; + + var Context = function(doc, state, line, lookAhead) { + this.state = state; + this.doc = doc; + this.line = line; + this.maxLookAhead = lookAhead || 0; + this.baseTokens = null; + this.baseTokenPos = 1; + }; + + Context.prototype.lookAhead = function (n) { + var line = this.doc.getLine(this.line + n); + if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; } + return line + }; + + Context.prototype.baseToken = function (n) { + if (!this.baseTokens) { return null } + while (this.baseTokens[this.baseTokenPos] <= n) + { this.baseTokenPos += 2; } + var type = this.baseTokens[this.baseTokenPos + 1]; + return {type: type && type.replace(/( |^)overlay .*/, ""), + size: this.baseTokens[this.baseTokenPos] - n} + }; + + Context.prototype.nextLine = function () { + this.line++; + if (this.maxLookAhead > 0) { this.maxLookAhead--; } + }; + + Context.fromSaved = function (doc, saved, line) { + if (saved instanceof SavedContext) + { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) } + else + { return new Context(doc, copyState(doc.mode, saved), line) } + }; + + Context.prototype.save = function (copy) { + var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state; + return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state + }; + + + // Compute a style array (an array starting with a mode generation + // -- for invalidation -- followed by pairs of end positions and + // style strings), which is used to highlight the tokens on the + // line. + function highlightLine(cm, line, context, forceToEnd) { + // A styles array always starts with a number identifying the + // mode/overlays that it is based on (for easy invalidation). + var st = [cm.state.modeGen], lineClasses = {}; + // Compute the base array of styles + runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); }, + lineClasses, forceToEnd); + var state = context.state; + + // Run overlays, adjust style array. + var loop = function ( o ) { + context.baseTokens = st; + var overlay = cm.state.overlays[o], i = 1, at = 0; + context.state = true; + runMode(cm, line.text, overlay.mode, context, function (end, style) { + var start = i; + // Ensure there's a token end at the current position, and that i points at it + while (at < end) { + var i_end = st[i]; + if (i_end > end) + { st.splice(i, 1, end, st[i+1], i_end); } + i += 2; + at = Math.min(end, i_end); + } + if (!style) { return } + if (overlay.opaque) { + st.splice(start, i - start, end, "overlay " + style); + i = start + 2; + } else { + for (; start < i; start += 2) { + var cur = st[start+1]; + st[start+1] = (cur ? cur + " " : "") + "overlay " + style; + } + } + }, lineClasses); + context.state = state; + context.baseTokens = null; + context.baseTokenPos = 1; + }; + + for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); + + return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} + } + + function getLineStyles(cm, line, updateFrontier) { + if (!line.styles || line.styles[0] != cm.state.modeGen) { + var context = getContextBefore(cm, lineNo(line)); + var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state); + var result = highlightLine(cm, line, context); + if (resetState) { context.state = resetState; } + line.stateAfter = context.save(!resetState); + line.styles = result.styles; + if (result.classes) { line.styleClasses = result.classes; } + else if (line.styleClasses) { line.styleClasses = null; } + if (updateFrontier === cm.doc.highlightFrontier) + { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); } + } + return line.styles + } + + function getContextBefore(cm, n, precise) { + var doc = cm.doc, display = cm.display; + if (!doc.mode.startState) { return new Context(doc, true, n) } + var start = findStartLine(cm, n, precise); + var saved = start > doc.first && getLine(doc, start - 1).stateAfter; + var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start); + + doc.iter(start, n, function (line) { + processLine(cm, line.text, context); + var pos = context.line; + line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null; + context.nextLine(); + }); + if (precise) { doc.modeFrontier = context.line; } + return context + } + + // Lightweight form of highlight -- proceed over this line and + // update state, but don't save a style array. Used for lines that + // aren't currently visible. + function processLine(cm, text, context, startAt) { + var mode = cm.doc.mode; + var stream = new StringStream(text, cm.options.tabSize, context); + stream.start = stream.pos = startAt || 0; + if (text == "") { callBlankLine(mode, context.state); } + while (!stream.eol()) { + readToken(mode, stream, context.state); + stream.start = stream.pos; + } + } + + function callBlankLine(mode, state) { + if (mode.blankLine) { return mode.blankLine(state) } + if (!mode.innerMode) { return } + var inner = innerMode(mode, state); + if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } + } + + function readToken(mode, stream, state, inner) { + for (var i = 0; i < 10; i++) { + if (inner) { inner[0] = innerMode(mode, state).mode; } + var style = mode.token(stream, state); + if (stream.pos > stream.start) { return style } + } + throw new Error("Mode " + mode.name + " failed to advance stream.") + } + + var Token = function(stream, type, state) { + this.start = stream.start; this.end = stream.pos; + this.string = stream.current(); + this.type = type || null; + this.state = state; + }; + + // Utility for getTokenAt and getLineTokens + function takeToken(cm, pos, precise, asArray) { + var doc = cm.doc, mode = doc.mode, style; + pos = clipPos(doc, pos); + var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise); + var stream = new StringStream(line.text, cm.options.tabSize, context), tokens; + if (asArray) { tokens = []; } + while ((asArray || stream.pos < pos.ch) && !stream.eol()) { + stream.start = stream.pos; + style = readToken(mode, stream, context.state); + if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); } + } + return asArray ? tokens : new Token(stream, style, context.state) + } + + function extractLineClasses(type, output) { + if (type) { for (;;) { + var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); + if (!lineClass) { break } + type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); + var prop = lineClass[1] ? "bgClass" : "textClass"; + if (output[prop] == null) + { output[prop] = lineClass[2]; } + else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop])) + { output[prop] += " " + lineClass[2]; } + } } + return type + } + + // Run the given mode's parser over a line, calling f for each token. + function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { + var flattenSpans = mode.flattenSpans; + if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; } + var curStart = 0, curStyle = null; + var stream = new StringStream(text, cm.options.tabSize, context), style; + var inner = cm.options.addModeClass && [null]; + if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); } + while (!stream.eol()) { + if (stream.pos > cm.options.maxHighlightLength) { + flattenSpans = false; + if (forceToEnd) { processLine(cm, text, context, stream.pos); } + stream.pos = text.length; + style = null; + } else { + style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses); + } + if (inner) { + var mName = inner[0].name; + if (mName) { style = "m-" + (style ? mName + " " + style : mName); } + } + if (!flattenSpans || curStyle != style) { + while (curStart < stream.start) { + curStart = Math.min(stream.start, curStart + 5000); + f(curStart, curStyle); + } + curStyle = style; + } + stream.start = stream.pos; + } + while (curStart < stream.pos) { + // Webkit seems to refuse to render text nodes longer than 57444 + // characters, and returns inaccurate measurements in nodes + // starting around 5000 chars. + var pos = Math.min(stream.pos, curStart + 5000); + f(pos, curStyle); + curStart = pos; + } + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(cm, n, precise) { + var minindent, minline, doc = cm.doc; + var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); + for (var search = n; search > lim; --search) { + if (search <= doc.first) { return doc.first } + var line = getLine(doc, search - 1), after = line.stateAfter; + if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) + { return search } + var indented = countColumn(line.text, null, cm.options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline + } + + function retreatFrontier(doc, n) { + doc.modeFrontier = Math.min(doc.modeFrontier, n); + if (doc.highlightFrontier < n - 10) { return } + var start = doc.first; + for (var line = n - 1; line > start; line--) { + var saved = getLine(doc, line).stateAfter; + // change is on 3 + // state on line 1 looked ahead 2 -- so saw 3 + // test 1 + 2 < 3 should cover this + if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { + start = line + 1; + break + } + } + doc.highlightFrontier = Math.min(doc.highlightFrontier, start); + } + + // Optimize some code when these features are not used. + var sawReadOnlySpans = false, sawCollapsedSpans = false; + + function seeReadOnlySpans() { + sawReadOnlySpans = true; + } + + function seeCollapsedSpans() { + sawCollapsedSpans = true; + } + + // TEXTMARKER SPANS + + function MarkedSpan(marker, from, to) { + this.marker = marker; + this.from = from; this.to = to; + } + + // Search an array of spans for a span matching the given marker. + function getMarkedSpanFor(spans, marker) { + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) { return span } + } } + } + // Remove a span from an array, returning undefined if no spans are + // left (we don't store arrays for lines without spans). + function removeMarkedSpan(spans, span) { + var r; + for (var i = 0; i < spans.length; ++i) + { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } + return r + } + // Add a span to a line. + function addMarkedSpan(line, span) { + line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; + span.marker.attachLine(line); + } + + // Used for the algorithm that adjusts markers for a change in the + // document. These functions cut an array of spans at a given + // character position, returning an array of remaining chunks (or + // undefined if nothing remains). + function markedSpansBefore(old, startCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); + } + } } + return nw + } + function markedSpansAfter(old, endCh, isInsert) { + var nw; + if (old) { for (var i = 0; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) + ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, + span.to == null ? null : span.to - endCh)); + } + } } + return nw + } + + // Given a change object, compute the new set of marker spans that + // cover the line in which the change took place. Removes spans + // entirely within the change, reconnects spans belonging to the + // same marker that appear on both sides of the change, and cuts off + // spans partially within the change. Returns an array of span + // arrays with one element for each line in (after) the change. + function stretchSpansOverChange(doc, change) { + if (change.full) { return null } + var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; + var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; + if (!oldFirst && !oldLast) { return null } + + var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh, isInsert); + var last = markedSpansAfter(oldLast, endCh, isInsert); + + // Next, merge those two ends + var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) { span.to = startCh; } + else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i$1 = 0; i$1 < last.length; ++i$1) { + var span$1 = last[i$1]; + if (span$1.to != null) { span$1.to += offset; } + if (span$1.from == null) { + var found$1 = getMarkedSpanFor(first, span$1.marker); + if (!found$1) { + span$1.from = offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } else { + span$1.from += offset; + if (sameLine) { (first || (first = [])).push(span$1); } + } + } + } + // Make sure we didn't create any zero-length spans + if (first) { first = clearEmptySpans(first); } + if (last && last != first) { last = clearEmptySpans(last); } + + var newMarkers = [first]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = change.text.length - 2, gapMarkers; + if (gap > 0 && first) + { for (var i$2 = 0; i$2 < first.length; ++i$2) + { if (first[i$2].to == null) + { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } + for (var i$3 = 0; i$3 < gap; ++i$3) + { newMarkers.push(gapMarkers); } + newMarkers.push(last); + } + return newMarkers + } + + // Remove spans that are empty and don't have a clearWhenEmpty + // option of false. + function clearEmptySpans(spans) { + for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) + { spans.splice(i--, 1); } + } + if (!spans.length) { return null } + return spans + } + + // Used to 'clip' out readOnly ranges when making a change. + function removeReadOnlyRanges(doc, from, to) { + var markers = null; + doc.iter(from.line, to.line + 1, function (line) { + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var mark = line.markedSpans[i].marker; + if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) + { (markers || (markers = [])).push(mark); } + } } + }); + if (!markers) { return null } + var parts = [{from: from, to: to}]; + for (var i = 0; i < markers.length; ++i) { + var mk = markers[i], m = mk.find(0); + for (var j = 0; j < parts.length; ++j) { + var p = parts[j]; + if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } + var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); + if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) + { newParts.push({from: p.from, to: m.from}); } + if (dto > 0 || !mk.inclusiveRight && !dto) + { newParts.push({from: m.to, to: p.to}); } + parts.splice.apply(parts, newParts); + j += newParts.length - 3; + } + } + return parts + } + + // Connect or disconnect spans from a line. + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.detachLine(line); } + line.markedSpans = null; + } + function attachMarkedSpans(line, spans) { + if (!spans) { return } + for (var i = 0; i < spans.length; ++i) + { spans[i].marker.attachLine(line); } + line.markedSpans = spans; + } + + // Helpers used when computing which overlapping collapsed span + // counts as the larger one. + function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } + function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } + + // Returns a number indicating which of two overlapping collapsed + // spans is larger (and thus includes the other). Falls back to + // comparing ids when the spans cover exactly the same range. + function compareCollapsedMarkers(a, b) { + var lenDiff = a.lines.length - b.lines.length; + if (lenDiff != 0) { return lenDiff } + var aPos = a.find(), bPos = b.find(); + var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); + if (fromCmp) { return -fromCmp } + var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); + if (toCmp) { return toCmp } + return b.id - a.id + } + + // Find out whether a line ends or starts in a collapsed span. If + // so, return the marker for that span. + function collapsedSpanAtSide(line, start) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) + { found = sp.marker; } + } } + return found + } + function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } + function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } + + function collapsedSpanAround(line, ch) { + var sps = sawCollapsedSpans && line.markedSpans, found; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && + (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } + } } + return found + } + + // Test whether there exists a collapsed span that partially + // overlaps (covers the start or end, but not both) of a new span. + // Such overlap is not allowed. + function conflictingCollapsedRange(doc, lineNo, from, to, marker) { + var line = getLine(doc, lineNo); + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var i = 0; i < sps.length; ++i) { + var sp = sps[i]; + if (!sp.marker.collapsed) { continue } + var found = sp.marker.find(0); + var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); + var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); + if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } + if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || + fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) + { return true } + } } + } + + // A visual line is a line as drawn on the screen. Folding, for + // example, can cause multiple logical lines to appear on the same + // visual line. This finds the start of the visual line that the + // given line is part of (usually that is the line itself). + function visualLine(line) { + var merged; + while (merged = collapsedSpanAtStart(line)) + { line = merged.find(-1, true).line; } + return line + } + + function visualLineEnd(line) { + var merged; + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return line + } + + // Returns an array of logical lines that continue the visual line + // started by the argument, or undefined if there are no such lines. + function visualLineContinued(line) { + var merged, lines; + while (merged = collapsedSpanAtEnd(line)) { + line = merged.find(1, true).line + ;(lines || (lines = [])).push(line); + } + return lines + } + + // Get the line number of the start of the visual line that the + // given line number is part of. + function visualLineNo(doc, lineN) { + var line = getLine(doc, lineN), vis = visualLine(line); + if (line == vis) { return lineN } + return lineNo(vis) + } + + // Get the line number of the start of the next visual line after + // the given line. + function visualLineEndNo(doc, lineN) { + if (lineN > doc.lastLine()) { return lineN } + var line = getLine(doc, lineN), merged; + if (!lineIsHidden(doc, line)) { return lineN } + while (merged = collapsedSpanAtEnd(line)) + { line = merged.find(1, true).line; } + return lineNo(line) + 1 + } + + // Compute whether a line is hidden. Lines count as hidden when they + // are part of a visual line that starts with another line, or when + // they are entirely covered by collapsed, non-widget span. + function lineIsHidden(doc, line) { + var sps = sawCollapsedSpans && line.markedSpans; + if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { + sp = sps[i]; + if (!sp.marker.collapsed) { continue } + if (sp.from == null) { return true } + if (sp.marker.widgetNode) { continue } + if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) + { return true } + } } + } + function lineIsHiddenInner(doc, line, span) { + if (span.to == null) { + var end = span.marker.find(1, true); + return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) + } + if (span.marker.inclusiveRight && span.to == line.text.length) + { return true } + for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { + sp = line.markedSpans[i]; + if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && + (sp.to == null || sp.to != span.from) && + (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && + lineIsHiddenInner(doc, line, sp)) { return true } + } + } + + // Find the height above the given line. + function heightAtLine(lineObj) { + lineObj = visualLine(lineObj); + + var h = 0, chunk = lineObj.parent; + for (var i = 0; i < chunk.lines.length; ++i) { + var line = chunk.lines[i]; + if (line == lineObj) { break } + else { h += line.height; } + } + for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { + for (var i$1 = 0; i$1 < p.children.length; ++i$1) { + var cur = p.children[i$1]; + if (cur == chunk) { break } + else { h += cur.height; } + } + } + return h + } + + // Compute the character length of a line, taking into account + // collapsed ranges (see markText) that might hide parts, and join + // other lines onto it. + function lineLength(line) { + if (line.height == 0) { return 0 } + var len = line.text.length, merged, cur = line; + while (merged = collapsedSpanAtStart(cur)) { + var found = merged.find(0, true); + cur = found.from.line; + len += found.from.ch - found.to.ch; + } + cur = line; + while (merged = collapsedSpanAtEnd(cur)) { + var found$1 = merged.find(0, true); + len -= cur.text.length - found$1.from.ch; + cur = found$1.to.line; + len += cur.text.length - found$1.to.ch; + } + return len + } + + // Find the longest line in the document. + function findMaxLine(cm) { + var d = cm.display, doc = cm.doc; + d.maxLine = getLine(doc, doc.first); + d.maxLineLength = lineLength(d.maxLine); + d.maxLineChanged = true; + doc.iter(function (line) { + var len = lineLength(line); + if (len > d.maxLineLength) { + d.maxLineLength = len; + d.maxLine = line; + } + }); + } + + // LINE DATA STRUCTURE + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + var Line = function(text, markedSpans, estimateHeight) { + this.text = text; + attachMarkedSpans(this, markedSpans); + this.height = estimateHeight ? estimateHeight(this) : 1; + }; + + Line.prototype.lineNo = function () { return lineNo(this) }; + eventMixin(Line); + + // Change the content (text, markers) of a line. Automatically + // invalidates cached information and tries to re-estimate the + // line's height. + function updateLine(line, text, markedSpans, estimateHeight) { + line.text = text; + if (line.stateAfter) { line.stateAfter = null; } + if (line.styles) { line.styles = null; } + if (line.order != null) { line.order = null; } + detachMarkedSpans(line); + attachMarkedSpans(line, markedSpans); + var estHeight = estimateHeight ? estimateHeight(line) : 1; + if (estHeight != line.height) { updateLineHeight(line, estHeight); } + } + + // Detach a line from the document tree and its markers. + function cleanUpLine(line) { + line.parent = null; + detachMarkedSpans(line); + } + + // Convert a style as returned by a mode (either null, or a string + // containing one or more styles) to a CSS style. This is cached, + // and also looks for line-wide styles. + var styleToClassCache = {}, styleToClassCacheWithMode = {}; + function interpretTokenStyle(style, options) { + if (!style || /^\s*$/.test(style)) { return null } + var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; + return cache[style] || + (cache[style] = style.replace(/\S+/g, "cm-$&")) + } + + // Render the DOM representation of the text of a line. Also builds + // up a 'line map', which points at the DOM nodes that represent + // specific stretches of text, and is used by the measuring code. + // The returned object contains the DOM node, this map, and + // information about line-wide styles that were set by the mode. + function buildLineContent(cm, lineView) { + // The padding-right forces the element to have a 'border', which + // is needed on Webkit to be able to get line-level bounding + // rectangles for it (in measureChar). + var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null); + var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, + col: 0, pos: 0, cm: cm, + trailingSpace: false, + splitSpaces: cm.getOption("lineWrapping")}; + lineView.measure = {}; + + // Iterate over the logical lines that make up this visual line. + for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { + var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0); + builder.pos = 0; + builder.addToken = buildToken; + // Optionally wire in some hacks into the token-rendering + // algorithm, to deal with browser quirks. + if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) + { builder.addToken = buildTokenBadBidi(builder.addToken, order); } + builder.map = []; + var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); + insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); + if (line.styleClasses) { + if (line.styleClasses.bgClass) + { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); } + if (line.styleClasses.textClass) + { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); } + } + + // Ensure at least a single node is present, for measuring. + if (builder.map.length == 0) + { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); } + + // Store the map and a cache object for the current logical line + if (i == 0) { + lineView.measure.map = builder.map; + lineView.measure.cache = {}; + } else { + (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) + ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}); + } + } + + // See issue #2901 + if (webkit) { + var last = builder.content.lastChild; + if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) + { builder.content.className = "cm-tab-wrap-hack"; } + } + + signal(cm, "renderLine", cm, lineView.line, builder.pre); + if (builder.pre.className) + { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); } + + return builder + } + + function defaultSpecialCharPlaceholder(ch) { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + ch.charCodeAt(0).toString(16); + token.setAttribute("aria-label", token.title); + return token + } + + // Build up the DOM representation for a single token, and add it to + // the line map. Takes care to render special characters separately. + function buildToken(builder, text, style, startStyle, endStyle, css, attributes) { + if (!text) { return } + var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text; + var special = builder.cm.state.specialChars, mustWrap = false; + var content; + if (!special.test(text)) { + builder.col += text.length; + content = document.createTextNode(displayText); + builder.map.push(builder.pos, builder.pos + text.length, content); + if (ie && ie_version < 9) { mustWrap = true; } + builder.pos += text.length; + } else { + content = document.createDocumentFragment(); + var pos = 0; + while (true) { + special.lastIndex = pos; + var m = special.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); } + else { content.appendChild(txt); } + builder.map.push(builder.pos, builder.pos + skipped, txt); + builder.col += skipped; + builder.pos += skipped; + } + if (!m) { break } + pos += skipped + 1; + var txt$1 = (void 0); + if (m[0] == "\t") { + var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; + txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + txt$1.setAttribute("role", "presentation"); + txt$1.setAttribute("cm-text", "\t"); + builder.col += tabWidth; + } else if (m[0] == "\r" || m[0] == "\n") { + txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); + txt$1.setAttribute("cm-text", m[0]); + builder.col += 1; + } else { + txt$1 = builder.cm.options.specialCharPlaceholder(m[0]); + txt$1.setAttribute("cm-text", m[0]); + if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); } + else { content.appendChild(txt$1); } + builder.col += 1; + } + builder.map.push(builder.pos, builder.pos + 1, txt$1); + builder.pos++; + } + } + builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32; + if (style || startStyle || endStyle || mustWrap || css || attributes) { + var fullStyle = style || ""; + if (startStyle) { fullStyle += startStyle; } + if (endStyle) { fullStyle += endStyle; } + var token = elt("span", [content], fullStyle, css); + if (attributes) { + for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class") + { token.setAttribute(attr, attributes[attr]); } } + } + return builder.content.appendChild(token) + } + builder.content.appendChild(content); + } + + // Change some spaces to NBSP to prevent the browser from collapsing + // trailing spaces at the end of a line when rendering text (issue #1362). + function splitSpaces(text, trailingBefore) { + if (text.length > 1 && !/ /.test(text)) { return text } + var spaceBefore = trailingBefore, result = ""; + for (var i = 0; i < text.length; i++) { + var ch = text.charAt(i); + if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) + { ch = "\u00a0"; } + result += ch; + spaceBefore = ch == " "; + } + return result + } + + // Work around nonsense dimensions being reported for stretches of + // right-to-left text. + function buildTokenBadBidi(inner, order) { + return function (builder, text, style, startStyle, endStyle, css, attributes) { + style = style ? style + " cm-force-border" : "cm-force-border"; + var start = builder.pos, end = start + text.length; + for (;;) { + // Find the part that overlaps with the start of this text + var part = (void 0); + for (var i = 0; i < order.length; i++) { + part = order[i]; + if (part.to > start && part.from <= start) { break } + } + if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) } + inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes); + startStyle = null; + text = text.slice(part.to - start); + start = part.to; + } + } + } + + function buildCollapsedSpan(builder, size, marker, ignoreWidget) { + var widget = !ignoreWidget && marker.widgetNode; + if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); } + if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { + if (!widget) + { widget = builder.content.appendChild(document.createElement("span")); } + widget.setAttribute("cm-marker", marker.id); + } + if (widget) { + builder.cm.display.input.setUneditable(widget); + builder.content.appendChild(widget); + } + builder.pos += size; + builder.trailingSpace = false; + } + + // Outputs a number of spans to make up a line, taking highlighting + // and marked text into account. + function insertLineContent(line, builder, styles) { + var spans = line.markedSpans, allText = line.text, at = 0; + if (!spans) { + for (var i$1 = 1; i$1 < styles.length; i$1+=2) + { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); } + return + } + + var len = allText.length, pos = 0, i = 1, text = "", style, css; + var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes; + for (;;) { + if (nextChange == pos) { // Update current marker set + spanStyle = spanEndStyle = spanStartStyle = css = ""; + attributes = null; + collapsed = null; nextChange = Infinity; + var foundBookmarks = [], endStyles = (void 0); + for (var j = 0; j < spans.length; ++j) { + var sp = spans[j], m = sp.marker; + if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { + foundBookmarks.push(m); + } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { + if (sp.to != null && sp.to != pos && nextChange > sp.to) { + nextChange = sp.to; + spanEndStyle = ""; + } + if (m.className) { spanStyle += " " + m.className; } + if (m.css) { css = (css ? css + ";" : "") + m.css; } + if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; } + if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); } + // support for the old title property + // https://github.com/codemirror/CodeMirror/pull/5673 + if (m.title) { (attributes || (attributes = {})).title = m.title; } + if (m.attributes) { + for (var attr in m.attributes) + { (attributes || (attributes = {}))[attr] = m.attributes[attr]; } + } + if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) + { collapsed = sp; } + } else if (sp.from > pos && nextChange > sp.from) { + nextChange = sp.from; + } + } + if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) + { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } } + + if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) + { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } } + if (collapsed && (collapsed.from || 0) == pos) { + buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, + collapsed.marker, collapsed.from == null); + if (collapsed.to == null) { return } + if (collapsed.to == pos) { collapsed = false; } + } + } + if (pos >= len) { break } + + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + if (!collapsed) { + var tokenText = end > upto ? text.slice(0, upto - pos) : text; + builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, + spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes); + } + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} + pos = end; + spanStartStyle = ""; + } + text = allText.slice(at, at = styles[i++]); + style = interpretTokenStyle(styles[i++], builder.cm.options); + } + } + } + + + // These objects are used to represent the visible (currently drawn) + // part of the document. A LineView may correspond to multiple + // logical lines, if those are connected by collapsed ranges. + function LineView(doc, line, lineN) { + // The starting line + this.line = line; + // Continuing lines, if any + this.rest = visualLineContinued(line); + // Number of logical lines in this visual line + this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; + this.node = this.text = null; + this.hidden = lineIsHidden(doc, line); + } + + // Create a range of LineView objects for the given lines. + function buildViewArray(cm, from, to) { + var array = [], nextPos; + for (var pos = from; pos < to; pos = nextPos) { + var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); + nextPos = pos + view.size; + array.push(view); + } + return array + } + + var operationGroup = null; + + function pushOperation(op) { + if (operationGroup) { + operationGroup.ops.push(op); + } else { + op.ownsGroup = operationGroup = { + ops: [op], + delayedCallbacks: [] + }; + } + } + + function fireCallbacksForOps(group) { + // Calls delayed callbacks and cursorActivity handlers until no + // new ones appear + var callbacks = group.delayedCallbacks, i = 0; + do { + for (; i < callbacks.length; i++) + { callbacks[i].call(null); } + for (var j = 0; j < group.ops.length; j++) { + var op = group.ops[j]; + if (op.cursorActivityHandlers) + { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) + { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } } + } + } while (i < callbacks.length) + } + + function finishOperation(op, endCb) { + var group = op.ownsGroup; + if (!group) { return } + + try { fireCallbacksForOps(group); } + finally { + operationGroup = null; + endCb(group); + } + } + + var orphanDelayedCallbacks = null; + + // Often, we want to signal events at a point where we are in the + // middle of some work, but don't want the handler to start calling + // other methods on the editor, which might be in an inconsistent + // state or simply not expect any other events to happen. + // signalLater looks whether there are any handlers, and schedules + // them to be executed when the last operation ends, or, if no + // operation is active, when a timeout fires. + function signalLater(emitter, type /*, values...*/) { + var arr = getHandlers(emitter, type); + if (!arr.length) { return } + var args = Array.prototype.slice.call(arguments, 2), list; + if (operationGroup) { + list = operationGroup.delayedCallbacks; + } else if (orphanDelayedCallbacks) { + list = orphanDelayedCallbacks; + } else { + list = orphanDelayedCallbacks = []; + setTimeout(fireOrphanDelayed, 0); + } + var loop = function ( i ) { + list.push(function () { return arr[i].apply(null, args); }); + }; + + for (var i = 0; i < arr.length; ++i) + loop( i ); + } + + function fireOrphanDelayed() { + var delayed = orphanDelayedCallbacks; + orphanDelayedCallbacks = null; + for (var i = 0; i < delayed.length; ++i) { delayed[i](); } + } + + // When an aspect of a line changes, a string is added to + // lineView.changes. This updates the relevant part of the line's + // DOM structure. + function updateLineForChanges(cm, lineView, lineN, dims) { + for (var j = 0; j < lineView.changes.length; j++) { + var type = lineView.changes[j]; + if (type == "text") { updateLineText(cm, lineView); } + else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); } + else if (type == "class") { updateLineClasses(cm, lineView); } + else if (type == "widget") { updateLineWidgets(cm, lineView, dims); } + } + lineView.changes = null; + } + + // Lines with gutter elements, widgets or a background class need to + // be wrapped, and have the extra elements added to the wrapper div + function ensureLineWrapped(lineView) { + if (lineView.node == lineView.text) { + lineView.node = elt("div", null, null, "position: relative"); + if (lineView.text.parentNode) + { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); } + lineView.node.appendChild(lineView.text); + if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; } + } + return lineView.node + } + + function updateLineBackground(cm, lineView) { + var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; + if (cls) { cls += " CodeMirror-linebackground"; } + if (lineView.background) { + if (cls) { lineView.background.className = cls; } + else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } + } else if (cls) { + var wrap = ensureLineWrapped(lineView); + lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); + cm.display.input.setUneditable(lineView.background); + } + } + + // Wrapper around buildLineContent which will reuse the structure + // in display.externalMeasured when possible. + function getLineContent(cm, lineView) { + var ext = cm.display.externalMeasured; + if (ext && ext.line == lineView.line) { + cm.display.externalMeasured = null; + lineView.measure = ext.measure; + return ext.built + } + return buildLineContent(cm, lineView) + } + + // Redraw the line's text. Interacts with the background and text + // classes because the mode may output tokens that influence these + // classes. + function updateLineText(cm, lineView) { + var cls = lineView.text.className; + var built = getLineContent(cm, lineView); + if (lineView.text == lineView.node) { lineView.node = built.pre; } + lineView.text.parentNode.replaceChild(built.pre, lineView.text); + lineView.text = built.pre; + if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { + lineView.bgClass = built.bgClass; + lineView.textClass = built.textClass; + updateLineClasses(cm, lineView); + } else if (cls) { + lineView.text.className = cls; + } + } + + function updateLineClasses(cm, lineView) { + updateLineBackground(cm, lineView); + if (lineView.line.wrapClass) + { ensureLineWrapped(lineView).className = lineView.line.wrapClass; } + else if (lineView.node != lineView.text) + { lineView.node.className = ""; } + var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; + lineView.text.className = textClass || ""; + } + + function updateLineGutter(cm, lineView, lineN, dims) { + if (lineView.gutter) { + lineView.node.removeChild(lineView.gutter); + lineView.gutter = null; + } + if (lineView.gutterBackground) { + lineView.node.removeChild(lineView.gutterBackground); + lineView.gutterBackground = null; + } + if (lineView.line.gutterClass) { + var wrap = ensureLineWrapped(lineView); + lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, + ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")); + cm.display.input.setUneditable(lineView.gutterBackground); + wrap.insertBefore(lineView.gutterBackground, lineView.text); + } + var markers = lineView.line.gutterMarkers; + if (cm.options.lineNumbers || markers) { + var wrap$1 = ensureLineWrapped(lineView); + var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")); + cm.display.input.setUneditable(gutterWrap); + wrap$1.insertBefore(gutterWrap, lineView.text); + if (lineView.line.gutterClass) + { gutterWrap.className += " " + lineView.line.gutterClass; } + if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) + { lineView.lineNumber = gutterWrap.appendChild( + elt("div", lineNumberFor(cm.options, lineN), + "CodeMirror-linenumber CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); } + if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { + var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id]; + if (found) + { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", + ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); } + } } + } + } + + function updateLineWidgets(cm, lineView, dims) { + if (lineView.alignable) { lineView.alignable = null; } + var isWidget = classTest("CodeMirror-linewidget"); + for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { + next = node.nextSibling; + if (isWidget.test(node.className)) { lineView.node.removeChild(node); } + } + insertLineWidgets(cm, lineView, dims); + } + + // Build a line's DOM representation from scratch + function buildLineElement(cm, lineView, lineN, dims) { + var built = getLineContent(cm, lineView); + lineView.text = lineView.node = built.pre; + if (built.bgClass) { lineView.bgClass = built.bgClass; } + if (built.textClass) { lineView.textClass = built.textClass; } + + updateLineClasses(cm, lineView); + updateLineGutter(cm, lineView, lineN, dims); + insertLineWidgets(cm, lineView, dims); + return lineView.node + } + + // A lineView may contain multiple logical lines (when merged by + // collapsed spans). The widgets for all of them need to be drawn. + function insertLineWidgets(cm, lineView, dims) { + insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } } + } + + function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { + if (!line.widgets) { return } + var wrap = ensureLineWrapped(lineView); + for (var i = 0, ws = line.widgets; i < ws.length; ++i) { + var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : "")); + if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); } + positionLineWidget(widget, node, lineView, dims); + cm.display.input.setUneditable(node); + if (allowAbove && widget.above) + { wrap.insertBefore(node, lineView.gutter || lineView.text); } + else + { wrap.appendChild(node); } + signalLater(widget, "redraw"); + } + } + + function positionLineWidget(widget, node, lineView, dims) { + if (widget.noHScroll) { + (lineView.alignable || (lineView.alignable = [])).push(node); + var width = dims.wrapperWidth; + node.style.left = dims.fixedPos + "px"; + if (!widget.coverGutter) { + width -= dims.gutterTotalWidth; + node.style.paddingLeft = dims.gutterTotalWidth + "px"; + } + node.style.width = width + "px"; + } + if (widget.coverGutter) { + node.style.zIndex = 5; + node.style.position = "relative"; + if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; } + } + } + + function widgetHeight(widget) { + if (widget.height != null) { return widget.height } + var cm = widget.doc.cm; + if (!cm) { return 0 } + if (!contains(document.body, widget.node)) { + var parentStyle = "position: relative;"; + if (widget.coverGutter) + { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; } + if (widget.noHScroll) + { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; } + removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); + } + return widget.height = widget.node.parentNode.offsetHeight + } + + // Return true when the given mouse event happened in a widget + function eventInWidget(display, e) { + for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { + if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || + (n.parentNode == display.sizer && n != display.mover)) + { return true } + } + } + + // POSITION MEASUREMENT + + function paddingTop(display) {return display.lineSpace.offsetTop} + function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} + function paddingH(display) { + if (display.cachedPaddingH) { return display.cachedPaddingH } + var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); + var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; + var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; + if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; } + return data + } + + function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } + function displayWidth(cm) { + return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth + } + function displayHeight(cm) { + return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight + } + + // Ensure the lineView.wrapping.heights array is populated. This is + // an array of bottom offsets for the lines that make up a drawn + // line. When lineWrapping is on, there might be more than one + // height. + function ensureLineHeights(cm, lineView, rect) { + var wrapping = cm.options.lineWrapping; + var curWidth = wrapping && displayWidth(cm); + if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { + var heights = lineView.measure.heights = []; + if (wrapping) { + lineView.measure.width = curWidth; + var rects = lineView.text.firstChild.getClientRects(); + for (var i = 0; i < rects.length - 1; i++) { + var cur = rects[i], next = rects[i + 1]; + if (Math.abs(cur.bottom - next.bottom) > 2) + { heights.push((cur.bottom + next.top) / 2 - rect.top); } + } + } + heights.push(rect.bottom - rect.top); + } + } + + // Find a line map (mapping character offsets to text nodes) and a + // measurement cache for the given line number. (A line view might + // contain multiple lines when collapsed ranges are present.) + function mapFromLineView(lineView, line, lineN) { + if (lineView.line == line) + { return {map: lineView.measure.map, cache: lineView.measure.cache} } + for (var i = 0; i < lineView.rest.length; i++) + { if (lineView.rest[i] == line) + { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } + for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) + { if (lineNo(lineView.rest[i$1]) > lineN) + { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } + } + + // Render a line into the hidden node display.externalMeasured. Used + // when measurement is needed for a line that's not in the viewport. + function updateExternalMeasurement(cm, line) { + line = visualLine(line); + var lineN = lineNo(line); + var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); + view.lineN = lineN; + var built = view.built = buildLineContent(cm, view); + view.text = built.pre; + removeChildrenAndAdd(cm.display.lineMeasure, built.pre); + return view + } + + // Get a {top, bottom, left, right} box (in line-local coordinates) + // for a given character. + function measureChar(cm, line, ch, bias) { + return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) + } + + // Find a line view that corresponds to the given line number. + function findViewForLine(cm, lineN) { + if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) + { return cm.display.view[findViewIndex(cm, lineN)] } + var ext = cm.display.externalMeasured; + if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) + { return ext } + } + + // Measurement can be split in two steps, the set-up work that + // applies to the whole line, and the measurement of the actual + // character. Functions like coordsChar, that need to do a lot of + // measurements in a row, can thus ensure that the set-up work is + // only done once. + function prepareMeasureForLine(cm, line) { + var lineN = lineNo(line); + var view = findViewForLine(cm, lineN); + if (view && !view.text) { + view = null; + } else if (view && view.changes) { + updateLineForChanges(cm, view, lineN, getDimensions(cm)); + cm.curOp.forceUpdate = true; + } + if (!view) + { view = updateExternalMeasurement(cm, line); } + + var info = mapFromLineView(view, line, lineN); + return { + line: line, view: view, rect: null, + map: info.map, cache: info.cache, before: info.before, + hasHeights: false + } + } + + // Given a prepared measurement object, measures the position of an + // actual character (or fetches it from the cache). + function measureCharPrepared(cm, prepared, ch, bias, varHeight) { + if (prepared.before) { ch = -1; } + var key = ch + (bias || ""), found; + if (prepared.cache.hasOwnProperty(key)) { + found = prepared.cache[key]; + } else { + if (!prepared.rect) + { prepared.rect = prepared.view.text.getBoundingClientRect(); } + if (!prepared.hasHeights) { + ensureLineHeights(cm, prepared.view, prepared.rect); + prepared.hasHeights = true; + } + found = measureCharInner(cm, prepared, ch, bias); + if (!found.bogus) { prepared.cache[key] = found; } + } + return {left: found.left, right: found.right, + top: varHeight ? found.rtop : found.top, + bottom: varHeight ? found.rbottom : found.bottom} + } + + var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; + + function nodeAndOffsetInLineMap(map, ch, bias) { + var node, start, end, collapse, mStart, mEnd; + // First, search the line map for the text node corresponding to, + // or closest to, the target character. + for (var i = 0; i < map.length; i += 3) { + mStart = map[i]; + mEnd = map[i + 1]; + if (ch < mStart) { + start = 0; end = 1; + collapse = "left"; + } else if (ch < mEnd) { + start = ch - mStart; + end = start + 1; + } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { + end = mEnd - mStart; + start = end - 1; + if (ch >= mEnd) { collapse = "right"; } + } + if (start != null) { + node = map[i + 2]; + if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) + { collapse = bias; } + if (bias == "left" && start == 0) + { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { + node = map[(i -= 3) + 2]; + collapse = "left"; + } } + if (bias == "right" && start == mEnd - mStart) + { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { + node = map[(i += 3) + 2]; + collapse = "right"; + } } + break + } + } + return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} + } + + function getUsefulRect(rects, bias) { + var rect = nullRect; + if (bias == "left") { for (var i = 0; i < rects.length; i++) { + if ((rect = rects[i]).left != rect.right) { break } + } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { + if ((rect = rects[i$1]).left != rect.right) { break } + } } + return rect + } + + function measureCharInner(cm, prepared, ch, bias) { + var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); + var node = place.node, start = place.start, end = place.end, collapse = place.collapse; + + var rect; + if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. + for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned + while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; } + while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; } + if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) + { rect = node.parentNode.getBoundingClientRect(); } + else + { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); } + if (rect.left || rect.right || start == 0) { break } + end = start; + start = start - 1; + collapse = "right"; + } + if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); } + } else { // If it is a widget, simply get the box for the whole widget. + if (start > 0) { collapse = bias = "right"; } + var rects; + if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) + { rect = rects[bias == "right" ? rects.length - 1 : 0]; } + else + { rect = node.getBoundingClientRect(); } + } + if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { + var rSpan = node.parentNode.getClientRects()[0]; + if (rSpan) + { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; } + else + { rect = nullRect; } + } + + var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; + var mid = (rtop + rbot) / 2; + var heights = prepared.view.measure.heights; + var i = 0; + for (; i < heights.length - 1; i++) + { if (mid < heights[i]) { break } } + var top = i ? heights[i - 1] : 0, bot = heights[i]; + var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, + right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, + top: top, bottom: bot}; + if (!rect.left && !rect.right) { result.bogus = true; } + if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } + + return result + } + + // Work around problem with bounding client rects on ranges being + // returned incorrectly when zoomed on IE10 and below. + function maybeUpdateRectForZooming(measure, rect) { + if (!window.screen || screen.logicalXDPI == null || + screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) + { return rect } + var scaleX = screen.logicalXDPI / screen.deviceXDPI; + var scaleY = screen.logicalYDPI / screen.deviceYDPI; + return {left: rect.left * scaleX, right: rect.right * scaleX, + top: rect.top * scaleY, bottom: rect.bottom * scaleY} + } + + function clearLineMeasurementCacheFor(lineView) { + if (lineView.measure) { + lineView.measure.cache = {}; + lineView.measure.heights = null; + if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) + { lineView.measure.caches[i] = {}; } } + } + } + + function clearLineMeasurementCache(cm) { + cm.display.externalMeasure = null; + removeChildren(cm.display.lineMeasure); + for (var i = 0; i < cm.display.view.length; i++) + { clearLineMeasurementCacheFor(cm.display.view[i]); } + } + + function clearCaches(cm) { + clearLineMeasurementCache(cm); + cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; + if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; } + cm.display.lineNumChars = null; + } + + function pageScrollX() { + // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 + // which causes page_Offset and bounding client rects to use + // different reference viewports and invalidate our calculations. + if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) } + return window.pageXOffset || (document.documentElement || document.body).scrollLeft + } + function pageScrollY() { + if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) } + return window.pageYOffset || (document.documentElement || document.body).scrollTop + } + + function widgetTopHeight(lineObj) { + var height = 0; + if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) + { height += widgetHeight(lineObj.widgets[i]); } } } + return height + } + + // Converts a {top, bottom, left, right} box from line-local + // coordinates into another coordinate system. Context may be one of + // "line", "div" (display.lineDiv), "local"./null (editor), "window", + // or "page". + function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { + if (!includeWidgets) { + var height = widgetTopHeight(lineObj); + rect.top += height; rect.bottom += height; + } + if (context == "line") { return rect } + if (!context) { context = "local"; } + var yOff = heightAtLine(lineObj); + if (context == "local") { yOff += paddingTop(cm.display); } + else { yOff -= cm.display.viewOffset; } + if (context == "page" || context == "window") { + var lOff = cm.display.lineSpace.getBoundingClientRect(); + yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); + var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); + rect.left += xOff; rect.right += xOff; + } + rect.top += yOff; rect.bottom += yOff; + return rect + } + + // Coverts a box from "div" coords to another coordinate system. + // Context may be "window", "page", "div", or "local"./null. + function fromCoordSystem(cm, coords, context) { + if (context == "div") { return coords } + var left = coords.left, top = coords.top; + // First move into "page" coordinate system + if (context == "page") { + left -= pageScrollX(); + top -= pageScrollY(); + } else if (context == "local" || !context) { + var localBox = cm.display.sizer.getBoundingClientRect(); + left += localBox.left; + top += localBox.top; + } + + var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); + return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} + } + + function charCoords(cm, pos, context, lineObj, bias) { + if (!lineObj) { lineObj = getLine(cm.doc, pos.line); } + return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) + } + + // Returns a box for a given cursor position, which may have an + // 'other' property containing the position of the secondary cursor + // on a bidi boundary. + // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` + // and after `char - 1` in writing order of `char - 1` + // A cursor Pos(line, char, "after") is on the same visual line as `char` + // and before `char` in writing order of `char` + // Examples (upper-case letters are RTL, lower-case are LTR): + // Pos(0, 1, ...) + // before after + // ab a|b a|b + // aB a|B aB| + // Ab |Ab A|b + // AB B|A B|A + // Every position after the last character on a line is considered to stick + // to the last character on the line. + function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { + lineObj = lineObj || getLine(cm.doc, pos.line); + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } + function get(ch, right) { + var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); + if (right) { m.left = m.right; } else { m.right = m.left; } + return intoCoordSystem(cm, lineObj, m, context) + } + var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky; + if (ch >= lineObj.text.length) { + ch = lineObj.text.length; + sticky = "before"; + } else if (ch <= 0) { + ch = 0; + sticky = "after"; + } + if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } + + function getBidi(ch, partPos, invert) { + var part = order[partPos], right = part.level == 1; + return get(invert ? ch - 1 : ch, right != invert) + } + var partPos = getBidiPartAt(order, ch, sticky); + var other = bidiOther; + var val = getBidi(ch, partPos, sticky == "before"); + if (other != null) { val.other = getBidi(ch, other, sticky != "before"); } + return val + } + + // Used to cheaply estimate the coordinates for a position. Used for + // intermediate scroll updates. + function estimateCoords(cm, pos) { + var left = 0; + pos = clipPos(cm.doc, pos); + if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; } + var lineObj = getLine(cm.doc, pos.line); + var top = heightAtLine(lineObj) + paddingTop(cm.display); + return {left: left, right: left, top: top, bottom: top + lineObj.height} + } + + // Positions returned by coordsChar contain some extra information. + // xRel is the relative x position of the input coordinates compared + // to the found position (so xRel > 0 means the coordinates are to + // the right of the character position, for example). When outside + // is true, that means the coordinates lie outside the line's + // vertical range. + function PosWithInfo(line, ch, sticky, outside, xRel) { + var pos = Pos(line, ch, sticky); + pos.xRel = xRel; + if (outside) { pos.outside = outside; } + return pos + } + + // Compute the character position closest to the given coordinates. + // Input must be lineSpace-local ("div" coordinate system). + function coordsChar(cm, x, y) { + var doc = cm.doc; + y += cm.display.viewOffset; + if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) } + var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; + if (lineN > last) + { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) } + if (x < 0) { x = 0; } + + var lineObj = getLine(doc, lineN); + for (;;) { + var found = coordsCharInner(cm, lineObj, lineN, x, y); + var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); + if (!collapsed) { return found } + var rangeEnd = collapsed.find(1); + if (rangeEnd.line == lineN) { return rangeEnd } + lineObj = getLine(doc, lineN = rangeEnd.line); + } + } + + function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { + y -= widgetTopHeight(lineObj); + var end = lineObj.text.length; + var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0); + end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end); + return {begin: begin, end: end} + } + + function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { + if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } + var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top; + return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) + } + + // Returns true if the given side of a box is after the given + // coordinates, in top-to-bottom, left-to-right order. + function boxIsAfter(box, x, y, left) { + return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x + } + + function coordsCharInner(cm, lineObj, lineNo, x, y) { + // Move y into line-local coordinate space + y -= heightAtLine(lineObj); + var preparedMeasure = prepareMeasureForLine(cm, lineObj); + // When directly calling `measureCharPrepared`, we have to adjust + // for the widgets at this line. + var widgetHeight = widgetTopHeight(lineObj); + var begin = 0, end = lineObj.text.length, ltr = true; + + var order = getOrder(lineObj, cm.doc.direction); + // If the line isn't plain left-to-right text, first figure out + // which bidi section the coordinates fall into. + if (order) { + var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) + (cm, lineObj, lineNo, preparedMeasure, order, x, y); + ltr = part.level != 1; + // The awkward -1 offsets are needed because findFirst (called + // on these below) will treat its first bound as inclusive, + // second as exclusive, but we want to actually address the + // characters in the part's range + begin = ltr ? part.from : part.to - 1; + end = ltr ? part.to : part.from - 1; + } + + // A binary search to find the first character whose bounding box + // starts after the coordinates. If we run across any whose box wrap + // the coordinates, store that. + var chAround = null, boxAround = null; + var ch = findFirst(function (ch) { + var box = measureCharPrepared(cm, preparedMeasure, ch); + box.top += widgetHeight; box.bottom += widgetHeight; + if (!boxIsAfter(box, x, y, false)) { return false } + if (box.top <= y && box.left <= x) { + chAround = ch; + boxAround = box; + } + return true + }, begin, end); + + var baseX, sticky, outside = false; + // If a box around the coordinates was found, use that + if (boxAround) { + // Distinguish coordinates nearer to the left or right side of the box + var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr; + ch = chAround + (atStart ? 0 : 1); + sticky = atStart ? "after" : "before"; + baseX = atLeft ? boxAround.left : boxAround.right; + } else { + // (Adjust for extended bound, if necessary.) + if (!ltr && (ch == end || ch == begin)) { ch++; } + // To determine which side to associate with, get the box to the + // left of the character and compare it's vertical position to the + // coordinates + sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : + (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? + "after" : "before"; + // Now get accurate coordinates for this place, in order to get a + // base X position + var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure); + baseX = coords.left; + outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; + } + + ch = skipExtendingChars(lineObj.text, ch, 1); + return PosWithInfo(lineNo, ch, sticky, outside, x - baseX) + } + + function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) { + // Bidi parts are sorted left-to-right, and in a non-line-wrapping + // situation, we can take this ordering to correspond to the visual + // ordering. This finds the first part whose end is after the given + // coordinates. + var index = findFirst(function (i) { + var part = order[i], ltr = part.level != 1; + return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"), + "line", lineObj, preparedMeasure), x, y, true) + }, 0, order.length - 1); + var part = order[index]; + // If this isn't the first part, the part's start is also after + // the coordinates, and the coordinates aren't on the same line as + // that start, move one part back. + if (index > 0) { + var ltr = part.level != 1; + var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"), + "line", lineObj, preparedMeasure); + if (boxIsAfter(start, x, y, true) && start.top > y) + { part = order[index - 1]; } + } + return part + } + + function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { + // In a wrapped line, rtl text on wrapping boundaries can do things + // that don't correspond to the ordering in our `order` array at + // all, so a binary search doesn't work, and we want to return a + // part that only spans one line so that the binary search in + // coordsCharInner is safe. As such, we first find the extent of the + // wrapped line, and then do a flat search in which we discard any + // spans that aren't on the line. + var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); + var begin = ref.begin; + var end = ref.end; + if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; } + var part = null, closestDist = null; + for (var i = 0; i < order.length; i++) { + var p = order[i]; + if (p.from >= end || p.to <= begin) { continue } + var ltr = p.level != 1; + var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right; + // Weigh against spans ending before this, so that they are only + // picked if nothing ends after + var dist = endX < x ? x - endX + 1e9 : endX - x; + if (!part || closestDist > dist) { + part = p; + closestDist = dist; + } + } + if (!part) { part = order[order.length - 1]; } + // Clip the part to the wrapped line. + if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; } + if (part.to > end) { part = {from: part.from, to: end, level: part.level}; } + return part + } + + var measureText; + // Compute the default text height. + function textHeight(display) { + if (display.cachedTextHeight != null) { return display.cachedTextHeight } + if (measureText == null) { + measureText = elt("pre", null, "CodeMirror-line-like"); + // Measure a bunch of lines, for browsers that compute + // fractional heights. + for (var i = 0; i < 49; ++i) { + measureText.appendChild(document.createTextNode("x")); + measureText.appendChild(elt("br")); + } + measureText.appendChild(document.createTextNode("x")); + } + removeChildrenAndAdd(display.measure, measureText); + var height = measureText.offsetHeight / 50; + if (height > 3) { display.cachedTextHeight = height; } + removeChildren(display.measure); + return height || 1 + } + + // Compute the default character width. + function charWidth(display) { + if (display.cachedCharWidth != null) { return display.cachedCharWidth } + var anchor = elt("span", "xxxxxxxxxx"); + var pre = elt("pre", [anchor], "CodeMirror-line-like"); + removeChildrenAndAdd(display.measure, pre); + var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; + if (width > 2) { display.cachedCharWidth = width; } + return width || 10 + } + + // Do a bulk-read of the DOM positions and sizes needed to draw the + // view, so that we don't interleave reading and writing to the DOM. + function getDimensions(cm) { + var d = cm.display, left = {}, width = {}; + var gutterLeft = d.gutters.clientLeft; + for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { + var id = cm.display.gutterSpecs[i].className; + left[id] = n.offsetLeft + n.clientLeft + gutterLeft; + width[id] = n.clientWidth; + } + return {fixedPos: compensateForHScroll(d), + gutterTotalWidth: d.gutters.offsetWidth, + gutterLeft: left, + gutterWidth: width, + wrapperWidth: d.wrapper.clientWidth} + } + + // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, + // but using getBoundingClientRect to get a sub-pixel-accurate + // result. + function compensateForHScroll(display) { + return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left + } + + // Returns a function that estimates the height of a line, to use as + // first approximation until the line becomes visible (and is thus + // properly measurable). + function estimateHeight(cm) { + var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; + var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); + return function (line) { + if (lineIsHidden(cm.doc, line)) { return 0 } + + var widgetsHeight = 0; + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { + if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; } + } } + + if (wrapping) + { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } + else + { return widgetsHeight + th } + } + } + + function estimateLineHeights(cm) { + var doc = cm.doc, est = estimateHeight(cm); + doc.iter(function (line) { + var estHeight = est(line); + if (estHeight != line.height) { updateLineHeight(line, estHeight); } + }); + } + + // Given a mouse event, find the corresponding position. If liberal + // is false, it checks whether a gutter or scrollbar was clicked, + // and returns null if it was. forRect is used by rectangular + // selections, and tries to estimate a character position even for + // coordinates beyond the right of the text. + function posFromMouse(cm, e, liberal, forRect) { + var display = cm.display; + if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } + + var x, y, space = display.lineSpace.getBoundingClientRect(); + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX - space.left; y = e.clientY - space.top; } + catch (e$1) { return null } + var coords = coordsChar(cm, x, y), line; + if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { + var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; + coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); + } + return coords + } + + // Find the view element corresponding to a given line. Return null + // when the line isn't visible. + function findViewIndex(cm, n) { + if (n >= cm.display.viewTo) { return null } + n -= cm.display.viewFrom; + if (n < 0) { return null } + var view = cm.display.view; + for (var i = 0; i < view.length; i++) { + n -= view[i].size; + if (n < 0) { return i } + } + } + + // Updates the display.view data structure for a given change to the + // document. From and to are in pre-change coordinates. Lendiff is + // the amount of lines added or subtracted by the change. This is + // used for changes that span multiple lines, or change the way + // lines are divided into visual lines. regLineChange (below) + // registers single-line changes. + function regChange(cm, from, to, lendiff) { + if (from == null) { from = cm.doc.first; } + if (to == null) { to = cm.doc.first + cm.doc.size; } + if (!lendiff) { lendiff = 0; } + + var display = cm.display; + if (lendiff && to < display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers > from)) + { display.updateLineNumbers = from; } + + cm.curOp.viewChanged = true; + + if (from >= display.viewTo) { // Change after + if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) + { resetView(cm); } + } else if (to <= display.viewFrom) { // Change before + if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { + resetView(cm); + } else { + display.viewFrom += lendiff; + display.viewTo += lendiff; + } + } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap + resetView(cm); + } else if (from <= display.viewFrom) { // Top overlap + var cut = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cut) { + display.view = display.view.slice(cut.index); + display.viewFrom = cut.lineN; + display.viewTo += lendiff; + } else { + resetView(cm); + } + } else if (to >= display.viewTo) { // Bottom overlap + var cut$1 = viewCuttingPoint(cm, from, from, -1); + if (cut$1) { + display.view = display.view.slice(0, cut$1.index); + display.viewTo = cut$1.lineN; + } else { + resetView(cm); + } + } else { // Gap in the middle + var cutTop = viewCuttingPoint(cm, from, from, -1); + var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); + if (cutTop && cutBot) { + display.view = display.view.slice(0, cutTop.index) + .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) + .concat(display.view.slice(cutBot.index)); + display.viewTo += lendiff; + } else { + resetView(cm); + } + } + + var ext = display.externalMeasured; + if (ext) { + if (to < ext.lineN) + { ext.lineN += lendiff; } + else if (from < ext.lineN + ext.size) + { display.externalMeasured = null; } + } + } + + // Register a change to a single line. Type must be one of "text", + // "gutter", "class", "widget" + function regLineChange(cm, line, type) { + cm.curOp.viewChanged = true; + var display = cm.display, ext = cm.display.externalMeasured; + if (ext && line >= ext.lineN && line < ext.lineN + ext.size) + { display.externalMeasured = null; } + + if (line < display.viewFrom || line >= display.viewTo) { return } + var lineView = display.view[findViewIndex(cm, line)]; + if (lineView.node == null) { return } + var arr = lineView.changes || (lineView.changes = []); + if (indexOf(arr, type) == -1) { arr.push(type); } + } + + // Clear the view. + function resetView(cm) { + cm.display.viewFrom = cm.display.viewTo = cm.doc.first; + cm.display.view = []; + cm.display.viewOffset = 0; + } + + function viewCuttingPoint(cm, oldN, newN, dir) { + var index = findViewIndex(cm, oldN), diff, view = cm.display.view; + if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) + { return {index: index, lineN: newN} } + var n = cm.display.viewFrom; + for (var i = 0; i < index; i++) + { n += view[i].size; } + if (n != oldN) { + if (dir > 0) { + if (index == view.length - 1) { return null } + diff = (n + view[index].size) - oldN; + index++; + } else { + diff = n - oldN; + } + oldN += diff; newN += diff; + } + while (visualLineNo(cm.doc, newN) != newN) { + if (index == (dir < 0 ? 0 : view.length - 1)) { return null } + newN += dir * view[index - (dir < 0 ? 1 : 0)].size; + index += dir; + } + return {index: index, lineN: newN} + } + + // Force the view to cover a given range, adding empty view element + // or clipping off existing ones as needed. + function adjustView(cm, from, to) { + var display = cm.display, view = display.view; + if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { + display.view = buildViewArray(cm, from, to); + display.viewFrom = from; + } else { + if (display.viewFrom > from) + { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } + else if (display.viewFrom < from) + { display.view = display.view.slice(findViewIndex(cm, from)); } + display.viewFrom = from; + if (display.viewTo < to) + { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } + else if (display.viewTo > to) + { display.view = display.view.slice(0, findViewIndex(cm, to)); } + } + display.viewTo = to; + } + + // Count the number of lines in the view whose DOM representation is + // out of date (or nonexistent). + function countDirtyView(cm) { + var view = cm.display.view, dirty = 0; + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } + } + return dirty + } + + function updateSelection(cm) { + cm.display.input.showSelection(cm.display.input.prepareSelection()); + } + + function prepareSelection(cm, primary) { + if ( primary === void 0 ) primary = true; + + var doc = cm.doc, result = {}; + var curFragment = result.cursors = document.createDocumentFragment(); + var selFragment = result.selection = document.createDocumentFragment(); + + for (var i = 0; i < doc.sel.ranges.length; i++) { + if (!primary && i == doc.sel.primIndex) { continue } + var range = doc.sel.ranges[i]; + if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } + var collapsed = range.empty(); + if (collapsed || cm.options.showCursorWhenSelecting) + { drawSelectionCursor(cm, range.head, curFragment); } + if (!collapsed) + { drawSelectionRange(cm, range, selFragment); } + } + return result + } + + // Draws a cursor for the given range + function drawSelectionCursor(cm, head, output) { + var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); + + var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); + cursor.style.left = pos.left + "px"; + cursor.style.top = pos.top + "px"; + cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; + + if (pos.other) { + // Secondary cursor, shown when on a 'jump' in bi-directional text + var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); + otherCursor.style.display = ""; + otherCursor.style.left = pos.other.left + "px"; + otherCursor.style.top = pos.other.top + "px"; + otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; + } + } + + function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } + + // Draws the given range as a highlighted selection + function drawSelectionRange(cm, range, output) { + var display = cm.display, doc = cm.doc; + var fragment = document.createDocumentFragment(); + var padding = paddingH(cm.display), leftSide = padding.left; + var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; + var docLTR = doc.direction == "ltr"; + + function add(left, top, width, bottom) { + if (top < 0) { top = 0; } + top = Math.round(top); + bottom = Math.round(bottom); + fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))); + } + + function drawForLine(line, fromArg, toArg) { + var lineObj = getLine(doc, line); + var lineLen = lineObj.text.length; + var start, end; + function coords(ch, bias) { + return charCoords(cm, Pos(line, ch), "div", lineObj, bias) + } + + function wrapX(pos, dir, side) { + var extent = wrappedLineExtentChar(cm, lineObj, null, pos); + var prop = (dir == "ltr") == (side == "after") ? "left" : "right"; + var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1); + return coords(ch, prop)[prop] + } + + var order = getOrder(lineObj, doc.direction); + iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { + var ltr = dir == "ltr"; + var fromPos = coords(from, ltr ? "left" : "right"); + var toPos = coords(to - 1, ltr ? "right" : "left"); + + var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen; + var first = i == 0, last = !order || i == order.length - 1; + if (toPos.top - fromPos.top <= 3) { // Single line + var openLeft = (docLTR ? openStart : openEnd) && first; + var openRight = (docLTR ? openEnd : openStart) && last; + var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left; + var right = openRight ? rightSide : (ltr ? toPos : fromPos).right; + add(left, fromPos.top, right - left, fromPos.bottom); + } else { // Multiple lines + var topLeft, topRight, botLeft, botRight; + if (ltr) { + topLeft = docLTR && openStart && first ? leftSide : fromPos.left; + topRight = docLTR ? rightSide : wrapX(from, dir, "before"); + botLeft = docLTR ? leftSide : wrapX(to, dir, "after"); + botRight = docLTR && openEnd && last ? rightSide : toPos.right; + } else { + topLeft = !docLTR ? leftSide : wrapX(from, dir, "before"); + topRight = !docLTR && openStart && first ? rightSide : fromPos.right; + botLeft = !docLTR && openEnd && last ? leftSide : toPos.left; + botRight = !docLTR ? rightSide : wrapX(to, dir, "after"); + } + add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom); + if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } + add(botLeft, toPos.top, botRight - botLeft, toPos.bottom); + } + + if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; } + if (cmpCoords(toPos, start) < 0) { start = toPos; } + if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; } + if (cmpCoords(toPos, end) < 0) { end = toPos; } + }); + return {start: start, end: end} + } + + var sFrom = range.from(), sTo = range.to(); + if (sFrom.line == sTo.line) { + drawForLine(sFrom.line, sFrom.ch, sTo.ch); + } else { + var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); + var singleVLine = visualLine(fromLine) == visualLine(toLine); + var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; + var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; + if (singleVLine) { + if (leftEnd.top < rightStart.top - 2) { + add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); + add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); + } else { + add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); + } + } + if (leftEnd.bottom < rightStart.top) + { add(leftSide, leftEnd.bottom, null, rightStart.top); } + } + + output.appendChild(fragment); + } + + // Cursor-blinking + function restartBlink(cm) { + if (!cm.state.focused) { return } + var display = cm.display; + clearInterval(display.blinker); + var on = true; + display.cursorDiv.style.visibility = ""; + if (cm.options.cursorBlinkRate > 0) + { display.blinker = setInterval(function () { + if (!cm.hasFocus()) { onBlur(cm); } + display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; + }, cm.options.cursorBlinkRate); } + else if (cm.options.cursorBlinkRate < 0) + { display.cursorDiv.style.visibility = "hidden"; } + } + + function ensureFocus(cm) { + if (!cm.hasFocus()) { + cm.display.input.focus(); + if (!cm.state.focused) { onFocus(cm); } + } + } + + function delayBlurEvent(cm) { + cm.state.delayingBlurEvent = true; + setTimeout(function () { if (cm.state.delayingBlurEvent) { + cm.state.delayingBlurEvent = false; + if (cm.state.focused) { onBlur(cm); } + } }, 100); + } + + function onFocus(cm, e) { + if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; } + + if (cm.options.readOnly == "nocursor") { return } + if (!cm.state.focused) { + signal(cm, "focus", cm, e); + cm.state.focused = true; + addClass(cm.display.wrapper, "CodeMirror-focused"); + // This test prevents this from firing when a context + // menu is closed (since the input reset would kill the + // select-all detection hack) + if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { + cm.display.input.reset(); + if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730 + } + cm.display.input.receivedFocus(); + } + restartBlink(cm); + } + function onBlur(cm, e) { + if (cm.state.delayingBlurEvent) { return } + + if (cm.state.focused) { + signal(cm, "blur", cm, e); + cm.state.focused = false; + rmClass(cm.display.wrapper, "CodeMirror-focused"); + } + clearInterval(cm.display.blinker); + setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150); + } + + // Read the actual heights of the rendered lines, and update their + // stored heights to match. + function updateHeightsInViewport(cm) { + var display = cm.display; + var prevBottom = display.lineDiv.offsetTop; + for (var i = 0; i < display.view.length; i++) { + var cur = display.view[i], wrapping = cm.options.lineWrapping; + var height = (void 0), width = 0; + if (cur.hidden) { continue } + if (ie && ie_version < 8) { + var bot = cur.node.offsetTop + cur.node.offsetHeight; + height = bot - prevBottom; + prevBottom = bot; + } else { + var box = cur.node.getBoundingClientRect(); + height = box.bottom - box.top; + // Check that lines don't extend past the right of the current + // editor width + if (!wrapping && cur.text.firstChild) + { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; } + } + var diff = cur.line.height - height; + if (diff > .005 || diff < -.005) { + updateLineHeight(cur.line, height); + updateWidgetHeight(cur.line); + if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) + { updateWidgetHeight(cur.rest[j]); } } + } + if (width > cm.display.sizerWidth) { + var chWidth = Math.ceil(width / charWidth(cm.display)); + if (chWidth > cm.display.maxLineLength) { + cm.display.maxLineLength = chWidth; + cm.display.maxLine = cur.line; + cm.display.maxLineChanged = true; + } + } + } + } + + // Read and store the height of line widgets associated with the + // given line. + function updateWidgetHeight(line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) { + var w = line.widgets[i], parent = w.node.parentNode; + if (parent) { w.height = parent.offsetHeight; } + } } + } + + // Compute the lines that are visible in a given viewport (defaults + // the the current scroll position). viewport may contain top, + // height, and ensure (see op.scrollToPos) properties. + function visibleLines(display, doc, viewport) { + var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; + top = Math.floor(top - paddingTop(display)); + var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; + + var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); + // Ensure is a {from: {line, ch}, to: {line, ch}} object, and + // forces those lines into the viewport (if possible). + if (viewport && viewport.ensure) { + var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; + if (ensureFrom < from) { + from = ensureFrom; + to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); + } else if (Math.min(ensureTo, doc.lastLine()) >= to) { + from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); + to = ensureTo; + } + } + return {from: from, to: Math.max(to, from + 1)} + } + + // SCROLLING THINGS INTO VIEW + + // If an editor sits on the top or bottom of the window, partially + // scrolled out of view, this ensures that the cursor is visible. + function maybeScrollWindow(cm, rect) { + if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } + + var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; + if (rect.top + box.top < 0) { doScroll = true; } + else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; } + if (doScroll != null && !phantom) { + var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")); + cm.display.lineSpace.appendChild(scrollNode); + scrollNode.scrollIntoView(doScroll); + cm.display.lineSpace.removeChild(scrollNode); + } + } + + // Scroll a given position into view (immediately), verifying that + // it actually became visible (as line heights are accurately + // measured, the position of something may 'drift' during drawing). + function scrollPosIntoView(cm, pos, end, margin) { + if (margin == null) { margin = 0; } + var rect; + if (!cm.options.lineWrapping && pos == end) { + // Set pos and end to the cursor positions around the character pos sticks to + // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch + // If pos == Pos(_, 0, "before"), pos and end are unchanged + pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos; + end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos; + } + for (var limit = 0; limit < 5; limit++) { + var changed = false; + var coords = cursorCoords(cm, pos); + var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); + rect = {left: Math.min(coords.left, endCoords.left), + top: Math.min(coords.top, endCoords.top) - margin, + right: Math.max(coords.left, endCoords.left), + bottom: Math.max(coords.bottom, endCoords.bottom) + margin}; + var scrollPos = calculateScrollPos(cm, rect); + var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; + if (scrollPos.scrollTop != null) { + updateScrollTop(cm, scrollPos.scrollTop); + if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; } + } + if (scrollPos.scrollLeft != null) { + setScrollLeft(cm, scrollPos.scrollLeft); + if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; } + } + if (!changed) { break } + } + return rect + } + + // Scroll a given set of coordinates into view (immediately). + function scrollIntoView(cm, rect) { + var scrollPos = calculateScrollPos(cm, rect); + if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); } + if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); } + } + + // Calculate a new scroll position needed to scroll the given + // rectangle into view. Returns an object with scrollTop and + // scrollLeft properties. When these are undefined, the + // vertical/horizontal position does not need to be adjusted. + function calculateScrollPos(cm, rect) { + var display = cm.display, snapMargin = textHeight(cm.display); + if (rect.top < 0) { rect.top = 0; } + var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; + var screen = displayHeight(cm), result = {}; + if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; } + var docBottom = cm.doc.height + paddingVert(display); + var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin; + if (rect.top < screentop) { + result.scrollTop = atTop ? 0 : rect.top; + } else if (rect.bottom > screentop + screen) { + var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen); + if (newTop != screentop) { result.scrollTop = newTop; } + } + + var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth; + var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace; + var screenw = displayWidth(cm) - display.gutters.offsetWidth; + var tooWide = rect.right - rect.left > screenw; + if (tooWide) { rect.right = rect.left + screenw; } + if (rect.left < 10) + { result.scrollLeft = 0; } + else if (rect.left < screenleft) + { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); } + else if (rect.right > screenw + screenleft - 3) + { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; } + return result + } + + // Store a relative adjustment to the scroll position in the current + // operation (to be applied when the operation finishes). + function addToScrollTop(cm, top) { + if (top == null) { return } + resolveScrollToPos(cm); + cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; + } + + // Make sure that at the end of the operation the current cursor is + // shown. + function ensureCursorVisible(cm) { + resolveScrollToPos(cm); + var cur = cm.getCursor(); + cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin}; + } + + function scrollToCoords(cm, x, y) { + if (x != null || y != null) { resolveScrollToPos(cm); } + if (x != null) { cm.curOp.scrollLeft = x; } + if (y != null) { cm.curOp.scrollTop = y; } + } + + function scrollToRange(cm, range) { + resolveScrollToPos(cm); + cm.curOp.scrollToPos = range; + } + + // When an operation has its scrollToPos property set, and another + // scroll action is applied before the end of the operation, this + // 'simulates' scrolling that position into view in a cheap way, so + // that the effect of intermediate scroll commands is not ignored. + function resolveScrollToPos(cm) { + var range = cm.curOp.scrollToPos; + if (range) { + cm.curOp.scrollToPos = null; + var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); + scrollToCoordsRange(cm, from, to, range.margin); + } + } + + function scrollToCoordsRange(cm, from, to, margin) { + var sPos = calculateScrollPos(cm, { + left: Math.min(from.left, to.left), + top: Math.min(from.top, to.top) - margin, + right: Math.max(from.right, to.right), + bottom: Math.max(from.bottom, to.bottom) + margin + }); + scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop); + } + + // Sync the scrollable area and scrollbars, ensure the viewport + // covers the visible area. + function updateScrollTop(cm, val) { + if (Math.abs(cm.doc.scrollTop - val) < 2) { return } + if (!gecko) { updateDisplaySimple(cm, {top: val}); } + setScrollTop(cm, val, true); + if (gecko) { updateDisplaySimple(cm); } + startWorker(cm, 100); + } + + function setScrollTop(cm, val, forceScroll) { + val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val)); + if (cm.display.scroller.scrollTop == val && !forceScroll) { return } + cm.doc.scrollTop = val; + cm.display.scrollbars.setScrollTop(val); + if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; } + } + + // Sync scroller and scrollbar, ensure the gutter elements are + // aligned. + function setScrollLeft(cm, val, isScroller, forceScroll) { + val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)); + if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } + cm.doc.scrollLeft = val; + alignHorizontally(cm); + if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; } + cm.display.scrollbars.setScrollLeft(val); + } + + // SCROLLBARS + + // Prepare DOM reads needed to update the scrollbars. Done in one + // shot to minimize update/measure roundtrips. + function measureForScrollbars(cm) { + var d = cm.display, gutterW = d.gutters.offsetWidth; + var docH = Math.round(cm.doc.height + paddingVert(cm.display)); + return { + clientHeight: d.scroller.clientHeight, + viewHeight: d.wrapper.clientHeight, + scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, + viewWidth: d.wrapper.clientWidth, + barLeft: cm.options.fixedGutter ? gutterW : 0, + docHeight: docH, + scrollHeight: docH + scrollGap(cm) + d.barHeight, + nativeBarWidth: d.nativeBarWidth, + gutterWidth: gutterW + } + } + + var NativeScrollbars = function(place, scroll, cm) { + this.cm = cm; + var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); + var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); + vert.tabIndex = horiz.tabIndex = -1; + place(vert); place(horiz); + + on(vert, "scroll", function () { + if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); } + }); + on(horiz, "scroll", function () { + if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); } + }); + + this.checkedZeroWidth = false; + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; } + }; + + NativeScrollbars.prototype.update = function (measure) { + var needsH = measure.scrollWidth > measure.clientWidth + 1; + var needsV = measure.scrollHeight > measure.clientHeight + 1; + var sWidth = measure.nativeBarWidth; + + if (needsV) { + this.vert.style.display = "block"; + this.vert.style.bottom = needsH ? sWidth + "px" : "0"; + var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); + // A bug in IE8 can cause this value to be negative, so guard it. + this.vert.firstChild.style.height = + Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; + } else { + this.vert.style.display = ""; + this.vert.firstChild.style.height = "0"; + } + + if (needsH) { + this.horiz.style.display = "block"; + this.horiz.style.right = needsV ? sWidth + "px" : "0"; + this.horiz.style.left = measure.barLeft + "px"; + var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); + this.horiz.firstChild.style.width = + Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; + } else { + this.horiz.style.display = ""; + this.horiz.firstChild.style.width = "0"; + } + + if (!this.checkedZeroWidth && measure.clientHeight > 0) { + if (sWidth == 0) { this.zeroWidthHack(); } + this.checkedZeroWidth = true; + } + + return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} + }; + + NativeScrollbars.prototype.setScrollLeft = function (pos) { + if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; } + if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); } + }; + + NativeScrollbars.prototype.setScrollTop = function (pos) { + if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; } + if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); } + }; + + NativeScrollbars.prototype.zeroWidthHack = function () { + var w = mac && !mac_geMountainLion ? "12px" : "18px"; + this.horiz.style.height = this.vert.style.width = w; + this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; + this.disableHoriz = new Delayed; + this.disableVert = new Delayed; + }; + + NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { + bar.style.pointerEvents = "auto"; + function maybeDisable() { + // To find out whether the scrollbar is still visible, we + // check whether the element under the pixel in the bottom + // right corner of the scrollbar box is the scrollbar box + // itself (when the bar is still visible) or its filler child + // (when the bar is hidden). If it is still visible, we keep + // it enabled, if it's hidden, we disable pointer events. + var box = bar.getBoundingClientRect(); + var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) + : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1); + if (elt != bar) { bar.style.pointerEvents = "none"; } + else { delay.set(1000, maybeDisable); } + } + delay.set(1000, maybeDisable); + }; + + NativeScrollbars.prototype.clear = function () { + var parent = this.horiz.parentNode; + parent.removeChild(this.horiz); + parent.removeChild(this.vert); + }; + + var NullScrollbars = function () {}; + + NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; + NullScrollbars.prototype.setScrollLeft = function () {}; + NullScrollbars.prototype.setScrollTop = function () {}; + NullScrollbars.prototype.clear = function () {}; + + function updateScrollbars(cm, measure) { + if (!measure) { measure = measureForScrollbars(cm); } + var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; + updateScrollbarsInner(cm, measure); + for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { + if (startWidth != cm.display.barWidth && cm.options.lineWrapping) + { updateHeightsInViewport(cm); } + updateScrollbarsInner(cm, measureForScrollbars(cm)); + startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; + } + } + + // Re-synchronize the fake scrollbars with the actual size of the + // content. + function updateScrollbarsInner(cm, measure) { + var d = cm.display; + var sizes = d.scrollbars.update(measure); + + d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; + d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; + d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"; + + if (sizes.right && sizes.bottom) { + d.scrollbarFiller.style.display = "block"; + d.scrollbarFiller.style.height = sizes.bottom + "px"; + d.scrollbarFiller.style.width = sizes.right + "px"; + } else { d.scrollbarFiller.style.display = ""; } + if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { + d.gutterFiller.style.display = "block"; + d.gutterFiller.style.height = sizes.bottom + "px"; + d.gutterFiller.style.width = measure.gutterWidth + "px"; + } else { d.gutterFiller.style.display = ""; } + } + + var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; + + function initScrollbars(cm) { + if (cm.display.scrollbars) { + cm.display.scrollbars.clear(); + if (cm.display.scrollbars.addClass) + { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); } + } + + cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { + cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); + // Prevent clicks in the scrollbars from killing focus + on(node, "mousedown", function () { + if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); } + }); + node.setAttribute("cm-not-content", "true"); + }, function (pos, axis) { + if (axis == "horizontal") { setScrollLeft(cm, pos); } + else { updateScrollTop(cm, pos); } + }, cm); + if (cm.display.scrollbars.addClass) + { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); } + } + + // Operations are used to wrap a series of changes to the editor + // state in such a way that each change won't have to update the + // cursor and display (which would be awkward, slow, and + // error-prone). Instead, display updates are batched and then all + // combined and executed at once. + + var nextOpId = 0; + // Start a new operation. + function startOperation(cm) { + cm.curOp = { + cm: cm, + viewChanged: false, // Flag that indicates that lines might need to be redrawn + startHeight: cm.doc.height, // Used to detect need to update scrollbar + forceUpdate: false, // Used to force a redraw + updateInput: 0, // Whether to reset the input textarea + typing: false, // Whether this reset should be careful to leave existing text (for compositing) + changeObjs: null, // Accumulated changes, for firing change events + cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on + cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already + selectionChanged: false, // Whether the selection needs to be redrawn + updateMaxLine: false, // Set when the widest line needs to be determined anew + scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet + scrollToPos: null, // Used to scroll to a specific position + focus: false, + id: ++nextOpId // Unique ID + }; + pushOperation(cm.curOp); + } + + // Finish an operation, updating the display and signalling delayed events + function endOperation(cm) { + var op = cm.curOp; + if (op) { finishOperation(op, function (group) { + for (var i = 0; i < group.ops.length; i++) + { group.ops[i].cm.curOp = null; } + endOperations(group); + }); } + } + + // The DOM updates done when an operation finishes are batched so + // that the minimum number of relayouts are required. + function endOperations(group) { + var ops = group.ops; + for (var i = 0; i < ops.length; i++) // Read DOM + { endOperation_R1(ops[i]); } + for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) + { endOperation_W1(ops[i$1]); } + for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM + { endOperation_R2(ops[i$2]); } + for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) + { endOperation_W2(ops[i$3]); } + for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM + { endOperation_finish(ops[i$4]); } + } + + function endOperation_R1(op) { + var cm = op.cm, display = cm.display; + maybeClipScrollbars(cm); + if (op.updateMaxLine) { findMaxLine(cm); } + + op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || + op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || + op.scrollToPos.to.line >= display.viewTo) || + display.maxLineChanged && cm.options.lineWrapping; + op.update = op.mustUpdate && + new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); + } + + function endOperation_W1(op) { + op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); + } + + function endOperation_R2(op) { + var cm = op.cm, display = cm.display; + if (op.updatedDisplay) { updateHeightsInViewport(cm); } + + op.barMeasure = measureForScrollbars(cm); + + // If the max line changed since it was last measured, measure it, + // and ensure the document's width matches it. + // updateDisplay_W2 will use these properties to do the actual resizing + if (display.maxLineChanged && !cm.options.lineWrapping) { + op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; + cm.display.sizerWidth = op.adjustWidthTo; + op.barMeasure.scrollWidth = + Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); + op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); + } + + if (op.updatedDisplay || op.selectionChanged) + { op.preparedSelection = display.input.prepareSelection(); } + } + + function endOperation_W2(op) { + var cm = op.cm; + + if (op.adjustWidthTo != null) { + cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; + if (op.maxScrollLeft < cm.doc.scrollLeft) + { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); } + cm.display.maxLineChanged = false; + } + + var takeFocus = op.focus && op.focus == activeElt(); + if (op.preparedSelection) + { cm.display.input.showSelection(op.preparedSelection, takeFocus); } + if (op.updatedDisplay || op.startHeight != cm.doc.height) + { updateScrollbars(cm, op.barMeasure); } + if (op.updatedDisplay) + { setDocumentHeight(cm, op.barMeasure); } + + if (op.selectionChanged) { restartBlink(cm); } + + if (cm.state.focused && op.updateInput) + { cm.display.input.reset(op.typing); } + if (takeFocus) { ensureFocus(op.cm); } + } + + function endOperation_finish(op) { + var cm = op.cm, display = cm.display, doc = cm.doc; + + if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); } + + // Abort mouse wheel delta measurement, when scrolling explicitly + if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) + { display.wheelStartX = display.wheelStartY = null; } + + // Propagate the scroll position to the actual DOM scroller + if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); } + + if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); } + // If we need to scroll a specific position into view, do so. + if (op.scrollToPos) { + var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), + clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); + maybeScrollWindow(cm, rect); + } + + // Fire events for markers that are hidden/unidden by editing or + // undoing + var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; + if (hidden) { for (var i = 0; i < hidden.length; ++i) + { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } } + if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) + { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } } + + if (display.wrapper.offsetHeight) + { doc.scrollTop = cm.display.scroller.scrollTop; } + + // Fire change events, and delayed event handlers + if (op.changeObjs) + { signal(cm, "changes", cm, op.changeObjs); } + if (op.update) + { op.update.finish(); } + } + + // Run the given function in an operation + function runInOp(cm, f) { + if (cm.curOp) { return f() } + startOperation(cm); + try { return f() } + finally { endOperation(cm); } + } + // Wraps a function in an operation. Returns the wrapped function. + function operation(cm, f) { + return function() { + if (cm.curOp) { return f.apply(cm, arguments) } + startOperation(cm); + try { return f.apply(cm, arguments) } + finally { endOperation(cm); } + } + } + // Used to add methods to editor and doc instances, wrapping them in + // operations. + function methodOp(f) { + return function() { + if (this.curOp) { return f.apply(this, arguments) } + startOperation(this); + try { return f.apply(this, arguments) } + finally { endOperation(this); } + } + } + function docMethodOp(f) { + return function() { + var cm = this.cm; + if (!cm || cm.curOp) { return f.apply(this, arguments) } + startOperation(cm); + try { return f.apply(this, arguments) } + finally { endOperation(cm); } + } + } + + // HIGHLIGHT WORKER + + function startWorker(cm, time) { + if (cm.doc.highlightFrontier < cm.display.viewTo) + { cm.state.highlight.set(time, bind(highlightWorker, cm)); } + } + + function highlightWorker(cm) { + var doc = cm.doc; + if (doc.highlightFrontier >= cm.display.viewTo) { return } + var end = +new Date + cm.options.workTime; + var context = getContextBefore(cm, doc.highlightFrontier); + var changedLines = []; + + doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { + if (context.line >= cm.display.viewFrom) { // Visible + var oldStyles = line.styles; + var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null; + var highlighted = highlightLine(cm, line, context, true); + if (resetState) { context.state = resetState; } + line.styles = highlighted.styles; + var oldCls = line.styleClasses, newCls = highlighted.classes; + if (newCls) { line.styleClasses = newCls; } + else if (oldCls) { line.styleClasses = null; } + var ischange = !oldStyles || oldStyles.length != line.styles.length || + oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); + for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; } + if (ischange) { changedLines.push(context.line); } + line.stateAfter = context.save(); + context.nextLine(); + } else { + if (line.text.length <= cm.options.maxHighlightLength) + { processLine(cm, line.text, context); } + line.stateAfter = context.line % 5 == 0 ? context.save() : null; + context.nextLine(); + } + if (+new Date > end) { + startWorker(cm, cm.options.workDelay); + return true + } + }); + doc.highlightFrontier = context.line; + doc.modeFrontier = Math.max(doc.modeFrontier, context.line); + if (changedLines.length) { runInOp(cm, function () { + for (var i = 0; i < changedLines.length; i++) + { regLineChange(cm, changedLines[i], "text"); } + }); } + } + + // DISPLAY DRAWING + + var DisplayUpdate = function(cm, viewport, force) { + var display = cm.display; + + this.viewport = viewport; + // Store some values that we'll need later (but don't want to force a relayout for) + this.visible = visibleLines(display, cm.doc, viewport); + this.editorIsHidden = !display.wrapper.offsetWidth; + this.wrapperHeight = display.wrapper.clientHeight; + this.wrapperWidth = display.wrapper.clientWidth; + this.oldDisplayWidth = displayWidth(cm); + this.force = force; + this.dims = getDimensions(cm); + this.events = []; + }; + + DisplayUpdate.prototype.signal = function (emitter, type) { + if (hasHandler(emitter, type)) + { this.events.push(arguments); } + }; + DisplayUpdate.prototype.finish = function () { + for (var i = 0; i < this.events.length; i++) + { signal.apply(null, this.events[i]); } + }; + + function maybeClipScrollbars(cm) { + var display = cm.display; + if (!display.scrollbarsClipped && display.scroller.offsetWidth) { + display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; + display.heightForcer.style.height = scrollGap(cm) + "px"; + display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; + display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; + display.scrollbarsClipped = true; + } + } + + function selectionSnapshot(cm) { + if (cm.hasFocus()) { return null } + var active = activeElt(); + if (!active || !contains(cm.display.lineDiv, active)) { return null } + var result = {activeElt: active}; + if (window.getSelection) { + var sel = window.getSelection(); + if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { + result.anchorNode = sel.anchorNode; + result.anchorOffset = sel.anchorOffset; + result.focusNode = sel.focusNode; + result.focusOffset = sel.focusOffset; + } + } + return result + } + + function restoreSelection(snapshot) { + if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return } + snapshot.activeElt.focus(); + if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) && + snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { + var sel = window.getSelection(), range = document.createRange(); + range.setEnd(snapshot.anchorNode, snapshot.anchorOffset); + range.collapse(false); + sel.removeAllRanges(); + sel.addRange(range); + sel.extend(snapshot.focusNode, snapshot.focusOffset); + } + } + + // Does the actual updating of the line display. Bails out + // (returning false) when there is nothing to be done and forced is + // false. + function updateDisplayIfNeeded(cm, update) { + var display = cm.display, doc = cm.doc; + + if (update.editorIsHidden) { + resetView(cm); + return false + } + + // Bail out if the visible area is already rendered and nothing changed. + if (!update.force && + update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && + display.renderedView == display.view && countDirtyView(cm) == 0) + { return false } + + if (maybeUpdateLineNumberWidth(cm)) { + resetView(cm); + update.dims = getDimensions(cm); + } + + // Compute a suitable new viewport (from & to) + var end = doc.first + doc.size; + var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); + var to = Math.min(end, update.visible.to + cm.options.viewportMargin); + if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); } + if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); } + if (sawCollapsedSpans) { + from = visualLineNo(cm.doc, from); + to = visualLineEndNo(cm.doc, to); + } + + var different = from != display.viewFrom || to != display.viewTo || + display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; + adjustView(cm, from, to); + + display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); + // Position the mover div to align with the current scroll position + cm.display.mover.style.top = display.viewOffset + "px"; + + var toUpdate = countDirtyView(cm); + if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && + (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) + { return false } + + // For big changes, we hide the enclosing element during the + // update, since that speeds up the operations on most browsers. + var selSnapshot = selectionSnapshot(cm); + if (toUpdate > 4) { display.lineDiv.style.display = "none"; } + patchDisplay(cm, display.updateLineNumbers, update.dims); + if (toUpdate > 4) { display.lineDiv.style.display = ""; } + display.renderedView = display.view; + // There might have been a widget with a focused element that got + // hidden or updated, if so re-focus it. + restoreSelection(selSnapshot); + + // Prevent selection and cursors from interfering with the scroll + // width and height. + removeChildren(display.cursorDiv); + removeChildren(display.selectionDiv); + display.gutters.style.height = display.sizer.style.minHeight = 0; + + if (different) { + display.lastWrapHeight = update.wrapperHeight; + display.lastWrapWidth = update.wrapperWidth; + startWorker(cm, 400); + } + + display.updateLineNumbers = null; + + return true + } + + function postUpdateDisplay(cm, update) { + var viewport = update.viewport; + + for (var first = true;; first = false) { + if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { + // Clip forced viewport to actual scrollable area. + if (viewport && viewport.top != null) + { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; } + // Updated line heights might result in the drawn area not + // actually covering the viewport. Keep looping until it does. + update.visible = visibleLines(cm.display, cm.doc, viewport); + if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) + { break } + } else if (first) { + update.visible = visibleLines(cm.display, cm.doc, viewport); + } + if (!updateDisplayIfNeeded(cm, update)) { break } + updateHeightsInViewport(cm); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.force = false; + } + + update.signal(cm, "update", cm); + if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { + update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); + cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; + } + } + + function updateDisplaySimple(cm, viewport) { + var update = new DisplayUpdate(cm, viewport); + if (updateDisplayIfNeeded(cm, update)) { + updateHeightsInViewport(cm); + postUpdateDisplay(cm, update); + var barMeasure = measureForScrollbars(cm); + updateSelection(cm); + updateScrollbars(cm, barMeasure); + setDocumentHeight(cm, barMeasure); + update.finish(); + } + } + + // Sync the actual display DOM structure with display.view, removing + // nodes for lines that are no longer in view, and creating the ones + // that are not there yet, and updating the ones that are out of + // date. + function patchDisplay(cm, updateNumbersFrom, dims) { + var display = cm.display, lineNumbers = cm.options.lineNumbers; + var container = display.lineDiv, cur = container.firstChild; + + function rm(node) { + var next = node.nextSibling; + // Works around a throw-scroll bug in OS X Webkit + if (webkit && mac && cm.display.currentWheelTarget == node) + { node.style.display = "none"; } + else + { node.parentNode.removeChild(node); } + return next + } + + var view = display.view, lineN = display.viewFrom; + // Loop over the elements in the view, syncing cur (the DOM nodes + // in display.lineDiv) with the view as we go. + for (var i = 0; i < view.length; i++) { + var lineView = view[i]; + if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet + var node = buildLineElement(cm, lineView, lineN, dims); + container.insertBefore(node, cur); + } else { // Already drawn + while (cur != lineView.node) { cur = rm(cur); } + var updateNumber = lineNumbers && updateNumbersFrom != null && + updateNumbersFrom <= lineN && lineView.lineNumber; + if (lineView.changes) { + if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; } + updateLineForChanges(cm, lineView, lineN, dims); + } + if (updateNumber) { + removeChildren(lineView.lineNumber); + lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); + } + cur = lineView.node.nextSibling; + } + lineN += lineView.size; + } + while (cur) { cur = rm(cur); } + } + + function updateGutterSpace(display) { + var width = display.gutters.offsetWidth; + display.sizer.style.marginLeft = width + "px"; + } + + function setDocumentHeight(cm, measure) { + cm.display.sizer.style.minHeight = measure.docHeight + "px"; + cm.display.heightForcer.style.top = measure.docHeight + "px"; + cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; + } + + // Re-align line numbers and gutter marks to compensate for + // horizontal scrolling. + function alignHorizontally(cm) { + var display = cm.display, view = display.view; + if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } + var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; + var gutterW = display.gutters.offsetWidth, left = comp + "px"; + for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { + if (cm.options.fixedGutter) { + if (view[i].gutter) + { view[i].gutter.style.left = left; } + if (view[i].gutterBackground) + { view[i].gutterBackground.style.left = left; } + } + var align = view[i].alignable; + if (align) { for (var j = 0; j < align.length; j++) + { align[j].style.left = left; } } + } } + if (cm.options.fixedGutter) + { display.gutters.style.left = (comp + gutterW) + "px"; } + } + + // Used to ensure that the line number gutter is still the right + // size for the current document size. Returns true when an update + // is needed. + function maybeUpdateLineNumberWidth(cm) { + if (!cm.options.lineNumbers) { return false } + var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; + if (last.length != display.lineNumChars) { + var test = display.measure.appendChild(elt("div", [elt("div", last)], + "CodeMirror-linenumber CodeMirror-gutter-elt")); + var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; + display.lineGutter.style.width = ""; + display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; + display.lineNumWidth = display.lineNumInnerWidth + padding; + display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; + display.lineGutter.style.width = display.lineNumWidth + "px"; + updateGutterSpace(cm.display); + return true + } + return false + } + + function getGutters(gutters, lineNumbers) { + var result = [], sawLineNumbers = false; + for (var i = 0; i < gutters.length; i++) { + var name = gutters[i], style = null; + if (typeof name != "string") { style = name.style; name = name.className; } + if (name == "CodeMirror-linenumbers") { + if (!lineNumbers) { continue } + else { sawLineNumbers = true; } + } + result.push({className: name, style: style}); + } + if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); } + return result + } + + // Rebuild the gutter elements, ensure the margin to the left of the + // code matches their width. + function renderGutters(display) { + var gutters = display.gutters, specs = display.gutterSpecs; + removeChildren(gutters); + display.lineGutter = null; + for (var i = 0; i < specs.length; ++i) { + var ref = specs[i]; + var className = ref.className; + var style = ref.style; + var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); + if (style) { gElt.style.cssText = style; } + if (className == "CodeMirror-linenumbers") { + display.lineGutter = gElt; + gElt.style.width = (display.lineNumWidth || 1) + "px"; + } + } + gutters.style.display = specs.length ? "" : "none"; + updateGutterSpace(display); + } + + function updateGutters(cm) { + renderGutters(cm.display); + regChange(cm); + alignHorizontally(cm); + } + + // The display handles the DOM integration, both for input reading + // and content drawing. It holds references to DOM nodes and + // display-related state. + + function Display(place, doc, input, options) { + var d = this; + this.input = input; + + // Covers bottom-right square when both scrollbars are present. + d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); + d.scrollbarFiller.setAttribute("cm-not-content", "true"); + // Covers bottom of gutter when coverGutterNextToScrollbar is on + // and h scrollbar is present. + d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); + d.gutterFiller.setAttribute("cm-not-content", "true"); + // Will contain the actual code, positioned to cover the viewport. + d.lineDiv = eltP("div", null, "CodeMirror-code"); + // Elements are added to these to represent selection and cursors. + d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); + d.cursorDiv = elt("div", null, "CodeMirror-cursors"); + // A visibility: hidden element used to find the size of things. + d.measure = elt("div", null, "CodeMirror-measure"); + // When lines outside of the viewport are measured, they are drawn in this. + d.lineMeasure = elt("div", null, "CodeMirror-measure"); + // Wraps everything that needs to exist inside the vertically-padded coordinate system + d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], + null, "position: relative; outline: none"); + var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); + // Moved around its parent to cover visible view. + d.mover = elt("div", [lines], null, "position: relative"); + // Set to the height of the document, allowing scrolling. + d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); + d.sizerWidth = null; + // Behavior of elts with overflow: auto and padding is + // inconsistent across browsers. This is used to ensure the + // scrollable area is big enough. + d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); + // Will contain the gutters, if any. + d.gutters = elt("div", null, "CodeMirror-gutters"); + d.lineGutter = null; + // Actual scrollable element. + d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); + d.scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); + + // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) + if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } + if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } + + if (place) { + if (place.appendChild) { place.appendChild(d.wrapper); } + else { place(d.wrapper); } + } + + // Current rendered range (may be bigger than the view window). + d.viewFrom = d.viewTo = doc.first; + d.reportedViewFrom = d.reportedViewTo = doc.first; + // Information about the rendered lines. + d.view = []; + d.renderedView = null; + // Holds info about a single rendered line when it was rendered + // for measurement, while not in view. + d.externalMeasured = null; + // Empty space (in pixels) above the view + d.viewOffset = 0; + d.lastWrapHeight = d.lastWrapWidth = 0; + d.updateLineNumbers = null; + + d.nativeBarWidth = d.barHeight = d.barWidth = 0; + d.scrollbarsClipped = false; + + // Used to only resize the line number gutter when necessary (when + // the amount of lines crosses a boundary that makes its width change) + d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; + // Set to true when a non-horizontal-scrolling line widget is + // added. As an optimization, line widget aligning is skipped when + // this is false. + d.alignWidgets = false; + + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + d.maxLine = null; + d.maxLineLength = 0; + d.maxLineChanged = false; + + // Used for measuring wheel scrolling granularity + d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; + + // True when shift is held down. + d.shift = false; + + // Used to track whether anything happened since the context menu + // was opened. + d.selForContextMenu = null; + + d.activeTouch = null; + + d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); + renderGutters(d); + + input.init(d); + } + + // Since the delta values reported on mouse wheel events are + // unstandardized between browsers and even browser versions, and + // generally horribly unpredictable, this code starts by measuring + // the scroll effect that the first few mouse wheel events have, + // and, from that, detects the way it can convert deltas to pixel + // offsets afterwards. + // + // The reason we want to know the amount a wheel event will scroll + // is that it gives us a chance to update the display before the + // actual scrolling happens, reducing flickering. + + var wheelSamples = 0, wheelPixelsPerUnit = null; + // Fill in a browser-detected starting value on browsers where we + // know one. These don't have to be accurate -- the result of them + // being wrong would just be a slight flicker on the first wheel + // scroll (if it is large enough). + if (ie) { wheelPixelsPerUnit = -.53; } + else if (gecko) { wheelPixelsPerUnit = 15; } + else if (chrome) { wheelPixelsPerUnit = -.7; } + else if (safari) { wheelPixelsPerUnit = -1/3; } + + function wheelEventDelta(e) { + var dx = e.wheelDeltaX, dy = e.wheelDeltaY; + if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; } + if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; } + else if (dy == null) { dy = e.wheelDelta; } + return {x: dx, y: dy} + } + function wheelEventPixels(e) { + var delta = wheelEventDelta(e); + delta.x *= wheelPixelsPerUnit; + delta.y *= wheelPixelsPerUnit; + return delta + } + + function onScrollWheel(cm, e) { + var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; + + var display = cm.display, scroll = display.scroller; + // Quit if there's nothing to scroll here + var canScrollX = scroll.scrollWidth > scroll.clientWidth; + var canScrollY = scroll.scrollHeight > scroll.clientHeight; + if (!(dx && canScrollX || dy && canScrollY)) { return } + + // Webkit browsers on OS X abort momentum scrolls when the target + // of the scroll event is removed from the scrollable element. + // This hack (see related code in patchDisplay) makes sure the + // element is kept around. + if (dy && mac && webkit) { + outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { + for (var i = 0; i < view.length; i++) { + if (view[i].node == cur) { + cm.display.currentWheelTarget = cur; + break outer + } + } + } + } + + // On some browsers, horizontal scrolling will cause redraws to + // happen before the gutter has been realigned, causing it to + // wriggle around in a most unseemly way. When we have an + // estimated pixels/delta value, we just handle horizontal + // scrolling entirely here. It'll be slightly off from native, but + // better than glitching out. + if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { + if (dy && canScrollY) + { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); } + setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit)); + // Only prevent default scrolling if vertical scrolling is + // actually possible. Otherwise, it causes vertical scroll + // jitter on OSX trackpads when deltaX is small and deltaY + // is large (issue #3579) + if (!dy || (dy && canScrollY)) + { e_preventDefault(e); } + display.wheelStartX = null; // Abort measurement, if in progress + return + } + + // 'Project' the visible viewport to cover the area that is being + // scrolled into view (if we know enough to estimate it). + if (dy && wheelPixelsPerUnit != null) { + var pixels = dy * wheelPixelsPerUnit; + var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; + if (pixels < 0) { top = Math.max(0, top + pixels - 50); } + else { bot = Math.min(cm.doc.height, bot + pixels + 50); } + updateDisplaySimple(cm, {top: top, bottom: bot}); + } + + if (wheelSamples < 20) { + if (display.wheelStartX == null) { + display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; + display.wheelDX = dx; display.wheelDY = dy; + setTimeout(function () { + if (display.wheelStartX == null) { return } + var movedX = scroll.scrollLeft - display.wheelStartX; + var movedY = scroll.scrollTop - display.wheelStartY; + var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || + (movedX && display.wheelDX && movedX / display.wheelDX); + display.wheelStartX = display.wheelStartY = null; + if (!sample) { return } + wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); + ++wheelSamples; + }, 200); + } else { + display.wheelDX += dx; display.wheelDY += dy; + } + } + } + + // Selection objects are immutable. A new one is created every time + // the selection changes. A selection is one or more non-overlapping + // (and non-touching) ranges, sorted, and an integer that indicates + // which one is the primary selection (the one that's scrolled into + // view, that getCursor returns, etc). + var Selection = function(ranges, primIndex) { + this.ranges = ranges; + this.primIndex = primIndex; + }; + + Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; + + Selection.prototype.equals = function (other) { + if (other == this) { return true } + if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } + for (var i = 0; i < this.ranges.length; i++) { + var here = this.ranges[i], there = other.ranges[i]; + if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } + } + return true + }; + + Selection.prototype.deepCopy = function () { + var out = []; + for (var i = 0; i < this.ranges.length; i++) + { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); } + return new Selection(out, this.primIndex) + }; + + Selection.prototype.somethingSelected = function () { + for (var i = 0; i < this.ranges.length; i++) + { if (!this.ranges[i].empty()) { return true } } + return false + }; + + Selection.prototype.contains = function (pos, end) { + if (!end) { end = pos; } + for (var i = 0; i < this.ranges.length; i++) { + var range = this.ranges[i]; + if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) + { return i } + } + return -1 + }; + + var Range = function(anchor, head) { + this.anchor = anchor; this.head = head; + }; + + Range.prototype.from = function () { return minPos(this.anchor, this.head) }; + Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; + Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; + + // Take an unsorted, potentially overlapping set of ranges, and + // build a selection out of it. 'Consumes' ranges array (modifying + // it). + function normalizeSelection(cm, ranges, primIndex) { + var mayTouch = cm && cm.options.selectionsMayTouch; + var prim = ranges[primIndex]; + ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }); + primIndex = indexOf(ranges, prim); + for (var i = 1; i < ranges.length; i++) { + var cur = ranges[i], prev = ranges[i - 1]; + var diff = cmp(prev.to(), cur.from()); + if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) { + var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); + var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; + if (i <= primIndex) { --primIndex; } + ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); + } + } + return new Selection(ranges, primIndex) + } + + function simpleSelection(anchor, head) { + return new Selection([new Range(anchor, head || anchor)], 0) + } + + // Compute the position of the end of a change (its 'to' property + // refers to the pre-change end). + function changeEnd(change) { + if (!change.text) { return change.to } + return Pos(change.from.line + change.text.length - 1, + lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) + } + + // Adjust a position to refer to the post-change position of the + // same text, or the end of the change if the change covers it. + function adjustForChange(pos, change) { + if (cmp(pos, change.from) < 0) { return pos } + if (cmp(pos, change.to) <= 0) { return changeEnd(change) } + + var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; + if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; } + return Pos(line, ch) + } + + function computeSelAfterChange(doc, change) { + var out = []; + for (var i = 0; i < doc.sel.ranges.length; i++) { + var range = doc.sel.ranges[i]; + out.push(new Range(adjustForChange(range.anchor, change), + adjustForChange(range.head, change))); + } + return normalizeSelection(doc.cm, out, doc.sel.primIndex) + } + + function offsetPos(pos, old, nw) { + if (pos.line == old.line) + { return Pos(nw.line, pos.ch - old.ch + nw.ch) } + else + { return Pos(nw.line + (pos.line - old.line), pos.ch) } + } + + // Used by replaceSelections to allow moving the selection to the + // start or around the replaced test. Hint may be "start" or "around". + function computeReplacedSel(doc, changes, hint) { + var out = []; + var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; + for (var i = 0; i < changes.length; i++) { + var change = changes[i]; + var from = offsetPos(change.from, oldPrev, newPrev); + var to = offsetPos(changeEnd(change), oldPrev, newPrev); + oldPrev = change.to; + newPrev = to; + if (hint == "around") { + var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; + out[i] = new Range(inv ? to : from, inv ? from : to); + } else { + out[i] = new Range(from, from); + } + } + return new Selection(out, doc.sel.primIndex) + } + + // Used to get the editor into a consistent state again when options change. + + function loadMode(cm) { + cm.doc.mode = getMode(cm.options, cm.doc.modeOption); + resetModeState(cm); + } + + function resetModeState(cm) { + cm.doc.iter(function (line) { + if (line.stateAfter) { line.stateAfter = null; } + if (line.styles) { line.styles = null; } + }); + cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first; + startWorker(cm, 100); + cm.state.modeGen++; + if (cm.curOp) { regChange(cm); } + } + + // DOCUMENT DATA STRUCTURE + + // By default, updates that start and end at the beginning of a line + // are treated specially, in order to make the association of line + // widgets and marker elements with the text behave more intuitive. + function isWholeLineUpdate(doc, change) { + return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && + (!doc.cm || doc.cm.options.wholeLineUpdateBefore) + } + + // Perform a change on the document data structure. + function updateDoc(doc, change, markedSpans, estimateHeight) { + function spansFor(n) {return markedSpans ? markedSpans[n] : null} + function update(line, text, spans) { + updateLine(line, text, spans, estimateHeight); + signalLater(line, "change", line, change); + } + function linesFor(start, end) { + var result = []; + for (var i = start; i < end; ++i) + { result.push(new Line(text[i], spansFor(i), estimateHeight)); } + return result + } + + var from = change.from, to = change.to, text = change.text; + var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); + var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; + + // Adjust the line structure + if (change.full) { + doc.insert(0, linesFor(0, text.length)); + doc.remove(text.length, doc.size - text.length); + } else if (isWholeLineUpdate(doc, change)) { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = linesFor(0, text.length - 1); + update(lastLine, lastLine.text, lastSpans); + if (nlines) { doc.remove(from.line, nlines); } + if (added.length) { doc.insert(from.line, added); } + } else if (firstLine == lastLine) { + if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); + } else { + var added$1 = linesFor(1, text.length - 1); + added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + doc.insert(from.line + 1, added$1); + } + } else if (text.length == 1) { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); + doc.remove(from.line + 1, nlines); + } else { + update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); + update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); + var added$2 = linesFor(1, text.length - 1); + if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); } + doc.insert(from.line + 1, added$2); + } + + signalLater(doc, "change", doc, change); + } + + // Call f for all linked documents. + function linkedDocs(doc, f, sharedHistOnly) { + function propagate(doc, skip, sharedHist) { + if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { + var rel = doc.linked[i]; + if (rel.doc == skip) { continue } + var shared = sharedHist && rel.sharedHist; + if (sharedHistOnly && !shared) { continue } + f(rel.doc, shared); + propagate(rel.doc, doc, shared); + } } + } + propagate(doc, null, true); + } + + // Attach a document to an editor. + function attachDoc(cm, doc) { + if (doc.cm) { throw new Error("This document is already in use.") } + cm.doc = doc; + doc.cm = cm; + estimateLineHeights(cm); + loadMode(cm); + setDirectionClass(cm); + if (!cm.options.lineWrapping) { findMaxLine(cm); } + cm.options.mode = doc.modeOption; + regChange(cm); + } + + function setDirectionClass(cm) { + (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl"); + } + + function directionChanged(cm) { + runInOp(cm, function () { + setDirectionClass(cm); + regChange(cm); + }); + } + + function History(startGen) { + // Arrays of change events and selections. Doing something adds an + // event to done and clears undo. Undoing moves events from done + // to undone, redoing moves them in the other direction. + this.done = []; this.undone = []; + this.undoDepth = Infinity; + // Used to track when changes can be merged into a single undo + // event + this.lastModTime = this.lastSelTime = 0; + this.lastOp = this.lastSelOp = null; + this.lastOrigin = this.lastSelOrigin = null; + // Used by the isClean() method + this.generation = this.maxGeneration = startGen || 1; + } + + // Create a history change event from an updateDoc-style change + // object. + function historyChangeFromChange(doc, change) { + var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; + attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); + linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true); + return histChange + } + + // Pop all selection events off the end of a history array. Stop at + // a change event. + function clearSelectionEvents(array) { + while (array.length) { + var last = lst(array); + if (last.ranges) { array.pop(); } + else { break } + } + } + + // Find the top change event in the history. Pop off selection + // events that are in the way. + function lastChangeEvent(hist, force) { + if (force) { + clearSelectionEvents(hist.done); + return lst(hist.done) + } else if (hist.done.length && !lst(hist.done).ranges) { + return lst(hist.done) + } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { + hist.done.pop(); + return lst(hist.done) + } + } + + // Register a change in the history. Merges changes that are within + // a single operation, or are close together with an origin that + // allows merging (starting with "+") into a single event. + function addChangeToHistory(doc, change, selAfter, opId) { + var hist = doc.history; + hist.undone.length = 0; + var time = +new Date, cur; + var last; + + if ((hist.lastOp == opId || + hist.lastOrigin == change.origin && change.origin && + ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) || + change.origin.charAt(0) == "*")) && + (cur = lastChangeEvent(hist, hist.lastOp == opId))) { + // Merge this change into the last event + last = lst(cur.changes); + if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { + // Optimized case for simple insertion -- don't want to add + // new changesets for every character typed + last.to = changeEnd(change); + } else { + // Add new sub-event + cur.changes.push(historyChangeFromChange(doc, change)); + } + } else { + // Can not be merged, start a new event. + var before = lst(hist.done); + if (!before || !before.ranges) + { pushSelectionToHistory(doc.sel, hist.done); } + cur = {changes: [historyChangeFromChange(doc, change)], + generation: hist.generation}; + hist.done.push(cur); + while (hist.done.length > hist.undoDepth) { + hist.done.shift(); + if (!hist.done[0].ranges) { hist.done.shift(); } + } + } + hist.done.push(selAfter); + hist.generation = ++hist.maxGeneration; + hist.lastModTime = hist.lastSelTime = time; + hist.lastOp = hist.lastSelOp = opId; + hist.lastOrigin = hist.lastSelOrigin = change.origin; + + if (!last) { signal(doc, "historyAdded"); } + } + + function selectionEventCanBeMerged(doc, origin, prev, sel) { + var ch = origin.charAt(0); + return ch == "*" || + ch == "+" && + prev.ranges.length == sel.ranges.length && + prev.somethingSelected() == sel.somethingSelected() && + new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) + } + + // Called whenever the selection changes, sets the new selection as + // the pending selection in the history, and pushes the old pending + // selection into the 'done' array when it was significantly + // different (in number of selected ranges, emptiness, or time). + function addSelectionToHistory(doc, sel, opId, options) { + var hist = doc.history, origin = options && options.origin; + + // A new event is started when the previous origin does not match + // the current, or the origins don't allow matching. Origins + // starting with * are always merged, those starting with + are + // merged when similar and close together in time. + if (opId == hist.lastSelOp || + (origin && hist.lastSelOrigin == origin && + (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || + selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) + { hist.done[hist.done.length - 1] = sel; } + else + { pushSelectionToHistory(sel, hist.done); } + + hist.lastSelTime = +new Date; + hist.lastSelOrigin = origin; + hist.lastSelOp = opId; + if (options && options.clearRedo !== false) + { clearSelectionEvents(hist.undone); } + } + + function pushSelectionToHistory(sel, dest) { + var top = lst(dest); + if (!(top && top.ranges && top.equals(sel))) + { dest.push(sel); } + } + + // Used to store marked span information in the history. + function attachLocalSpans(doc, change, from, to) { + var existing = change["spans_" + doc.id], n = 0; + doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { + if (line.markedSpans) + { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; } + ++n; + }); + } + + // When un/re-doing restores text containing marked spans, those + // that have been explicitly cleared should not be restored. + function removeClearedSpans(spans) { + if (!spans) { return null } + var out; + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } } + else if (out) { out.push(spans[i]); } + } + return !out ? spans : out.length ? out : null + } + + // Retrieve and filter the old marked spans stored in a change event. + function getOldSpans(doc, change) { + var found = change["spans_" + doc.id]; + if (!found) { return null } + var nw = []; + for (var i = 0; i < change.text.length; ++i) + { nw.push(removeClearedSpans(found[i])); } + return nw + } + + // Used for un/re-doing changes from the history. Combines the + // result of computing the existing spans with the set of spans that + // existed in the history (so that deleting around a span and then + // undoing brings back the span). + function mergeOldSpans(doc, change) { + var old = getOldSpans(doc, change); + var stretched = stretchSpansOverChange(doc, change); + if (!old) { return stretched } + if (!stretched) { return old } + + for (var i = 0; i < old.length; ++i) { + var oldCur = old[i], stretchCur = stretched[i]; + if (oldCur && stretchCur) { + spans: for (var j = 0; j < stretchCur.length; ++j) { + var span = stretchCur[j]; + for (var k = 0; k < oldCur.length; ++k) + { if (oldCur[k].marker == span.marker) { continue spans } } + oldCur.push(span); + } + } else if (stretchCur) { + old[i] = stretchCur; + } + } + return old + } + + // Used both to provide a JSON-safe object in .getHistory, and, when + // detaching a document, to split the history in two + function copyHistoryArray(events, newGroup, instantiateSel) { + var copy = []; + for (var i = 0; i < events.length; ++i) { + var event = events[i]; + if (event.ranges) { + copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); + continue + } + var changes = event.changes, newChanges = []; + copy.push({changes: newChanges}); + for (var j = 0; j < changes.length; ++j) { + var change = changes[j], m = (void 0); + newChanges.push({from: change.from, to: change.to, text: change.text}); + if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { + if (indexOf(newGroup, Number(m[1])) > -1) { + lst(newChanges)[prop] = change[prop]; + delete change[prop]; + } + } } } + } + } + return copy + } + + // The 'scroll' parameter given to many of these indicated whether + // the new cursor position should be scrolled into view after + // modifying the selection. + + // If shift is held or the extend flag is set, extends a range to + // include a given position (and optionally a second position). + // Otherwise, simply returns the range between the given positions. + // Used for cursor motion and such. + function extendRange(range, head, other, extend) { + if (extend) { + var anchor = range.anchor; + if (other) { + var posBefore = cmp(head, anchor) < 0; + if (posBefore != (cmp(other, anchor) < 0)) { + anchor = head; + head = other; + } else if (posBefore != (cmp(head, other) < 0)) { + head = other; + } + } + return new Range(anchor, head) + } else { + return new Range(other || head, head) + } + } + + // Extend the primary selection range, discard the rest. + function extendSelection(doc, head, other, options, extend) { + if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); } + setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options); + } + + // Extend all selections (pos is an array of selections with length + // equal the number of selections) + function extendSelections(doc, heads, options) { + var out = []; + var extend = doc.cm && (doc.cm.display.shift || doc.extend); + for (var i = 0; i < doc.sel.ranges.length; i++) + { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); } + var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex); + setSelection(doc, newSel, options); + } + + // Updates a single range in the selection. + function replaceOneSelection(doc, i, range, options) { + var ranges = doc.sel.ranges.slice(0); + ranges[i] = range; + setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options); + } + + // Reset the selection to a single range. + function setSimpleSelection(doc, anchor, head, options) { + setSelection(doc, simpleSelection(anchor, head), options); + } + + // Give beforeSelectionChange handlers a change to influence a + // selection update. + function filterSelectionChange(doc, sel, options) { + var obj = { + ranges: sel.ranges, + update: function(ranges) { + this.ranges = []; + for (var i = 0; i < ranges.length; i++) + { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), + clipPos(doc, ranges[i].head)); } + }, + origin: options && options.origin + }; + signal(doc, "beforeSelectionChange", doc, obj); + if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); } + if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) } + else { return sel } + } + + function setSelectionReplaceHistory(doc, sel, options) { + var done = doc.history.done, last = lst(done); + if (last && last.ranges) { + done[done.length - 1] = sel; + setSelectionNoUndo(doc, sel, options); + } else { + setSelection(doc, sel, options); + } + } + + // Set a new selection. + function setSelection(doc, sel, options) { + setSelectionNoUndo(doc, sel, options); + addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); + } + + function setSelectionNoUndo(doc, sel, options) { + if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) + { sel = filterSelectionChange(doc, sel, options); } + + var bias = options && options.bias || + (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); + setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); + + if (!(options && options.scroll === false) && doc.cm) + { ensureCursorVisible(doc.cm); } + } + + function setSelectionInner(doc, sel) { + if (sel.equals(doc.sel)) { return } + + doc.sel = sel; + + if (doc.cm) { + doc.cm.curOp.updateInput = 1; + doc.cm.curOp.selectionChanged = true; + signalCursorActivity(doc.cm); + } + signalLater(doc, "cursorActivity", doc); + } + + // Verify that the selection does not partially select any atomic + // marked ranges. + function reCheckSelection(doc) { + setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)); + } + + // Return a selection that does not partially select any atomic + // ranges. + function skipAtomicInSelection(doc, sel, bias, mayClear) { + var out; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; + var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); + var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear); + if (out || newAnchor != range.anchor || newHead != range.head) { + if (!out) { out = sel.ranges.slice(0, i); } + out[i] = new Range(newAnchor, newHead); + } + } + return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel + } + + function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { + var line = getLine(doc, pos.line); + if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { + var sp = line.markedSpans[i], m = sp.marker; + + // Determine if we should prevent the cursor being placed to the left/right of an atomic marker + // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it + // is with selectLeft/Right + var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; + var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; + + if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && + (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { + if (mayClear) { + signal(m, "beforeCursorEnter"); + if (m.explicitlyCleared) { + if (!line.markedSpans) { break } + else {--i; continue} + } + } + if (!m.atomic) { continue } + + if (oldPos) { + var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); + if (dir < 0 ? preventCursorRight : preventCursorLeft) + { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } + if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) + { return skipAtomicInner(doc, near, pos, dir, mayClear) } + } + + var far = m.find(dir < 0 ? -1 : 1); + if (dir < 0 ? preventCursorLeft : preventCursorRight) + { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } + return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null + } + } } + return pos + } + + // Ensure a given position is not inside an atomic range. + function skipAtomic(doc, pos, oldPos, bias, mayClear) { + var dir = bias || 1; + var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || + skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || + (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); + if (!found) { + doc.cantEdit = true; + return Pos(doc.first, 0) + } + return found + } + + function movePos(doc, pos, dir, line) { + if (dir < 0 && pos.ch == 0) { + if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } + else { return null } + } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { + if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } + else { return null } + } else { + return new Pos(pos.line, pos.ch + dir) + } + } + + function selectAll(cm) { + cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll); + } + + // UPDATING + + // Allow "beforeChange" event handlers to influence a change + function filterChange(doc, change, update) { + var obj = { + canceled: false, + from: change.from, + to: change.to, + text: change.text, + origin: change.origin, + cancel: function () { return obj.canceled = true; } + }; + if (update) { obj.update = function (from, to, text, origin) { + if (from) { obj.from = clipPos(doc, from); } + if (to) { obj.to = clipPos(doc, to); } + if (text) { obj.text = text; } + if (origin !== undefined) { obj.origin = origin; } + }; } + signal(doc, "beforeChange", doc, obj); + if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); } + + if (obj.canceled) { + if (doc.cm) { doc.cm.curOp.updateInput = 2; } + return null + } + return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} + } + + // Apply a change to a document, and add it to the document's + // history, and propagating it to all linked documents. + function makeChange(doc, change, ignoreReadOnly) { + if (doc.cm) { + if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } + if (doc.cm.state.suppressEdits) { return } + } + + if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { + change = filterChange(doc, change, true); + if (!change) { return } + } + + // Possibly split or suppress the update based on the presence + // of read-only spans in its range. + var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); + if (split) { + for (var i = split.length - 1; i >= 0; --i) + { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); } + } else { + makeChangeInner(doc, change); + } + } + + function makeChangeInner(doc, change) { + if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } + var selAfter = computeSelAfterChange(doc, change); + addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); + + makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); + var rebased = []; + + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); + }); + } + + // Revert a change stored in a document's history. + function makeChangeFromHistory(doc, type, allowSelectionOnly) { + var suppress = doc.cm && doc.cm.state.suppressEdits; + if (suppress && !allowSelectionOnly) { return } + + var hist = doc.history, event, selAfter = doc.sel; + var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; + + // Verify that there is a useable event (so that ctrl-z won't + // needlessly clear selection events) + var i = 0; + for (; i < source.length; i++) { + event = source[i]; + if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) + { break } + } + if (i == source.length) { return } + hist.lastOrigin = hist.lastSelOrigin = null; + + for (;;) { + event = source.pop(); + if (event.ranges) { + pushSelectionToHistory(event, dest); + if (allowSelectionOnly && !event.equals(doc.sel)) { + setSelection(doc, event, {clearRedo: false}); + return + } + selAfter = event; + } else if (suppress) { + source.push(event); + return + } else { break } + } + + // Build up a reverse change object to add to the opposite history + // stack (redo when undoing, and vice versa). + var antiChanges = []; + pushSelectionToHistory(selAfter, dest); + dest.push({changes: antiChanges, generation: hist.generation}); + hist.generation = event.generation || ++hist.maxGeneration; + + var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); + + var loop = function ( i ) { + var change = event.changes[i]; + change.origin = type; + if (filter && !filterChange(doc, change, false)) { + source.length = 0; + return {} + } + + antiChanges.push(historyChangeFromChange(doc, change)); + + var after = i ? computeSelAfterChange(doc, change) : lst(source); + makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); + if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); } + var rebased = []; + + // Propagate to the linked documents + linkedDocs(doc, function (doc, sharedHist) { + if (!sharedHist && indexOf(rebased, doc.history) == -1) { + rebaseHist(doc.history, change); + rebased.push(doc.history); + } + makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); + }); + }; + + for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { + var returned = loop( i$1 ); + + if ( returned ) return returned.v; + } + } + + // Sub-views need their line numbers shifted when text is added + // above or below them in the parent document. + function shiftDoc(doc, distance) { + if (distance == 0) { return } + doc.first += distance; + doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( + Pos(range.anchor.line + distance, range.anchor.ch), + Pos(range.head.line + distance, range.head.ch) + ); }), doc.sel.primIndex); + if (doc.cm) { + regChange(doc.cm, doc.first, doc.first - distance, distance); + for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) + { regLineChange(doc.cm, l, "gutter"); } + } + } + + // More lower-level change function, handling only a single document + // (not linked ones). + function makeChangeSingleDoc(doc, change, selAfter, spans) { + if (doc.cm && !doc.cm.curOp) + { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } + + if (change.to.line < doc.first) { + shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); + return + } + if (change.from.line > doc.lastLine()) { return } + + // Clip the change to the size of this doc + if (change.from.line < doc.first) { + var shift = change.text.length - 1 - (doc.first - change.from.line); + shiftDoc(doc, shift); + change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), + text: [lst(change.text)], origin: change.origin}; + } + var last = doc.lastLine(); + if (change.to.line > last) { + change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), + text: [change.text[0]], origin: change.origin}; + } + + change.removed = getBetween(doc, change.from, change.to); + + if (!selAfter) { selAfter = computeSelAfterChange(doc, change); } + if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); } + else { updateDoc(doc, change, spans); } + setSelectionNoUndo(doc, selAfter, sel_dontScroll); + + if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) + { doc.cantEdit = false; } + } + + // Handle the interaction of a change to a document with the editor + // that this document is part of. + function makeChangeSingleDocInEditor(cm, change, spans) { + var doc = cm.doc, display = cm.display, from = change.from, to = change.to; + + var recomputeMaxLength = false, checkWidthStart = from.line; + if (!cm.options.lineWrapping) { + checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); + doc.iter(checkWidthStart, to.line + 1, function (line) { + if (line == display.maxLine) { + recomputeMaxLength = true; + return true + } + }); + } + + if (doc.sel.contains(change.from, change.to) > -1) + { signalCursorActivity(cm); } + + updateDoc(doc, change, spans, estimateHeight(cm)); + + if (!cm.options.lineWrapping) { + doc.iter(checkWidthStart, from.line + change.text.length, function (line) { + var len = lineLength(line); + if (len > display.maxLineLength) { + display.maxLine = line; + display.maxLineLength = len; + display.maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; } + } + + retreatFrontier(doc, from.line); + startWorker(cm, 400); + + var lendiff = change.text.length - (to.line - from.line) - 1; + // Remember that these lines changed, for updating the display + if (change.full) + { regChange(cm); } + else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) + { regLineChange(cm, from.line, "text"); } + else + { regChange(cm, from.line, to.line + 1, lendiff); } + + var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); + if (changeHandler || changesHandler) { + var obj = { + from: from, to: to, + text: change.text, + removed: change.removed, + origin: change.origin + }; + if (changeHandler) { signalLater(cm, "change", cm, obj); } + if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); } + } + cm.display.selForContextMenu = null; + } + + function replaceRange(doc, code, from, to, origin) { + var assign; + + if (!to) { to = from; } + if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); } + if (typeof code == "string") { code = doc.splitLines(code); } + makeChange(doc, {from: from, to: to, text: code, origin: origin}); + } + + // Rebasing/resetting history to deal with externally-sourced changes + + function rebaseHistSelSingle(pos, from, to, diff) { + if (to < pos.line) { + pos.line += diff; + } else if (from < pos.line) { + pos.line = from; + pos.ch = 0; + } + } + + // Tries to rebase an array of history events given a change in the + // document. If the change touches the same lines as the event, the + // event, and everything 'behind' it, is discarded. If the change is + // before the event, the event's positions are updated. Uses a + // copy-on-write scheme for the positions, to avoid having to + // reallocate them all on every rebase, but also avoid problems with + // shared position objects being unsafely updated. + function rebaseHistArray(array, from, to, diff) { + for (var i = 0; i < array.length; ++i) { + var sub = array[i], ok = true; + if (sub.ranges) { + if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } + for (var j = 0; j < sub.ranges.length; j++) { + rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); + rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); + } + continue + } + for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { + var cur = sub.changes[j$1]; + if (to < cur.from.line) { + cur.from = Pos(cur.from.line + diff, cur.from.ch); + cur.to = Pos(cur.to.line + diff, cur.to.ch); + } else if (from <= cur.to.line) { + ok = false; + break + } + } + if (!ok) { + array.splice(0, i + 1); + i = 0; + } + } + } + + function rebaseHist(hist, change) { + var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; + rebaseHistArray(hist.done, from, to, diff); + rebaseHistArray(hist.undone, from, to, diff); + } + + // Utility for applying a change to a line by handle or number, + // returning the number and optionally registering the line as + // changed. + function changeLine(doc, handle, changeType, op) { + var no = handle, line = handle; + if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); } + else { no = lineNo(handle); } + if (no == null) { return null } + if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); } + return line + } + + // The document is represented as a BTree consisting of leaves, with + // chunk of lines in them, and branches, with up to ten leaves or + // other branch nodes below them. The top node is always a branch + // node, and is the document object itself (meaning it has + // additional methods and properties). + // + // All nodes have parent links. The tree is used both to go from + // line numbers to line objects, and to go from objects to numbers. + // It also indexes by height, and is used to convert between height + // and line object, and to find the total height of the document. + // + // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html + + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + var height = 0; + for (var i = 0; i < lines.length; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length }, + + // Remove the n lines at offset 'at'. + removeInner: function(at, n) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + cleanUpLine(line); + signalLater(line, "delete"); + } + this.lines.splice(at, n); + }, + + // Helper used to collapse a small branch into a single leaf. + collapse: function(lines) { + lines.push.apply(lines, this.lines); + }, + + // Insert the given array of lines at offset 'at', count them as + // having the given height. + insertInner: function(at, lines, height) { + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; } + }, + + // Used to iterate over a part of the tree. + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + { if (op(this.lines[at])) { return true } } + } + }; + + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0; i < children.length; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + + BranchChunk.prototype = { + chunkSize: function() { return this.size }, + + removeInner: function(at, n) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.removeInner(at, rm); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) { break } + at = 0; + } else { at -= sz; } + } + // If the result is smaller than 25 lines, ensure that it is a + // single leaf node. + if (this.size - n < 25 && + (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + + collapse: function(lines) { + for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); } + }, + + insertInner: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertInner(at, lines, height); + if (child.lines && child.lines.length > 50) { + // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. + // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. + var remaining = child.lines.length % 25 + 25; + for (var pos = remaining; pos < child.lines.length;) { + var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); + child.height -= leaf.height; + this.children.splice(++i, 0, leaf); + leaf.parent = this; + } + child.lines = child.lines.slice(0, remaining); + this.maybeSpill(); + } + break + } + at -= sz; + } + }, + + // When a node has grown, check whether it should be split. + maybeSpill: function() { + if (this.children.length <= 10) { return } + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10) + me.parent.maybeSpill(); + }, + + iterN: function(at, n, op) { + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) { return true } + if ((n -= used) == 0) { break } + at = 0; + } else { at -= sz; } + } + } + }; + + // Line widgets are block elements displayed above or below a line. + + var LineWidget = function(doc, node, options) { + if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) + { this[opt] = options[opt]; } } } + this.doc = doc; + this.node = node; + }; + + LineWidget.prototype.clear = function () { + var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); + if (no == null || !ws) { return } + for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } } + if (!ws.length) { line.widgets = null; } + var height = widgetHeight(this); + updateLineHeight(line, Math.max(0, line.height - height)); + if (cm) { + runInOp(cm, function () { + adjustScrollWhenAboveVisible(cm, line, -height); + regLineChange(cm, no, "widget"); + }); + signalLater(cm, "lineWidgetCleared", cm, this, no); + } + }; + + LineWidget.prototype.changed = function () { + var this$1 = this; + + var oldH = this.height, cm = this.doc.cm, line = this.line; + this.height = null; + var diff = widgetHeight(this) - oldH; + if (!diff) { return } + if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); } + if (cm) { + runInOp(cm, function () { + cm.curOp.forceUpdate = true; + adjustScrollWhenAboveVisible(cm, line, diff); + signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)); + }); + } + }; + eventMixin(LineWidget); + + function adjustScrollWhenAboveVisible(cm, line, diff) { + if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) + { addToScrollTop(cm, diff); } + } + + function addLineWidget(doc, handle, node, options) { + var widget = new LineWidget(doc, node, options); + var cm = doc.cm; + if (cm && widget.noHScroll) { cm.display.alignWidgets = true; } + changeLine(doc, handle, "widget", function (line) { + var widgets = line.widgets || (line.widgets = []); + if (widget.insertAt == null) { widgets.push(widget); } + else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); } + widget.line = line; + if (cm && !lineIsHidden(doc, line)) { + var aboveVisible = heightAtLine(line) < doc.scrollTop; + updateLineHeight(line, line.height + widgetHeight(widget)); + if (aboveVisible) { addToScrollTop(cm, widget.height); } + cm.curOp.forceUpdate = true; + } + return true + }); + if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); } + return widget + } + + // TEXTMARKERS + + // Created with markText and setBookmark methods. A TextMarker is a + // handle that can be used to clear or find a marked position in the + // document. Line objects hold arrays (markedSpans) containing + // {from, to, marker} object pointing to such marker objects, and + // indicating that such a marker is present on that line. Multiple + // lines may point to the same marker when it spans across lines. + // The spans will have null for their from/to properties when the + // marker continues beyond the start/end of the line. Markers have + // links back to the lines they currently touch. + + // Collapsed markers have unique ids, in order to be able to order + // them, which is needed for uniquely determining an outer marker + // when they overlap (they may nest, but not partially overlap). + var nextMarkerId = 0; + + var TextMarker = function(doc, type) { + this.lines = []; + this.type = type; + this.doc = doc; + this.id = ++nextMarkerId; + }; + + // Clear the marker. + TextMarker.prototype.clear = function () { + if (this.explicitlyCleared) { return } + var cm = this.doc.cm, withOp = cm && !cm.curOp; + if (withOp) { startOperation(cm); } + if (hasHandler(this, "clear")) { + var found = this.find(); + if (found) { signalLater(this, "clear", found.from, found.to); } + } + var min = null, max = null; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); } + else if (cm) { + if (span.to != null) { max = lineNo(line); } + if (span.from != null) { min = lineNo(line); } + } + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) + { updateLineHeight(line, textHeight(cm.display)); } + } + if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { + var visual = visualLine(this.lines[i$1]), len = lineLength(visual); + if (len > cm.display.maxLineLength) { + cm.display.maxLine = visual; + cm.display.maxLineLength = len; + cm.display.maxLineChanged = true; + } + } } + + if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); } + this.lines.length = 0; + this.explicitlyCleared = true; + if (this.atomic && this.doc.cantEdit) { + this.doc.cantEdit = false; + if (cm) { reCheckSelection(cm.doc); } + } + if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); } + if (withOp) { endOperation(cm); } + if (this.parent) { this.parent.clear(); } + }; + + // Find the position of the marker in the document. Returns a {from, + // to} object by default. Side can be passed to get a specific side + // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the + // Pos objects returned contain a line object, rather than a line + // number (used to prevent looking up the same line twice). + TextMarker.prototype.find = function (side, lineObj) { + if (side == null && this.type == "bookmark") { side = 1; } + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null) { + from = Pos(lineObj ? line : lineNo(line), span.from); + if (side == -1) { return from } + } + if (span.to != null) { + to = Pos(lineObj ? line : lineNo(line), span.to); + if (side == 1) { return to } + } + } + return from && {from: from, to: to} + }; + + // Signals that the marker's widget changed, and surrounding layout + // should be recomputed. + TextMarker.prototype.changed = function () { + var this$1 = this; + + var pos = this.find(-1, true), widget = this, cm = this.doc.cm; + if (!pos || !cm) { return } + runInOp(cm, function () { + var line = pos.line, lineN = lineNo(pos.line); + var view = findViewForLine(cm, lineN); + if (view) { + clearLineMeasurementCacheFor(view); + cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; + } + cm.curOp.updateMaxLine = true; + if (!lineIsHidden(widget.doc, line) && widget.height != null) { + var oldHeight = widget.height; + widget.height = null; + var dHeight = widgetHeight(widget) - oldHeight; + if (dHeight) + { updateLineHeight(line, line.height + dHeight); } + } + signalLater(cm, "markerChanged", cm, this$1); + }); + }; + + TextMarker.prototype.attachLine = function (line) { + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp; + if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) + { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); } + } + this.lines.push(line); + }; + + TextMarker.prototype.detachLine = function (line) { + this.lines.splice(indexOf(this.lines, line), 1); + if (!this.lines.length && this.doc.cm) { + var op = this.doc.cm.curOp + ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); + } + }; + eventMixin(TextMarker); + + // Create a marker, wire it up to the right lines, and + function markText(doc, from, to, options, type) { + // Shared markers (across linked documents) are handled separately + // (markTextShared will call out to this again, once per + // document). + if (options && options.shared) { return markTextShared(doc, from, to, options, type) } + // Ensure we are in an operation. + if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } + + var marker = new TextMarker(doc, type), diff = cmp(from, to); + if (options) { copyObj(options, marker, false); } + // Don't connect empty markers unless clearWhenEmpty is false + if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) + { return marker } + if (marker.replacedWith) { + // Showing up as a widget implies collapsed (widget replaces text) + marker.collapsed = true; + marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget"); + if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); } + if (options.insertLeft) { marker.widgetNode.insertLeft = true; } + } + if (marker.collapsed) { + if (conflictingCollapsedRange(doc, from.line, from, to, marker) || + from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) + { throw new Error("Inserting collapsed marker partially overlapping an existing one") } + seeCollapsedSpans(); + } + + if (marker.addToHistory) + { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); } + + var curLine = from.line, cm = doc.cm, updateMaxLine; + doc.iter(curLine, to.line + 1, function (line) { + if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) + { updateMaxLine = true; } + if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); } + addMarkedSpan(line, new MarkedSpan(marker, + curLine == from.line ? from.ch : null, + curLine == to.line ? to.ch : null)); + ++curLine; + }); + // lineIsHidden depends on the presence of the spans, so needs a second pass + if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { + if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); } + }); } + + if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); } + + if (marker.readOnly) { + seeReadOnlySpans(); + if (doc.history.done.length || doc.history.undone.length) + { doc.clearHistory(); } + } + if (marker.collapsed) { + marker.id = ++nextMarkerId; + marker.atomic = true; + } + if (cm) { + // Sync editor state + if (updateMaxLine) { cm.curOp.updateMaxLine = true; } + if (marker.collapsed) + { regChange(cm, from.line, to.line + 1); } + else if (marker.className || marker.startStyle || marker.endStyle || marker.css || + marker.attributes || marker.title) + { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } } + if (marker.atomic) { reCheckSelection(cm.doc); } + signalLater(cm, "markerAdded", cm, marker); + } + return marker + } + + // SHARED TEXTMARKERS + + // A shared marker spans multiple linked documents. It is + // implemented as a meta-marker-object controlling multiple normal + // markers. + var SharedTextMarker = function(markers, primary) { + this.markers = markers; + this.primary = primary; + for (var i = 0; i < markers.length; ++i) + { markers[i].parent = this; } + }; + + SharedTextMarker.prototype.clear = function () { + if (this.explicitlyCleared) { return } + this.explicitlyCleared = true; + for (var i = 0; i < this.markers.length; ++i) + { this.markers[i].clear(); } + signalLater(this, "clear"); + }; + + SharedTextMarker.prototype.find = function (side, lineObj) { + return this.primary.find(side, lineObj) + }; + eventMixin(SharedTextMarker); + + function markTextShared(doc, from, to, options, type) { + options = copyObj(options); + options.shared = false; + var markers = [markText(doc, from, to, options, type)], primary = markers[0]; + var widget = options.widgetNode; + linkedDocs(doc, function (doc) { + if (widget) { options.widgetNode = widget.cloneNode(true); } + markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); + for (var i = 0; i < doc.linked.length; ++i) + { if (doc.linked[i].isParent) { return } } + primary = lst(markers); + }); + return new SharedTextMarker(markers, primary) + } + + function findSharedMarkers(doc) { + return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) + } + + function copySharedMarkers(doc, markers) { + for (var i = 0; i < markers.length; i++) { + var marker = markers[i], pos = marker.find(); + var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); + if (cmp(mFrom, mTo)) { + var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); + marker.markers.push(subMark); + subMark.parent = marker; + } + } + } + + function detachSharedMarkers(markers) { + var loop = function ( i ) { + var marker = markers[i], linked = [marker.primary.doc]; + linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }); + for (var j = 0; j < marker.markers.length; j++) { + var subMarker = marker.markers[j]; + if (indexOf(linked, subMarker.doc) == -1) { + subMarker.parent = null; + marker.markers.splice(j--, 1); + } + } + }; + + for (var i = 0; i < markers.length; i++) loop( i ); + } + + var nextDocId = 0; + var Doc = function(text, mode, firstLine, lineSep, direction) { + if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } + if (firstLine == null) { firstLine = 0; } + + BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); + this.first = firstLine; + this.scrollTop = this.scrollLeft = 0; + this.cantEdit = false; + this.cleanGeneration = 1; + this.modeFrontier = this.highlightFrontier = firstLine; + var start = Pos(firstLine, 0); + this.sel = simpleSelection(start); + this.history = new History(null); + this.id = ++nextDocId; + this.modeOption = mode; + this.lineSep = lineSep; + this.direction = (direction == "rtl") ? "rtl" : "ltr"; + this.extend = false; + + if (typeof text == "string") { text = this.splitLines(text); } + updateDoc(this, {from: start, to: start, text: text}); + setSelection(this, simpleSelection(start), sel_dontScroll); + }; + + Doc.prototype = createObj(BranchChunk.prototype, { + constructor: Doc, + // Iterate over the document. Supports two forms -- with only one + // argument, it calls that for each line in the document. With + // three, it iterates over the range given by the first two (with + // the second being non-inclusive). + iter: function(from, to, op) { + if (op) { this.iterN(from - this.first, to - from, op); } + else { this.iterN(this.first, this.first + this.size, from); } + }, + + // Non-public interface for adding and removing lines. + insert: function(at, lines) { + var height = 0; + for (var i = 0; i < lines.length; ++i) { height += lines[i].height; } + this.insertInner(at - this.first, lines, height); + }, + remove: function(at, n) { this.removeInner(at - this.first, n); }, + + // From here, the methods are part of the public interface. Most + // are also available from CodeMirror (editor) instances. + + getValue: function(lineSep) { + var lines = getLines(this, this.first, this.first + this.size); + if (lineSep === false) { return lines } + return lines.join(lineSep || this.lineSeparator()) + }, + setValue: docMethodOp(function(code) { + var top = Pos(this.first, 0), last = this.first + this.size - 1; + makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), + text: this.splitLines(code), origin: "setValue", full: true}, true); + if (this.cm) { scrollToCoords(this.cm, 0, 0); } + setSelection(this, simpleSelection(top), sel_dontScroll); + }), + replaceRange: function(code, from, to, origin) { + from = clipPos(this, from); + to = to ? clipPos(this, to) : from; + replaceRange(this, code, from, to, origin); + }, + getRange: function(from, to, lineSep) { + var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); + if (lineSep === false) { return lines } + return lines.join(lineSep || this.lineSeparator()) + }, + + getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, + + getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, + getLineNumber: function(line) {return lineNo(line)}, + + getLineHandleVisualStart: function(line) { + if (typeof line == "number") { line = getLine(this, line); } + return visualLine(line) + }, + + lineCount: function() {return this.size}, + firstLine: function() {return this.first}, + lastLine: function() {return this.first + this.size - 1}, + + clipPos: function(pos) {return clipPos(this, pos)}, + + getCursor: function(start) { + var range = this.sel.primary(), pos; + if (start == null || start == "head") { pos = range.head; } + else if (start == "anchor") { pos = range.anchor; } + else if (start == "end" || start == "to" || start === false) { pos = range.to(); } + else { pos = range.from(); } + return pos + }, + listSelections: function() { return this.sel.ranges }, + somethingSelected: function() {return this.sel.somethingSelected()}, + + setCursor: docMethodOp(function(line, ch, options) { + setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); + }), + setSelection: docMethodOp(function(anchor, head, options) { + setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); + }), + extendSelection: docMethodOp(function(head, other, options) { + extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); + }), + extendSelections: docMethodOp(function(heads, options) { + extendSelections(this, clipPosArray(this, heads), options); + }), + extendSelectionsBy: docMethodOp(function(f, options) { + var heads = map(this.sel.ranges, f); + extendSelections(this, clipPosArray(this, heads), options); + }), + setSelections: docMethodOp(function(ranges, primary, options) { + if (!ranges.length) { return } + var out = []; + for (var i = 0; i < ranges.length; i++) + { out[i] = new Range(clipPos(this, ranges[i].anchor), + clipPos(this, ranges[i].head)); } + if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); } + setSelection(this, normalizeSelection(this.cm, out, primary), options); + }), + addSelection: docMethodOp(function(anchor, head, options) { + var ranges = this.sel.ranges.slice(0); + ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); + setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options); + }), + + getSelection: function(lineSep) { + var ranges = this.sel.ranges, lines; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + lines = lines ? lines.concat(sel) : sel; + } + if (lineSep === false) { return lines } + else { return lines.join(lineSep || this.lineSeparator()) } + }, + getSelections: function(lineSep) { + var parts = [], ranges = this.sel.ranges; + for (var i = 0; i < ranges.length; i++) { + var sel = getBetween(this, ranges[i].from(), ranges[i].to()); + if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); } + parts[i] = sel; + } + return parts + }, + replaceSelection: function(code, collapse, origin) { + var dup = []; + for (var i = 0; i < this.sel.ranges.length; i++) + { dup[i] = code; } + this.replaceSelections(dup, collapse, origin || "+input"); + }, + replaceSelections: docMethodOp(function(code, collapse, origin) { + var changes = [], sel = this.sel; + for (var i = 0; i < sel.ranges.length; i++) { + var range = sel.ranges[i]; + changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; + } + var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); + for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) + { makeChange(this, changes[i$1]); } + if (newSel) { setSelectionReplaceHistory(this, newSel); } + else if (this.cm) { ensureCursorVisible(this.cm); } + }), + undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), + redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), + undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), + redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), + + setExtending: function(val) {this.extend = val;}, + getExtending: function() {return this.extend}, + + historySize: function() { + var hist = this.history, done = 0, undone = 0; + for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } } + for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } } + return {undo: done, redo: undone} + }, + clearHistory: function() { + var this$1 = this; + + this.history = new History(this.history.maxGeneration); + linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true); + }, + + markClean: function() { + this.cleanGeneration = this.changeGeneration(true); + }, + changeGeneration: function(forceSplit) { + if (forceSplit) + { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; } + return this.history.generation + }, + isClean: function (gen) { + return this.history.generation == (gen || this.cleanGeneration) + }, + + getHistory: function() { + return {done: copyHistoryArray(this.history.done), + undone: copyHistoryArray(this.history.undone)} + }, + setHistory: function(histData) { + var hist = this.history = new History(this.history.maxGeneration); + hist.done = copyHistoryArray(histData.done.slice(0), null, true); + hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); + }, + + setGutterMarker: docMethodOp(function(line, gutterID, value) { + return changeLine(this, line, "gutter", function (line) { + var markers = line.gutterMarkers || (line.gutterMarkers = {}); + markers[gutterID] = value; + if (!value && isEmpty(markers)) { line.gutterMarkers = null; } + return true + }) + }), + + clearGutter: docMethodOp(function(gutterID) { + var this$1 = this; + + this.iter(function (line) { + if (line.gutterMarkers && line.gutterMarkers[gutterID]) { + changeLine(this$1, line, "gutter", function () { + line.gutterMarkers[gutterID] = null; + if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; } + return true + }); + } + }); + }), + + lineInfo: function(line) { + var n; + if (typeof line == "number") { + if (!isLine(this, line)) { return null } + n = line; + line = getLine(this, line); + if (!line) { return null } + } else { + n = lineNo(line); + if (n == null) { return null } + } + return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, + textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, + widgets: line.widgets} + }, + + addLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + if (!line[prop]) { line[prop] = cls; } + else if (classTest(cls).test(line[prop])) { return false } + else { line[prop] += " " + cls; } + return true + }) + }), + removeLineClass: docMethodOp(function(handle, where, cls) { + return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { + var prop = where == "text" ? "textClass" + : where == "background" ? "bgClass" + : where == "gutter" ? "gutterClass" : "wrapClass"; + var cur = line[prop]; + if (!cur) { return false } + else if (cls == null) { line[prop] = null; } + else { + var found = cur.match(classTest(cls)); + if (!found) { return false } + var end = found.index + found[0].length; + line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; + } + return true + }) + }), + + addLineWidget: docMethodOp(function(handle, node, options) { + return addLineWidget(this, handle, node, options) + }), + removeLineWidget: function(widget) { widget.clear(); }, + + markText: function(from, to, options) { + return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") + }, + setBookmark: function(pos, options) { + var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), + insertLeft: options && options.insertLeft, + clearWhenEmpty: false, shared: options && options.shared, + handleMouseEvents: options && options.handleMouseEvents}; + pos = clipPos(this, pos); + return markText(this, pos, pos, realOpts, "bookmark") + }, + findMarksAt: function(pos) { + pos = clipPos(this, pos); + var markers = [], spans = getLine(this, pos.line).markedSpans; + if (spans) { for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + { markers.push(span.marker.parent || span.marker); } + } } + return markers + }, + findMarks: function(from, to, filter) { + from = clipPos(this, from); to = clipPos(this, to); + var found = [], lineNo = from.line; + this.iter(from.line, to.line + 1, function (line) { + var spans = line.markedSpans; + if (spans) { for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + if (!(span.to != null && lineNo == from.line && from.ch >= span.to || + span.from == null && lineNo != from.line || + span.from != null && lineNo == to.line && span.from >= to.ch) && + (!filter || filter(span.marker))) + { found.push(span.marker.parent || span.marker); } + } } + ++lineNo; + }); + return found + }, + getAllMarks: function() { + var markers = []; + this.iter(function (line) { + var sps = line.markedSpans; + if (sps) { for (var i = 0; i < sps.length; ++i) + { if (sps[i].from != null) { markers.push(sps[i].marker); } } } + }); + return markers + }, + + posFromIndex: function(off) { + var ch, lineNo = this.first, sepSize = this.lineSeparator().length; + this.iter(function (line) { + var sz = line.text.length + sepSize; + if (sz > off) { ch = off; return true } + off -= sz; + ++lineNo; + }); + return clipPos(this, Pos(lineNo, ch)) + }, + indexFromPos: function (coords) { + coords = clipPos(this, coords); + var index = coords.ch; + if (coords.line < this.first || coords.ch < 0) { return 0 } + var sepSize = this.lineSeparator().length; + this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value + index += line.text.length + sepSize; + }); + return index + }, + + copy: function(copyHistory) { + var doc = new Doc(getLines(this, this.first, this.first + this.size), + this.modeOption, this.first, this.lineSep, this.direction); + doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; + doc.sel = this.sel; + doc.extend = false; + if (copyHistory) { + doc.history.undoDepth = this.history.undoDepth; + doc.setHistory(this.getHistory()); + } + return doc + }, + + linkedDoc: function(options) { + if (!options) { options = {}; } + var from = this.first, to = this.first + this.size; + if (options.from != null && options.from > from) { from = options.from; } + if (options.to != null && options.to < to) { to = options.to; } + var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction); + if (options.sharedHist) { copy.history = this.history + ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); + copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; + copySharedMarkers(copy, findSharedMarkers(this)); + return copy + }, + unlinkDoc: function(other) { + if (other instanceof CodeMirror) { other = other.doc; } + if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { + var link = this.linked[i]; + if (link.doc != other) { continue } + this.linked.splice(i, 1); + other.unlinkDoc(this); + detachSharedMarkers(findSharedMarkers(this)); + break + } } + // If the histories were shared, split them again + if (other.history == this.history) { + var splitIds = [other.id]; + linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true); + other.history = new History(null); + other.history.done = copyHistoryArray(this.history.done, splitIds); + other.history.undone = copyHistoryArray(this.history.undone, splitIds); + } + }, + iterLinkedDocs: function(f) {linkedDocs(this, f);}, + + getMode: function() {return this.mode}, + getEditor: function() {return this.cm}, + + splitLines: function(str) { + if (this.lineSep) { return str.split(this.lineSep) } + return splitLinesAuto(str) + }, + lineSeparator: function() { return this.lineSep || "\n" }, + + setDirection: docMethodOp(function (dir) { + if (dir != "rtl") { dir = "ltr"; } + if (dir == this.direction) { return } + this.direction = dir; + this.iter(function (line) { return line.order = null; }); + if (this.cm) { directionChanged(this.cm); } + }) + }); + + // Public alias. + Doc.prototype.eachLine = Doc.prototype.iter; + + // Kludge to work around strange IE behavior where it'll sometimes + // re-fire a series of drag-related events right after the drop (#1551) + var lastDrop = 0; + + function onDrop(e) { + var cm = this; + clearDragCursor(cm); + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) + { return } + e_preventDefault(e); + if (ie) { lastDrop = +new Date; } + var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; + if (!pos || cm.isReadOnly()) { return } + // Might be a file drop, in which case we simply extract the text + // and insert it. + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var markAsReadAndPasteIfAllFilesAreRead = function () { + if (++read == n) { + operation(cm, function () { + pos = clipPos(cm.doc, pos); + var change = {from: pos, to: pos, + text: cm.doc.splitLines( + text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())), + origin: "paste"}; + makeChange(cm.doc, change); + setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change)))); + })(); + } + }; + var readTextFromFile = function (file, i) { + if (cm.options.allowDropFileTypes && + indexOf(cm.options.allowDropFileTypes, file.type) == -1) { + markAsReadAndPasteIfAllFilesAreRead(); + return + } + var reader = new FileReader; + reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); }; + reader.onload = function () { + var content = reader.result; + if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { + markAsReadAndPasteIfAllFilesAreRead(); + return + } + text[i] = content; + markAsReadAndPasteIfAllFilesAreRead(); + }; + reader.readAsText(file); + }; + for (var i = 0; i < files.length; i++) { readTextFromFile(files[i], i); } + } else { // Normal drop + // Don't do a replace if the drop happened inside of the selected text. + if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { + cm.state.draggingText(e); + // Ensure the editor is re-focused + setTimeout(function () { return cm.display.input.focus(); }, 20); + return + } + try { + var text$1 = e.dataTransfer.getData("Text"); + if (text$1) { + var selected; + if (cm.state.draggingText && !cm.state.draggingText.copy) + { selected = cm.listSelections(); } + setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); + if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) + { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } } + cm.replaceSelection(text$1, "around", "paste"); + cm.display.input.focus(); + } + } + catch(e$1){} + } + } + + function onDragStart(cm, e) { + if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } + if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } + + e.dataTransfer.setData("Text", cm.getSelection()); + e.dataTransfer.effectAllowed = "copyMove"; + + // Use dummy image instead of default browsers image. + // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. + if (e.dataTransfer.setDragImage && !safari) { + var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); + img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; + if (presto) { + img.width = img.height = 1; + cm.display.wrapper.appendChild(img); + // Force a relayout, or Opera won't use our image for some obscure reason + img._top = img.offsetTop; + } + e.dataTransfer.setDragImage(img, 0, 0); + if (presto) { img.parentNode.removeChild(img); } + } + } + + function onDragOver(cm, e) { + var pos = posFromMouse(cm, e); + if (!pos) { return } + var frag = document.createDocumentFragment(); + drawSelectionCursor(cm, pos, frag); + if (!cm.display.dragCursor) { + cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); + cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); + } + removeChildrenAndAdd(cm.display.dragCursor, frag); + } + + function clearDragCursor(cm) { + if (cm.display.dragCursor) { + cm.display.lineSpace.removeChild(cm.display.dragCursor); + cm.display.dragCursor = null; + } + } + + // These must be handled carefully, because naively registering a + // handler for each editor will cause the editors to never be + // garbage collected. + + function forEachCodeMirror(f) { + if (!document.getElementsByClassName) { return } + var byClass = document.getElementsByClassName("CodeMirror"), editors = []; + for (var i = 0; i < byClass.length; i++) { + var cm = byClass[i].CodeMirror; + if (cm) { editors.push(cm); } + } + if (editors.length) { editors[0].operation(function () { + for (var i = 0; i < editors.length; i++) { f(editors[i]); } + }); } + } + + var globalsRegistered = false; + function ensureGlobalHandlers() { + if (globalsRegistered) { return } + registerGlobalHandlers(); + globalsRegistered = true; + } + function registerGlobalHandlers() { + // When the window resizes, we need to refresh active editors. + var resizeTimer; + on(window, "resize", function () { + if (resizeTimer == null) { resizeTimer = setTimeout(function () { + resizeTimer = null; + forEachCodeMirror(onResize); + }, 100); } + }); + // When the window loses focus, we want to show the editor as blurred + on(window, "blur", function () { return forEachCodeMirror(onBlur); }); + } + // Called when the window resizes + function onResize(cm) { + var d = cm.display; + // Might be a text scaling operation, clear size caches. + d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; + d.scrollbarsClipped = false; + cm.setSize(); + } + + var keyNames = { + 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", + 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock", + 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", + 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" + }; + + // Number keys + for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); } + // Alphabetic keys + for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); } + // Function keys + for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; } + + var keyMap = {}; + + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", + "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", + "Esc": "singleSelection" + }; + // Note that the save and find-related commands aren't defined by + // default. User code or addons can define them. Unknown commands + // are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", + "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", + "fallthrough": "basic" + }; + // Very basic readline/emacs-style bindings, which are standard on Mac. + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", + "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", + "Ctrl-O": "openLine" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", + "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", + "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", + "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", + "fallthrough": ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + + // KEYMAP DISPATCH + + function normalizeKeyName(name) { + var parts = name.split(/-(?!$)/); + name = parts[parts.length - 1]; + var alt, ctrl, shift, cmd; + for (var i = 0; i < parts.length - 1; i++) { + var mod = parts[i]; + if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } + else if (/^a(lt)?$/i.test(mod)) { alt = true; } + else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } + else if (/^s(hift)?$/i.test(mod)) { shift = true; } + else { throw new Error("Unrecognized modifier name: " + mod) } + } + if (alt) { name = "Alt-" + name; } + if (ctrl) { name = "Ctrl-" + name; } + if (cmd) { name = "Cmd-" + name; } + if (shift) { name = "Shift-" + name; } + return name + } + + // This is a kludge to keep keymaps mostly working as raw objects + // (backwards compatibility) while at the same time support features + // like normalization and multi-stroke key bindings. It compiles a + // new normalized keymap, and then updates the old object to reflect + // this. + function normalizeKeyMap(keymap) { + var copy = {}; + for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { + var value = keymap[keyname]; + if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } + if (value == "...") { delete keymap[keyname]; continue } + + var keys = map(keyname.split(" "), normalizeKeyName); + for (var i = 0; i < keys.length; i++) { + var val = (void 0), name = (void 0); + if (i == keys.length - 1) { + name = keys.join(" "); + val = value; + } else { + name = keys.slice(0, i + 1).join(" "); + val = "..."; + } + var prev = copy[name]; + if (!prev) { copy[name] = val; } + else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } + } + delete keymap[keyname]; + } } + for (var prop in copy) { keymap[prop] = copy[prop]; } + return keymap + } + + function lookupKey(key, map, handle, context) { + map = getKeyMap(map); + var found = map.call ? map.call(key, context) : map[key]; + if (found === false) { return "nothing" } + if (found === "...") { return "multi" } + if (found != null && handle(found)) { return "handled" } + + if (map.fallthrough) { + if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") + { return lookupKey(key, map.fallthrough, handle, context) } + for (var i = 0; i < map.fallthrough.length; i++) { + var result = lookupKey(key, map.fallthrough[i], handle, context); + if (result) { return result } + } + } + } + + // Modifier key presses don't count as 'real' key presses for the + // purpose of keymap fallthrough. + function isModifierKey(value) { + var name = typeof value == "string" ? value : keyNames[value.keyCode]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" + } + + function addModifierNames(name, event, noShift) { + var base = name; + if (event.altKey && base != "Alt") { name = "Alt-" + name; } + if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; } + if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; } + if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; } + return name + } + + // Look up the name of a key as indicated by an event object. + function keyName(event, noShift) { + if (presto && event.keyCode == 34 && event["char"]) { return false } + var name = keyNames[event.keyCode]; + if (name == null || event.altGraphKey) { return false } + // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, + // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) + if (event.keyCode == 3 && event.code) { name = event.code; } + return addModifierNames(name, event, noShift) + } + + function getKeyMap(val) { + return typeof val == "string" ? keyMap[val] : val + } + + // Helper for deleting text near the selection(s), used to implement + // backspace, delete, and similar functionality. + function deleteNearSelection(cm, compute) { + var ranges = cm.doc.sel.ranges, kill = []; + // Build up a set of ranges to kill first, merging overlapping + // ranges. + for (var i = 0; i < ranges.length; i++) { + var toKill = compute(ranges[i]); + while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { + var replaced = kill.pop(); + if (cmp(replaced.from, toKill.from) < 0) { + toKill.from = replaced.from; + break + } + } + kill.push(toKill); + } + // Next, remove those actual ranges. + runInOp(cm, function () { + for (var i = kill.length - 1; i >= 0; i--) + { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); } + ensureCursorVisible(cm); + }); + } + + function moveCharLogically(line, ch, dir) { + var target = skipExtendingChars(line.text, ch + dir, dir); + return target < 0 || target > line.text.length ? null : target + } + + function moveLogically(line, start, dir) { + var ch = moveCharLogically(line, start.ch, dir); + return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") + } + + function endOfLine(visually, cm, lineObj, lineNo, dir) { + if (visually) { + if (cm.doc.direction == "rtl") { dir = -dir; } + var order = getOrder(lineObj, cm.doc.direction); + if (order) { + var part = dir < 0 ? lst(order) : order[0]; + var moveInStorageOrder = (dir < 0) == (part.level == 1); + var sticky = moveInStorageOrder ? "after" : "before"; + var ch; + // With a wrapped rtl chunk (possibly spanning multiple bidi parts), + // it could be that the last bidi part is not on the last visual line, + // since visual lines contain content order-consecutive chunks. + // Thus, in rtl, we are looking for the first (content-order) character + // in the rtl chunk that is on the last line (that is, the same line + // as the last (content-order) character). + if (part.level > 0 || cm.doc.direction == "rtl") { + var prep = prepareMeasureForLine(cm, lineObj); + ch = dir < 0 ? lineObj.text.length - 1 : 0; + var targetTop = measureCharPrepared(cm, prep, ch).top; + ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch); + if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); } + } else { ch = dir < 0 ? part.to : part.from; } + return new Pos(lineNo, ch, sticky) + } + } + return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") + } + + function moveVisually(cm, line, start, dir) { + var bidi = getOrder(line, cm.doc.direction); + if (!bidi) { return moveLogically(line, start, dir) } + if (start.ch >= line.text.length) { + start.ch = line.text.length; + start.sticky = "before"; + } else if (start.ch <= 0) { + start.ch = 0; + start.sticky = "after"; + } + var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos]; + if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { + // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, + // nothing interesting happens. + return moveLogically(line, start, dir) + } + + var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); }; + var prep; + var getWrappedLineExtent = function (ch) { + if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } + prep = prep || prepareMeasureForLine(cm, line); + return wrappedLineExtentChar(cm, line, prep, ch) + }; + var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch); + + if (cm.doc.direction == "rtl" || part.level == 1) { + var moveInStorageOrder = (part.level == 1) == (dir < 0); + var ch = mv(start, moveInStorageOrder ? 1 : -1); + if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { + // Case 2: We move within an rtl part or in an rtl editor on the same visual line + var sticky = moveInStorageOrder ? "before" : "after"; + return new Pos(start.line, ch, sticky) + } + } + + // Case 3: Could not move within this bidi part in this visual line, so leave + // the current bidi part + + var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { + var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder + ? new Pos(start.line, mv(ch, 1), "before") + : new Pos(start.line, ch, "after"); }; + + for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { + var part = bidi[partPos]; + var moveInStorageOrder = (dir > 0) == (part.level != 1); + var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1); + if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } + ch = moveInStorageOrder ? part.from : mv(part.to, -1); + if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } + } + }; + + // Case 3a: Look for other bidi parts on the same visual line + var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent); + if (res) { return res } + + // Case 3b: Look for other bidi parts on the next visual line + var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1); + if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { + res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)); + if (res) { return res } + } + + // Case 4: Nowhere to move + return null + } + + // Commands are parameter-less actions that can be performed on an + // editor, mostly used for keybindings. + var commands = { + selectAll: selectAll, + singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, + killLine: function (cm) { return deleteNearSelection(cm, function (range) { + if (range.empty()) { + var len = getLine(cm.doc, range.head.line).text.length; + if (range.head.ch == len && range.head.line < cm.lastLine()) + { return {from: range.head, to: Pos(range.head.line + 1, 0)} } + else + { return {from: range.head, to: Pos(range.head.line, len)} } + } else { + return {from: range.from(), to: range.to()} + } + }); }, + deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), + to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) + }); }); }, + delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ + from: Pos(range.from().line, 0), to: range.from() + }); }); }, + delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var leftPos = cm.coordsChar({left: 0, top: top}, "div"); + return {from: leftPos, to: range.from()} + }); }, + delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { + var top = cm.charCoords(range.head, "div").top + 5; + var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); + return {from: range.from(), to: rightPos } + }); }, + undo: function (cm) { return cm.undo(); }, + redo: function (cm) { return cm.redo(); }, + undoSelection: function (cm) { return cm.undoSelection(); }, + redoSelection: function (cm) { return cm.redoSelection(); }, + goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, + goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, + goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, + {origin: "+move", bias: 1} + ); }, + goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, + {origin: "+move", bias: 1} + ); }, + goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, + {origin: "+move", bias: -1} + ); }, + goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") + }, sel_move); }, + goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + return cm.coordsChar({left: 0, top: top}, "div") + }, sel_move); }, + goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { + var top = cm.cursorCoords(range.head, "div").top + 5; + var pos = cm.coordsChar({left: 0, top: top}, "div"); + if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } + return pos + }, sel_move); }, + goLineUp: function (cm) { return cm.moveV(-1, "line"); }, + goLineDown: function (cm) { return cm.moveV(1, "line"); }, + goPageUp: function (cm) { return cm.moveV(-1, "page"); }, + goPageDown: function (cm) { return cm.moveV(1, "page"); }, + goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, + goCharRight: function (cm) { return cm.moveH(1, "char"); }, + goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, + goColumnRight: function (cm) { return cm.moveH(1, "column"); }, + goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, + goGroupRight: function (cm) { return cm.moveH(1, "group"); }, + goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, + goWordRight: function (cm) { return cm.moveH(1, "word"); }, + delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); }, + delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, + delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, + delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, + delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, + delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, + indentAuto: function (cm) { return cm.indentSelection("smart"); }, + indentMore: function (cm) { return cm.indentSelection("add"); }, + indentLess: function (cm) { return cm.indentSelection("subtract"); }, + insertTab: function (cm) { return cm.replaceSelection("\t"); }, + insertSoftTab: function (cm) { + var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; + for (var i = 0; i < ranges.length; i++) { + var pos = ranges[i].from(); + var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); + spaces.push(spaceStr(tabSize - col % tabSize)); + } + cm.replaceSelections(spaces); + }, + defaultTab: function (cm) { + if (cm.somethingSelected()) { cm.indentSelection("add"); } + else { cm.execCommand("insertTab"); } + }, + // Swap the two chars left and right of each selection's head. + // Move cursor behind the two swapped characters afterwards. + // + // Doesn't consider line feeds a character. + // Doesn't scan more than one line above to find a character. + // Doesn't do anything on an empty line. + // Doesn't do anything with non-empty selections. + transposeChars: function (cm) { return runInOp(cm, function () { + var ranges = cm.listSelections(), newSel = []; + for (var i = 0; i < ranges.length; i++) { + if (!ranges[i].empty()) { continue } + var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; + if (line) { + if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); } + if (cur.ch > 0) { + cur = new Pos(cur.line, cur.ch + 1); + cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), + Pos(cur.line, cur.ch - 2), cur, "+transpose"); + } else if (cur.line > cm.doc.first) { + var prev = getLine(cm.doc, cur.line - 1).text; + if (prev) { + cur = new Pos(cur.line, 1); + cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + + prev.charAt(prev.length - 1), + Pos(cur.line - 1, prev.length - 1), cur, "+transpose"); + } + } + } + newSel.push(new Range(cur, cur)); + } + cm.setSelections(newSel); + }); }, + newlineAndIndent: function (cm) { return runInOp(cm, function () { + var sels = cm.listSelections(); + for (var i = sels.length - 1; i >= 0; i--) + { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); } + sels = cm.listSelections(); + for (var i$1 = 0; i$1 < sels.length; i$1++) + { cm.indentLine(sels[i$1].from().line, null, true); } + ensureCursorVisible(cm); + }); }, + openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, + toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } + }; + + + function lineStart(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLine(line); + if (visual != line) { lineN = lineNo(visual); } + return endOfLine(true, cm, visual, lineN, 1) + } + function lineEnd(cm, lineN) { + var line = getLine(cm.doc, lineN); + var visual = visualLineEnd(line); + if (visual != line) { lineN = lineNo(visual); } + return endOfLine(true, cm, line, lineN, -1) + } + function lineStartSmart(cm, pos) { + var start = lineStart(cm, pos.line); + var line = getLine(cm.doc, start.line); + var order = getOrder(line, cm.doc.direction); + if (!order || order[0].level == 0) { + var firstNonWS = Math.max(start.ch, line.text.search(/\S/)); + var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; + return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) + } + return start + } + + // Run a handler that was bound to a key. + function doHandleBinding(cm, bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) { return false } + } + // Ensure previous input has been read, so that the handler sees a + // consistent view of the document + cm.display.input.ensurePolled(); + var prevShift = cm.display.shift, done = false; + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true; } + if (dropShift) { cm.display.shift = false; } + done = bound(cm) != Pass; + } finally { + cm.display.shift = prevShift; + cm.state.suppressEdits = false; + } + return done + } + + function lookupKeyForEditor(cm, name, handle) { + for (var i = 0; i < cm.state.keyMaps.length; i++) { + var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); + if (result) { return result } + } + return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) + || lookupKey(name, cm.options.keyMap, handle, cm) + } + + // Note that, despite the name, this function is also used to check + // for bound mouse clicks. + + var stopSeq = new Delayed; + + function dispatchKey(cm, name, e, handle) { + var seq = cm.state.keySeq; + if (seq) { + if (isModifierKey(name)) { return "handled" } + if (/\'$/.test(name)) + { cm.state.keySeq = null; } + else + { stopSeq.set(50, function () { + if (cm.state.keySeq == seq) { + cm.state.keySeq = null; + cm.display.input.reset(); + } + }); } + if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true } + } + return dispatchKeyInner(cm, name, e, handle) + } + + function dispatchKeyInner(cm, name, e, handle) { + var result = lookupKeyForEditor(cm, name, handle); + + if (result == "multi") + { cm.state.keySeq = name; } + if (result == "handled") + { signalLater(cm, "keyHandled", cm, name, e); } + + if (result == "handled" || result == "multi") { + e_preventDefault(e); + restartBlink(cm); + } + + return !!result + } + + // Handle a key from the keydown event. + function handleKeyBinding(cm, e) { + var name = keyName(e, true); + if (!name) { return false } + + if (e.shiftKey && !cm.state.keySeq) { + // First try to resolve full name (including 'Shift-'). Failing + // that, see if there is a cursor-motion command (starting with + // 'go') bound to the keyname without 'Shift-'. + return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) + || dispatchKey(cm, name, e, function (b) { + if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) + { return doHandleBinding(cm, b) } + }) + } else { + return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) + } + } + + // Handle a key from the keypress event + function handleCharBinding(cm, e, ch) { + return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) + } + + var lastStoppedKey = null; + function onKeyDown(e) { + var cm = this; + if (e.target && e.target != cm.display.input.getField()) { return } + cm.curOp.focus = activeElt(); + if (signalDOMEvent(cm, e)) { return } + // IE does strange things with escape. + if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; } + var code = e.keyCode; + cm.display.shift = code == 16 || e.shiftKey; + var handled = handleKeyBinding(cm, e); + if (presto) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) + { cm.replaceSelection("", null, "cut"); } + } + if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand) + { document.execCommand("cut"); } + + // Turn mouse into crosshair when Alt is held on Mac. + if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) + { showCrossHair(cm); } + } + + function showCrossHair(cm) { + var lineDiv = cm.display.lineDiv; + addClass(lineDiv, "CodeMirror-crosshair"); + + function up(e) { + if (e.keyCode == 18 || !e.altKey) { + rmClass(lineDiv, "CodeMirror-crosshair"); + off(document, "keyup", up); + off(document, "mouseover", up); + } + } + on(document, "keyup", up); + on(document, "mouseover", up); + } + + function onKeyUp(e) { + if (e.keyCode == 16) { this.doc.sel.shift = false; } + signalDOMEvent(this, e); + } + + function onKeyPress(e) { + var cm = this; + if (e.target && e.target != cm.display.input.getField()) { return } + if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } + var keyCode = e.keyCode, charCode = e.charCode; + if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} + if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + // Some browsers fire keypress events for backspace + if (ch == "\x08") { return } + if (handleCharBinding(cm, e, ch)) { return } + cm.display.input.onKeyPress(e); + } + + var DOUBLECLICK_DELAY = 400; + + var PastClick = function(time, pos, button) { + this.time = time; + this.pos = pos; + this.button = button; + }; + + PastClick.prototype.compare = function (time, pos, button) { + return this.time + DOUBLECLICK_DELAY > time && + cmp(pos, this.pos) == 0 && button == this.button + }; + + var lastClick, lastDoubleClick; + function clickRepeat(pos, button) { + var now = +new Date; + if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { + lastClick = lastDoubleClick = null; + return "triple" + } else if (lastClick && lastClick.compare(now, pos, button)) { + lastDoubleClick = new PastClick(now, pos, button); + lastClick = null; + return "double" + } else { + lastClick = new PastClick(now, pos, button); + lastDoubleClick = null; + return "single" + } + } + + // A mouse down can be a single click, double click, triple click, + // start of selection drag, start of text drag, new cursor + // (ctrl-click), rectangle drag (alt-drag), or xwin + // middle-click-paste. Or it might be a click on something we should + // not interfere with, such as a scrollbar or widget. + function onMouseDown(e) { + var cm = this, display = cm.display; + if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } + display.input.ensurePolled(); + display.shift = e.shiftKey; + + if (eventInWidget(display, e)) { + if (!webkit) { + // Briefly turn off draggability, to allow widgets to do + // normal dragging things. + display.scroller.draggable = false; + setTimeout(function () { return display.scroller.draggable = true; }, 100); + } + return + } + if (clickInGutter(cm, e)) { return } + var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single"; + window.focus(); + + // #3261: make sure, that we're not starting a second selection + if (button == 1 && cm.state.selectingText) + { cm.state.selectingText(e); } + + if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return } + + if (button == 1) { + if (pos) { leftButtonDown(cm, pos, repeat, e); } + else if (e_target(e) == display.scroller) { e_preventDefault(e); } + } else if (button == 2) { + if (pos) { extendSelection(cm.doc, pos); } + setTimeout(function () { return display.input.focus(); }, 20); + } else if (button == 3) { + if (captureRightClick) { cm.display.input.onContextMenu(e); } + else { delayBlurEvent(cm); } + } + } + + function handleMappedButton(cm, button, pos, repeat, event) { + var name = "Click"; + if (repeat == "double") { name = "Double" + name; } + else if (repeat == "triple") { name = "Triple" + name; } + name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name; + + return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { + if (typeof bound == "string") { bound = commands[bound]; } + if (!bound) { return false } + var done = false; + try { + if (cm.isReadOnly()) { cm.state.suppressEdits = true; } + done = bound(cm, pos) != Pass; + } finally { + cm.state.suppressEdits = false; + } + return done + }) + } + + function configureMouse(cm, repeat, event) { + var option = cm.getOption("configureMouse"); + var value = option ? option(cm, repeat, event) : {}; + if (value.unit == null) { + var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey; + value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line"; + } + if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; } + if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; } + if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); } + return value + } + + function leftButtonDown(cm, pos, repeat, event) { + if (ie) { setTimeout(bind(ensureFocus, cm), 0); } + else { cm.curOp.focus = activeElt(); } + + var behavior = configureMouse(cm, repeat, event); + + var sel = cm.doc.sel, contained; + if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && + repeat == "single" && (contained = sel.contains(pos)) > -1 && + (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && + (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) + { leftButtonStartDrag(cm, event, pos, behavior); } + else + { leftButtonSelect(cm, event, pos, behavior); } + } + + // Start a text drag. When it ends, see if any dragging actually + // happen, and treat as a click if it didn't. + function leftButtonStartDrag(cm, event, pos, behavior) { + var display = cm.display, moved = false; + var dragEnd = operation(cm, function (e) { + if (webkit) { display.scroller.draggable = false; } + cm.state.draggingText = false; + if (cm.state.delayingBlurEvent) { + if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; } + else { delayBlurEvent(cm); } + } + off(display.wrapper.ownerDocument, "mouseup", dragEnd); + off(display.wrapper.ownerDocument, "mousemove", mouseMove); + off(display.scroller, "dragstart", dragStart); + off(display.scroller, "drop", dragEnd); + if (!moved) { + e_preventDefault(e); + if (!behavior.addNew) + { extendSelection(cm.doc, pos, null, null, behavior.extend); } + // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) + if ((webkit && !safari) || ie && ie_version == 9) + { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); } + else + { display.input.focus(); } + } + }); + var mouseMove = function(e2) { + moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10; + }; + var dragStart = function () { return moved = true; }; + // Let the drag handler handle this. + if (webkit) { display.scroller.draggable = true; } + cm.state.draggingText = dragEnd; + dragEnd.copy = !behavior.moveOnDrag; + on(display.wrapper.ownerDocument, "mouseup", dragEnd); + on(display.wrapper.ownerDocument, "mousemove", mouseMove); + on(display.scroller, "dragstart", dragStart); + on(display.scroller, "drop", dragEnd); + + cm.state.delayingBlurEvent = true; + setTimeout(function () { return display.input.focus(); }, 20); + // IE's approach to draggable + if (display.scroller.dragDrop) { display.scroller.dragDrop(); } + } + + function rangeForUnit(cm, pos, unit) { + if (unit == "char") { return new Range(pos, pos) } + if (unit == "word") { return cm.findWordAt(pos) } + if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } + var result = unit(cm, pos); + return new Range(result.from, result.to) + } + + // Normal selection, as opposed to text dragging. + function leftButtonSelect(cm, event, start, behavior) { + if (ie) { delayBlurEvent(cm); } + var display = cm.display, doc = cm.doc; + e_preventDefault(event); + + var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; + if (behavior.addNew && !behavior.extend) { + ourIndex = doc.sel.contains(start); + if (ourIndex > -1) + { ourRange = ranges[ourIndex]; } + else + { ourRange = new Range(start, start); } + } else { + ourRange = doc.sel.primary(); + ourIndex = doc.sel.primIndex; + } + + if (behavior.unit == "rectangle") { + if (!behavior.addNew) { ourRange = new Range(start, start); } + start = posFromMouse(cm, event, true, true); + ourIndex = -1; + } else { + var range = rangeForUnit(cm, start, behavior.unit); + if (behavior.extend) + { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); } + else + { ourRange = range; } + } + + if (!behavior.addNew) { + ourIndex = 0; + setSelection(doc, new Selection([ourRange], 0), sel_mouse); + startSel = doc.sel; + } else if (ourIndex == -1) { + ourIndex = ranges.length; + setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), + {scroll: false, origin: "*mouse"}); + } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { + setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), + {scroll: false, origin: "*mouse"}); + startSel = doc.sel; + } else { + replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); + } + + var lastPos = start; + function extendTo(pos) { + if (cmp(lastPos, pos) == 0) { return } + lastPos = pos; + + if (behavior.unit == "rectangle") { + var ranges = [], tabSize = cm.options.tabSize; + var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); + var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); + var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); + for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); + line <= end; line++) { + var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); + if (left == right) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); } + else if (text.length > leftPos) + { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); } + } + if (!ranges.length) { ranges.push(new Range(start, start)); } + setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), + {origin: "*mouse", scroll: false}); + cm.scrollIntoView(pos); + } else { + var oldRange = ourRange; + var range = rangeForUnit(cm, pos, behavior.unit); + var anchor = oldRange.anchor, head; + if (cmp(range.anchor, anchor) > 0) { + head = range.head; + anchor = minPos(oldRange.from(), range.anchor); + } else { + head = range.anchor; + anchor = maxPos(oldRange.to(), range.head); + } + var ranges$1 = startSel.ranges.slice(0); + ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)); + setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse); + } + } + + var editorSize = display.wrapper.getBoundingClientRect(); + // Used to ensure timeout re-tries don't fire when another extend + // happened in the meantime (clearTimeout isn't reliable -- at + // least on Chrome, the timeouts still happen even when cleared, + // if the clear happens after their scheduled firing time). + var counter = 0; + + function extend(e) { + var curCount = ++counter; + var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle"); + if (!cur) { return } + if (cmp(cur, lastPos) != 0) { + cm.curOp.focus = activeElt(); + extendTo(cur); + var visible = visibleLines(display, doc); + if (cur.line >= visible.to || cur.line < visible.from) + { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); } + } else { + var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; + if (outside) { setTimeout(operation(cm, function () { + if (counter != curCount) { return } + display.scroller.scrollTop += outside; + extend(e); + }), 50); } + } + } + + function done(e) { + cm.state.selectingText = false; + counter = Infinity; + // If e is null or undefined we interpret this as someone trying + // to explicitly cancel the selection rather than the user + // letting go of the mouse button. + if (e) { + e_preventDefault(e); + display.input.focus(); + } + off(display.wrapper.ownerDocument, "mousemove", move); + off(display.wrapper.ownerDocument, "mouseup", up); + doc.history.lastSelOrigin = null; + } + + var move = operation(cm, function (e) { + if (e.buttons === 0 || !e_button(e)) { done(e); } + else { extend(e); } + }); + var up = operation(cm, done); + cm.state.selectingText = up; + on(display.wrapper.ownerDocument, "mousemove", move); + on(display.wrapper.ownerDocument, "mouseup", up); + } + + // Used when mouse-selecting to adjust the anchor to the proper side + // of a bidi jump depending on the visual position of the head. + function bidiSimplify(cm, range) { + var anchor = range.anchor; + var head = range.head; + var anchorLine = getLine(cm.doc, anchor.line); + if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range } + var order = getOrder(anchorLine); + if (!order) { return range } + var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index]; + if (part.from != anchor.ch && part.to != anchor.ch) { return range } + var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1); + if (boundary == 0 || boundary == order.length) { return range } + + // Compute the relative visual position of the head compared to the + // anchor (<0 is to the left, >0 to the right) + var leftSide; + if (head.line != anchor.line) { + leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0; + } else { + var headIndex = getBidiPartAt(order, head.ch, head.sticky); + var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1); + if (headIndex == boundary - 1 || headIndex == boundary) + { leftSide = dir < 0; } + else + { leftSide = dir > 0; } + } + + var usePart = order[boundary + (leftSide ? -1 : 0)]; + var from = leftSide == (usePart.level == 1); + var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before"; + return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) + } + + + // Determines whether an event happened in the gutter, and fires the + // handlers for the corresponding event. + function gutterEvent(cm, e, type, prevent) { + var mX, mY; + if (e.touches) { + mX = e.touches[0].clientX; + mY = e.touches[0].clientY; + } else { + try { mX = e.clientX; mY = e.clientY; } + catch(e$1) { return false } + } + if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } + if (prevent) { e_preventDefault(e); } + + var display = cm.display; + var lineBox = display.lineDiv.getBoundingClientRect(); + + if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } + mY -= lineBox.top - display.viewOffset; + + for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { + var g = display.gutters.childNodes[i]; + if (g && g.getBoundingClientRect().right >= mX) { + var line = lineAtHeight(cm.doc, mY); + var gutter = cm.display.gutterSpecs[i]; + signal(cm, type, cm, line, gutter.className, e); + return e_defaultPrevented(e) + } + } + } + + function clickInGutter(cm, e) { + return gutterEvent(cm, e, "gutterClick", true) + } + + // CONTEXT MENU HANDLING + + // To make the context menu work, we need to briefly unhide the + // textarea (making it as unobtrusive as possible) to let the + // right-click take effect on it. + function onContextMenu(cm, e) { + if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } + if (signalDOMEvent(cm, e, "contextmenu")) { return } + if (!captureRightClick) { cm.display.input.onContextMenu(e); } + } + + function contextMenuInGutter(cm, e) { + if (!hasHandler(cm, "gutterContextMenu")) { return false } + return gutterEvent(cm, e, "gutterContextMenu", false) + } + + function themeChanged(cm) { + cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + + cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + clearCaches(cm); + } + + var Init = {toString: function(){return "CodeMirror.Init"}}; + + var defaults = {}; + var optionHandlers = {}; + + function defineOptions(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + + function option(name, deflt, handle, notOnInit) { + CodeMirror.defaults[name] = deflt; + if (handle) { optionHandlers[name] = + notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; } + } + + CodeMirror.defineOption = option; + + // Passed to option handlers when there is no old value. + CodeMirror.Init = Init; + + // These two are, on init, called from the constructor because they + // have to be initialized before the editor can start at all. + option("value", "", function (cm, val) { return cm.setValue(val); }, true); + option("mode", null, function (cm, val) { + cm.doc.modeOption = val; + loadMode(cm); + }, true); + + option("indentUnit", 2, loadMode, true); + option("indentWithTabs", false); + option("smartIndent", true); + option("tabSize", 4, function (cm) { + resetModeState(cm); + clearCaches(cm); + regChange(cm); + }, true); + + option("lineSeparator", null, function (cm, val) { + cm.doc.lineSep = val; + if (!val) { return } + var newBreaks = [], lineNo = cm.doc.first; + cm.doc.iter(function (line) { + for (var pos = 0;;) { + var found = line.text.indexOf(val, pos); + if (found == -1) { break } + pos = found + val.length; + newBreaks.push(Pos(lineNo, found)); + } + lineNo++; + }); + for (var i = newBreaks.length - 1; i >= 0; i--) + { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); } + }); + option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { + cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); + if (old != Init) { cm.refresh(); } + }); + option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true); + option("electricChars", true); + option("inputStyle", mobile ? "contenteditable" : "textarea", function () { + throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME + }, true); + option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true); + option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true); + option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true); + option("rtlMoveVisually", !windows); + option("wholeLineUpdateBefore", true); + + option("theme", "default", function (cm) { + themeChanged(cm); + updateGutters(cm); + }, true); + option("keyMap", "default", function (cm, val, old) { + var next = getKeyMap(val); + var prev = old != Init && getKeyMap(old); + if (prev && prev.detach) { prev.detach(cm, next); } + if (next.attach) { next.attach(cm, prev || null); } + }); + option("extraKeys", null); + option("configureMouse", null); + + option("lineWrapping", false, wrappingChanged, true); + option("gutters", [], function (cm, val) { + cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); + updateGutters(cm); + }, true); + option("fixedGutter", true, function (cm, val) { + cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; + cm.refresh(); + }, true); + option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true); + option("scrollbarStyle", "native", function (cm) { + initScrollbars(cm); + updateScrollbars(cm); + cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); + cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); + }, true); + option("lineNumbers", false, function (cm, val) { + cm.display.gutterSpecs = getGutters(cm.options.gutters, val); + updateGutters(cm); + }, true); + option("firstLineNumber", 1, updateGutters, true); + option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true); + option("showCursorWhenSelecting", false, updateSelection, true); + + option("resetSelectionOnContextMenu", true); + option("lineWiseCopyCut", true); + option("pasteLinesPerSelection", true); + option("selectionsMayTouch", false); + + option("readOnly", false, function (cm, val) { + if (val == "nocursor") { + onBlur(cm); + cm.display.input.blur(); + } + cm.display.input.readOnlyChanged(val); + }); + + option("screenReaderLabel", null, function (cm, val) { + val = (val === '') ? null : val; + cm.display.input.screenReaderLabelChanged(val); + }); + + option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true); + option("dragDrop", true, dragDropChanged); + option("allowDropFileTypes", null); + + option("cursorBlinkRate", 530); + option("cursorScrollMargin", 0); + option("cursorHeight", 1, updateSelection, true); + option("singleCursorHeightPerLine", true, updateSelection, true); + option("workTime", 100); + option("workDelay", 100); + option("flattenSpans", true, resetModeState, true); + option("addModeClass", false, resetModeState, true); + option("pollInterval", 100); + option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }); + option("historyEventDelay", 1250); + option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true); + option("maxHighlightLength", 10000, resetModeState, true); + option("moveInputWithCursor", true, function (cm, val) { + if (!val) { cm.display.input.resetPosition(); } + }); + + option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }); + option("autofocus", null); + option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true); + option("phrases", null); + } + + function dragDropChanged(cm, value, old) { + var wasOn = old && old != Init; + if (!value != !wasOn) { + var funcs = cm.display.dragFunctions; + var toggle = value ? on : off; + toggle(cm.display.scroller, "dragstart", funcs.start); + toggle(cm.display.scroller, "dragenter", funcs.enter); + toggle(cm.display.scroller, "dragover", funcs.over); + toggle(cm.display.scroller, "dragleave", funcs.leave); + toggle(cm.display.scroller, "drop", funcs.drop); + } + } + + function wrappingChanged(cm) { + if (cm.options.lineWrapping) { + addClass(cm.display.wrapper, "CodeMirror-wrap"); + cm.display.sizer.style.minWidth = ""; + cm.display.sizerWidth = null; + } else { + rmClass(cm.display.wrapper, "CodeMirror-wrap"); + findMaxLine(cm); + } + estimateLineHeights(cm); + regChange(cm); + clearCaches(cm); + setTimeout(function () { return updateScrollbars(cm); }, 100); + } + + // A CodeMirror instance represents an editor. This is the object + // that user code is usually dealing with. + + function CodeMirror(place, options) { + var this$1 = this; + + if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } + + this.options = options = options ? copyObj(options) : {}; + // Determine effective options based on given values and defaults. + copyObj(defaults, options, false); + + var doc = options.value; + if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); } + else if (options.mode) { doc.modeOption = options.mode; } + this.doc = doc; + + var input = new CodeMirror.inputStyles[options.inputStyle](this); + var display = this.display = new Display(place, doc, input, options); + display.wrapper.CodeMirror = this; + themeChanged(this); + if (options.lineWrapping) + { this.display.wrapper.className += " CodeMirror-wrap"; } + initScrollbars(this); + + this.state = { + keyMaps: [], // stores maps added by addKeyMap + overlays: [], // highlighting overlays, as added by addOverlay + modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info + overwrite: false, + delayingBlurEvent: false, + focused: false, + suppressEdits: false, // used to disable editing during key handlers when in readOnly mode + pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll + selectingText: false, + draggingText: false, + highlight: new Delayed(), // stores highlight worker timeout + keySeq: null, // Unfinished key sequence + specialChars: null + }; + + if (options.autofocus && !mobile) { display.input.focus(); } + + // Override magic textarea content restore that IE sometimes does + // on our hidden textarea on reload + if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); } + + registerEventHandlers(this); + ensureGlobalHandlers(); + + startOperation(this); + this.curOp.forceUpdate = true; + attachDoc(this, doc); + + if ((options.autofocus && !mobile) || this.hasFocus()) + { setTimeout(function () { + if (this$1.hasFocus() && !this$1.state.focused) { onFocus(this$1); } + }, 20); } + else + { onBlur(this); } + + for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) + { optionHandlers[opt](this, options[opt], Init); } } + maybeUpdateLineNumberWidth(this); + if (options.finishInit) { options.finishInit(this); } + for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); } + endOperation(this); + // Suppress optimizelegibility in Webkit, since it breaks text + // measuring on line wrapping boundaries. + if (webkit && options.lineWrapping && + getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") + { display.lineDiv.style.textRendering = "auto"; } + } + + // The default configuration options. + CodeMirror.defaults = defaults; + // Functions to run when options are changed. + CodeMirror.optionHandlers = optionHandlers; + + // Attach the necessary event handlers when initializing the editor + function registerEventHandlers(cm) { + var d = cm.display; + on(d.scroller, "mousedown", operation(cm, onMouseDown)); + // Older IE's will not fire a second mousedown for a double click + if (ie && ie_version < 11) + { on(d.scroller, "dblclick", operation(cm, function (e) { + if (signalDOMEvent(cm, e)) { return } + var pos = posFromMouse(cm, e); + if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } + e_preventDefault(e); + var word = cm.findWordAt(pos); + extendSelection(cm.doc, word.anchor, word.head); + })); } + else + { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); } + // Some browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for these browsers. + on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }); + on(d.input.getField(), "contextmenu", function (e) { + if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); } + }); + + // Used to suppress mouse event handling when a touch happens + var touchFinished, prevTouch = {end: 0}; + function finishTouch() { + if (d.activeTouch) { + touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000); + prevTouch = d.activeTouch; + prevTouch.end = +new Date; + } + } + function isMouseLikeTouchEvent(e) { + if (e.touches.length != 1) { return false } + var touch = e.touches[0]; + return touch.radiusX <= 1 && touch.radiusY <= 1 + } + function farAway(touch, other) { + if (other.left == null) { return true } + var dx = other.left - touch.left, dy = other.top - touch.top; + return dx * dx + dy * dy > 20 * 20 + } + on(d.scroller, "touchstart", function (e) { + if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { + d.input.ensurePolled(); + clearTimeout(touchFinished); + var now = +new Date; + d.activeTouch = {start: now, moved: false, + prev: now - prevTouch.end <= 300 ? prevTouch : null}; + if (e.touches.length == 1) { + d.activeTouch.left = e.touches[0].pageX; + d.activeTouch.top = e.touches[0].pageY; + } + } + }); + on(d.scroller, "touchmove", function () { + if (d.activeTouch) { d.activeTouch.moved = true; } + }); + on(d.scroller, "touchend", function (e) { + var touch = d.activeTouch; + if (touch && !eventInWidget(d, e) && touch.left != null && + !touch.moved && new Date - touch.start < 300) { + var pos = cm.coordsChar(d.activeTouch, "page"), range; + if (!touch.prev || farAway(touch, touch.prev)) // Single tap + { range = new Range(pos, pos); } + else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap + { range = cm.findWordAt(pos); } + else // Triple tap + { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); } + cm.setSelection(range.anchor, range.head); + cm.focus(); + e_preventDefault(e); + } + finishTouch(); + }); + on(d.scroller, "touchcancel", finishTouch); + + // Sync scrolling between fake scrollbars and real scrollable + // area, ensure viewport is updated when scrolling. + on(d.scroller, "scroll", function () { + if (d.scroller.clientHeight) { + updateScrollTop(cm, d.scroller.scrollTop); + setScrollLeft(cm, d.scroller.scrollLeft, true); + signal(cm, "scroll", cm); + } + }); + + // Listen to wheel events in order to try and update the viewport on time. + on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }); + on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }); + + // Prevent wrapper from ever scrolling + on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); + + d.dragFunctions = { + enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }}, + over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, + start: function (e) { return onDragStart(cm, e); }, + drop: operation(cm, onDrop), + leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} + }; + + var inp = d.input.getField(); + on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }); + on(inp, "keydown", operation(cm, onKeyDown)); + on(inp, "keypress", operation(cm, onKeyPress)); + on(inp, "focus", function (e) { return onFocus(cm, e); }); + on(inp, "blur", function (e) { return onBlur(cm, e); }); + } + + var initHooks = []; + CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }; + + // Indent the given line. The how parameter can be "smart", + // "add"/null, "subtract", or "prev". When aggressive is false + // (typically set to true for forced single-line indents), empty + // lines are not indented, and places where the mode returns Pass + // are left alone. + function indentLine(cm, n, how, aggressive) { + var doc = cm.doc, state; + if (how == null) { how = "add"; } + if (how == "smart") { + // Fall back to "prev" when the mode doesn't have an indentation + // method. + if (!doc.mode.indent) { how = "prev"; } + else { state = getContextBefore(cm, n).state; } + } + + var tabSize = cm.options.tabSize; + var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); + if (line.stateAfter) { line.stateAfter = null; } + var curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (!aggressive && !/\S/.test(line.text)) { + indentation = 0; + how = "not"; + } else if (how == "smart") { + indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass || indentation > 150) { + if (!aggressive) { return } + how = "prev"; + } + } + if (how == "prev") { + if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); } + else { indentation = 0; } + } else if (how == "add") { + indentation = curSpace + cm.options.indentUnit; + } else if (how == "subtract") { + indentation = curSpace - cm.options.indentUnit; + } else if (typeof how == "number") { + indentation = curSpace + how; + } + indentation = Math.max(0, indentation); + + var indentString = "", pos = 0; + if (cm.options.indentWithTabs) + { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} } + if (pos < indentation) { indentString += spaceStr(indentation - pos); } + + if (indentString != curSpaceString) { + replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); + line.stateAfter = null; + return true + } else { + // Ensure that, if the cursor was in the whitespace at the start + // of the line, it is moved to the end of that space. + for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { + var range = doc.sel.ranges[i$1]; + if (range.head.line == n && range.head.ch < curSpaceString.length) { + var pos$1 = Pos(n, curSpaceString.length); + replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)); + break + } + } + } + } + + // This will be set to a {lineWise: bool, text: [string]} object, so + // that, when pasting, we know what kind of selections the copied + // text was made out of. + var lastCopied = null; + + function setLastCopied(newLastCopied) { + lastCopied = newLastCopied; + } + + function applyTextInput(cm, inserted, deleted, sel, origin) { + var doc = cm.doc; + cm.display.shift = false; + if (!sel) { sel = doc.sel; } + + var recent = +new Date - 200; + var paste = origin == "paste" || cm.state.pasteIncoming > recent; + var textLines = splitLinesAuto(inserted), multiPaste = null; + // When pasting N lines into N selections, insert one line per selection + if (paste && sel.ranges.length > 1) { + if (lastCopied && lastCopied.text.join("\n") == inserted) { + if (sel.ranges.length % lastCopied.text.length == 0) { + multiPaste = []; + for (var i = 0; i < lastCopied.text.length; i++) + { multiPaste.push(doc.splitLines(lastCopied.text[i])); } + } + } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { + multiPaste = map(textLines, function (l) { return [l]; }); + } + } + + var updateInput = cm.curOp.updateInput; + // Normal behavior is to insert the new text into every selection + for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { + var range = sel.ranges[i$1]; + var from = range.from(), to = range.to(); + if (range.empty()) { + if (deleted && deleted > 0) // Handle deletion + { from = Pos(from.line, from.ch - deleted); } + else if (cm.state.overwrite && !paste) // Handle overwrite + { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); } + else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n")) + { from = to = Pos(from.line, 0); } + } + var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, + origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")}; + makeChange(cm.doc, changeEvent); + signalLater(cm, "inputRead", cm, changeEvent); + } + if (inserted && !paste) + { triggerElectric(cm, inserted); } + + ensureCursorVisible(cm); + if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; } + cm.curOp.typing = true; + cm.state.pasteIncoming = cm.state.cutIncoming = -1; + } + + function handlePaste(e, cm) { + var pasted = e.clipboardData && e.clipboardData.getData("Text"); + if (pasted) { + e.preventDefault(); + if (!cm.isReadOnly() && !cm.options.disableInput) + { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); } + return true + } + } + + function triggerElectric(cm, inserted) { + // When an 'electric' character is inserted, immediately trigger a reindent + if (!cm.options.electricChars || !cm.options.smartIndent) { return } + var sel = cm.doc.sel; + + for (var i = sel.ranges.length - 1; i >= 0; i--) { + var range = sel.ranges[i]; + if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue } + var mode = cm.getModeAt(range.head); + var indented = false; + if (mode.electricChars) { + for (var j = 0; j < mode.electricChars.length; j++) + { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { + indented = indentLine(cm, range.head.line, "smart"); + break + } } + } else if (mode.electricInput) { + if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) + { indented = indentLine(cm, range.head.line, "smart"); } + } + if (indented) { signalLater(cm, "electricInput", cm, range.head.line); } + } + } + + function copyableRanges(cm) { + var text = [], ranges = []; + for (var i = 0; i < cm.doc.sel.ranges.length; i++) { + var line = cm.doc.sel.ranges[i].head.line; + var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; + ranges.push(lineRange); + text.push(cm.getRange(lineRange.anchor, lineRange.head)); + } + return {text: text, ranges: ranges} + } + + function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { + field.setAttribute("autocorrect", autocorrect ? "" : "off"); + field.setAttribute("autocapitalize", autocapitalize ? "" : "off"); + field.setAttribute("spellcheck", !!spellcheck); + } + + function hiddenTextarea() { + var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); + var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The textarea is kept positioned near the cursor to prevent the + // fact that it'll be scrolled into view on input from scrolling + // our fake cursor out of view. On webkit, when wrap=off, paste is + // very slow. So make the area wide instead. + if (webkit) { te.style.width = "1000px"; } + else { te.setAttribute("wrap", "off"); } + // If border: 0; -- iOS fails to open keyboard (issue #1287) + if (ios) { te.style.border = "1px solid black"; } + disableBrowserMagic(te); + return div + } + + // The publicly visible API. Note that methodOp(f) means + // 'wrap f in an operation, performed on its `this` parameter'. + + // This is not the complete set of editor methods. Most of the + // methods defined on the Doc type are also injected into + // CodeMirror.prototype, for backwards compatibility and + // convenience. + + function addEditorMethods(CodeMirror) { + var optionHandlers = CodeMirror.optionHandlers; + + var helpers = CodeMirror.helpers = {}; + + CodeMirror.prototype = { + constructor: CodeMirror, + focus: function(){window.focus(); this.display.input.focus();}, + + setOption: function(option, value) { + var options = this.options, old = options[option]; + if (options[option] == value && option != "mode") { return } + options[option] = value; + if (optionHandlers.hasOwnProperty(option)) + { operation(this, optionHandlers[option])(this, value, old); } + signal(this, "optionChange", this, option); + }, + + getOption: function(option) {return this.options[option]}, + getDoc: function() {return this.doc}, + + addKeyMap: function(map, bottom) { + this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); + }, + removeKeyMap: function(map) { + var maps = this.state.keyMaps; + for (var i = 0; i < maps.length; ++i) + { if (maps[i] == map || maps[i].name == map) { + maps.splice(i, 1); + return true + } } + }, + + addOverlay: methodOp(function(spec, options) { + var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); + if (mode.startState) { throw new Error("Overlays may not be stateful.") } + insertSorted(this.state.overlays, + {mode: mode, modeSpec: spec, opaque: options && options.opaque, + priority: (options && options.priority) || 0}, + function (overlay) { return overlay.priority; }); + this.state.modeGen++; + regChange(this); + }), + removeOverlay: methodOp(function(spec) { + var overlays = this.state.overlays; + for (var i = 0; i < overlays.length; ++i) { + var cur = overlays[i].modeSpec; + if (cur == spec || typeof spec == "string" && cur.name == spec) { + overlays.splice(i, 1); + this.state.modeGen++; + regChange(this); + return + } + } + }), + + indentLine: methodOp(function(n, dir, aggressive) { + if (typeof dir != "string" && typeof dir != "number") { + if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; } + else { dir = dir ? "add" : "subtract"; } + } + if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); } + }), + indentSelection: methodOp(function(how) { + var ranges = this.doc.sel.ranges, end = -1; + for (var i = 0; i < ranges.length; i++) { + var range = ranges[i]; + if (!range.empty()) { + var from = range.from(), to = range.to(); + var start = Math.max(end, from.line); + end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; + for (var j = start; j < end; ++j) + { indentLine(this, j, how); } + var newRanges = this.doc.sel.ranges; + if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) + { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); } + } else if (range.head.line > end) { + indentLine(this, range.head.line, how, true); + end = range.head.line; + if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); } + } + } + }), + + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(pos, precise) { + return takeToken(this, pos, precise) + }, + + getLineTokens: function(line, precise) { + return takeToken(this, Pos(line), precise, true) + }, + + getTokenTypeAt: function(pos) { + pos = clipPos(this.doc, pos); + var styles = getLineStyles(this, getLine(this.doc, pos.line)); + var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; + var type; + if (ch == 0) { type = styles[2]; } + else { for (;;) { + var mid = (before + after) >> 1; + if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; } + else if (styles[mid * 2 + 1] < ch) { before = mid + 1; } + else { type = styles[mid * 2 + 2]; break } + } } + var cut = type ? type.indexOf("overlay ") : -1; + return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) + }, + + getModeAt: function(pos) { + var mode = this.doc.mode; + if (!mode.innerMode) { return mode } + return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode + }, + + getHelper: function(pos, type) { + return this.getHelpers(pos, type)[0] + }, + + getHelpers: function(pos, type) { + var found = []; + if (!helpers.hasOwnProperty(type)) { return found } + var help = helpers[type], mode = this.getModeAt(pos); + if (typeof mode[type] == "string") { + if (help[mode[type]]) { found.push(help[mode[type]]); } + } else if (mode[type]) { + for (var i = 0; i < mode[type].length; i++) { + var val = help[mode[type][i]]; + if (val) { found.push(val); } + } + } else if (mode.helperType && help[mode.helperType]) { + found.push(help[mode.helperType]); + } else if (help[mode.name]) { + found.push(help[mode.name]); + } + for (var i$1 = 0; i$1 < help._global.length; i$1++) { + var cur = help._global[i$1]; + if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) + { found.push(cur.val); } + } + return found + }, + + getStateAfter: function(line, precise) { + var doc = this.doc; + line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); + return getContextBefore(this, line + 1, precise).state + }, + + cursorCoords: function(start, mode) { + var pos, range = this.doc.sel.primary(); + if (start == null) { pos = range.head; } + else if (typeof start == "object") { pos = clipPos(this.doc, start); } + else { pos = start ? range.from() : range.to(); } + return cursorCoords(this, pos, mode || "page") + }, + + charCoords: function(pos, mode) { + return charCoords(this, clipPos(this.doc, pos), mode || "page") + }, + + coordsChar: function(coords, mode) { + coords = fromCoordSystem(this, coords, mode || "page"); + return coordsChar(this, coords.left, coords.top) + }, + + lineAtHeight: function(height, mode) { + height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; + return lineAtHeight(this.doc, height + this.display.viewOffset) + }, + heightAtLine: function(line, mode, includeWidgets) { + var end = false, lineObj; + if (typeof line == "number") { + var last = this.doc.first + this.doc.size - 1; + if (line < this.doc.first) { line = this.doc.first; } + else if (line > last) { line = last; end = true; } + lineObj = getLine(this.doc, line); + } else { + lineObj = line; + } + return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + + (end ? this.doc.height - heightAtLine(lineObj) : 0) + }, + + defaultTextHeight: function() { return textHeight(this.display) }, + defaultCharWidth: function() { return charWidth(this.display) }, + + getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, + + addWidget: function(pos, node, scroll, vert, horiz) { + var display = this.display; + pos = cursorCoords(this, clipPos(this.doc, pos)); + var top = pos.bottom, left = pos.left; + node.style.position = "absolute"; + node.setAttribute("cm-ignore-events", "true"); + this.display.input.setUneditable(node); + display.sizer.appendChild(node); + if (vert == "over") { + top = pos.top; + } else if (vert == "above" || vert == "near") { + var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), + hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); + // Default to positioning above (if specified and possible); otherwise default to positioning below + if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) + { top = pos.top - node.offsetHeight; } + else if (pos.bottom + node.offsetHeight <= vspace) + { top = pos.bottom; } + if (left + node.offsetWidth > hspace) + { left = hspace - node.offsetWidth; } + } + node.style.top = top + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = display.sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") { left = 0; } + else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; } + node.style.left = left + "px"; + } + if (scroll) + { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); } + }, + + triggerOnKeyDown: methodOp(onKeyDown), + triggerOnKeyPress: methodOp(onKeyPress), + triggerOnKeyUp: onKeyUp, + triggerOnMouseDown: methodOp(onMouseDown), + + execCommand: function(cmd) { + if (commands.hasOwnProperty(cmd)) + { return commands[cmd].call(null, this) } + }, + + triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), + + findPosH: function(from, amount, unit, visually) { + var dir = 1; + if (amount < 0) { dir = -1; amount = -amount; } + var cur = clipPos(this.doc, from); + for (var i = 0; i < amount; ++i) { + cur = findPosH(this.doc, cur, dir, unit, visually); + if (cur.hitSide) { break } + } + return cur + }, + + moveH: methodOp(function(dir, unit) { + var this$1 = this; + + this.extendSelectionsBy(function (range) { + if (this$1.display.shift || this$1.doc.extend || range.empty()) + { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) } + else + { return dir < 0 ? range.from() : range.to() } + }, sel_move); + }), + + deleteH: methodOp(function(dir, unit) { + var sel = this.doc.sel, doc = this.doc; + if (sel.somethingSelected()) + { doc.replaceSelection("", null, "+delete"); } + else + { deleteNearSelection(this, function (range) { + var other = findPosH(doc, range.head, dir, unit, false); + return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} + }); } + }), + + findPosV: function(from, amount, unit, goalColumn) { + var dir = 1, x = goalColumn; + if (amount < 0) { dir = -1; amount = -amount; } + var cur = clipPos(this.doc, from); + for (var i = 0; i < amount; ++i) { + var coords = cursorCoords(this, cur, "div"); + if (x == null) { x = coords.left; } + else { coords.left = x; } + cur = findPosV(this, coords, dir, unit); + if (cur.hitSide) { break } + } + return cur + }, + + moveV: methodOp(function(dir, unit) { + var this$1 = this; + + var doc = this.doc, goals = []; + var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected(); + doc.extendSelectionsBy(function (range) { + if (collapse) + { return dir < 0 ? range.from() : range.to() } + var headPos = cursorCoords(this$1, range.head, "div"); + if (range.goalColumn != null) { headPos.left = range.goalColumn; } + goals.push(headPos.left); + var pos = findPosV(this$1, headPos, dir, unit); + if (unit == "page" && range == doc.sel.primary()) + { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); } + return pos + }, sel_move); + if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) + { doc.sel.ranges[i].goalColumn = goals[i]; } } + }), + + // Find the word at the given position (as returned by coordsChar). + findWordAt: function(pos) { + var doc = this.doc, line = getLine(doc, pos.line).text; + var start = pos.ch, end = pos.ch; + if (line) { + var helper = this.getHelper(pos, "wordChars"); + if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; } + var startChar = line.charAt(start); + var check = isWordChar(startChar, helper) + ? function (ch) { return isWordChar(ch, helper); } + : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } + : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }; + while (start > 0 && check(line.charAt(start - 1))) { --start; } + while (end < line.length && check(line.charAt(end))) { ++end; } + } + return new Range(Pos(pos.line, start), Pos(pos.line, end)) + }, + + toggleOverwrite: function(value) { + if (value != null && value == this.state.overwrite) { return } + if (this.state.overwrite = !this.state.overwrite) + { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); } + else + { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); } + + signal(this, "overwriteToggle", this, this.state.overwrite); + }, + hasFocus: function() { return this.display.input.getField() == activeElt() }, + isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, + + scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }), + getScrollInfo: function() { + var scroller = this.display.scroller; + return {left: scroller.scrollLeft, top: scroller.scrollTop, + height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, + width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, + clientHeight: displayHeight(this), clientWidth: displayWidth(this)} + }, + + scrollIntoView: methodOp(function(range, margin) { + if (range == null) { + range = {from: this.doc.sel.primary().head, to: null}; + if (margin == null) { margin = this.options.cursorScrollMargin; } + } else if (typeof range == "number") { + range = {from: Pos(range, 0), to: null}; + } else if (range.from == null) { + range = {from: range, to: null}; + } + if (!range.to) { range.to = range.from; } + range.margin = margin || 0; + + if (range.from.line != null) { + scrollToRange(this, range); + } else { + scrollToCoordsRange(this, range.from, range.to, range.margin); + } + }), + + setSize: methodOp(function(width, height) { + var this$1 = this; + + var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }; + if (width != null) { this.display.wrapper.style.width = interpret(width); } + if (height != null) { this.display.wrapper.style.height = interpret(height); } + if (this.options.lineWrapping) { clearLineMeasurementCache(this); } + var lineNo = this.display.viewFrom; + this.doc.iter(lineNo, this.display.viewTo, function (line) { + if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) + { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } } + ++lineNo; + }); + this.curOp.forceUpdate = true; + signal(this, "refresh", this); + }), + + operation: function(f){return runInOp(this, f)}, + startOperation: function(){return startOperation(this)}, + endOperation: function(){return endOperation(this)}, + + refresh: methodOp(function() { + var oldHeight = this.display.cachedTextHeight; + regChange(this); + this.curOp.forceUpdate = true; + clearCaches(this); + scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); + updateGutterSpace(this.display); + if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping) + { estimateLineHeights(this); } + signal(this, "refresh", this); + }), + + swapDoc: methodOp(function(doc) { + var old = this.doc; + old.cm = null; + // Cancel the current text selection if any (#5821) + if (this.state.selectingText) { this.state.selectingText(); } + attachDoc(this, doc); + clearCaches(this); + this.display.input.reset(); + scrollToCoords(this, doc.scrollLeft, doc.scrollTop); + this.curOp.forceScroll = true; + signalLater(this, "swapDoc", this, old); + return old + }), + + phrase: function(phraseText) { + var phrases = this.options.phrases; + return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText + }, + + getInputField: function(){return this.display.input.getField()}, + getWrapperElement: function(){return this.display.wrapper}, + getScrollerElement: function(){return this.display.scroller}, + getGutterElement: function(){return this.display.gutters} + }; + eventMixin(CodeMirror); + + CodeMirror.registerHelper = function(type, name, value) { + if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; } + helpers[type][name] = value; + }; + CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { + CodeMirror.registerHelper(type, name, value); + helpers[type]._global.push({pred: predicate, val: value}); + }; + } + + // Used for horizontal relative motion. Dir is -1 or 1 (left or + // right), unit can be "codepoint", "char", "column" (like char, but + // doesn't cross line boundaries), "word" (across next word), or + // "group" (to the start of next group of word or + // non-word-non-whitespace chars). The visually param controls + // whether, in right-to-left text, direction 1 means to move towards + // the next index in the string, or towards the character to the right + // of the current position. The resulting position will have a + // hitSide=true property if it reached the end of the document. + function findPosH(doc, pos, dir, unit, visually) { + var oldPos = pos; + var origDir = dir; + var lineObj = getLine(doc, pos.line); + var lineDir = visually && doc.direction == "rtl" ? -dir : dir; + function findNextLine() { + var l = pos.line + lineDir; + if (l < doc.first || l >= doc.first + doc.size) { return false } + pos = new Pos(l, pos.ch, pos.sticky); + return lineObj = getLine(doc, l) + } + function moveOnce(boundToLine) { + var next; + if (unit == "codepoint") { + var ch = lineObj.text.charCodeAt(pos.ch + (unit > 0 ? 0 : -1)); + if (isNaN(ch)) { next = null; } + else { next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (ch >= 0xD800 && ch < 0xDC00 ? 2 : 1))), + -dir); } + } else if (visually) { + next = moveVisually(doc.cm, lineObj, pos, dir); + } else { + next = moveLogically(lineObj, pos, dir); + } + if (next == null) { + if (!boundToLine && findNextLine()) + { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); } + else + { return false } + } else { + pos = next; + } + return true + } + + if (unit == "char" || unit == "codepoint") { + moveOnce(); + } else if (unit == "column") { + moveOnce(true); + } else if (unit == "word" || unit == "group") { + var sawType = null, group = unit == "group"; + var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); + for (var first = true;; first = false) { + if (dir < 0 && !moveOnce(!first)) { break } + var cur = lineObj.text.charAt(pos.ch) || "\n"; + var type = isWordChar(cur, helper) ? "w" + : group && cur == "\n" ? "n" + : !group || /\s/.test(cur) ? null + : "p"; + if (group && !first && !type) { type = "s"; } + if (sawType && sawType != type) { + if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";} + break + } + + if (type) { sawType = type; } + if (dir > 0 && !moveOnce(!first)) { break } + } + } + var result = skipAtomic(doc, pos, oldPos, origDir, true); + if (equalCursorPos(oldPos, result)) { result.hitSide = true; } + return result + } + + // For relative vertical movement. Dir may be -1 or 1. Unit can be + // "page" or "line". The resulting position will have a hitSide=true + // property if it reached the end of the document. + function findPosV(cm, pos, dir, unit) { + var doc = cm.doc, x = pos.left, y; + if (unit == "page") { + var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); + var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3); + y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount; + + } else if (unit == "line") { + y = dir > 0 ? pos.bottom + 3 : pos.top - 3; + } + var target; + for (;;) { + target = coordsChar(cm, x, y); + if (!target.outside) { break } + if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } + y += dir * 5; + } + return target + } + + // CONTENTEDITABLE INPUT STYLE + + var ContentEditableInput = function(cm) { + this.cm = cm; + this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; + this.polling = new Delayed(); + this.composing = null; + this.gracePeriod = false; + this.readDOMTimeout = null; + }; + + ContentEditableInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = input.cm; + var div = input.div = display.lineDiv; + disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); + + function belongsToInput(e) { + for (var t = e.target; t; t = t.parentNode) { + if (t == div) { return true } + if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break } + } + return false + } + + on(div, "paste", function (e) { + if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + // IE doesn't fire input events, so we schedule a read for the pasted content in this way + if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); } + }); + + on(div, "compositionstart", function (e) { + this$1.composing = {data: e.data, done: false}; + }); + on(div, "compositionupdate", function (e) { + if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; } + }); + on(div, "compositionend", function (e) { + if (this$1.composing) { + if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); } + this$1.composing.done = true; + } + }); + + on(div, "touchstart", function () { return input.forceCompositionEnd(); }); + + on(div, "input", function () { + if (!this$1.composing) { this$1.readFromDOMSoon(); } + }); + + function onCopyCut(e) { + if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}); + if (e.type == "cut") { cm.replaceSelection("", null, "cut"); } + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm); + setLastCopied({lineWise: true, text: ranges.text}); + if (e.type == "cut") { + cm.operation(function () { + cm.setSelections(ranges.ranges, 0, sel_dontScroll); + cm.replaceSelection("", null, "cut"); + }); + } + } + if (e.clipboardData) { + e.clipboardData.clearData(); + var content = lastCopied.text.join("\n"); + // iOS exposes the clipboard API, but seems to discard content inserted into it + e.clipboardData.setData("Text", content); + if (e.clipboardData.getData("Text") == content) { + e.preventDefault(); + return + } + } + // Old-fashioned briefly-focus-a-textarea hack + var kludge = hiddenTextarea(), te = kludge.firstChild; + cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); + te.value = lastCopied.text.join("\n"); + var hadFocus = document.activeElement; + selectInput(te); + setTimeout(function () { + cm.display.lineSpace.removeChild(kludge); + hadFocus.focus(); + if (hadFocus == div) { input.showPrimarySelection(); } + }, 50); + } + on(div, "copy", onCopyCut); + on(div, "cut", onCopyCut); + }; + + ContentEditableInput.prototype.screenReaderLabelChanged = function (label) { + // Label for screenreaders, accessibility + if(label) { + this.div.setAttribute('aria-label', label); + } else { + this.div.removeAttribute('aria-label'); + } + }; + + ContentEditableInput.prototype.prepareSelection = function () { + var result = prepareSelection(this.cm, false); + result.focus = document.activeElement == this.div; + return result + }; + + ContentEditableInput.prototype.showSelection = function (info, takeFocus) { + if (!info || !this.cm.display.view.length) { return } + if (info.focus || takeFocus) { this.showPrimarySelection(); } + this.showMultipleSelections(info); + }; + + ContentEditableInput.prototype.getSelection = function () { + return this.cm.display.wrapper.ownerDocument.getSelection() + }; + + ContentEditableInput.prototype.showPrimarySelection = function () { + var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary(); + var from = prim.from(), to = prim.to(); + + if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { + sel.removeAllRanges(); + return + } + + var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset); + if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && + cmp(minPos(curAnchor, curFocus), from) == 0 && + cmp(maxPos(curAnchor, curFocus), to) == 0) + { return } + + var view = cm.display.view; + var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) || + {node: view[0].measure.map[2], offset: 0}; + var end = to.line < cm.display.viewTo && posToDOM(cm, to); + if (!end) { + var measure = view[view.length - 1].measure; + var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; + end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; + } + + if (!start || !end) { + sel.removeAllRanges(); + return + } + + var old = sel.rangeCount && sel.getRangeAt(0), rng; + try { rng = range(start.node, start.offset, end.offset, end.node); } + catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible + if (rng) { + if (!gecko && cm.state.focused) { + sel.collapse(start.node, start.offset); + if (!rng.collapsed) { + sel.removeAllRanges(); + sel.addRange(rng); + } + } else { + sel.removeAllRanges(); + sel.addRange(rng); + } + if (old && sel.anchorNode == null) { sel.addRange(old); } + else if (gecko) { this.startGracePeriod(); } + } + this.rememberSelection(); + }; + + ContentEditableInput.prototype.startGracePeriod = function () { + var this$1 = this; + + clearTimeout(this.gracePeriod); + this.gracePeriod = setTimeout(function () { + this$1.gracePeriod = false; + if (this$1.selectionChanged()) + { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); } + }, 20); + }; + + ContentEditableInput.prototype.showMultipleSelections = function (info) { + removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); + removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); + }; + + ContentEditableInput.prototype.rememberSelection = function () { + var sel = this.getSelection(); + this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; + this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; + }; + + ContentEditableInput.prototype.selectionInEditor = function () { + var sel = this.getSelection(); + if (!sel.rangeCount) { return false } + var node = sel.getRangeAt(0).commonAncestorContainer; + return contains(this.div, node) + }; + + ContentEditableInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor") { + if (!this.selectionInEditor() || document.activeElement != this.div) + { this.showSelection(this.prepareSelection(), true); } + this.div.focus(); + } + }; + ContentEditableInput.prototype.blur = function () { this.div.blur(); }; + ContentEditableInput.prototype.getField = function () { return this.div }; + + ContentEditableInput.prototype.supportsTouch = function () { return true }; + + ContentEditableInput.prototype.receivedFocus = function () { + var input = this; + if (this.selectionInEditor()) + { this.pollSelection(); } + else + { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); } + + function poll() { + if (input.cm.state.focused) { + input.pollSelection(); + input.polling.set(input.cm.options.pollInterval, poll); + } + } + this.polling.set(this.cm.options.pollInterval, poll); + }; + + ContentEditableInput.prototype.selectionChanged = function () { + var sel = this.getSelection(); + return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || + sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset + }; + + ContentEditableInput.prototype.pollSelection = function () { + if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } + var sel = this.getSelection(), cm = this.cm; + // On Android Chrome (version 56, at least), backspacing into an + // uneditable block element will put the cursor in that element, + // and then, because it's not editable, hide the virtual keyboard. + // Because Android doesn't allow us to actually detect backspace + // presses in a sane way, this code checks for when that happens + // and simulates a backspace press in this case. + if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { + this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}); + this.blur(); + this.focus(); + return + } + if (this.composing) { return } + this.rememberSelection(); + var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); + var head = domToPos(cm, sel.focusNode, sel.focusOffset); + if (anchor && head) { runInOp(cm, function () { + setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); + if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; } + }); } + }; + + ContentEditableInput.prototype.pollContent = function () { + if (this.readDOMTimeout != null) { + clearTimeout(this.readDOMTimeout); + this.readDOMTimeout = null; + } + + var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); + var from = sel.from(), to = sel.to(); + if (from.ch == 0 && from.line > cm.firstLine()) + { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); } + if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) + { to = Pos(to.line + 1, 0); } + if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } + + var fromIndex, fromLine, fromNode; + if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { + fromLine = lineNo(display.view[0].line); + fromNode = display.view[0].node; + } else { + fromLine = lineNo(display.view[fromIndex].line); + fromNode = display.view[fromIndex - 1].node.nextSibling; + } + var toIndex = findViewIndex(cm, to.line); + var toLine, toNode; + if (toIndex == display.view.length - 1) { + toLine = display.viewTo - 1; + toNode = display.lineDiv.lastChild; + } else { + toLine = lineNo(display.view[toIndex + 1].line) - 1; + toNode = display.view[toIndex + 1].node.previousSibling; + } + + if (!fromNode) { return false } + var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); + var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); + while (newText.length > 1 && oldText.length > 1) { + if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } + else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } + else { break } + } + + var cutFront = 0, cutEnd = 0; + var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); + while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) + { ++cutFront; } + var newBot = lst(newText), oldBot = lst(oldText); + var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), + oldBot.length - (oldText.length == 1 ? cutFront : 0)); + while (cutEnd < maxCutEnd && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) + { ++cutEnd; } + // Try to move start of change to start of selection if ambiguous + if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { + while (cutFront && cutFront > from.ch && + newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { + cutFront--; + cutEnd++; + } + } + + newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, ""); + newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, ""); + + var chFrom = Pos(fromLine, cutFront); + var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); + if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { + replaceRange(cm.doc, newText, chFrom, chTo, "+input"); + return true + } + }; + + ContentEditableInput.prototype.ensurePolled = function () { + this.forceCompositionEnd(); + }; + ContentEditableInput.prototype.reset = function () { + this.forceCompositionEnd(); + }; + ContentEditableInput.prototype.forceCompositionEnd = function () { + if (!this.composing) { return } + clearTimeout(this.readDOMTimeout); + this.composing = null; + this.updateFromDOM(); + this.div.blur(); + this.div.focus(); + }; + ContentEditableInput.prototype.readFromDOMSoon = function () { + var this$1 = this; + + if (this.readDOMTimeout != null) { return } + this.readDOMTimeout = setTimeout(function () { + this$1.readDOMTimeout = null; + if (this$1.composing) { + if (this$1.composing.done) { this$1.composing = null; } + else { return } + } + this$1.updateFromDOM(); + }, 80); + }; + + ContentEditableInput.prototype.updateFromDOM = function () { + var this$1 = this; + + if (this.cm.isReadOnly() || !this.pollContent()) + { runInOp(this.cm, function () { return regChange(this$1.cm); }); } + }; + + ContentEditableInput.prototype.setUneditable = function (node) { + node.contentEditable = "false"; + }; + + ContentEditableInput.prototype.onKeyPress = function (e) { + if (e.charCode == 0 || this.composing) { return } + e.preventDefault(); + if (!this.cm.isReadOnly()) + { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); } + }; + + ContentEditableInput.prototype.readOnlyChanged = function (val) { + this.div.contentEditable = String(val != "nocursor"); + }; + + ContentEditableInput.prototype.onContextMenu = function () {}; + ContentEditableInput.prototype.resetPosition = function () {}; + + ContentEditableInput.prototype.needsContentAttribute = true; + + function posToDOM(cm, pos) { + var view = findViewForLine(cm, pos.line); + if (!view || view.hidden) { return null } + var line = getLine(cm.doc, pos.line); + var info = mapFromLineView(view, line, pos.line); + + var order = getOrder(line, cm.doc.direction), side = "left"; + if (order) { + var partPos = getBidiPartAt(order, pos.ch); + side = partPos % 2 ? "right" : "left"; + } + var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); + result.offset = result.collapse == "right" ? result.end : result.start; + return result + } + + function isInGutter(node) { + for (var scan = node; scan; scan = scan.parentNode) + { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } + return false + } + + function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } + + function domTextBetween(cm, from, to, fromLine, toLine) { + var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false; + function recognizeMarker(id) { return function (marker) { return marker.id == id; } } + function close() { + if (closing) { + text += lineSep; + if (extraLinebreak) { text += lineSep; } + closing = extraLinebreak = false; + } + } + function addText(str) { + if (str) { + close(); + text += str; + } + } + function walk(node) { + if (node.nodeType == 1) { + var cmText = node.getAttribute("cm-text"); + if (cmText) { + addText(cmText); + return + } + var markerID = node.getAttribute("cm-marker"), range; + if (markerID) { + var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); + if (found.length && (range = found[0].find(0))) + { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); } + return + } + if (node.getAttribute("contenteditable") == "false") { return } + var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName); + if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return } + + if (isBlock) { close(); } + for (var i = 0; i < node.childNodes.length; i++) + { walk(node.childNodes[i]); } + + if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; } + if (isBlock) { closing = true; } + } else if (node.nodeType == 3) { + addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")); + } + } + for (;;) { + walk(from); + if (from == to) { break } + from = from.nextSibling; + extraLinebreak = false; + } + return text + } + + function domToPos(cm, node, offset) { + var lineNode; + if (node == cm.display.lineDiv) { + lineNode = cm.display.lineDiv.childNodes[offset]; + if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } + node = null; offset = 0; + } else { + for (lineNode = node;; lineNode = lineNode.parentNode) { + if (!lineNode || lineNode == cm.display.lineDiv) { return null } + if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } + } + } + for (var i = 0; i < cm.display.view.length; i++) { + var lineView = cm.display.view[i]; + if (lineView.node == lineNode) + { return locateNodeInLineView(lineView, node, offset) } + } + } + + function locateNodeInLineView(lineView, node, offset) { + var wrapper = lineView.text.firstChild, bad = false; + if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } + if (node == wrapper) { + bad = true; + node = wrapper.childNodes[offset]; + offset = 0; + if (!node) { + var line = lineView.rest ? lst(lineView.rest) : lineView.line; + return badPos(Pos(lineNo(line), line.text.length), bad) + } + } + + var textNode = node.nodeType == 3 ? node : null, topNode = node; + if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { + textNode = node.firstChild; + if (offset) { offset = textNode.nodeValue.length; } + } + while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; } + var measure = lineView.measure, maps = measure.maps; + + function find(textNode, topNode, offset) { + for (var i = -1; i < (maps ? maps.length : 0); i++) { + var map = i < 0 ? measure.map : maps[i]; + for (var j = 0; j < map.length; j += 3) { + var curNode = map[j + 2]; + if (curNode == textNode || curNode == topNode) { + var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); + var ch = map[j] + offset; + if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; } + return Pos(line, ch) + } + } + } + } + var found = find(textNode, topNode, offset); + if (found) { return badPos(found, bad) } + + // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems + for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { + found = find(after, after.firstChild, 0); + if (found) + { return badPos(Pos(found.line, found.ch - dist), bad) } + else + { dist += after.textContent.length; } + } + for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { + found = find(before, before.firstChild, -1); + if (found) + { return badPos(Pos(found.line, found.ch + dist$1), bad) } + else + { dist$1 += before.textContent.length; } + } + } + + // TEXTAREA INPUT STYLE + + var TextareaInput = function(cm) { + this.cm = cm; + // See input.poll and input.reset + this.prevInput = ""; + + // Flag that indicates whether we expect input to appear real soon + // now (after some event like 'keypress' or 'input') and are + // polling intensively. + this.pollingFast = false; + // Self-resetting timeout for the poller + this.polling = new Delayed(); + // Used to work around IE issue with selection being forgotten when focus moves away from textarea + this.hasSelection = false; + this.composing = null; + }; + + TextareaInput.prototype.init = function (display) { + var this$1 = this; + + var input = this, cm = this.cm; + this.createField(display); + var te = this.textarea; + + display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild); + + // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) + if (ios) { te.style.width = "0px"; } + + on(te, "input", function () { + if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; } + input.poll(); + }); + + on(te, "paste", function (e) { + if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } + + cm.state.pasteIncoming = +new Date; + input.fastPoll(); + }); + + function prepareCopyCut(e) { + if (signalDOMEvent(cm, e)) { return } + if (cm.somethingSelected()) { + setLastCopied({lineWise: false, text: cm.getSelections()}); + } else if (!cm.options.lineWiseCopyCut) { + return + } else { + var ranges = copyableRanges(cm); + setLastCopied({lineWise: true, text: ranges.text}); + if (e.type == "cut") { + cm.setSelections(ranges.ranges, null, sel_dontScroll); + } else { + input.prevInput = ""; + te.value = ranges.text.join("\n"); + selectInput(te); + } + } + if (e.type == "cut") { cm.state.cutIncoming = +new Date; } + } + on(te, "cut", prepareCopyCut); + on(te, "copy", prepareCopyCut); + + on(display.scroller, "paste", function (e) { + if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } + if (!te.dispatchEvent) { + cm.state.pasteIncoming = +new Date; + input.focus(); + return + } + + // Pass the `paste` event to the textarea so it's handled by its event listener. + var event = new Event("paste"); + event.clipboardData = e.clipboardData; + te.dispatchEvent(event); + }); + + // Prevent normal selection in the editor (we handle our own) + on(display.lineSpace, "selectstart", function (e) { + if (!eventInWidget(display, e)) { e_preventDefault(e); } + }); + + on(te, "compositionstart", function () { + var start = cm.getCursor("from"); + if (input.composing) { input.composing.range.clear(); } + input.composing = { + start: start, + range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) + }; + }); + on(te, "compositionend", function () { + if (input.composing) { + input.poll(); + input.composing.range.clear(); + input.composing = null; + } + }); + }; + + TextareaInput.prototype.createField = function (_display) { + // Wraps and hides input textarea + this.wrapper = hiddenTextarea(); + // The semihidden textarea that is focused when the editor is + // focused, and receives input. + this.textarea = this.wrapper.firstChild; + }; + + TextareaInput.prototype.screenReaderLabelChanged = function (label) { + // Label for screenreaders, accessibility + if(label) { + this.textarea.setAttribute('aria-label', label); + } else { + this.textarea.removeAttribute('aria-label'); + } + }; + + TextareaInput.prototype.prepareSelection = function () { + // Redraw the selection and/or cursor + var cm = this.cm, display = cm.display, doc = cm.doc; + var result = prepareSelection(cm); + + // Move the hidden textarea near the cursor to prevent scrolling artifacts + if (cm.options.moveInputWithCursor) { + var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); + var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); + result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, + headPos.top + lineOff.top - wrapOff.top)); + result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, + headPos.left + lineOff.left - wrapOff.left)); + } + + return result + }; + + TextareaInput.prototype.showSelection = function (drawn) { + var cm = this.cm, display = cm.display; + removeChildrenAndAdd(display.cursorDiv, drawn.cursors); + removeChildrenAndAdd(display.selectionDiv, drawn.selection); + if (drawn.teTop != null) { + this.wrapper.style.top = drawn.teTop + "px"; + this.wrapper.style.left = drawn.teLeft + "px"; + } + }; + + // Reset the input to correspond to the selection (or to be empty, + // when not typing and nothing is selected) + TextareaInput.prototype.reset = function (typing) { + if (this.contextMenuPending || this.composing) { return } + var cm = this.cm; + if (cm.somethingSelected()) { + this.prevInput = ""; + var content = cm.getSelection(); + this.textarea.value = content; + if (cm.state.focused) { selectInput(this.textarea); } + if (ie && ie_version >= 9) { this.hasSelection = content; } + } else if (!typing) { + this.prevInput = this.textarea.value = ""; + if (ie && ie_version >= 9) { this.hasSelection = null; } + } + }; + + TextareaInput.prototype.getField = function () { return this.textarea }; + + TextareaInput.prototype.supportsTouch = function () { return false }; + + TextareaInput.prototype.focus = function () { + if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { + try { this.textarea.focus(); } + catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM + } + }; + + TextareaInput.prototype.blur = function () { this.textarea.blur(); }; + + TextareaInput.prototype.resetPosition = function () { + this.wrapper.style.top = this.wrapper.style.left = 0; + }; + + TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); }; + + // Poll for input changes, using the normal rate of polling. This + // runs as long as the editor is focused. + TextareaInput.prototype.slowPoll = function () { + var this$1 = this; + + if (this.pollingFast) { return } + this.polling.set(this.cm.options.pollInterval, function () { + this$1.poll(); + if (this$1.cm.state.focused) { this$1.slowPoll(); } + }); + }; + + // When an event has just come in that is likely to add or change + // something in the input textarea, we poll faster, to ensure that + // the change appears on the screen quickly. + TextareaInput.prototype.fastPoll = function () { + var missed = false, input = this; + input.pollingFast = true; + function p() { + var changed = input.poll(); + if (!changed && !missed) {missed = true; input.polling.set(60, p);} + else {input.pollingFast = false; input.slowPoll();} + } + input.polling.set(20, p); + }; + + // Read input from the textarea, and update the document to match. + // When something is selected, it is present in the textarea, and + // selected (unless it is huge, in which case a placeholder is + // used). When nothing is selected, the cursor sits after previously + // seen text (can be empty), which is stored in prevInput (we must + // not reset the textarea when typing, because that breaks IME). + TextareaInput.prototype.poll = function () { + var this$1 = this; + + var cm = this.cm, input = this.textarea, prevInput = this.prevInput; + // Since this is called a *lot*, try to bail out as cheaply as + // possible when it is clear that nothing happened. hasSelection + // will be the case when there is a lot of text in the textarea, + // in which case reading its value would be expensive. + if (this.contextMenuPending || !cm.state.focused || + (hasSelection(input) && !prevInput && !this.composing) || + cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) + { return false } + + var text = input.value; + // If nothing changed, bail. + if (text == prevInput && !cm.somethingSelected()) { return false } + // Work around nonsensical selection resetting in IE9/10, and + // inexplicable appearance of private area unicode characters on + // some key combos in Mac (#2689). + if (ie && ie_version >= 9 && this.hasSelection === text || + mac && /[\uf700-\uf7ff]/.test(text)) { + cm.display.input.reset(); + return false + } + + if (cm.doc.sel == cm.display.selForContextMenu) { + var first = text.charCodeAt(0); + if (first == 0x200b && !prevInput) { prevInput = "\u200b"; } + if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } + } + // Find the part of the input that is actually new + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; } + + runInOp(cm, function () { + applyTextInput(cm, text.slice(same), prevInput.length - same, + null, this$1.composing ? "*compose" : null); + + // Don't leave long text in the textarea, since it makes further polling slow + if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; } + else { this$1.prevInput = text; } + + if (this$1.composing) { + this$1.composing.range.clear(); + this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), + {className: "CodeMirror-composing"}); + } + }); + return true + }; + + TextareaInput.prototype.ensurePolled = function () { + if (this.pollingFast && this.poll()) { this.pollingFast = false; } + }; + + TextareaInput.prototype.onKeyPress = function () { + if (ie && ie_version >= 9) { this.hasSelection = null; } + this.fastPoll(); + }; + + TextareaInput.prototype.onContextMenu = function (e) { + var input = this, cm = input.cm, display = cm.display, te = input.textarea; + if (input.contextMenuPending) { input.contextMenuPending(); } + var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; + if (!pos || presto) { return } // Opera is difficult. + + // Reset the current text selection only if the click is done outside of the selection + // and 'resetSelectionOnContextMenu' option is true. + var reset = cm.options.resetSelectionOnContextMenu; + if (reset && cm.doc.sel.contains(pos) == -1) + { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); } + + var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; + var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); + input.wrapper.style.cssText = "position: static"; + te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + var oldScrollY; + if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712) + display.input.focus(); + if (webkit) { window.scrollTo(null, oldScrollY); } + display.input.reset(); + // Adds "Select all" to context menu in FF + if (!cm.somethingSelected()) { te.value = input.prevInput = " "; } + input.contextMenuPending = rehide; + display.selForContextMenu = cm.doc.sel; + clearTimeout(display.detectingSelectAll); + + // Select-all will be greyed out if there's nothing to select, so + // this adds a zero-width space so that we can later check whether + // it got selected. + function prepareSelectAllHack() { + if (te.selectionStart != null) { + var selected = cm.somethingSelected(); + var extval = "\u200b" + (selected ? te.value : ""); + te.value = "\u21da"; // Used to catch context-menu undo + te.value = extval; + input.prevInput = selected ? "" : "\u200b"; + te.selectionStart = 1; te.selectionEnd = extval.length; + // Re-set this, in case some other handler touched the + // selection in the meantime. + display.selForContextMenu = cm.doc.sel; + } + } + function rehide() { + if (input.contextMenuPending != rehide) { return } + input.contextMenuPending = false; + input.wrapper.style.cssText = oldWrapperCSS; + te.style.cssText = oldCSS; + if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); } + + // Try to detect the user choosing select-all + if (te.selectionStart != null) { + if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); } + var i = 0, poll = function () { + if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && + te.selectionEnd > 0 && input.prevInput == "\u200b") { + operation(cm, selectAll)(cm); + } else if (i++ < 10) { + display.detectingSelectAll = setTimeout(poll, 500); + } else { + display.selForContextMenu = null; + display.input.reset(); + } + }; + display.detectingSelectAll = setTimeout(poll, 200); + } + } + + if (ie && ie_version >= 9) { prepareSelectAllHack(); } + if (captureRightClick) { + e_stop(e); + var mouseup = function () { + off(window, "mouseup", mouseup); + setTimeout(rehide, 20); + }; + on(window, "mouseup", mouseup); + } else { + setTimeout(rehide, 50); + } + }; + + TextareaInput.prototype.readOnlyChanged = function (val) { + if (!val) { this.reset(); } + this.textarea.disabled = val == "nocursor"; + this.textarea.readOnly = !!val; + }; + + TextareaInput.prototype.setUneditable = function () {}; + + TextareaInput.prototype.needsContentAttribute = false; + + function fromTextArea(textarea, options) { + options = options ? copyObj(options) : {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabIndex) + { options.tabindex = textarea.tabIndex; } + if (!options.placeholder && textarea.placeholder) + { options.placeholder = textarea.placeholder; } + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = activeElt(); + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = cm.getValue();} + + var realSubmit; + if (textarea.form) { + on(textarea.form, "submit", save); + // Deplorable hack to make the submit method do the right thing. + if (!options.leaveSubmitMethodAlone) { + var form = textarea.form; + realSubmit = form.submit; + try { + var wrappedSubmit = form.submit = function () { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } catch(e) {} + } + } + + options.finishInit = function (cm) { + cm.save = save; + cm.getTextArea = function () { return textarea; }; + cm.toTextArea = function () { + cm.toTextArea = isNaN; // Prevent this from being ran twice + save(); + textarea.parentNode.removeChild(cm.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + off(textarea.form, "submit", save); + if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") + { textarea.form.submit = realSubmit; } + } + }; + }; + + textarea.style.display = "none"; + var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, + options); + return cm + } + + function addLegacyProps(CodeMirror) { + CodeMirror.off = off; + CodeMirror.on = on; + CodeMirror.wheelEventPixels = wheelEventPixels; + CodeMirror.Doc = Doc; + CodeMirror.splitLines = splitLinesAuto; + CodeMirror.countColumn = countColumn; + CodeMirror.findColumn = findColumn; + CodeMirror.isWordChar = isWordCharBasic; + CodeMirror.Pass = Pass; + CodeMirror.signal = signal; + CodeMirror.Line = Line; + CodeMirror.changeEnd = changeEnd; + CodeMirror.scrollbarModel = scrollbarModel; + CodeMirror.Pos = Pos; + CodeMirror.cmpPos = cmp; + CodeMirror.modes = modes; + CodeMirror.mimeModes = mimeModes; + CodeMirror.resolveMode = resolveMode; + CodeMirror.getMode = getMode; + CodeMirror.modeExtensions = modeExtensions; + CodeMirror.extendMode = extendMode; + CodeMirror.copyState = copyState; + CodeMirror.startState = startState; + CodeMirror.innerMode = innerMode; + CodeMirror.commands = commands; + CodeMirror.keyMap = keyMap; + CodeMirror.keyName = keyName; + CodeMirror.isModifierKey = isModifierKey; + CodeMirror.lookupKey = lookupKey; + CodeMirror.normalizeKeyMap = normalizeKeyMap; + CodeMirror.StringStream = StringStream; + CodeMirror.SharedTextMarker = SharedTextMarker; + CodeMirror.TextMarker = TextMarker; + CodeMirror.LineWidget = LineWidget; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + CodeMirror.e_stop = e_stop; + CodeMirror.addClass = addClass; + CodeMirror.contains = contains; + CodeMirror.rmClass = rmClass; + CodeMirror.keyNames = keyNames; + } + + // EDITOR CONSTRUCTOR + + defineOptions(CodeMirror); + + addEditorMethods(CodeMirror); + + // Set up methods on CodeMirror's prototype to redirect to the editor's document. + var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); + for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) + { CodeMirror.prototype[prop] = (function(method) { + return function() {return method.apply(this.doc, arguments)} + })(Doc.prototype[prop]); } } + + eventMixin(Doc); + CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; + + // Extra arguments are stored as the mode's dependencies, which is + // used by (legacy) mechanisms like loadmode.js to automatically + // load a mode. (Preferred mechanism is the require/define calls.) + CodeMirror.defineMode = function(name/*, mode, …*/) { + if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; } + defineMode.apply(this, arguments); + }; + + CodeMirror.defineMIME = defineMIME; + + // Minimal default mode. + CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }); + CodeMirror.defineMIME("text/plain", "null"); + + // EXTENSIONS + + CodeMirror.defineExtension = function (name, func) { + CodeMirror.prototype[name] = func; + }; + CodeMirror.defineDocExtension = function (name, func) { + Doc.prototype[name] = func; + }; + + CodeMirror.fromTextArea = fromTextArea; + + addLegacyProps(CodeMirror); + + CodeMirror.version = "5.58.3"; + + return CodeMirror; + +}))); From c6bb7833087156e77b9f2e779e87ad65cc9982f8 Mon Sep 17 00:00:00 2001 From: Joshua Fontany <joshua.fontany@gmail.com> Date: Wed, 2 Dec 2020 01:47:51 -0800 Subject: [PATCH 104/124] Fix filesystem regression (#5176) * $:/config/OriginalTiddlerPaths if no filters match * fixed & docs updated * tested with tiddlywiki.files & tw.com edition * typos * originalpath to options, propigate isEditableFile * syntax cleanup --- boot/boot.js | 38 +++++++++++-------- core/modules/utils/filesystem.js | 20 ++++++++-- .../Customising Tiddler File Naming.tid | 13 ++++--- .../nodejs/tiddlywiki.files_Files.tid | 10 ++--- .../filesystem/filesystemadaptor.js | 7 ++-- 5 files changed, 54 insertions(+), 34 deletions(-) diff --git a/boot/boot.js b/boot/boot.js index f6341dab0..c065cfb61 100644 --- a/boot/boot.js +++ b/boot/boot.js @@ -1894,7 +1894,7 @@ $tw.loadTiddlersFromSpecification = function(filepath,excludeRegExp) { }); }); if(isEditableFile) { - tiddlers.push({filepath: pathname, hasMetaFile: !!metadata && !isTiddlerFile, tiddlers: fileTiddlers}); + tiddlers.push({filepath: pathname, hasMetaFile: !!metadata && !isTiddlerFile, isEditableFile: true, tiddlers: fileTiddlers}); } else { tiddlers.push({tiddlers: fileTiddlers}); } @@ -2074,6 +2074,11 @@ $tw.loadWikiTiddlers = function(wikiPath,options) { } else { return null; } + // Save the path to the tiddlers folder for the filesystemadaptor + var config = wikiInfo.config || {}; + if($tw.boot.wikiPath == wikiPath) { + $tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir); + } // Load any parent wikis if(wikiInfo.includeWikis) { parentPaths = parentPaths.slice(0); @@ -2107,27 +2112,30 @@ $tw.loadWikiTiddlers = function(wikiPath,options) { $tw.boot.files[tiddler.title] = { filepath: tiddlerFile.filepath, type: tiddlerFile.type, - hasMetaFile: tiddlerFile.hasMetaFile + hasMetaFile: tiddlerFile.hasMetaFile, + isEditableFile: config["retain-original-tiddler-path"] || tiddlerFile.isEditableFile || tiddlerFile.filepath.indexOf($tw.boot.wikiTiddlersPath) !== 0 }; }); } $tw.wiki.addTiddlers(tiddlerFile.tiddlers); }); - // Save the original tiddler file locations if requested - var config = wikiInfo.config || {}; - if(config["retain-original-tiddler-path"]) { - var output = {}, relativePath; + if ($tw.boot.wikiPath == wikiPath) { + // Save the original tiddler file locations if requested + var output = {}, relativePath, fileInfo; for(var title in $tw.boot.files) { - relativePath = path.relative(resolvedWikiPath,$tw.boot.files[title].filepath); - output[title] = - path.sep === "/" ? - relativePath : - relativePath.split(path.sep).join("/"); + fileInfo = $tw.boot.files[title]; + if(fileInfo.isEditableFile) { + relativePath = path.relative($tw.boot.wikiTiddlersPath,fileInfo.filepath); + output[title] = + path.sep === "/" ? + relativePath : + relativePath.split(path.sep).join("/"); + } + } + if(Object.keys(output).length > 0){ + $tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)}); } - $tw.wiki.addTiddler({title: "$:/config/OriginalTiddlerPaths", type: "application/json", text: JSON.stringify(output)}); } - // Save the path to the tiddlers folder for the filesystemadaptor - $tw.boot.wikiTiddlersPath = path.resolve($tw.boot.wikiPath,config["default-tiddler-location"] || $tw.config.wikiTiddlersSubDir); // Load any plugins within the wiki folder var wikiPluginsPath = path.resolve(wikiPath,$tw.config.wikiPluginsSubDir); if(fs.existsSync(wikiPluginsPath)) { @@ -2174,7 +2182,7 @@ $tw.loadTiddlersNode = function() { // Load any extra plugins $tw.utils.each($tw.boot.extraPlugins,function(name) { if(name.charAt(0) === "+") { // Relative path to plugin - var pluginFields = $tw.loadPluginFolder(name.substring(1));; + var pluginFields = $tw.loadPluginFolder(name.substring(1)); if(pluginFields) { $tw.wiki.addTiddler(pluginFields); } diff --git a/core/modules/utils/filesystem.js b/core/modules/utils/filesystem.js index 7c77eb0d7..9ee2e8acd 100644 --- a/core/modules/utils/filesystem.js +++ b/core/modules/utils/filesystem.js @@ -206,12 +206,14 @@ Create a fileInfo object for saving a tiddler: filepath: the absolute path to the file containing the tiddler type: the type of the tiddler file on disk (NOT the type of the tiddler) hasMetaFile: true if the file also has a companion .meta file + isEditableFile: true if the tiddler was loaded via non-standard options & marked editable Options include: directory: absolute path of root directory to which we are saving pathFilters: optional array of filters to be used to generate the base path extFilters: optional array of filters to be used to generate the base path wiki: optional wiki for evaluating the pathFilters, fileInfo: an existing fileInfo to check against + originalpath: a preferred filepath if no pathFilters match */ exports.generateTiddlerFileInfo = function(tiddler,options) { var fileInfo = {}, metaExt; @@ -271,8 +273,13 @@ exports.generateTiddlerFileInfo = function(tiddler,options) { directory: options.directory, pathFilters: options.pathFilters, wiki: options.wiki, - fileInfo: options.fileInfo + fileInfo: options.fileInfo, + originalpath: options.originalpath }); + // Propigate the isEditableFile flag + if(options.fileInfo) { + fileInfo.isEditableFile = options.fileInfo.isEditableFile || false; + } return fileInfo; }; @@ -313,6 +320,7 @@ exports.generateTiddlerFilepath = function(title,options) { var self = this, directory = options.directory || "", extension = options.extension || "", + originalpath = options.originalpath || "", filepath; // Check if any of the pathFilters applies if(options.pathFilters && options.wiki) { @@ -326,7 +334,11 @@ exports.generateTiddlerFilepath = function(title,options) { } }); } - if(!filepath) { + if(!filepath && originalpath !== "") { + //Use the originalpath without the extension + var ext = path.extname(originalpath); + filepath = originalpath.substring(0,originalpath.length - ext.length);; + } else if(!filepath) { filepath = title; // If the filepath already ends in the extension then remove it if(filepath.substring(filepath.length - extension.length) === extension) { @@ -367,8 +379,8 @@ exports.generateTiddlerFilepath = function(title,options) { } count++; } while(fs.existsSync(fullPath)); - //If the path does not start with the wiki directory, or if the last write failed - var encode = fullPath.indexOf($tw.boot.wikiPath) !== 0 || ((options.fileInfo || {writeError: false}).writeError == true); + //If the path does not start with the wikiPath directory or the wikiTiddlersPath directory, or if the last write failed + var encode = !(fullPath.indexOf($tw.boot.wikiPath) == 0 || fullPath.indexOf($tw.boot.wikiTiddlersPath) == 0) || ((options.fileInfo || {writeError: false}).writeError == true); if(encode){ //encodeURIComponent() and then resolve to tiddler directory fullPath = path.resolve(directory, encodeURIComponent(fullPath)); diff --git a/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid b/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid index d13a6ce3b..3aef1351f 100644 --- a/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid +++ b/editions/tw5.com/tiddlers/nodejs/Customising Tiddler File Naming.tid @@ -4,13 +4,15 @@ tags: [[TiddlyWiki on Node.js]] title: Customising Tiddler File Naming type: text/vnd.tiddlywiki -By default, a [[TiddlyWiki on Node.js]] instance using a [[wiki folder|TiddlyWikiFolders]] will create new tiddler files by using the sanitised and disambiguated title as filename and write them to the wiki folder's `tiddlers/` directory. The default file extension of `.tid` is used for tiddlers that are missing the `type` field, or for tiddlers of type "text/vnd.tiddlywiki". Tidders of other types are saved according to their IMIE types (defined at boot startup). Both the logical path (directory and file name) and the file extension can be customized independently by creating optional tiddlers: [[$:/config/FileSystemPaths]] and [[$:/config/FileSystemExtensions]]. +By default, a [[TiddlyWiki on Node.js]] instance using a [[wiki folder|TiddlyWikiFolders]] will create new tiddler files by using the sanitised and disambiguated title as filename and write them to the wiki folder's `tiddlers/` directory. This can be overridden by mapping a path in the wiki's tiddlywiki.info file, using a `default-tiddler-location` property in the `config` object. All filepath operations are relative to this `$tw.boot.wikiTiddlersPath` internal javacript variable. + +The default file extension of `.tid` is used for tiddlers that are missing the `type` field, or for tiddlers of type "text/vnd.tiddlywiki". Tidders of other types are saved according to their IMIE types (defined at boot startup). Both the logical path (directory and file name) and the file extension can be customized independently by creating optional tiddlers: [[$:/config/FileSystemPaths]] and [[$:/config/FileSystemExtensions]]. ! File System Paths The logical path can be customised by creating a tiddler [[$:/config/FileSystemPaths]] containing one or more [[filter expressions|Filter Syntax]], each on a line of its own. Newly created tiddlers are matched to each filter in turn, and the first output of the first filter to produce any output is taken as a logical path to be used for the tiddler file. Tiddlers are also tested against the [[$:/config/FileSystemPaths]] on every save to disk, and if the logical path has changed a new file is created and the old file deleted. -Tiddlers are limited to being written to the [[wiki folder|TiddlyWikiFolders]]. Any error saving a tiddler to disk, with a logical path that does not start with the wiki folder's path the most common error, causes the filepath to be encoded via Javascript's `encodeURIComponent()` method and the tiddler is saved as this file in the wiki folder's `tiddlers/` directory. +Tiddlers are limited to being written to the [[wiki folder|TiddlyWikiFolders]]. Any error saving a tiddler to disk, with a logical path that does not start with the wiki folder's path the most common error, causes the filepath to be encoded via Javascript's `encodeURIComponent()` method and the tiddler is saved as this file in the wiki folder's `$tw.boot.wikiTiddlersPath` directory. Logical paths do not include the file-on-disk's extension (see below), and they can use `/` or `\` as directory separator (when generating the physical path, this is replaced by the correct separator for the platform ~TiddlyWiki is running on). If none of the filters matches, the logical path is simply the title with all occurences of `/` replaced by `_` (for backwards compatibility). @@ -22,13 +24,12 @@ In both cases, the characters `<>~:"\|?*^` are replaced by `_` in order to guara [is[system]!has[draft.of]removeprefix[$:/]addprefix[_system/]] [is[draft]search-replace:g:regexp[/|\\],[_]addprefix[drafts/]] [tag[task]addprefix[mytasks/]] -[tag[externalnote]addprefix[../externalnotes/]] -[addprefix[wiki/]] +[!tag[externalnote]addprefix[wiki/]] ``` -This will store newly created system tiddlers that are not drafts of other tiddlers in `tiddlers/_system` (after stripping the `$:/` prefix). Next, all drafts have the path seperator characters in their titles replaced by "_" and are stored in `tiddlers/drafts/`. Then tiddlers tagged [[task]] are stored in a subdirectory `tiddlers/mytasks/`. Next, all tiddlers tagged "externalnote" will be written to `<wikiFolder>/tiddlers/../externalnotes/`, which resolves to `<wikiFolder>/externalnotes/` and places these tiddlers outside of the tiddler folder. Use [[tiddlywiki.files Files|tiddlywiki.files_Files]] to reimport these tiddlers when the wiki server is restarted. Finally, all tidders will match the final `[addprefix[wiki/]]` storing these in `<wikiFolder>/tiddlers/wiki/`. +This will store newly created system tiddlers that are not drafts of other tiddlers in `tiddlers/_system` (after stripping the `$:/` prefix). Next, all drafts have the path seperator characters in their titles replaced by "_" and are stored in `tiddlers/drafts/`. Then tiddlers tagged [[task]] are stored in a subdirectory `tiddlers/mytasks/`. Finally, all tidders not tagged with "externalnote" will match the final `[!tag[externalnote]addprefix[wiki/]]` storing these in `/wiki/`. In this example, tiddlers tagged with "externalnote" have been imported using [[tiddlywiki.files Files|tiddlywiki.files_Files]] with an "isEditableFile" flag set to true, causing the server to remember their original file path. -Because there was a filter match, any `/` or `\` in the tiddler title is mapped to a path separator. With the above filters, the non-system, non-draft tiddler `some/thing/entirely/new` (with no tags) will be saved to `<wikiFolder>/tiddlers/wiki/some/thing/entirely/new.tid` (ie, the file `new.tid` in a directory called `entirely/`). Thus, $:/config/FileSystemPaths itself will end up in `tiddlers/_system/config/FileSystemPaths.tid` or `tiddlers\_system\config\FileSystemPaths.tid`, depending on the platform. +Whenever a tiddler generates a $:/config/FileSystemPaths filter match, any `/` or `\` in the tiddler title is mapped to a path separator. With the above filters, the non-system, non-draft tiddler `some/thing/entirely/new` (with no tags) will be saved to `<wikiFolder>/tiddlers/wiki/some/thing/entirely/new.tid` (ie, the file `new.tid` in a directory called `entirely/`). Thus, $:/config/FileSystemPaths itself will end up in `tiddlers/_system/config/FileSystemPaths.tid` or `tiddlers\_system\config\FileSystemPaths.tid`, depending on the platform. ! File System Extensions diff --git a/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid b/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid index 389643175..b519b6bf7 100644 --- a/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid +++ b/editions/tw5.com/tiddlers/nodejs/tiddlywiki.files_Files.tid @@ -51,7 +51,7 @@ Directory specifications in the `directories` array may take the following forms ** ''path'' - (required) the absolute or relative path to the directory containing the tiddler files (relative paths are interpreted relative to the path of the `tiddlywiki.files` file). Note that the directory is not recursively searched; sub-directories are ignored ** ''filesRegExp'' - (optional) a [[regular expression|https://developer.mozilla.org/en/docs/Web/JavaScript/Guide/Regular_Expressions]] that matches the filenames of the files that should be processed within the directory ** ''isTiddlerFile'' - (required) if `true`, the file will be treated as a [[tiddler file|TiddlerFiles]] and deserialised to extract the tiddlers. Otherwise, the raw content of the file is assigned to the `text` field without any parsing -** ''isEditableFile'' - (optional) if `true`, changes to the tiddler be saved back to the original file. The ''path'' of the current directory being read must be within the wiki's base directory, and a $:/config/FileSystemPath filter is required to add the correct logical path to the tiddler's title (see second **Example**). <<.from-version "5.1.23">> +** ''isEditableFile'' - (optional) if `true`, changes to the tiddler be saved back to the original file. The tiddler will be saved back to the original filepath as long as it does not generate a result from the $:/config/FileSystemPath filters, which will override the final filepath generated if a result is returned from a filter. <<.from-version "5.1.23">> ** ''fields'' - (required) an object containing values that override or customise the fields provided in the tiddler file (see above) Fields can be overridden for particular files by creating a file with the same name plus the suffix `.meta` -- see TiddlerFiles. @@ -102,7 +102,7 @@ This example retrieves all the files with the extension `.txt` from a folder spe * ''created'' - set to the creation date/time of the text file * ''modified'' - set to the modification date/time of the text file * ''type'' - set to `text/plain` -* ''tags'' - set to `[[note]] [[externalnote]]` (using array notation) +* ''tags'' - set to `[[note]] [[externalnote]] [[.txt]]` (using array notation) * ''text'' - not set, thus the content of the file is loaded as the text field ``` @@ -125,8 +125,8 @@ This example retrieves all the files with the extension `.txt` from a folder spe } ``` -This will load all text files in the `<wikiBase>/externalnotes/` directory into the wiki as individual tiddlers. These can be a collection of snippets in various markup-languages. Then, the `type` field of each of these tiddlers can be changed to match their languages For example, "text/vnd.tiddlywiki" for wikitext, or "text/markdown" for markdown files. Then, using $:/config/FileSystemPaths and $:/config/FileSystemExtentions tiddlers with the following lines we can cause any changes to these tiddlers to be saved back to the directory they started from, and as "*.txt" files with accompanying "*.txt.meta" files. These meta files will then over-ride any fields generated from the config `tiddlywiki.files` file (such as the tiddler's `type` field) when the server is restarted. +This will load all text files in the `../../externalnotes/` directory into the wiki as individual tiddlers. These can be a collection of snippets in various markup-languages. Then, the `type` field of each of these tiddlers can be changed to match their languages For example, "text/vnd.tiddlywiki" for wikitext, or "text/markdown" for markdown files. Then, using $:/config/FileSystemPaths and $:/config/FileSystemExtentions tiddlers with the following lines we can cause any changes to these tiddlers to be saved back to the directory they started from, and also as "*.txt" files with accompanying "*.txt.meta" files. These meta files will be generated as required, and will then over-ride any fields generated from the config `tiddlywiki.files` file (such as the tiddler's `type` field) when the server is restarted. -From the examples in [[Customising Tiddler File Naming]] we see that the `[tag[externalnote]addprefix[../externalnotes/]]` filter in the $:/config/FileSystemPaths tiddler catches all tiddlers tagged with `externalnotes` (that have not matched an earlier filter). These tiddlers have "../externalnotes/" appended to their titles to render the final logical path. As this path starts in the wiki's "tiddlers/" folder by default (one folder above the folder holding the above config file) it differes by one set of "../". +From the examples in [[Customising Tiddler File Naming]] we see that the final `[!tag[externalnote]addprefix[wiki/]]` filter in the $:/config/FileSystemPaths tiddler excludes all tiddlers tagged with `externalnotes` (that have not matched an earlier filter). These tiddlers have their filepath retrieved from the $:/config/OriginalTiddlerPaths generated upon boot startup. -Then, the `[tag[.txt]then[.txt]]` filter in the $:/config/FileSystemExtensions tiddler forces all these text files (which start with tag ".txt") to be saved back to disk as *.txt and accompanying *.txt.meta files (overriding the normal tiddler-type to file-type mapping). In this case, allowing the snippets of Tiddlywiki wikitext or markdown-text to be saved back to "text" *.txt files. \ No newline at end of file +Then, the `[tag[.txt]then[.txt]]` filter in the $:/config/FileSystemExtensions tiddler forces all these tiddlers to be saved back to disk as *.txt and accompanying *.txt.meta files (overriding the normal tiddler-type to file-type mapping). In this case, allowing the snippets of Tiddlywiki wikitext or markdown-text to be saved back to "text" *.txt files. \ No newline at end of file diff --git a/plugins/tiddlywiki/filesystem/filesystemadaptor.js b/plugins/tiddlywiki/filesystem/filesystemadaptor.js index fce2eaeaa..5cef917bf 100644 --- a/plugins/tiddlywiki/filesystem/filesystemadaptor.js +++ b/plugins/tiddlywiki/filesystem/filesystemadaptor.js @@ -52,16 +52,15 @@ The type is found by looking up the extension in $tw.config.fileExtensionInfo (e It is the responsibility of the filesystem adaptor to update this.boot.files for new files that are created. */ FileSystemAdaptor.prototype.getTiddlerFileInfo = function(tiddler,callback) { - // See if we've already got information about this file - var title = tiddler.fields.title, - newInfo, fileInfo = this.boot.files[title]; // Always generate a fileInfo object when this fuction is called + var title = tiddler.fields.title, newInfo; newInfo = $tw.utils.generateTiddlerFileInfo(tiddler,{ directory: this.boot.wikiTiddlersPath, pathFilters: this.wiki.getTiddlerText("$:/config/FileSystemPaths","").split("\n"), extFilters: this.wiki.getTiddlerText("$:/config/FileSystemExtensions","").split("\n"), wiki: this.wiki, - fileInfo: fileInfo + fileInfo: this.boot.files[title], + originalpath: this.wiki.extractTiddlerDataItem("$:/config/OriginalTiddlerPaths",title, "") }); this.boot.files[title] = newInfo; callback(null,newInfo); From fc797f3722b44141606b8362e43c5517729d37a5 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 2 Dec 2020 13:21:02 +0100 Subject: [PATCH 105/124] Fix #5162 - tiddler opening position is incorrect, bug in navigator.js --- core/modules/widgets/navigator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/modules/widgets/navigator.js b/core/modules/widgets/navigator.js index c44a24afb..2f8e2421e 100755 --- a/core/modules/widgets/navigator.js +++ b/core/modules/widgets/navigator.js @@ -128,7 +128,7 @@ NavigatorWidget.prototype.replaceFirstTitleInStory = function(storyList,oldTitle NavigatorWidget.prototype.addToStory = function(title,fromTitle) { if(this.storyTitle) { - this.story.addToStory(title,fromTitle,this.storyTitle,{ + this.story.addToStory(title,fromTitle,{ openLinkFromInsideRiver: this.getAttribute("openLinkFromInsideRiver","top"), openLinkFromOutsideRiver: this.getAttribute("openLinkFromOutsideRiver","top") }); From a1ef66ec6ddaa4bd929ebe19bbb260dbf8b0fb4a Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 2 Dec 2020 13:21:23 +0100 Subject: [PATCH 106/124] Better readability for codemirror linenumbers + CupertinoDark muted-foreground better contrast (#5164) * Update styles.tid * Update CupertinoDark.tid --- core/palettes/CupertinoDark.tid | 2 +- plugins/tiddlywiki/codemirror/styles.tid | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index 0880054ca..f97cab56d 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -42,7 +42,7 @@ modal-border: <<colour very-muted-foreground>> modal-footer-background: <<colour background>> modal-footer-border: <<colour background>> modal-header-border: <<colour very-muted-foreground>> -muted-foreground: #464646 +muted-foreground: #98989D notification-background: <<colour dropdown-background>> notification-border: <<colour dropdown-background>> page-background: #323232 diff --git a/plugins/tiddlywiki/codemirror/styles.tid b/plugins/tiddlywiki/codemirror/styles.tid index 135584b2a..4b57f664d 100755 --- a/plugins/tiddlywiki/codemirror/styles.tid +++ b/plugins/tiddlywiki/codemirror/styles.tid @@ -25,7 +25,7 @@ name: tiddlywiki .cm-s-tiddlywiki.CodeMirror, .cm-s-tiddlywiki .CodeMirror-gutters { background-color: <<colour tiddler-editor-background>>; color: <<colour foreground>>; } .cm-s-tiddlywiki .CodeMirror-gutters {background: <<colour tiddler-editor-background>>; border-right: 0px;} -.cm-s-tiddlywiki .CodeMirror-linenumber {color: <<colour primary>>;} +.cm-s-tiddlywiki .CodeMirror-linenumber {color: <<colour foreground>>;} .cm-s-tiddlywiki .CodeMirror-cursor { border-left: 2px solid <<colour foreground>>; } .cm-s-tiddlywiki div.CodeMirror-selected { background: <<colour selection-background>>; } .cm-s-tiddlywiki .CodeMirror-selectedtext, @@ -38,7 +38,7 @@ name: tiddlywiki .cm-s-tiddlywiki .CodeMirror-line > span > span::-moz-selection { background: <<colour selection-background>>; } .cm-s-tiddlywiki span.cm-comment { color: <<colour muted-foreground>>; font-style:italic; font-weight:normal; } .cm-s-tiddlywiki .CodeMirror-activeline-background, .cm-s-tiddlywiki .CodeMirror-activeline-gutter .CodeMirror-linenumber { background: <<colour background>>; } -.cm-s-tiddlywiki .CodeMirror-activeline .CodeMirror-linenumber.CodeMirror-gutter-elt { background: <<colour background>>; color: <<colour foreground>>; } +.cm-s-tiddlywiki .CodeMirror-activeline .CodeMirror-linenumber.CodeMirror-gutter-elt { background: <<colour primary>>; color: <<colour foreground>>; } .cm-s-tiddlywiki .CodeMirror-matchingbracket { background: <<colour primary>>; color:<<colour foreground>> !important; } .cm-s-tiddlywiki span.cm-matchhighlight { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} .cm-s-tiddlywiki span.cm-searching { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} From 9871c1a6a9b495c6b3532a672b491907b8697822 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 2 Dec 2020 17:54:36 +0100 Subject: [PATCH 107/124] Small tweak for codemirror selected-linenumber (#5181) --- plugins/tiddlywiki/codemirror/styles.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/codemirror/styles.tid b/plugins/tiddlywiki/codemirror/styles.tid index 4b57f664d..2c44f8d1a 100755 --- a/plugins/tiddlywiki/codemirror/styles.tid +++ b/plugins/tiddlywiki/codemirror/styles.tid @@ -38,7 +38,7 @@ name: tiddlywiki .cm-s-tiddlywiki .CodeMirror-line > span > span::-moz-selection { background: <<colour selection-background>>; } .cm-s-tiddlywiki span.cm-comment { color: <<colour muted-foreground>>; font-style:italic; font-weight:normal; } .cm-s-tiddlywiki .CodeMirror-activeline-background, .cm-s-tiddlywiki .CodeMirror-activeline-gutter .CodeMirror-linenumber { background: <<colour background>>; } -.cm-s-tiddlywiki .CodeMirror-activeline .CodeMirror-linenumber.CodeMirror-gutter-elt { background: <<colour primary>>; color: <<colour foreground>>; } +.cm-s-tiddlywiki .CodeMirror-activeline .CodeMirror-linenumber.CodeMirror-gutter-elt { background: <<colour primary>>; color: <<colour background>>; } .cm-s-tiddlywiki .CodeMirror-matchingbracket { background: <<colour primary>>; color:<<colour foreground>> !important; } .cm-s-tiddlywiki span.cm-matchhighlight { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} .cm-s-tiddlywiki span.cm-searching { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} From f0eba7fdc629c805ab185373870e8841b16bd4ac Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 2 Dec 2020 17:55:37 +0100 Subject: [PATCH 108/124] Re-add minified codemirror, without minification bug (#5180) --- .../tiddlywiki/codemirror/files/codemirror.js | 9798 +---------------- 1 file changed, 1 insertion(+), 9797 deletions(-) diff --git a/plugins/tiddlywiki/codemirror/files/codemirror.js b/plugins/tiddlywiki/codemirror/files/codemirror.js index 0436a9968..cd4b00d89 100755 --- a/plugins/tiddlywiki/codemirror/files/codemirror.js +++ b/plugins/tiddlywiki/codemirror/files/codemirror.js @@ -1,9797 +1 @@ -// CodeMirror, copyright (c) by Marijn Haverbeke and others -// Distributed under an MIT license: https://codemirror.net/LICENSE - -// This is CodeMirror (https://codemirror.net), a code editor -// implemented in JavaScript on top of the browser's DOM. -// -// You can find some technical background for some of the code below -// at http://marijnhaverbeke.nl/blog/#cm-internals . - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : - typeof define === 'function' && define.amd ? define(factory) : - (global = global || self, global.CodeMirror = factory()); -}(this, (function () { 'use strict'; - - // Kludges for bugs and behavior differences that can't be feature - // detected are enabled based on userAgent etc sniffing. - var userAgent = navigator.userAgent; - var platform = navigator.platform; - - var gecko = /gecko\/\d/i.test(userAgent); - var ie_upto10 = /MSIE \d/.test(userAgent); - var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(userAgent); - var edge = /Edge\/(\d+)/.exec(userAgent); - var ie = ie_upto10 || ie_11up || edge; - var ie_version = ie && (ie_upto10 ? document.documentMode || 6 : +(edge || ie_11up)[1]); - var webkit = !edge && /WebKit\//.test(userAgent); - var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(userAgent); - var chrome = !edge && /Chrome\//.test(userAgent); - var presto = /Opera\//.test(userAgent); - var safari = /Apple Computer/.test(navigator.vendor); - var mac_geMountainLion = /Mac OS X 1\d\D([8-9]|\d\d)\D/.test(userAgent); - var phantom = /PhantomJS/.test(userAgent); - - var ios = !edge && /AppleWebKit/.test(userAgent) && /Mobile\/\w+/.test(userAgent); - var android = /Android/.test(userAgent); - // This is woefully incomplete. Suggestions for alternative methods welcome. - var mobile = ios || android || /webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(userAgent); - var mac = ios || /Mac/.test(platform); - var chromeOS = /\bCrOS\b/.test(userAgent); - var windows = /win/i.test(platform); - - var presto_version = presto && userAgent.match(/Version\/(\d*\.\d*)/); - if (presto_version) { presto_version = Number(presto_version[1]); } - if (presto_version && presto_version >= 15) { presto = false; webkit = true; } - // Some browsers use the wrong event properties to signal cmd/ctrl on OS X - var flipCtrlCmd = mac && (qtwebkit || presto && (presto_version == null || presto_version < 12.11)); - var captureRightClick = gecko || (ie && ie_version >= 9); - - function classTest(cls) { return new RegExp("(^|\\s)" + cls + "(?:$|\\s)\\s*") } - - var rmClass = function(node, cls) { - var current = node.className; - var match = classTest(cls).exec(current); - if (match) { - var after = current.slice(match.index + match[0].length); - node.className = current.slice(0, match.index) + (after ? match[1] + after : ""); - } - }; - - function removeChildren(e) { - for (var count = e.childNodes.length; count > 0; --count) - { e.removeChild(e.firstChild); } - return e - } - - function removeChildrenAndAdd(parent, e) { - return removeChildren(parent).appendChild(e) - } - - function elt(tag, content, className, style) { - var e = document.createElement(tag); - if (className) { e.className = className; } - if (style) { e.style.cssText = style; } - if (typeof content == "string") { e.appendChild(document.createTextNode(content)); } - else if (content) { for (var i = 0; i < content.length; ++i) { e.appendChild(content[i]); } } - return e - } - // wrapper for elt, which removes the elt from the accessibility tree - function eltP(tag, content, className, style) { - var e = elt(tag, content, className, style); - e.setAttribute("role", "presentation"); - return e - } - - var range; - if (document.createRange) { range = function(node, start, end, endNode) { - var r = document.createRange(); - r.setEnd(endNode || node, end); - r.setStart(node, start); - return r - }; } - else { range = function(node, start, end) { - var r = document.body.createTextRange(); - try { r.moveToElementText(node.parentNode); } - catch(e) { return r } - r.collapse(true); - r.moveEnd("character", end); - r.moveStart("character", start); - return r - }; } - - function contains(parent, child) { - if (child.nodeType == 3) // Android browser always returns false when child is a textnode - { child = child.parentNode; } - if (parent.contains) - { return parent.contains(child) } - do { - if (child.nodeType == 11) { child = child.host; } - if (child == parent) { return true } - } while (child = child.parentNode) - } - - function activeElt() { - // IE and Edge may throw an "Unspecified Error" when accessing document.activeElement. - // IE < 10 will throw when accessed while the page is loading or in an iframe. - // IE > 9 and Edge will throw when accessed in an iframe if document.body is unavailable. - var activeElement; - try { - activeElement = document.activeElement; - } catch(e) { - activeElement = document.body || null; - } - while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) - { activeElement = activeElement.shadowRoot.activeElement; } - return activeElement - } - - function addClass(node, cls) { - var current = node.className; - if (!classTest(cls).test(current)) { node.className += (current ? " " : "") + cls; } - } - function joinClasses(a, b) { - var as = a.split(" "); - for (var i = 0; i < as.length; i++) - { if (as[i] && !classTest(as[i]).test(b)) { b += " " + as[i]; } } - return b - } - - var selectInput = function(node) { node.select(); }; - if (ios) // Mobile Safari apparently has a bug where select() is broken. - { selectInput = function(node) { node.selectionStart = 0; node.selectionEnd = node.value.length; }; } - else if (ie) // Suppress mysterious IE10 errors - { selectInput = function(node) { try { node.select(); } catch(_e) {} }; } - - function bind(f) { - var args = Array.prototype.slice.call(arguments, 1); - return function(){return f.apply(null, args)} - } - - function copyObj(obj, target, overwrite) { - if (!target) { target = {}; } - for (var prop in obj) - { if (obj.hasOwnProperty(prop) && (overwrite !== false || !target.hasOwnProperty(prop))) - { target[prop] = obj[prop]; } } - return target - } - - // Counts the column offset in a string, taking tabs into account. - // Used mostly to find indentation. - function countColumn(string, end, tabSize, startIndex, startValue) { - if (end == null) { - end = string.search(/[^\s\u00a0]/); - if (end == -1) { end = string.length; } - } - for (var i = startIndex || 0, n = startValue || 0;;) { - var nextTab = string.indexOf("\t", i); - if (nextTab < 0 || nextTab >= end) - { return n + (end - i) } - n += nextTab - i; - n += tabSize - (n % tabSize); - i = nextTab + 1; - } - } - - var Delayed = function() { - this.id = null; - this.f = null; - this.time = 0; - this.handler = bind(this.onTimeout, this); - }; - Delayed.prototype.onTimeout = function (self) { - self.id = 0; - if (self.time <= +new Date) { - self.f(); - } else { - setTimeout(self.handler, self.time - +new Date); - } - }; - Delayed.prototype.set = function (ms, f) { - this.f = f; - var time = +new Date + ms; - if (!this.id || time < this.time) { - clearTimeout(this.id); - this.id = setTimeout(this.handler, ms); - this.time = time; - } - }; - - function indexOf(array, elt) { - for (var i = 0; i < array.length; ++i) - { if (array[i] == elt) { return i } } - return -1 - } - - // Number of pixels added to scroller and sizer to hide scrollbar - var scrollerGap = 50; - - // Returned or thrown by various protocols to signal 'I'm not - // handling this'. - var Pass = {toString: function(){return "CodeMirror.Pass"}}; - - // Reused option objects for setSelection & friends - var sel_dontScroll = {scroll: false}, sel_mouse = {origin: "*mouse"}, sel_move = {origin: "+move"}; - - // The inverse of countColumn -- find the offset that corresponds to - // a particular column. - function findColumn(string, goal, tabSize) { - for (var pos = 0, col = 0;;) { - var nextTab = string.indexOf("\t", pos); - if (nextTab == -1) { nextTab = string.length; } - var skipped = nextTab - pos; - if (nextTab == string.length || col + skipped >= goal) - { return pos + Math.min(skipped, goal - col) } - col += nextTab - pos; - col += tabSize - (col % tabSize); - pos = nextTab + 1; - if (col >= goal) { return pos } - } - } - - var spaceStrs = [""]; - function spaceStr(n) { - while (spaceStrs.length <= n) - { spaceStrs.push(lst(spaceStrs) + " "); } - return spaceStrs[n] - } - - function lst(arr) { return arr[arr.length-1] } - - function map(array, f) { - var out = []; - for (var i = 0; i < array.length; i++) { out[i] = f(array[i], i); } - return out - } - - function insertSorted(array, value, score) { - var pos = 0, priority = score(value); - while (pos < array.length && score(array[pos]) <= priority) { pos++; } - array.splice(pos, 0, value); - } - - function nothing() {} - - function createObj(base, props) { - var inst; - if (Object.create) { - inst = Object.create(base); - } else { - nothing.prototype = base; - inst = new nothing(); - } - if (props) { copyObj(props, inst); } - return inst - } - - var nonASCIISingleCaseWordChar = /[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/; - function isWordCharBasic(ch) { - return /\w/.test(ch) || ch > "\x80" && - (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)) - } - function isWordChar(ch, helper) { - if (!helper) { return isWordCharBasic(ch) } - if (helper.source.indexOf("\\w") > -1 && isWordCharBasic(ch)) { return true } - return helper.test(ch) - } - - function isEmpty(obj) { - for (var n in obj) { if (obj.hasOwnProperty(n) && obj[n]) { return false } } - return true - } - - // Extending unicode characters. A series of a non-extending char + - // any number of extending chars is treated as a single unit as far - // as editing and measuring is concerned. This is not fully correct, - // since some scripts/fonts/browsers also treat other configurations - // of code points as a group. - var extendingChars = /[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/; - function isExtendingChar(ch) { return ch.charCodeAt(0) >= 768 && extendingChars.test(ch) } - - // Returns a number from the range [`0`; `str.length`] unless `pos` is outside that range. - function skipExtendingChars(str, pos, dir) { - while ((dir < 0 ? pos > 0 : pos < str.length) && isExtendingChar(str.charAt(pos))) { pos += dir; } - return pos - } - - // Returns the value from the range [`from`; `to`] that satisfies - // `pred` and is closest to `from`. Assumes that at least `to` - // satisfies `pred`. Supports `from` being greater than `to`. - function findFirst(pred, from, to) { - // At any point we are certain `to` satisfies `pred`, don't know - // whether `from` does. - var dir = from > to ? -1 : 1; - for (;;) { - if (from == to) { return from } - var midF = (from + to) / 2, mid = dir < 0 ? Math.ceil(midF) : Math.floor(midF); - if (mid == from) { return pred(mid) ? from : to } - if (pred(mid)) { to = mid; } - else { from = mid + dir; } - } - } - - // BIDI HELPERS - - function iterateBidiSections(order, from, to, f) { - if (!order) { return f(from, to, "ltr", 0) } - var found = false; - for (var i = 0; i < order.length; ++i) { - var part = order[i]; - if (part.from < to && part.to > from || from == to && part.to == from) { - f(Math.max(part.from, from), Math.min(part.to, to), part.level == 1 ? "rtl" : "ltr", i); - found = true; - } - } - if (!found) { f(from, to, "ltr"); } - } - - var bidiOther = null; - function getBidiPartAt(order, ch, sticky) { - var found; - bidiOther = null; - for (var i = 0; i < order.length; ++i) { - var cur = order[i]; - if (cur.from < ch && cur.to > ch) { return i } - if (cur.to == ch) { - if (cur.from != cur.to && sticky == "before") { found = i; } - else { bidiOther = i; } - } - if (cur.from == ch) { - if (cur.from != cur.to && sticky != "before") { found = i; } - else { bidiOther = i; } - } - } - return found != null ? found : bidiOther - } - - // Bidirectional ordering algorithm - // See http://unicode.org/reports/tr9/tr9-13.html for the algorithm - // that this (partially) implements. - - // One-char codes used for character types: - // L (L): Left-to-Right - // R (R): Right-to-Left - // r (AL): Right-to-Left Arabic - // 1 (EN): European Number - // + (ES): European Number Separator - // % (ET): European Number Terminator - // n (AN): Arabic Number - // , (CS): Common Number Separator - // m (NSM): Non-Spacing Mark - // b (BN): Boundary Neutral - // s (B): Paragraph Separator - // t (S): Segment Separator - // w (WS): Whitespace - // N (ON): Other Neutrals - - // Returns null if characters are ordered as they appear - // (left-to-right), or an array of sections ({from, to, level} - // objects) in the order in which they occur visually. - var bidiOrdering = (function() { - // Character types for codepoints 0 to 0xff - var lowTypes = "bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN"; - // Character types for codepoints 0x600 to 0x6f9 - var arabicTypes = "nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111"; - function charType(code) { - if (code <= 0xf7) { return lowTypes.charAt(code) } - else if (0x590 <= code && code <= 0x5f4) { return "R" } - else if (0x600 <= code && code <= 0x6f9) { return arabicTypes.charAt(code - 0x600) } - else if (0x6ee <= code && code <= 0x8ac) { return "r" } - else if (0x2000 <= code && code <= 0x200b) { return "w" } - else if (code == 0x200c) { return "b" } - else { return "L" } - } - - var bidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/; - var isNeutral = /[stwN]/, isStrong = /[LRr]/, countsAsLeft = /[Lb1n]/, countsAsNum = /[1n]/; - - function BidiSpan(level, from, to) { - this.level = level; - this.from = from; this.to = to; - } - - return function(str, direction) { - var outerType = direction == "ltr" ? "L" : "R"; - - if (str.length == 0 || direction == "ltr" && !bidiRE.test(str)) { return false } - var len = str.length, types = []; - for (var i = 0; i < len; ++i) - { types.push(charType(str.charCodeAt(i))); } - - // W1. Examine each non-spacing mark (NSM) in the level run, and - // change the type of the NSM to the type of the previous - // character. If the NSM is at the start of the level run, it will - // get the type of sor. - for (var i$1 = 0, prev = outerType; i$1 < len; ++i$1) { - var type = types[i$1]; - if (type == "m") { types[i$1] = prev; } - else { prev = type; } - } - - // W2. Search backwards from each instance of a European number - // until the first strong type (R, L, AL, or sor) is found. If an - // AL is found, change the type of the European number to Arabic - // number. - // W3. Change all ALs to R. - for (var i$2 = 0, cur = outerType; i$2 < len; ++i$2) { - var type$1 = types[i$2]; - if (type$1 == "1" && cur == "r") { types[i$2] = "n"; } - else if (isStrong.test(type$1)) { cur = type$1; if (type$1 == "r") { types[i$2] = "R"; } } - } - - // W4. A single European separator between two European numbers - // changes to a European number. A single common separator between - // two numbers of the same type changes to that type. - for (var i$3 = 1, prev$1 = types[0]; i$3 < len - 1; ++i$3) { - var type$2 = types[i$3]; - if (type$2 == "+" && prev$1 == "1" && types[i$3+1] == "1") { types[i$3] = "1"; } - else if (type$2 == "," && prev$1 == types[i$3+1] && - (prev$1 == "1" || prev$1 == "n")) { types[i$3] = prev$1; } - prev$1 = type$2; - } - - // W5. A sequence of European terminators adjacent to European - // numbers changes to all European numbers. - // W6. Otherwise, separators and terminators change to Other - // Neutral. - for (var i$4 = 0; i$4 < len; ++i$4) { - var type$3 = types[i$4]; - if (type$3 == ",") { types[i$4] = "N"; } - else if (type$3 == "%") { - var end = (void 0); - for (end = i$4 + 1; end < len && types[end] == "%"; ++end) {} - var replace = (i$4 && types[i$4-1] == "!") || (end < len && types[end] == "1") ? "1" : "N"; - for (var j = i$4; j < end; ++j) { types[j] = replace; } - i$4 = end - 1; - } - } - - // W7. Search backwards from each instance of a European number - // until the first strong type (R, L, or sor) is found. If an L is - // found, then change the type of the European number to L. - for (var i$5 = 0, cur$1 = outerType; i$5 < len; ++i$5) { - var type$4 = types[i$5]; - if (cur$1 == "L" && type$4 == "1") { types[i$5] = "L"; } - else if (isStrong.test(type$4)) { cur$1 = type$4; } - } - - // N1. A sequence of neutrals takes the direction of the - // surrounding strong text if the text on both sides has the same - // direction. European and Arabic numbers act as if they were R in - // terms of their influence on neutrals. Start-of-level-run (sor) - // and end-of-level-run (eor) are used at level run boundaries. - // N2. Any remaining neutrals take the embedding direction. - for (var i$6 = 0; i$6 < len; ++i$6) { - if (isNeutral.test(types[i$6])) { - var end$1 = (void 0); - for (end$1 = i$6 + 1; end$1 < len && isNeutral.test(types[end$1]); ++end$1) {} - var before = (i$6 ? types[i$6-1] : outerType) == "L"; - var after = (end$1 < len ? types[end$1] : outerType) == "L"; - var replace$1 = before == after ? (before ? "L" : "R") : outerType; - for (var j$1 = i$6; j$1 < end$1; ++j$1) { types[j$1] = replace$1; } - i$6 = end$1 - 1; - } - } - - // Here we depart from the documented algorithm, in order to avoid - // building up an actual levels array. Since there are only three - // levels (0, 1, 2) in an implementation that doesn't take - // explicit embedding into account, we can build up the order on - // the fly, without following the level-based algorithm. - var order = [], m; - for (var i$7 = 0; i$7 < len;) { - if (countsAsLeft.test(types[i$7])) { - var start = i$7; - for (++i$7; i$7 < len && countsAsLeft.test(types[i$7]); ++i$7) {} - order.push(new BidiSpan(0, start, i$7)); - } else { - var pos = i$7, at = order.length, isRTL = direction == "rtl" ? 1 : 0; - for (++i$7; i$7 < len && types[i$7] != "L"; ++i$7) {} - for (var j$2 = pos; j$2 < i$7;) { - if (countsAsNum.test(types[j$2])) { - if (pos < j$2) { order.splice(at, 0, new BidiSpan(1, pos, j$2)); at += isRTL; } - var nstart = j$2; - for (++j$2; j$2 < i$7 && countsAsNum.test(types[j$2]); ++j$2) {} - order.splice(at, 0, new BidiSpan(2, nstart, j$2)); - at += isRTL; - pos = j$2; - } else { ++j$2; } - } - if (pos < i$7) { order.splice(at, 0, new BidiSpan(1, pos, i$7)); } - } - } - if (direction == "ltr") { - if (order[0].level == 1 && (m = str.match(/^\s+/))) { - order[0].from = m[0].length; - order.unshift(new BidiSpan(0, 0, m[0].length)); - } - if (lst(order).level == 1 && (m = str.match(/\s+$/))) { - lst(order).to -= m[0].length; - order.push(new BidiSpan(0, len - m[0].length, len)); - } - } - - return direction == "rtl" ? order.reverse() : order - } - })(); - - // Get the bidi ordering for the given line (and cache it). Returns - // false for lines that are fully left-to-right, and an array of - // BidiSpan objects otherwise. - function getOrder(line, direction) { - var order = line.order; - if (order == null) { order = line.order = bidiOrdering(line.text, direction); } - return order - } - - // EVENT HANDLING - - // Lightweight event framework. on/off also work on DOM nodes, - // registering native DOM handlers. - - var noHandlers = []; - - var on = function(emitter, type, f) { - if (emitter.addEventListener) { - emitter.addEventListener(type, f, false); - } else if (emitter.attachEvent) { - emitter.attachEvent("on" + type, f); - } else { - var map = emitter._handlers || (emitter._handlers = {}); - map[type] = (map[type] || noHandlers).concat(f); - } - }; - - function getHandlers(emitter, type) { - return emitter._handlers && emitter._handlers[type] || noHandlers - } - - function off(emitter, type, f) { - if (emitter.removeEventListener) { - emitter.removeEventListener(type, f, false); - } else if (emitter.detachEvent) { - emitter.detachEvent("on" + type, f); - } else { - var map = emitter._handlers, arr = map && map[type]; - if (arr) { - var index = indexOf(arr, f); - if (index > -1) - { map[type] = arr.slice(0, index).concat(arr.slice(index + 1)); } - } - } - } - - function signal(emitter, type /*, values...*/) { - var handlers = getHandlers(emitter, type); - if (!handlers.length) { return } - var args = Array.prototype.slice.call(arguments, 2); - for (var i = 0; i < handlers.length; ++i) { handlers[i].apply(null, args); } - } - - // The DOM events that CodeMirror handles can be overridden by - // registering a (non-DOM) handler on the editor for the event name, - // and preventDefault-ing the event in that handler. - function signalDOMEvent(cm, e, override) { - if (typeof e == "string") - { e = {type: e, preventDefault: function() { this.defaultPrevented = true; }}; } - signal(cm, override || e.type, cm, e); - return e_defaultPrevented(e) || e.codemirrorIgnore - } - - function signalCursorActivity(cm) { - var arr = cm._handlers && cm._handlers.cursorActivity; - if (!arr) { return } - var set = cm.curOp.cursorActivityHandlers || (cm.curOp.cursorActivityHandlers = []); - for (var i = 0; i < arr.length; ++i) { if (indexOf(set, arr[i]) == -1) - { set.push(arr[i]); } } - } - - function hasHandler(emitter, type) { - return getHandlers(emitter, type).length > 0 - } - - // Add on and off methods to a constructor's prototype, to make - // registering events on such objects more convenient. - function eventMixin(ctor) { - ctor.prototype.on = function(type, f) {on(this, type, f);}; - ctor.prototype.off = function(type, f) {off(this, type, f);}; - } - - // Due to the fact that we still support jurassic IE versions, some - // compatibility wrappers are needed. - - function e_preventDefault(e) { - if (e.preventDefault) { e.preventDefault(); } - else { e.returnValue = false; } - } - function e_stopPropagation(e) { - if (e.stopPropagation) { e.stopPropagation(); } - else { e.cancelBubble = true; } - } - function e_defaultPrevented(e) { - return e.defaultPrevented != null ? e.defaultPrevented : e.returnValue == false - } - function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} - - function e_target(e) {return e.target || e.srcElement} - function e_button(e) { - var b = e.which; - if (b == null) { - if (e.button & 1) { b = 1; } - else if (e.button & 2) { b = 3; } - else if (e.button & 4) { b = 2; } - } - if (mac && e.ctrlKey && b == 1) { b = 3; } - return b - } - - // Detect drag-and-drop - var dragAndDrop = function() { - // There is *some* kind of drag-and-drop support in IE6-8, but I - // couldn't get it to work yet. - if (ie && ie_version < 9) { return false } - var div = elt('div'); - return "draggable" in div || "dragDrop" in div - }(); - - var zwspSupported; - function zeroWidthElement(measure) { - if (zwspSupported == null) { - var test = elt("span", "\u200b"); - removeChildrenAndAdd(measure, elt("span", [test, document.createTextNode("x")])); - if (measure.firstChild.offsetHeight != 0) - { zwspSupported = test.offsetWidth <= 1 && test.offsetHeight > 2 && !(ie && ie_version < 8); } - } - var node = zwspSupported ? elt("span", "\u200b") : - elt("span", "\u00a0", null, "display: inline-block; width: 1px; margin-right: -1px"); - node.setAttribute("cm-text", ""); - return node - } - - // Feature-detect IE's crummy client rect reporting for bidi text - var badBidiRects; - function hasBadBidiRects(measure) { - if (badBidiRects != null) { return badBidiRects } - var txt = removeChildrenAndAdd(measure, document.createTextNode("A\u062eA")); - var r0 = range(txt, 0, 1).getBoundingClientRect(); - var r1 = range(txt, 1, 2).getBoundingClientRect(); - removeChildren(measure); - if (!r0 || r0.left == r0.right) { return false } // Safari returns null in some cases (#2780) - return badBidiRects = (r1.right - r0.right < 3) - } - - // See if "".split is the broken IE version, if so, provide an - // alternative way to split lines. - var splitLinesAuto = "\n\nb".split(/\n/).length != 3 ? function (string) { - var pos = 0, result = [], l = string.length; - while (pos <= l) { - var nl = string.indexOf("\n", pos); - if (nl == -1) { nl = string.length; } - var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); - var rt = line.indexOf("\r"); - if (rt != -1) { - result.push(line.slice(0, rt)); - pos += rt + 1; - } else { - result.push(line); - pos = nl + 1; - } - } - return result - } : function (string) { return string.split(/\r\n?|\n/); }; - - var hasSelection = window.getSelection ? function (te) { - try { return te.selectionStart != te.selectionEnd } - catch(e) { return false } - } : function (te) { - var range; - try {range = te.ownerDocument.selection.createRange();} - catch(e) {} - if (!range || range.parentElement() != te) { return false } - return range.compareEndPoints("StartToEnd", range) != 0 - }; - - var hasCopyEvent = (function () { - var e = elt("div"); - if ("oncopy" in e) { return true } - e.setAttribute("oncopy", "return;"); - return typeof e.oncopy == "function" - })(); - - var badZoomedRects = null; - function hasBadZoomedRects(measure) { - if (badZoomedRects != null) { return badZoomedRects } - var node = removeChildrenAndAdd(measure, elt("span", "x")); - var normal = node.getBoundingClientRect(); - var fromRange = range(node, 0, 1).getBoundingClientRect(); - return badZoomedRects = Math.abs(normal.left - fromRange.left) > 1 - } - - // Known modes, by name and by MIME - var modes = {}, mimeModes = {}; - - // Extra arguments are stored as the mode's dependencies, which is - // used by (legacy) mechanisms like loadmode.js to automatically - // load a mode. (Preferred mechanism is the require/define calls.) - function defineMode(name, mode) { - if (arguments.length > 2) - { mode.dependencies = Array.prototype.slice.call(arguments, 2); } - modes[name] = mode; - } - - function defineMIME(mime, spec) { - mimeModes[mime] = spec; - } - - // Given a MIME type, a {name, ...options} config object, or a name - // string, return a mode config object. - function resolveMode(spec) { - if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) { - spec = mimeModes[spec]; - } else if (spec && typeof spec.name == "string" && mimeModes.hasOwnProperty(spec.name)) { - var found = mimeModes[spec.name]; - if (typeof found == "string") { found = {name: found}; } - spec = createObj(found, spec); - spec.name = found.name; - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) { - return resolveMode("application/xml") - } else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+json$/.test(spec)) { - return resolveMode("application/json") - } - if (typeof spec == "string") { return {name: spec} } - else { return spec || {name: "null"} } - } - - // Given a mode spec (anything that resolveMode accepts), find and - // initialize an actual mode object. - function getMode(options, spec) { - spec = resolveMode(spec); - var mfactory = modes[spec.name]; - if (!mfactory) { return getMode(options, "text/plain") } - var modeObj = mfactory(options, spec); - if (modeExtensions.hasOwnProperty(spec.name)) { - var exts = modeExtensions[spec.name]; - for (var prop in exts) { - if (!exts.hasOwnProperty(prop)) { continue } - if (modeObj.hasOwnProperty(prop)) { modeObj["_" + prop] = modeObj[prop]; } - modeObj[prop] = exts[prop]; - } - } - modeObj.name = spec.name; - if (spec.helperType) { modeObj.helperType = spec.helperType; } - if (spec.modeProps) { for (var prop$1 in spec.modeProps) - { modeObj[prop$1] = spec.modeProps[prop$1]; } } - - return modeObj - } - - // This can be used to attach properties to mode objects from - // outside the actual mode definition. - var modeExtensions = {}; - function extendMode(mode, properties) { - var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); - copyObj(properties, exts); - } - - function copyState(mode, state) { - if (state === true) { return state } - if (mode.copyState) { return mode.copyState(state) } - var nstate = {}; - for (var n in state) { - var val = state[n]; - if (val instanceof Array) { val = val.concat([]); } - nstate[n] = val; - } - return nstate - } - - // Given a mode and a state (for that mode), find the inner mode and - // state at the position that the state refers to. - function innerMode(mode, state) { - var info; - while (mode.innerMode) { - info = mode.innerMode(state); - if (!info || info.mode == mode) { break } - state = info.state; - mode = info.mode; - } - return info || {mode: mode, state: state} - } - - function startState(mode, a1, a2) { - return mode.startState ? mode.startState(a1, a2) : true - } - - // STRING STREAM - - // Fed to the mode parsers, provides helper functions to make - // parsers more succinct. - - var StringStream = function(string, tabSize, lineOracle) { - this.pos = this.start = 0; - this.string = string; - this.tabSize = tabSize || 8; - this.lastColumnPos = this.lastColumnValue = 0; - this.lineStart = 0; - this.lineOracle = lineOracle; - }; - - StringStream.prototype.eol = function () {return this.pos >= this.string.length}; - StringStream.prototype.sol = function () {return this.pos == this.lineStart}; - StringStream.prototype.peek = function () {return this.string.charAt(this.pos) || undefined}; - StringStream.prototype.next = function () { - if (this.pos < this.string.length) - { return this.string.charAt(this.pos++) } - }; - StringStream.prototype.eat = function (match) { - var ch = this.string.charAt(this.pos); - var ok; - if (typeof match == "string") { ok = ch == match; } - else { ok = ch && (match.test ? match.test(ch) : match(ch)); } - if (ok) {++this.pos; return ch} - }; - StringStream.prototype.eatWhile = function (match) { - var start = this.pos; - while (this.eat(match)){} - return this.pos > start - }; - StringStream.prototype.eatSpace = function () { - var start = this.pos; - while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) { ++this.pos; } - return this.pos > start - }; - StringStream.prototype.skipToEnd = function () {this.pos = this.string.length;}; - StringStream.prototype.skipTo = function (ch) { - var found = this.string.indexOf(ch, this.pos); - if (found > -1) {this.pos = found; return true} - }; - StringStream.prototype.backUp = function (n) {this.pos -= n;}; - StringStream.prototype.column = function () { - if (this.lastColumnPos < this.start) { - this.lastColumnValue = countColumn(this.string, this.start, this.tabSize, this.lastColumnPos, this.lastColumnValue); - this.lastColumnPos = this.start; - } - return this.lastColumnValue - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) - }; - StringStream.prototype.indentation = function () { - return countColumn(this.string, null, this.tabSize) - - (this.lineStart ? countColumn(this.string, this.lineStart, this.tabSize) : 0) - }; - StringStream.prototype.match = function (pattern, consume, caseInsensitive) { - if (typeof pattern == "string") { - var cased = function (str) { return caseInsensitive ? str.toLowerCase() : str; }; - var substr = this.string.substr(this.pos, pattern.length); - if (cased(substr) == cased(pattern)) { - if (consume !== false) { this.pos += pattern.length; } - return true - } - } else { - var match = this.string.slice(this.pos).match(pattern); - if (match && match.index > 0) { return null } - if (match && consume !== false) { this.pos += match[0].length; } - return match - } - }; - StringStream.prototype.current = function (){return this.string.slice(this.start, this.pos)}; - StringStream.prototype.hideFirstChars = function (n, inner) { - this.lineStart += n; - try { return inner() } - finally { this.lineStart -= n; } - }; - StringStream.prototype.lookAhead = function (n) { - var oracle = this.lineOracle; - return oracle && oracle.lookAhead(n) - }; - StringStream.prototype.baseToken = function () { - var oracle = this.lineOracle; - return oracle && oracle.baseToken(this.pos) - }; - - // Find the line object corresponding to the given line number. - function getLine(doc, n) { - n -= doc.first; - if (n < 0 || n >= doc.size) { throw new Error("There is no line " + (n + doc.first) + " in the document.") } - var chunk = doc; - while (!chunk.lines) { - for (var i = 0;; ++i) { - var child = chunk.children[i], sz = child.chunkSize(); - if (n < sz) { chunk = child; break } - n -= sz; - } - } - return chunk.lines[n] - } - - // Get the part of a document between two positions, as an array of - // strings. - function getBetween(doc, start, end) { - var out = [], n = start.line; - doc.iter(start.line, end.line + 1, function (line) { - var text = line.text; - if (n == end.line) { text = text.slice(0, end.ch); } - if (n == start.line) { text = text.slice(start.ch); } - out.push(text); - ++n; - }); - return out - } - // Get the lines between from and to, as array of strings. - function getLines(doc, from, to) { - var out = []; - doc.iter(from, to, function (line) { out.push(line.text); }); // iter aborts when callback returns truthy value - return out - } - - // Update the height of a line, propagating the height change - // upwards to parent nodes. - function updateLineHeight(line, height) { - var diff = height - line.height; - if (diff) { for (var n = line; n; n = n.parent) { n.height += diff; } } - } - - // Given a line object, find its line number by walking up through - // its parent links. - function lineNo(line) { - if (line.parent == null) { return null } - var cur = line.parent, no = indexOf(cur.lines, line); - for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { - for (var i = 0;; ++i) { - if (chunk.children[i] == cur) { break } - no += chunk.children[i].chunkSize(); - } - } - return no + cur.first - } - - // Find the line at the given vertical position, using the height - // information in the document tree. - function lineAtHeight(chunk, h) { - var n = chunk.first; - outer: do { - for (var i$1 = 0; i$1 < chunk.children.length; ++i$1) { - var child = chunk.children[i$1], ch = child.height; - if (h < ch) { chunk = child; continue outer } - h -= ch; - n += child.chunkSize(); - } - return n - } while (!chunk.lines) - var i = 0; - for (; i < chunk.lines.length; ++i) { - var line = chunk.lines[i], lh = line.height; - if (h < lh) { break } - h -= lh; - } - return n + i - } - - function isLine(doc, l) {return l >= doc.first && l < doc.first + doc.size} - - function lineNumberFor(options, i) { - return String(options.lineNumberFormatter(i + options.firstLineNumber)) - } - - // A Pos instance represents a position within the text. - function Pos(line, ch, sticky) { - if ( sticky === void 0 ) sticky = null; - - if (!(this instanceof Pos)) { return new Pos(line, ch, sticky) } - this.line = line; - this.ch = ch; - this.sticky = sticky; - } - - // Compare two positions, return 0 if they are the same, a negative - // number when a is less, and a positive number otherwise. - function cmp(a, b) { return a.line - b.line || a.ch - b.ch } - - function equalCursorPos(a, b) { return a.sticky == b.sticky && cmp(a, b) == 0 } - - function copyPos(x) {return Pos(x.line, x.ch)} - function maxPos(a, b) { return cmp(a, b) < 0 ? b : a } - function minPos(a, b) { return cmp(a, b) < 0 ? a : b } - - // Most of the external API clips given positions to make sure they - // actually exist within the document. - function clipLine(doc, n) {return Math.max(doc.first, Math.min(n, doc.first + doc.size - 1))} - function clipPos(doc, pos) { - if (pos.line < doc.first) { return Pos(doc.first, 0) } - var last = doc.first + doc.size - 1; - if (pos.line > last) { return Pos(last, getLine(doc, last).text.length) } - return clipToLen(pos, getLine(doc, pos.line).text.length) - } - function clipToLen(pos, linelen) { - var ch = pos.ch; - if (ch == null || ch > linelen) { return Pos(pos.line, linelen) } - else if (ch < 0) { return Pos(pos.line, 0) } - else { return pos } - } - function clipPosArray(doc, array) { - var out = []; - for (var i = 0; i < array.length; i++) { out[i] = clipPos(doc, array[i]); } - return out - } - - var SavedContext = function(state, lookAhead) { - this.state = state; - this.lookAhead = lookAhead; - }; - - var Context = function(doc, state, line, lookAhead) { - this.state = state; - this.doc = doc; - this.line = line; - this.maxLookAhead = lookAhead || 0; - this.baseTokens = null; - this.baseTokenPos = 1; - }; - - Context.prototype.lookAhead = function (n) { - var line = this.doc.getLine(this.line + n); - if (line != null && n > this.maxLookAhead) { this.maxLookAhead = n; } - return line - }; - - Context.prototype.baseToken = function (n) { - if (!this.baseTokens) { return null } - while (this.baseTokens[this.baseTokenPos] <= n) - { this.baseTokenPos += 2; } - var type = this.baseTokens[this.baseTokenPos + 1]; - return {type: type && type.replace(/( |^)overlay .*/, ""), - size: this.baseTokens[this.baseTokenPos] - n} - }; - - Context.prototype.nextLine = function () { - this.line++; - if (this.maxLookAhead > 0) { this.maxLookAhead--; } - }; - - Context.fromSaved = function (doc, saved, line) { - if (saved instanceof SavedContext) - { return new Context(doc, copyState(doc.mode, saved.state), line, saved.lookAhead) } - else - { return new Context(doc, copyState(doc.mode, saved), line) } - }; - - Context.prototype.save = function (copy) { - var state = copy !== false ? copyState(this.doc.mode, this.state) : this.state; - return this.maxLookAhead > 0 ? new SavedContext(state, this.maxLookAhead) : state - }; - - - // Compute a style array (an array starting with a mode generation - // -- for invalidation -- followed by pairs of end positions and - // style strings), which is used to highlight the tokens on the - // line. - function highlightLine(cm, line, context, forceToEnd) { - // A styles array always starts with a number identifying the - // mode/overlays that it is based on (for easy invalidation). - var st = [cm.state.modeGen], lineClasses = {}; - // Compute the base array of styles - runMode(cm, line.text, cm.doc.mode, context, function (end, style) { return st.push(end, style); }, - lineClasses, forceToEnd); - var state = context.state; - - // Run overlays, adjust style array. - var loop = function ( o ) { - context.baseTokens = st; - var overlay = cm.state.overlays[o], i = 1, at = 0; - context.state = true; - runMode(cm, line.text, overlay.mode, context, function (end, style) { - var start = i; - // Ensure there's a token end at the current position, and that i points at it - while (at < end) { - var i_end = st[i]; - if (i_end > end) - { st.splice(i, 1, end, st[i+1], i_end); } - i += 2; - at = Math.min(end, i_end); - } - if (!style) { return } - if (overlay.opaque) { - st.splice(start, i - start, end, "overlay " + style); - i = start + 2; - } else { - for (; start < i; start += 2) { - var cur = st[start+1]; - st[start+1] = (cur ? cur + " " : "") + "overlay " + style; - } - } - }, lineClasses); - context.state = state; - context.baseTokens = null; - context.baseTokenPos = 1; - }; - - for (var o = 0; o < cm.state.overlays.length; ++o) loop( o ); - - return {styles: st, classes: lineClasses.bgClass || lineClasses.textClass ? lineClasses : null} - } - - function getLineStyles(cm, line, updateFrontier) { - if (!line.styles || line.styles[0] != cm.state.modeGen) { - var context = getContextBefore(cm, lineNo(line)); - var resetState = line.text.length > cm.options.maxHighlightLength && copyState(cm.doc.mode, context.state); - var result = highlightLine(cm, line, context); - if (resetState) { context.state = resetState; } - line.stateAfter = context.save(!resetState); - line.styles = result.styles; - if (result.classes) { line.styleClasses = result.classes; } - else if (line.styleClasses) { line.styleClasses = null; } - if (updateFrontier === cm.doc.highlightFrontier) - { cm.doc.modeFrontier = Math.max(cm.doc.modeFrontier, ++cm.doc.highlightFrontier); } - } - return line.styles - } - - function getContextBefore(cm, n, precise) { - var doc = cm.doc, display = cm.display; - if (!doc.mode.startState) { return new Context(doc, true, n) } - var start = findStartLine(cm, n, precise); - var saved = start > doc.first && getLine(doc, start - 1).stateAfter; - var context = saved ? Context.fromSaved(doc, saved, start) : new Context(doc, startState(doc.mode), start); - - doc.iter(start, n, function (line) { - processLine(cm, line.text, context); - var pos = context.line; - line.stateAfter = pos == n - 1 || pos % 5 == 0 || pos >= display.viewFrom && pos < display.viewTo ? context.save() : null; - context.nextLine(); - }); - if (precise) { doc.modeFrontier = context.line; } - return context - } - - // Lightweight form of highlight -- proceed over this line and - // update state, but don't save a style array. Used for lines that - // aren't currently visible. - function processLine(cm, text, context, startAt) { - var mode = cm.doc.mode; - var stream = new StringStream(text, cm.options.tabSize, context); - stream.start = stream.pos = startAt || 0; - if (text == "") { callBlankLine(mode, context.state); } - while (!stream.eol()) { - readToken(mode, stream, context.state); - stream.start = stream.pos; - } - } - - function callBlankLine(mode, state) { - if (mode.blankLine) { return mode.blankLine(state) } - if (!mode.innerMode) { return } - var inner = innerMode(mode, state); - if (inner.mode.blankLine) { return inner.mode.blankLine(inner.state) } - } - - function readToken(mode, stream, state, inner) { - for (var i = 0; i < 10; i++) { - if (inner) { inner[0] = innerMode(mode, state).mode; } - var style = mode.token(stream, state); - if (stream.pos > stream.start) { return style } - } - throw new Error("Mode " + mode.name + " failed to advance stream.") - } - - var Token = function(stream, type, state) { - this.start = stream.start; this.end = stream.pos; - this.string = stream.current(); - this.type = type || null; - this.state = state; - }; - - // Utility for getTokenAt and getLineTokens - function takeToken(cm, pos, precise, asArray) { - var doc = cm.doc, mode = doc.mode, style; - pos = clipPos(doc, pos); - var line = getLine(doc, pos.line), context = getContextBefore(cm, pos.line, precise); - var stream = new StringStream(line.text, cm.options.tabSize, context), tokens; - if (asArray) { tokens = []; } - while ((asArray || stream.pos < pos.ch) && !stream.eol()) { - stream.start = stream.pos; - style = readToken(mode, stream, context.state); - if (asArray) { tokens.push(new Token(stream, style, copyState(doc.mode, context.state))); } - } - return asArray ? tokens : new Token(stream, style, context.state) - } - - function extractLineClasses(type, output) { - if (type) { for (;;) { - var lineClass = type.match(/(?:^|\s+)line-(background-)?(\S+)/); - if (!lineClass) { break } - type = type.slice(0, lineClass.index) + type.slice(lineClass.index + lineClass[0].length); - var prop = lineClass[1] ? "bgClass" : "textClass"; - if (output[prop] == null) - { output[prop] = lineClass[2]; } - else if (!(new RegExp("(?:^|\\s)" + lineClass[2] + "(?:$|\\s)")).test(output[prop])) - { output[prop] += " " + lineClass[2]; } - } } - return type - } - - // Run the given mode's parser over a line, calling f for each token. - function runMode(cm, text, mode, context, f, lineClasses, forceToEnd) { - var flattenSpans = mode.flattenSpans; - if (flattenSpans == null) { flattenSpans = cm.options.flattenSpans; } - var curStart = 0, curStyle = null; - var stream = new StringStream(text, cm.options.tabSize, context), style; - var inner = cm.options.addModeClass && [null]; - if (text == "") { extractLineClasses(callBlankLine(mode, context.state), lineClasses); } - while (!stream.eol()) { - if (stream.pos > cm.options.maxHighlightLength) { - flattenSpans = false; - if (forceToEnd) { processLine(cm, text, context, stream.pos); } - stream.pos = text.length; - style = null; - } else { - style = extractLineClasses(readToken(mode, stream, context.state, inner), lineClasses); - } - if (inner) { - var mName = inner[0].name; - if (mName) { style = "m-" + (style ? mName + " " + style : mName); } - } - if (!flattenSpans || curStyle != style) { - while (curStart < stream.start) { - curStart = Math.min(stream.start, curStart + 5000); - f(curStart, curStyle); - } - curStyle = style; - } - stream.start = stream.pos; - } - while (curStart < stream.pos) { - // Webkit seems to refuse to render text nodes longer than 57444 - // characters, and returns inaccurate measurements in nodes - // starting around 5000 chars. - var pos = Math.min(stream.pos, curStart + 5000); - f(pos, curStyle); - curStart = pos; - } - } - - // Finds the line to start with when starting a parse. Tries to - // find a line with a stateAfter, so that it can start with a - // valid state. If that fails, it returns the line with the - // smallest indentation, which tends to need the least context to - // parse correctly. - function findStartLine(cm, n, precise) { - var minindent, minline, doc = cm.doc; - var lim = precise ? -1 : n - (cm.doc.mode.innerMode ? 1000 : 100); - for (var search = n; search > lim; --search) { - if (search <= doc.first) { return doc.first } - var line = getLine(doc, search - 1), after = line.stateAfter; - if (after && (!precise || search + (after instanceof SavedContext ? after.lookAhead : 0) <= doc.modeFrontier)) - { return search } - var indented = countColumn(line.text, null, cm.options.tabSize); - if (minline == null || minindent > indented) { - minline = search - 1; - minindent = indented; - } - } - return minline - } - - function retreatFrontier(doc, n) { - doc.modeFrontier = Math.min(doc.modeFrontier, n); - if (doc.highlightFrontier < n - 10) { return } - var start = doc.first; - for (var line = n - 1; line > start; line--) { - var saved = getLine(doc, line).stateAfter; - // change is on 3 - // state on line 1 looked ahead 2 -- so saw 3 - // test 1 + 2 < 3 should cover this - if (saved && (!(saved instanceof SavedContext) || line + saved.lookAhead < n)) { - start = line + 1; - break - } - } - doc.highlightFrontier = Math.min(doc.highlightFrontier, start); - } - - // Optimize some code when these features are not used. - var sawReadOnlySpans = false, sawCollapsedSpans = false; - - function seeReadOnlySpans() { - sawReadOnlySpans = true; - } - - function seeCollapsedSpans() { - sawCollapsedSpans = true; - } - - // TEXTMARKER SPANS - - function MarkedSpan(marker, from, to) { - this.marker = marker; - this.from = from; this.to = to; - } - - // Search an array of spans for a span matching the given marker. - function getMarkedSpanFor(spans, marker) { - if (spans) { for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.marker == marker) { return span } - } } - } - // Remove a span from an array, returning undefined if no spans are - // left (we don't store arrays for lines without spans). - function removeMarkedSpan(spans, span) { - var r; - for (var i = 0; i < spans.length; ++i) - { if (spans[i] != span) { (r || (r = [])).push(spans[i]); } } - return r - } - // Add a span to a line. - function addMarkedSpan(line, span) { - line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]; - span.marker.attachLine(line); - } - - // Used for the algorithm that adjusts markers for a change in the - // document. These functions cut an array of spans at a given - // character position, returning an array of remaining chunks (or - // undefined if nothing remains). - function markedSpansBefore(old, startCh, isInsert) { - var nw; - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); - if (startsBefore || span.from == startCh && marker.type == "bookmark" && (!isInsert || !span.marker.insertLeft)) { - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, span.from, endsAfter ? null : span.to)); - } - } } - return nw - } - function markedSpansAfter(old, endCh, isInsert) { - var nw; - if (old) { for (var i = 0; i < old.length; ++i) { - var span = old[i], marker = span.marker; - var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); - if (endsAfter || span.from == endCh && marker.type == "bookmark" && (!isInsert || span.marker.insertLeft)) { - var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh) - ;(nw || (nw = [])).push(new MarkedSpan(marker, startsBefore ? null : span.from - endCh, - span.to == null ? null : span.to - endCh)); - } - } } - return nw - } - - // Given a change object, compute the new set of marker spans that - // cover the line in which the change took place. Removes spans - // entirely within the change, reconnects spans belonging to the - // same marker that appear on both sides of the change, and cuts off - // spans partially within the change. Returns an array of span - // arrays with one element for each line in (after) the change. - function stretchSpansOverChange(doc, change) { - if (change.full) { return null } - var oldFirst = isLine(doc, change.from.line) && getLine(doc, change.from.line).markedSpans; - var oldLast = isLine(doc, change.to.line) && getLine(doc, change.to.line).markedSpans; - if (!oldFirst && !oldLast) { return null } - - var startCh = change.from.ch, endCh = change.to.ch, isInsert = cmp(change.from, change.to) == 0; - // Get the spans that 'stick out' on both sides - var first = markedSpansBefore(oldFirst, startCh, isInsert); - var last = markedSpansAfter(oldLast, endCh, isInsert); - - // Next, merge those two ends - var sameLine = change.text.length == 1, offset = lst(change.text).length + (sameLine ? startCh : 0); - if (first) { - // Fix up .to properties of first - for (var i = 0; i < first.length; ++i) { - var span = first[i]; - if (span.to == null) { - var found = getMarkedSpanFor(last, span.marker); - if (!found) { span.to = startCh; } - else if (sameLine) { span.to = found.to == null ? null : found.to + offset; } - } - } - } - if (last) { - // Fix up .from in last (or move them into first in case of sameLine) - for (var i$1 = 0; i$1 < last.length; ++i$1) { - var span$1 = last[i$1]; - if (span$1.to != null) { span$1.to += offset; } - if (span$1.from == null) { - var found$1 = getMarkedSpanFor(first, span$1.marker); - if (!found$1) { - span$1.from = offset; - if (sameLine) { (first || (first = [])).push(span$1); } - } - } else { - span$1.from += offset; - if (sameLine) { (first || (first = [])).push(span$1); } - } - } - } - // Make sure we didn't create any zero-length spans - if (first) { first = clearEmptySpans(first); } - if (last && last != first) { last = clearEmptySpans(last); } - - var newMarkers = [first]; - if (!sameLine) { - // Fill gap with whole-line-spans - var gap = change.text.length - 2, gapMarkers; - if (gap > 0 && first) - { for (var i$2 = 0; i$2 < first.length; ++i$2) - { if (first[i$2].to == null) - { (gapMarkers || (gapMarkers = [])).push(new MarkedSpan(first[i$2].marker, null, null)); } } } - for (var i$3 = 0; i$3 < gap; ++i$3) - { newMarkers.push(gapMarkers); } - newMarkers.push(last); - } - return newMarkers - } - - // Remove spans that are empty and don't have a clearWhenEmpty - // option of false. - function clearEmptySpans(spans) { - for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if (span.from != null && span.from == span.to && span.marker.clearWhenEmpty !== false) - { spans.splice(i--, 1); } - } - if (!spans.length) { return null } - return spans - } - - // Used to 'clip' out readOnly ranges when making a change. - function removeReadOnlyRanges(doc, from, to) { - var markers = null; - doc.iter(from.line, to.line + 1, function (line) { - if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { - var mark = line.markedSpans[i].marker; - if (mark.readOnly && (!markers || indexOf(markers, mark) == -1)) - { (markers || (markers = [])).push(mark); } - } } - }); - if (!markers) { return null } - var parts = [{from: from, to: to}]; - for (var i = 0; i < markers.length; ++i) { - var mk = markers[i], m = mk.find(0); - for (var j = 0; j < parts.length; ++j) { - var p = parts[j]; - if (cmp(p.to, m.from) < 0 || cmp(p.from, m.to) > 0) { continue } - var newParts = [j, 1], dfrom = cmp(p.from, m.from), dto = cmp(p.to, m.to); - if (dfrom < 0 || !mk.inclusiveLeft && !dfrom) - { newParts.push({from: p.from, to: m.from}); } - if (dto > 0 || !mk.inclusiveRight && !dto) - { newParts.push({from: m.to, to: p.to}); } - parts.splice.apply(parts, newParts); - j += newParts.length - 3; - } - } - return parts - } - - // Connect or disconnect spans from a line. - function detachMarkedSpans(line) { - var spans = line.markedSpans; - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.detachLine(line); } - line.markedSpans = null; - } - function attachMarkedSpans(line, spans) { - if (!spans) { return } - for (var i = 0; i < spans.length; ++i) - { spans[i].marker.attachLine(line); } - line.markedSpans = spans; - } - - // Helpers used when computing which overlapping collapsed span - // counts as the larger one. - function extraLeft(marker) { return marker.inclusiveLeft ? -1 : 0 } - function extraRight(marker) { return marker.inclusiveRight ? 1 : 0 } - - // Returns a number indicating which of two overlapping collapsed - // spans is larger (and thus includes the other). Falls back to - // comparing ids when the spans cover exactly the same range. - function compareCollapsedMarkers(a, b) { - var lenDiff = a.lines.length - b.lines.length; - if (lenDiff != 0) { return lenDiff } - var aPos = a.find(), bPos = b.find(); - var fromCmp = cmp(aPos.from, bPos.from) || extraLeft(a) - extraLeft(b); - if (fromCmp) { return -fromCmp } - var toCmp = cmp(aPos.to, bPos.to) || extraRight(a) - extraRight(b); - if (toCmp) { return toCmp } - return b.id - a.id - } - - // Find out whether a line ends or starts in a collapsed span. If - // so, return the marker for that span. - function collapsedSpanAtSide(line, start) { - var sps = sawCollapsedSpans && line.markedSpans, found; - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (sp.marker.collapsed && (start ? sp.from : sp.to) == null && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) - { found = sp.marker; } - } } - return found - } - function collapsedSpanAtStart(line) { return collapsedSpanAtSide(line, true) } - function collapsedSpanAtEnd(line) { return collapsedSpanAtSide(line, false) } - - function collapsedSpanAround(line, ch) { - var sps = sawCollapsedSpans && line.markedSpans, found; - if (sps) { for (var i = 0; i < sps.length; ++i) { - var sp = sps[i]; - if (sp.marker.collapsed && (sp.from == null || sp.from < ch) && (sp.to == null || sp.to > ch) && - (!found || compareCollapsedMarkers(found, sp.marker) < 0)) { found = sp.marker; } - } } - return found - } - - // Test whether there exists a collapsed span that partially - // overlaps (covers the start or end, but not both) of a new span. - // Such overlap is not allowed. - function conflictingCollapsedRange(doc, lineNo, from, to, marker) { - var line = getLine(doc, lineNo); - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) { for (var i = 0; i < sps.length; ++i) { - var sp = sps[i]; - if (!sp.marker.collapsed) { continue } - var found = sp.marker.find(0); - var fromCmp = cmp(found.from, from) || extraLeft(sp.marker) - extraLeft(marker); - var toCmp = cmp(found.to, to) || extraRight(sp.marker) - extraRight(marker); - if (fromCmp >= 0 && toCmp <= 0 || fromCmp <= 0 && toCmp >= 0) { continue } - if (fromCmp <= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.to, from) >= 0 : cmp(found.to, from) > 0) || - fromCmp >= 0 && (sp.marker.inclusiveRight && marker.inclusiveLeft ? cmp(found.from, to) <= 0 : cmp(found.from, to) < 0)) - { return true } - } } - } - - // A visual line is a line as drawn on the screen. Folding, for - // example, can cause multiple logical lines to appear on the same - // visual line. This finds the start of the visual line that the - // given line is part of (usually that is the line itself). - function visualLine(line) { - var merged; - while (merged = collapsedSpanAtStart(line)) - { line = merged.find(-1, true).line; } - return line - } - - function visualLineEnd(line) { - var merged; - while (merged = collapsedSpanAtEnd(line)) - { line = merged.find(1, true).line; } - return line - } - - // Returns an array of logical lines that continue the visual line - // started by the argument, or undefined if there are no such lines. - function visualLineContinued(line) { - var merged, lines; - while (merged = collapsedSpanAtEnd(line)) { - line = merged.find(1, true).line - ;(lines || (lines = [])).push(line); - } - return lines - } - - // Get the line number of the start of the visual line that the - // given line number is part of. - function visualLineNo(doc, lineN) { - var line = getLine(doc, lineN), vis = visualLine(line); - if (line == vis) { return lineN } - return lineNo(vis) - } - - // Get the line number of the start of the next visual line after - // the given line. - function visualLineEndNo(doc, lineN) { - if (lineN > doc.lastLine()) { return lineN } - var line = getLine(doc, lineN), merged; - if (!lineIsHidden(doc, line)) { return lineN } - while (merged = collapsedSpanAtEnd(line)) - { line = merged.find(1, true).line; } - return lineNo(line) + 1 - } - - // Compute whether a line is hidden. Lines count as hidden when they - // are part of a visual line that starts with another line, or when - // they are entirely covered by collapsed, non-widget span. - function lineIsHidden(doc, line) { - var sps = sawCollapsedSpans && line.markedSpans; - if (sps) { for (var sp = (void 0), i = 0; i < sps.length; ++i) { - sp = sps[i]; - if (!sp.marker.collapsed) { continue } - if (sp.from == null) { return true } - if (sp.marker.widgetNode) { continue } - if (sp.from == 0 && sp.marker.inclusiveLeft && lineIsHiddenInner(doc, line, sp)) - { return true } - } } - } - function lineIsHiddenInner(doc, line, span) { - if (span.to == null) { - var end = span.marker.find(1, true); - return lineIsHiddenInner(doc, end.line, getMarkedSpanFor(end.line.markedSpans, span.marker)) - } - if (span.marker.inclusiveRight && span.to == line.text.length) - { return true } - for (var sp = (void 0), i = 0; i < line.markedSpans.length; ++i) { - sp = line.markedSpans[i]; - if (sp.marker.collapsed && !sp.marker.widgetNode && sp.from == span.to && - (sp.to == null || sp.to != span.from) && - (sp.marker.inclusiveLeft || span.marker.inclusiveRight) && - lineIsHiddenInner(doc, line, sp)) { return true } - } - } - - // Find the height above the given line. - function heightAtLine(lineObj) { - lineObj = visualLine(lineObj); - - var h = 0, chunk = lineObj.parent; - for (var i = 0; i < chunk.lines.length; ++i) { - var line = chunk.lines[i]; - if (line == lineObj) { break } - else { h += line.height; } - } - for (var p = chunk.parent; p; chunk = p, p = chunk.parent) { - for (var i$1 = 0; i$1 < p.children.length; ++i$1) { - var cur = p.children[i$1]; - if (cur == chunk) { break } - else { h += cur.height; } - } - } - return h - } - - // Compute the character length of a line, taking into account - // collapsed ranges (see markText) that might hide parts, and join - // other lines onto it. - function lineLength(line) { - if (line.height == 0) { return 0 } - var len = line.text.length, merged, cur = line; - while (merged = collapsedSpanAtStart(cur)) { - var found = merged.find(0, true); - cur = found.from.line; - len += found.from.ch - found.to.ch; - } - cur = line; - while (merged = collapsedSpanAtEnd(cur)) { - var found$1 = merged.find(0, true); - len -= cur.text.length - found$1.from.ch; - cur = found$1.to.line; - len += cur.text.length - found$1.to.ch; - } - return len - } - - // Find the longest line in the document. - function findMaxLine(cm) { - var d = cm.display, doc = cm.doc; - d.maxLine = getLine(doc, doc.first); - d.maxLineLength = lineLength(d.maxLine); - d.maxLineChanged = true; - doc.iter(function (line) { - var len = lineLength(line); - if (len > d.maxLineLength) { - d.maxLineLength = len; - d.maxLine = line; - } - }); - } - - // LINE DATA STRUCTURE - - // Line objects. These hold state related to a line, including - // highlighting info (the styles array). - var Line = function(text, markedSpans, estimateHeight) { - this.text = text; - attachMarkedSpans(this, markedSpans); - this.height = estimateHeight ? estimateHeight(this) : 1; - }; - - Line.prototype.lineNo = function () { return lineNo(this) }; - eventMixin(Line); - - // Change the content (text, markers) of a line. Automatically - // invalidates cached information and tries to re-estimate the - // line's height. - function updateLine(line, text, markedSpans, estimateHeight) { - line.text = text; - if (line.stateAfter) { line.stateAfter = null; } - if (line.styles) { line.styles = null; } - if (line.order != null) { line.order = null; } - detachMarkedSpans(line); - attachMarkedSpans(line, markedSpans); - var estHeight = estimateHeight ? estimateHeight(line) : 1; - if (estHeight != line.height) { updateLineHeight(line, estHeight); } - } - - // Detach a line from the document tree and its markers. - function cleanUpLine(line) { - line.parent = null; - detachMarkedSpans(line); - } - - // Convert a style as returned by a mode (either null, or a string - // containing one or more styles) to a CSS style. This is cached, - // and also looks for line-wide styles. - var styleToClassCache = {}, styleToClassCacheWithMode = {}; - function interpretTokenStyle(style, options) { - if (!style || /^\s*$/.test(style)) { return null } - var cache = options.addModeClass ? styleToClassCacheWithMode : styleToClassCache; - return cache[style] || - (cache[style] = style.replace(/\S+/g, "cm-$&")) - } - - // Render the DOM representation of the text of a line. Also builds - // up a 'line map', which points at the DOM nodes that represent - // specific stretches of text, and is used by the measuring code. - // The returned object contains the DOM node, this map, and - // information about line-wide styles that were set by the mode. - function buildLineContent(cm, lineView) { - // The padding-right forces the element to have a 'border', which - // is needed on Webkit to be able to get line-level bounding - // rectangles for it (in measureChar). - var content = eltP("span", null, null, webkit ? "padding-right: .1px" : null); - var builder = {pre: eltP("pre", [content], "CodeMirror-line"), content: content, - col: 0, pos: 0, cm: cm, - trailingSpace: false, - splitSpaces: cm.getOption("lineWrapping")}; - lineView.measure = {}; - - // Iterate over the logical lines that make up this visual line. - for (var i = 0; i <= (lineView.rest ? lineView.rest.length : 0); i++) { - var line = i ? lineView.rest[i - 1] : lineView.line, order = (void 0); - builder.pos = 0; - builder.addToken = buildToken; - // Optionally wire in some hacks into the token-rendering - // algorithm, to deal with browser quirks. - if (hasBadBidiRects(cm.display.measure) && (order = getOrder(line, cm.doc.direction))) - { builder.addToken = buildTokenBadBidi(builder.addToken, order); } - builder.map = []; - var allowFrontierUpdate = lineView != cm.display.externalMeasured && lineNo(line); - insertLineContent(line, builder, getLineStyles(cm, line, allowFrontierUpdate)); - if (line.styleClasses) { - if (line.styleClasses.bgClass) - { builder.bgClass = joinClasses(line.styleClasses.bgClass, builder.bgClass || ""); } - if (line.styleClasses.textClass) - { builder.textClass = joinClasses(line.styleClasses.textClass, builder.textClass || ""); } - } - - // Ensure at least a single node is present, for measuring. - if (builder.map.length == 0) - { builder.map.push(0, 0, builder.content.appendChild(zeroWidthElement(cm.display.measure))); } - - // Store the map and a cache object for the current logical line - if (i == 0) { - lineView.measure.map = builder.map; - lineView.measure.cache = {}; - } else { - (lineView.measure.maps || (lineView.measure.maps = [])).push(builder.map) - ;(lineView.measure.caches || (lineView.measure.caches = [])).push({}); - } - } - - // See issue #2901 - if (webkit) { - var last = builder.content.lastChild; - if (/\bcm-tab\b/.test(last.className) || (last.querySelector && last.querySelector(".cm-tab"))) - { builder.content.className = "cm-tab-wrap-hack"; } - } - - signal(cm, "renderLine", cm, lineView.line, builder.pre); - if (builder.pre.className) - { builder.textClass = joinClasses(builder.pre.className, builder.textClass || ""); } - - return builder - } - - function defaultSpecialCharPlaceholder(ch) { - var token = elt("span", "\u2022", "cm-invalidchar"); - token.title = "\\u" + ch.charCodeAt(0).toString(16); - token.setAttribute("aria-label", token.title); - return token - } - - // Build up the DOM representation for a single token, and add it to - // the line map. Takes care to render special characters separately. - function buildToken(builder, text, style, startStyle, endStyle, css, attributes) { - if (!text) { return } - var displayText = builder.splitSpaces ? splitSpaces(text, builder.trailingSpace) : text; - var special = builder.cm.state.specialChars, mustWrap = false; - var content; - if (!special.test(text)) { - builder.col += text.length; - content = document.createTextNode(displayText); - builder.map.push(builder.pos, builder.pos + text.length, content); - if (ie && ie_version < 9) { mustWrap = true; } - builder.pos += text.length; - } else { - content = document.createDocumentFragment(); - var pos = 0; - while (true) { - special.lastIndex = pos; - var m = special.exec(text); - var skipped = m ? m.index - pos : text.length - pos; - if (skipped) { - var txt = document.createTextNode(displayText.slice(pos, pos + skipped)); - if (ie && ie_version < 9) { content.appendChild(elt("span", [txt])); } - else { content.appendChild(txt); } - builder.map.push(builder.pos, builder.pos + skipped, txt); - builder.col += skipped; - builder.pos += skipped; - } - if (!m) { break } - pos += skipped + 1; - var txt$1 = (void 0); - if (m[0] == "\t") { - var tabSize = builder.cm.options.tabSize, tabWidth = tabSize - builder.col % tabSize; - txt$1 = content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); - txt$1.setAttribute("role", "presentation"); - txt$1.setAttribute("cm-text", "\t"); - builder.col += tabWidth; - } else if (m[0] == "\r" || m[0] == "\n") { - txt$1 = content.appendChild(elt("span", m[0] == "\r" ? "\u240d" : "\u2424", "cm-invalidchar")); - txt$1.setAttribute("cm-text", m[0]); - builder.col += 1; - } else { - txt$1 = builder.cm.options.specialCharPlaceholder(m[0]); - txt$1.setAttribute("cm-text", m[0]); - if (ie && ie_version < 9) { content.appendChild(elt("span", [txt$1])); } - else { content.appendChild(txt$1); } - builder.col += 1; - } - builder.map.push(builder.pos, builder.pos + 1, txt$1); - builder.pos++; - } - } - builder.trailingSpace = displayText.charCodeAt(text.length - 1) == 32; - if (style || startStyle || endStyle || mustWrap || css || attributes) { - var fullStyle = style || ""; - if (startStyle) { fullStyle += startStyle; } - if (endStyle) { fullStyle += endStyle; } - var token = elt("span", [content], fullStyle, css); - if (attributes) { - for (var attr in attributes) { if (attributes.hasOwnProperty(attr) && attr != "style" && attr != "class") - { token.setAttribute(attr, attributes[attr]); } } - } - return builder.content.appendChild(token) - } - builder.content.appendChild(content); - } - - // Change some spaces to NBSP to prevent the browser from collapsing - // trailing spaces at the end of a line when rendering text (issue #1362). - function splitSpaces(text, trailingBefore) { - if (text.length > 1 && !/ /.test(text)) { return text } - var spaceBefore = trailingBefore, result = ""; - for (var i = 0; i < text.length; i++) { - var ch = text.charAt(i); - if (ch == " " && spaceBefore && (i == text.length - 1 || text.charCodeAt(i + 1) == 32)) - { ch = "\u00a0"; } - result += ch; - spaceBefore = ch == " "; - } - return result - } - - // Work around nonsense dimensions being reported for stretches of - // right-to-left text. - function buildTokenBadBidi(inner, order) { - return function (builder, text, style, startStyle, endStyle, css, attributes) { - style = style ? style + " cm-force-border" : "cm-force-border"; - var start = builder.pos, end = start + text.length; - for (;;) { - // Find the part that overlaps with the start of this text - var part = (void 0); - for (var i = 0; i < order.length; i++) { - part = order[i]; - if (part.to > start && part.from <= start) { break } - } - if (part.to >= end) { return inner(builder, text, style, startStyle, endStyle, css, attributes) } - inner(builder, text.slice(0, part.to - start), style, startStyle, null, css, attributes); - startStyle = null; - text = text.slice(part.to - start); - start = part.to; - } - } - } - - function buildCollapsedSpan(builder, size, marker, ignoreWidget) { - var widget = !ignoreWidget && marker.widgetNode; - if (widget) { builder.map.push(builder.pos, builder.pos + size, widget); } - if (!ignoreWidget && builder.cm.display.input.needsContentAttribute) { - if (!widget) - { widget = builder.content.appendChild(document.createElement("span")); } - widget.setAttribute("cm-marker", marker.id); - } - if (widget) { - builder.cm.display.input.setUneditable(widget); - builder.content.appendChild(widget); - } - builder.pos += size; - builder.trailingSpace = false; - } - - // Outputs a number of spans to make up a line, taking highlighting - // and marked text into account. - function insertLineContent(line, builder, styles) { - var spans = line.markedSpans, allText = line.text, at = 0; - if (!spans) { - for (var i$1 = 1; i$1 < styles.length; i$1+=2) - { builder.addToken(builder, allText.slice(at, at = styles[i$1]), interpretTokenStyle(styles[i$1+1], builder.cm.options)); } - return - } - - var len = allText.length, pos = 0, i = 1, text = "", style, css; - var nextChange = 0, spanStyle, spanEndStyle, spanStartStyle, collapsed, attributes; - for (;;) { - if (nextChange == pos) { // Update current marker set - spanStyle = spanEndStyle = spanStartStyle = css = ""; - attributes = null; - collapsed = null; nextChange = Infinity; - var foundBookmarks = [], endStyles = (void 0); - for (var j = 0; j < spans.length; ++j) { - var sp = spans[j], m = sp.marker; - if (m.type == "bookmark" && sp.from == pos && m.widgetNode) { - foundBookmarks.push(m); - } else if (sp.from <= pos && (sp.to == null || sp.to > pos || m.collapsed && sp.to == pos && sp.from == pos)) { - if (sp.to != null && sp.to != pos && nextChange > sp.to) { - nextChange = sp.to; - spanEndStyle = ""; - } - if (m.className) { spanStyle += " " + m.className; } - if (m.css) { css = (css ? css + ";" : "") + m.css; } - if (m.startStyle && sp.from == pos) { spanStartStyle += " " + m.startStyle; } - if (m.endStyle && sp.to == nextChange) { (endStyles || (endStyles = [])).push(m.endStyle, sp.to); } - // support for the old title property - // https://github.com/codemirror/CodeMirror/pull/5673 - if (m.title) { (attributes || (attributes = {})).title = m.title; } - if (m.attributes) { - for (var attr in m.attributes) - { (attributes || (attributes = {}))[attr] = m.attributes[attr]; } - } - if (m.collapsed && (!collapsed || compareCollapsedMarkers(collapsed.marker, m) < 0)) - { collapsed = sp; } - } else if (sp.from > pos && nextChange > sp.from) { - nextChange = sp.from; - } - } - if (endStyles) { for (var j$1 = 0; j$1 < endStyles.length; j$1 += 2) - { if (endStyles[j$1 + 1] == nextChange) { spanEndStyle += " " + endStyles[j$1]; } } } - - if (!collapsed || collapsed.from == pos) { for (var j$2 = 0; j$2 < foundBookmarks.length; ++j$2) - { buildCollapsedSpan(builder, 0, foundBookmarks[j$2]); } } - if (collapsed && (collapsed.from || 0) == pos) { - buildCollapsedSpan(builder, (collapsed.to == null ? len + 1 : collapsed.to) - pos, - collapsed.marker, collapsed.from == null); - if (collapsed.to == null) { return } - if (collapsed.to == pos) { collapsed = false; } - } - } - if (pos >= len) { break } - - var upto = Math.min(len, nextChange); - while (true) { - if (text) { - var end = pos + text.length; - if (!collapsed) { - var tokenText = end > upto ? text.slice(0, upto - pos) : text; - builder.addToken(builder, tokenText, style ? style + spanStyle : spanStyle, - spanStartStyle, pos + tokenText.length == nextChange ? spanEndStyle : "", css, attributes); - } - if (end >= upto) {text = text.slice(upto - pos); pos = upto; break} - pos = end; - spanStartStyle = ""; - } - text = allText.slice(at, at = styles[i++]); - style = interpretTokenStyle(styles[i++], builder.cm.options); - } - } - } - - - // These objects are used to represent the visible (currently drawn) - // part of the document. A LineView may correspond to multiple - // logical lines, if those are connected by collapsed ranges. - function LineView(doc, line, lineN) { - // The starting line - this.line = line; - // Continuing lines, if any - this.rest = visualLineContinued(line); - // Number of logical lines in this visual line - this.size = this.rest ? lineNo(lst(this.rest)) - lineN + 1 : 1; - this.node = this.text = null; - this.hidden = lineIsHidden(doc, line); - } - - // Create a range of LineView objects for the given lines. - function buildViewArray(cm, from, to) { - var array = [], nextPos; - for (var pos = from; pos < to; pos = nextPos) { - var view = new LineView(cm.doc, getLine(cm.doc, pos), pos); - nextPos = pos + view.size; - array.push(view); - } - return array - } - - var operationGroup = null; - - function pushOperation(op) { - if (operationGroup) { - operationGroup.ops.push(op); - } else { - op.ownsGroup = operationGroup = { - ops: [op], - delayedCallbacks: [] - }; - } - } - - function fireCallbacksForOps(group) { - // Calls delayed callbacks and cursorActivity handlers until no - // new ones appear - var callbacks = group.delayedCallbacks, i = 0; - do { - for (; i < callbacks.length; i++) - { callbacks[i].call(null); } - for (var j = 0; j < group.ops.length; j++) { - var op = group.ops[j]; - if (op.cursorActivityHandlers) - { while (op.cursorActivityCalled < op.cursorActivityHandlers.length) - { op.cursorActivityHandlers[op.cursorActivityCalled++].call(null, op.cm); } } - } - } while (i < callbacks.length) - } - - function finishOperation(op, endCb) { - var group = op.ownsGroup; - if (!group) { return } - - try { fireCallbacksForOps(group); } - finally { - operationGroup = null; - endCb(group); - } - } - - var orphanDelayedCallbacks = null; - - // Often, we want to signal events at a point where we are in the - // middle of some work, but don't want the handler to start calling - // other methods on the editor, which might be in an inconsistent - // state or simply not expect any other events to happen. - // signalLater looks whether there are any handlers, and schedules - // them to be executed when the last operation ends, or, if no - // operation is active, when a timeout fires. - function signalLater(emitter, type /*, values...*/) { - var arr = getHandlers(emitter, type); - if (!arr.length) { return } - var args = Array.prototype.slice.call(arguments, 2), list; - if (operationGroup) { - list = operationGroup.delayedCallbacks; - } else if (orphanDelayedCallbacks) { - list = orphanDelayedCallbacks; - } else { - list = orphanDelayedCallbacks = []; - setTimeout(fireOrphanDelayed, 0); - } - var loop = function ( i ) { - list.push(function () { return arr[i].apply(null, args); }); - }; - - for (var i = 0; i < arr.length; ++i) - loop( i ); - } - - function fireOrphanDelayed() { - var delayed = orphanDelayedCallbacks; - orphanDelayedCallbacks = null; - for (var i = 0; i < delayed.length; ++i) { delayed[i](); } - } - - // When an aspect of a line changes, a string is added to - // lineView.changes. This updates the relevant part of the line's - // DOM structure. - function updateLineForChanges(cm, lineView, lineN, dims) { - for (var j = 0; j < lineView.changes.length; j++) { - var type = lineView.changes[j]; - if (type == "text") { updateLineText(cm, lineView); } - else if (type == "gutter") { updateLineGutter(cm, lineView, lineN, dims); } - else if (type == "class") { updateLineClasses(cm, lineView); } - else if (type == "widget") { updateLineWidgets(cm, lineView, dims); } - } - lineView.changes = null; - } - - // Lines with gutter elements, widgets or a background class need to - // be wrapped, and have the extra elements added to the wrapper div - function ensureLineWrapped(lineView) { - if (lineView.node == lineView.text) { - lineView.node = elt("div", null, null, "position: relative"); - if (lineView.text.parentNode) - { lineView.text.parentNode.replaceChild(lineView.node, lineView.text); } - lineView.node.appendChild(lineView.text); - if (ie && ie_version < 8) { lineView.node.style.zIndex = 2; } - } - return lineView.node - } - - function updateLineBackground(cm, lineView) { - var cls = lineView.bgClass ? lineView.bgClass + " " + (lineView.line.bgClass || "") : lineView.line.bgClass; - if (cls) { cls += " CodeMirror-linebackground"; } - if (lineView.background) { - if (cls) { lineView.background.className = cls; } - else { lineView.background.parentNode.removeChild(lineView.background); lineView.background = null; } - } else if (cls) { - var wrap = ensureLineWrapped(lineView); - lineView.background = wrap.insertBefore(elt("div", null, cls), wrap.firstChild); - cm.display.input.setUneditable(lineView.background); - } - } - - // Wrapper around buildLineContent which will reuse the structure - // in display.externalMeasured when possible. - function getLineContent(cm, lineView) { - var ext = cm.display.externalMeasured; - if (ext && ext.line == lineView.line) { - cm.display.externalMeasured = null; - lineView.measure = ext.measure; - return ext.built - } - return buildLineContent(cm, lineView) - } - - // Redraw the line's text. Interacts with the background and text - // classes because the mode may output tokens that influence these - // classes. - function updateLineText(cm, lineView) { - var cls = lineView.text.className; - var built = getLineContent(cm, lineView); - if (lineView.text == lineView.node) { lineView.node = built.pre; } - lineView.text.parentNode.replaceChild(built.pre, lineView.text); - lineView.text = built.pre; - if (built.bgClass != lineView.bgClass || built.textClass != lineView.textClass) { - lineView.bgClass = built.bgClass; - lineView.textClass = built.textClass; - updateLineClasses(cm, lineView); - } else if (cls) { - lineView.text.className = cls; - } - } - - function updateLineClasses(cm, lineView) { - updateLineBackground(cm, lineView); - if (lineView.line.wrapClass) - { ensureLineWrapped(lineView).className = lineView.line.wrapClass; } - else if (lineView.node != lineView.text) - { lineView.node.className = ""; } - var textClass = lineView.textClass ? lineView.textClass + " " + (lineView.line.textClass || "") : lineView.line.textClass; - lineView.text.className = textClass || ""; - } - - function updateLineGutter(cm, lineView, lineN, dims) { - if (lineView.gutter) { - lineView.node.removeChild(lineView.gutter); - lineView.gutter = null; - } - if (lineView.gutterBackground) { - lineView.node.removeChild(lineView.gutterBackground); - lineView.gutterBackground = null; - } - if (lineView.line.gutterClass) { - var wrap = ensureLineWrapped(lineView); - lineView.gutterBackground = elt("div", null, "CodeMirror-gutter-background " + lineView.line.gutterClass, - ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px; width: " + (dims.gutterTotalWidth) + "px")); - cm.display.input.setUneditable(lineView.gutterBackground); - wrap.insertBefore(lineView.gutterBackground, lineView.text); - } - var markers = lineView.line.gutterMarkers; - if (cm.options.lineNumbers || markers) { - var wrap$1 = ensureLineWrapped(lineView); - var gutterWrap = lineView.gutter = elt("div", null, "CodeMirror-gutter-wrapper", ("left: " + (cm.options.fixedGutter ? dims.fixedPos : -dims.gutterTotalWidth) + "px")); - cm.display.input.setUneditable(gutterWrap); - wrap$1.insertBefore(gutterWrap, lineView.text); - if (lineView.line.gutterClass) - { gutterWrap.className += " " + lineView.line.gutterClass; } - if (cm.options.lineNumbers && (!markers || !markers["CodeMirror-linenumbers"])) - { lineView.lineNumber = gutterWrap.appendChild( - elt("div", lineNumberFor(cm.options, lineN), - "CodeMirror-linenumber CodeMirror-gutter-elt", - ("left: " + (dims.gutterLeft["CodeMirror-linenumbers"]) + "px; width: " + (cm.display.lineNumInnerWidth) + "px"))); } - if (markers) { for (var k = 0; k < cm.display.gutterSpecs.length; ++k) { - var id = cm.display.gutterSpecs[k].className, found = markers.hasOwnProperty(id) && markers[id]; - if (found) - { gutterWrap.appendChild(elt("div", [found], "CodeMirror-gutter-elt", - ("left: " + (dims.gutterLeft[id]) + "px; width: " + (dims.gutterWidth[id]) + "px"))); } - } } - } - } - - function updateLineWidgets(cm, lineView, dims) { - if (lineView.alignable) { lineView.alignable = null; } - var isWidget = classTest("CodeMirror-linewidget"); - for (var node = lineView.node.firstChild, next = (void 0); node; node = next) { - next = node.nextSibling; - if (isWidget.test(node.className)) { lineView.node.removeChild(node); } - } - insertLineWidgets(cm, lineView, dims); - } - - // Build a line's DOM representation from scratch - function buildLineElement(cm, lineView, lineN, dims) { - var built = getLineContent(cm, lineView); - lineView.text = lineView.node = built.pre; - if (built.bgClass) { lineView.bgClass = built.bgClass; } - if (built.textClass) { lineView.textClass = built.textClass; } - - updateLineClasses(cm, lineView); - updateLineGutter(cm, lineView, lineN, dims); - insertLineWidgets(cm, lineView, dims); - return lineView.node - } - - // A lineView may contain multiple logical lines (when merged by - // collapsed spans). The widgets for all of them need to be drawn. - function insertLineWidgets(cm, lineView, dims) { - insertLineWidgetsFor(cm, lineView.line, lineView, dims, true); - if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) - { insertLineWidgetsFor(cm, lineView.rest[i], lineView, dims, false); } } - } - - function insertLineWidgetsFor(cm, line, lineView, dims, allowAbove) { - if (!line.widgets) { return } - var wrap = ensureLineWrapped(lineView); - for (var i = 0, ws = line.widgets; i < ws.length; ++i) { - var widget = ws[i], node = elt("div", [widget.node], "CodeMirror-linewidget" + (widget.className ? " " + widget.className : "")); - if (!widget.handleMouseEvents) { node.setAttribute("cm-ignore-events", "true"); } - positionLineWidget(widget, node, lineView, dims); - cm.display.input.setUneditable(node); - if (allowAbove && widget.above) - { wrap.insertBefore(node, lineView.gutter || lineView.text); } - else - { wrap.appendChild(node); } - signalLater(widget, "redraw"); - } - } - - function positionLineWidget(widget, node, lineView, dims) { - if (widget.noHScroll) { - (lineView.alignable || (lineView.alignable = [])).push(node); - var width = dims.wrapperWidth; - node.style.left = dims.fixedPos + "px"; - if (!widget.coverGutter) { - width -= dims.gutterTotalWidth; - node.style.paddingLeft = dims.gutterTotalWidth + "px"; - } - node.style.width = width + "px"; - } - if (widget.coverGutter) { - node.style.zIndex = 5; - node.style.position = "relative"; - if (!widget.noHScroll) { node.style.marginLeft = -dims.gutterTotalWidth + "px"; } - } - } - - function widgetHeight(widget) { - if (widget.height != null) { return widget.height } - var cm = widget.doc.cm; - if (!cm) { return 0 } - if (!contains(document.body, widget.node)) { - var parentStyle = "position: relative;"; - if (widget.coverGutter) - { parentStyle += "margin-left: -" + cm.display.gutters.offsetWidth + "px;"; } - if (widget.noHScroll) - { parentStyle += "width: " + cm.display.wrapper.clientWidth + "px;"; } - removeChildrenAndAdd(cm.display.measure, elt("div", [widget.node], null, parentStyle)); - } - return widget.height = widget.node.parentNode.offsetHeight - } - - // Return true when the given mouse event happened in a widget - function eventInWidget(display, e) { - for (var n = e_target(e); n != display.wrapper; n = n.parentNode) { - if (!n || (n.nodeType == 1 && n.getAttribute("cm-ignore-events") == "true") || - (n.parentNode == display.sizer && n != display.mover)) - { return true } - } - } - - // POSITION MEASUREMENT - - function paddingTop(display) {return display.lineSpace.offsetTop} - function paddingVert(display) {return display.mover.offsetHeight - display.lineSpace.offsetHeight} - function paddingH(display) { - if (display.cachedPaddingH) { return display.cachedPaddingH } - var e = removeChildrenAndAdd(display.measure, elt("pre", "x", "CodeMirror-line-like")); - var style = window.getComputedStyle ? window.getComputedStyle(e) : e.currentStyle; - var data = {left: parseInt(style.paddingLeft), right: parseInt(style.paddingRight)}; - if (!isNaN(data.left) && !isNaN(data.right)) { display.cachedPaddingH = data; } - return data - } - - function scrollGap(cm) { return scrollerGap - cm.display.nativeBarWidth } - function displayWidth(cm) { - return cm.display.scroller.clientWidth - scrollGap(cm) - cm.display.barWidth - } - function displayHeight(cm) { - return cm.display.scroller.clientHeight - scrollGap(cm) - cm.display.barHeight - } - - // Ensure the lineView.wrapping.heights array is populated. This is - // an array of bottom offsets for the lines that make up a drawn - // line. When lineWrapping is on, there might be more than one - // height. - function ensureLineHeights(cm, lineView, rect) { - var wrapping = cm.options.lineWrapping; - var curWidth = wrapping && displayWidth(cm); - if (!lineView.measure.heights || wrapping && lineView.measure.width != curWidth) { - var heights = lineView.measure.heights = []; - if (wrapping) { - lineView.measure.width = curWidth; - var rects = lineView.text.firstChild.getClientRects(); - for (var i = 0; i < rects.length - 1; i++) { - var cur = rects[i], next = rects[i + 1]; - if (Math.abs(cur.bottom - next.bottom) > 2) - { heights.push((cur.bottom + next.top) / 2 - rect.top); } - } - } - heights.push(rect.bottom - rect.top); - } - } - - // Find a line map (mapping character offsets to text nodes) and a - // measurement cache for the given line number. (A line view might - // contain multiple lines when collapsed ranges are present.) - function mapFromLineView(lineView, line, lineN) { - if (lineView.line == line) - { return {map: lineView.measure.map, cache: lineView.measure.cache} } - for (var i = 0; i < lineView.rest.length; i++) - { if (lineView.rest[i] == line) - { return {map: lineView.measure.maps[i], cache: lineView.measure.caches[i]} } } - for (var i$1 = 0; i$1 < lineView.rest.length; i$1++) - { if (lineNo(lineView.rest[i$1]) > lineN) - { return {map: lineView.measure.maps[i$1], cache: lineView.measure.caches[i$1], before: true} } } - } - - // Render a line into the hidden node display.externalMeasured. Used - // when measurement is needed for a line that's not in the viewport. - function updateExternalMeasurement(cm, line) { - line = visualLine(line); - var lineN = lineNo(line); - var view = cm.display.externalMeasured = new LineView(cm.doc, line, lineN); - view.lineN = lineN; - var built = view.built = buildLineContent(cm, view); - view.text = built.pre; - removeChildrenAndAdd(cm.display.lineMeasure, built.pre); - return view - } - - // Get a {top, bottom, left, right} box (in line-local coordinates) - // for a given character. - function measureChar(cm, line, ch, bias) { - return measureCharPrepared(cm, prepareMeasureForLine(cm, line), ch, bias) - } - - // Find a line view that corresponds to the given line number. - function findViewForLine(cm, lineN) { - if (lineN >= cm.display.viewFrom && lineN < cm.display.viewTo) - { return cm.display.view[findViewIndex(cm, lineN)] } - var ext = cm.display.externalMeasured; - if (ext && lineN >= ext.lineN && lineN < ext.lineN + ext.size) - { return ext } - } - - // Measurement can be split in two steps, the set-up work that - // applies to the whole line, and the measurement of the actual - // character. Functions like coordsChar, that need to do a lot of - // measurements in a row, can thus ensure that the set-up work is - // only done once. - function prepareMeasureForLine(cm, line) { - var lineN = lineNo(line); - var view = findViewForLine(cm, lineN); - if (view && !view.text) { - view = null; - } else if (view && view.changes) { - updateLineForChanges(cm, view, lineN, getDimensions(cm)); - cm.curOp.forceUpdate = true; - } - if (!view) - { view = updateExternalMeasurement(cm, line); } - - var info = mapFromLineView(view, line, lineN); - return { - line: line, view: view, rect: null, - map: info.map, cache: info.cache, before: info.before, - hasHeights: false - } - } - - // Given a prepared measurement object, measures the position of an - // actual character (or fetches it from the cache). - function measureCharPrepared(cm, prepared, ch, bias, varHeight) { - if (prepared.before) { ch = -1; } - var key = ch + (bias || ""), found; - if (prepared.cache.hasOwnProperty(key)) { - found = prepared.cache[key]; - } else { - if (!prepared.rect) - { prepared.rect = prepared.view.text.getBoundingClientRect(); } - if (!prepared.hasHeights) { - ensureLineHeights(cm, prepared.view, prepared.rect); - prepared.hasHeights = true; - } - found = measureCharInner(cm, prepared, ch, bias); - if (!found.bogus) { prepared.cache[key] = found; } - } - return {left: found.left, right: found.right, - top: varHeight ? found.rtop : found.top, - bottom: varHeight ? found.rbottom : found.bottom} - } - - var nullRect = {left: 0, right: 0, top: 0, bottom: 0}; - - function nodeAndOffsetInLineMap(map, ch, bias) { - var node, start, end, collapse, mStart, mEnd; - // First, search the line map for the text node corresponding to, - // or closest to, the target character. - for (var i = 0; i < map.length; i += 3) { - mStart = map[i]; - mEnd = map[i + 1]; - if (ch < mStart) { - start = 0; end = 1; - collapse = "left"; - } else if (ch < mEnd) { - start = ch - mStart; - end = start + 1; - } else if (i == map.length - 3 || ch == mEnd && map[i + 3] > ch) { - end = mEnd - mStart; - start = end - 1; - if (ch >= mEnd) { collapse = "right"; } - } - if (start != null) { - node = map[i + 2]; - if (mStart == mEnd && bias == (node.insertLeft ? "left" : "right")) - { collapse = bias; } - if (bias == "left" && start == 0) - { while (i && map[i - 2] == map[i - 3] && map[i - 1].insertLeft) { - node = map[(i -= 3) + 2]; - collapse = "left"; - } } - if (bias == "right" && start == mEnd - mStart) - { while (i < map.length - 3 && map[i + 3] == map[i + 4] && !map[i + 5].insertLeft) { - node = map[(i += 3) + 2]; - collapse = "right"; - } } - break - } - } - return {node: node, start: start, end: end, collapse: collapse, coverStart: mStart, coverEnd: mEnd} - } - - function getUsefulRect(rects, bias) { - var rect = nullRect; - if (bias == "left") { for (var i = 0; i < rects.length; i++) { - if ((rect = rects[i]).left != rect.right) { break } - } } else { for (var i$1 = rects.length - 1; i$1 >= 0; i$1--) { - if ((rect = rects[i$1]).left != rect.right) { break } - } } - return rect - } - - function measureCharInner(cm, prepared, ch, bias) { - var place = nodeAndOffsetInLineMap(prepared.map, ch, bias); - var node = place.node, start = place.start, end = place.end, collapse = place.collapse; - - var rect; - if (node.nodeType == 3) { // If it is a text node, use a range to retrieve the coordinates. - for (var i$1 = 0; i$1 < 4; i$1++) { // Retry a maximum of 4 times when nonsense rectangles are returned - while (start && isExtendingChar(prepared.line.text.charAt(place.coverStart + start))) { --start; } - while (place.coverStart + end < place.coverEnd && isExtendingChar(prepared.line.text.charAt(place.coverStart + end))) { ++end; } - if (ie && ie_version < 9 && start == 0 && end == place.coverEnd - place.coverStart) - { rect = node.parentNode.getBoundingClientRect(); } - else - { rect = getUsefulRect(range(node, start, end).getClientRects(), bias); } - if (rect.left || rect.right || start == 0) { break } - end = start; - start = start - 1; - collapse = "right"; - } - if (ie && ie_version < 11) { rect = maybeUpdateRectForZooming(cm.display.measure, rect); } - } else { // If it is a widget, simply get the box for the whole widget. - if (start > 0) { collapse = bias = "right"; } - var rects; - if (cm.options.lineWrapping && (rects = node.getClientRects()).length > 1) - { rect = rects[bias == "right" ? rects.length - 1 : 0]; } - else - { rect = node.getBoundingClientRect(); } - } - if (ie && ie_version < 9 && !start && (!rect || !rect.left && !rect.right)) { - var rSpan = node.parentNode.getClientRects()[0]; - if (rSpan) - { rect = {left: rSpan.left, right: rSpan.left + charWidth(cm.display), top: rSpan.top, bottom: rSpan.bottom}; } - else - { rect = nullRect; } - } - - var rtop = rect.top - prepared.rect.top, rbot = rect.bottom - prepared.rect.top; - var mid = (rtop + rbot) / 2; - var heights = prepared.view.measure.heights; - var i = 0; - for (; i < heights.length - 1; i++) - { if (mid < heights[i]) { break } } - var top = i ? heights[i - 1] : 0, bot = heights[i]; - var result = {left: (collapse == "right" ? rect.right : rect.left) - prepared.rect.left, - right: (collapse == "left" ? rect.left : rect.right) - prepared.rect.left, - top: top, bottom: bot}; - if (!rect.left && !rect.right) { result.bogus = true; } - if (!cm.options.singleCursorHeightPerLine) { result.rtop = rtop; result.rbottom = rbot; } - - return result - } - - // Work around problem with bounding client rects on ranges being - // returned incorrectly when zoomed on IE10 and below. - function maybeUpdateRectForZooming(measure, rect) { - if (!window.screen || screen.logicalXDPI == null || - screen.logicalXDPI == screen.deviceXDPI || !hasBadZoomedRects(measure)) - { return rect } - var scaleX = screen.logicalXDPI / screen.deviceXDPI; - var scaleY = screen.logicalYDPI / screen.deviceYDPI; - return {left: rect.left * scaleX, right: rect.right * scaleX, - top: rect.top * scaleY, bottom: rect.bottom * scaleY} - } - - function clearLineMeasurementCacheFor(lineView) { - if (lineView.measure) { - lineView.measure.cache = {}; - lineView.measure.heights = null; - if (lineView.rest) { for (var i = 0; i < lineView.rest.length; i++) - { lineView.measure.caches[i] = {}; } } - } - } - - function clearLineMeasurementCache(cm) { - cm.display.externalMeasure = null; - removeChildren(cm.display.lineMeasure); - for (var i = 0; i < cm.display.view.length; i++) - { clearLineMeasurementCacheFor(cm.display.view[i]); } - } - - function clearCaches(cm) { - clearLineMeasurementCache(cm); - cm.display.cachedCharWidth = cm.display.cachedTextHeight = cm.display.cachedPaddingH = null; - if (!cm.options.lineWrapping) { cm.display.maxLineChanged = true; } - cm.display.lineNumChars = null; - } - - function pageScrollX() { - // Work around https://bugs.chromium.org/p/chromium/issues/detail?id=489206 - // which causes page_Offset and bounding client rects to use - // different reference viewports and invalidate our calculations. - if (chrome && android) { return -(document.body.getBoundingClientRect().left - parseInt(getComputedStyle(document.body).marginLeft)) } - return window.pageXOffset || (document.documentElement || document.body).scrollLeft - } - function pageScrollY() { - if (chrome && android) { return -(document.body.getBoundingClientRect().top - parseInt(getComputedStyle(document.body).marginTop)) } - return window.pageYOffset || (document.documentElement || document.body).scrollTop - } - - function widgetTopHeight(lineObj) { - var height = 0; - if (lineObj.widgets) { for (var i = 0; i < lineObj.widgets.length; ++i) { if (lineObj.widgets[i].above) - { height += widgetHeight(lineObj.widgets[i]); } } } - return height - } - - // Converts a {top, bottom, left, right} box from line-local - // coordinates into another coordinate system. Context may be one of - // "line", "div" (display.lineDiv), "local"./null (editor), "window", - // or "page". - function intoCoordSystem(cm, lineObj, rect, context, includeWidgets) { - if (!includeWidgets) { - var height = widgetTopHeight(lineObj); - rect.top += height; rect.bottom += height; - } - if (context == "line") { return rect } - if (!context) { context = "local"; } - var yOff = heightAtLine(lineObj); - if (context == "local") { yOff += paddingTop(cm.display); } - else { yOff -= cm.display.viewOffset; } - if (context == "page" || context == "window") { - var lOff = cm.display.lineSpace.getBoundingClientRect(); - yOff += lOff.top + (context == "window" ? 0 : pageScrollY()); - var xOff = lOff.left + (context == "window" ? 0 : pageScrollX()); - rect.left += xOff; rect.right += xOff; - } - rect.top += yOff; rect.bottom += yOff; - return rect - } - - // Coverts a box from "div" coords to another coordinate system. - // Context may be "window", "page", "div", or "local"./null. - function fromCoordSystem(cm, coords, context) { - if (context == "div") { return coords } - var left = coords.left, top = coords.top; - // First move into "page" coordinate system - if (context == "page") { - left -= pageScrollX(); - top -= pageScrollY(); - } else if (context == "local" || !context) { - var localBox = cm.display.sizer.getBoundingClientRect(); - left += localBox.left; - top += localBox.top; - } - - var lineSpaceBox = cm.display.lineSpace.getBoundingClientRect(); - return {left: left - lineSpaceBox.left, top: top - lineSpaceBox.top} - } - - function charCoords(cm, pos, context, lineObj, bias) { - if (!lineObj) { lineObj = getLine(cm.doc, pos.line); } - return intoCoordSystem(cm, lineObj, measureChar(cm, lineObj, pos.ch, bias), context) - } - - // Returns a box for a given cursor position, which may have an - // 'other' property containing the position of the secondary cursor - // on a bidi boundary. - // A cursor Pos(line, char, "before") is on the same visual line as `char - 1` - // and after `char - 1` in writing order of `char - 1` - // A cursor Pos(line, char, "after") is on the same visual line as `char` - // and before `char` in writing order of `char` - // Examples (upper-case letters are RTL, lower-case are LTR): - // Pos(0, 1, ...) - // before after - // ab a|b a|b - // aB a|B aB| - // Ab |Ab A|b - // AB B|A B|A - // Every position after the last character on a line is considered to stick - // to the last character on the line. - function cursorCoords(cm, pos, context, lineObj, preparedMeasure, varHeight) { - lineObj = lineObj || getLine(cm.doc, pos.line); - if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } - function get(ch, right) { - var m = measureCharPrepared(cm, preparedMeasure, ch, right ? "right" : "left", varHeight); - if (right) { m.left = m.right; } else { m.right = m.left; } - return intoCoordSystem(cm, lineObj, m, context) - } - var order = getOrder(lineObj, cm.doc.direction), ch = pos.ch, sticky = pos.sticky; - if (ch >= lineObj.text.length) { - ch = lineObj.text.length; - sticky = "before"; - } else if (ch <= 0) { - ch = 0; - sticky = "after"; - } - if (!order) { return get(sticky == "before" ? ch - 1 : ch, sticky == "before") } - - function getBidi(ch, partPos, invert) { - var part = order[partPos], right = part.level == 1; - return get(invert ? ch - 1 : ch, right != invert) - } - var partPos = getBidiPartAt(order, ch, sticky); - var other = bidiOther; - var val = getBidi(ch, partPos, sticky == "before"); - if (other != null) { val.other = getBidi(ch, other, sticky != "before"); } - return val - } - - // Used to cheaply estimate the coordinates for a position. Used for - // intermediate scroll updates. - function estimateCoords(cm, pos) { - var left = 0; - pos = clipPos(cm.doc, pos); - if (!cm.options.lineWrapping) { left = charWidth(cm.display) * pos.ch; } - var lineObj = getLine(cm.doc, pos.line); - var top = heightAtLine(lineObj) + paddingTop(cm.display); - return {left: left, right: left, top: top, bottom: top + lineObj.height} - } - - // Positions returned by coordsChar contain some extra information. - // xRel is the relative x position of the input coordinates compared - // to the found position (so xRel > 0 means the coordinates are to - // the right of the character position, for example). When outside - // is true, that means the coordinates lie outside the line's - // vertical range. - function PosWithInfo(line, ch, sticky, outside, xRel) { - var pos = Pos(line, ch, sticky); - pos.xRel = xRel; - if (outside) { pos.outside = outside; } - return pos - } - - // Compute the character position closest to the given coordinates. - // Input must be lineSpace-local ("div" coordinate system). - function coordsChar(cm, x, y) { - var doc = cm.doc; - y += cm.display.viewOffset; - if (y < 0) { return PosWithInfo(doc.first, 0, null, -1, -1) } - var lineN = lineAtHeight(doc, y), last = doc.first + doc.size - 1; - if (lineN > last) - { return PosWithInfo(doc.first + doc.size - 1, getLine(doc, last).text.length, null, 1, 1) } - if (x < 0) { x = 0; } - - var lineObj = getLine(doc, lineN); - for (;;) { - var found = coordsCharInner(cm, lineObj, lineN, x, y); - var collapsed = collapsedSpanAround(lineObj, found.ch + (found.xRel > 0 || found.outside > 0 ? 1 : 0)); - if (!collapsed) { return found } - var rangeEnd = collapsed.find(1); - if (rangeEnd.line == lineN) { return rangeEnd } - lineObj = getLine(doc, lineN = rangeEnd.line); - } - } - - function wrappedLineExtent(cm, lineObj, preparedMeasure, y) { - y -= widgetTopHeight(lineObj); - var end = lineObj.text.length; - var begin = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch - 1).bottom <= y; }, end, 0); - end = findFirst(function (ch) { return measureCharPrepared(cm, preparedMeasure, ch).top > y; }, begin, end); - return {begin: begin, end: end} - } - - function wrappedLineExtentChar(cm, lineObj, preparedMeasure, target) { - if (!preparedMeasure) { preparedMeasure = prepareMeasureForLine(cm, lineObj); } - var targetTop = intoCoordSystem(cm, lineObj, measureCharPrepared(cm, preparedMeasure, target), "line").top; - return wrappedLineExtent(cm, lineObj, preparedMeasure, targetTop) - } - - // Returns true if the given side of a box is after the given - // coordinates, in top-to-bottom, left-to-right order. - function boxIsAfter(box, x, y, left) { - return box.bottom <= y ? false : box.top > y ? true : (left ? box.left : box.right) > x - } - - function coordsCharInner(cm, lineObj, lineNo, x, y) { - // Move y into line-local coordinate space - y -= heightAtLine(lineObj); - var preparedMeasure = prepareMeasureForLine(cm, lineObj); - // When directly calling `measureCharPrepared`, we have to adjust - // for the widgets at this line. - var widgetHeight = widgetTopHeight(lineObj); - var begin = 0, end = lineObj.text.length, ltr = true; - - var order = getOrder(lineObj, cm.doc.direction); - // If the line isn't plain left-to-right text, first figure out - // which bidi section the coordinates fall into. - if (order) { - var part = (cm.options.lineWrapping ? coordsBidiPartWrapped : coordsBidiPart) - (cm, lineObj, lineNo, preparedMeasure, order, x, y); - ltr = part.level != 1; - // The awkward -1 offsets are needed because findFirst (called - // on these below) will treat its first bound as inclusive, - // second as exclusive, but we want to actually address the - // characters in the part's range - begin = ltr ? part.from : part.to - 1; - end = ltr ? part.to : part.from - 1; - } - - // A binary search to find the first character whose bounding box - // starts after the coordinates. If we run across any whose box wrap - // the coordinates, store that. - var chAround = null, boxAround = null; - var ch = findFirst(function (ch) { - var box = measureCharPrepared(cm, preparedMeasure, ch); - box.top += widgetHeight; box.bottom += widgetHeight; - if (!boxIsAfter(box, x, y, false)) { return false } - if (box.top <= y && box.left <= x) { - chAround = ch; - boxAround = box; - } - return true - }, begin, end); - - var baseX, sticky, outside = false; - // If a box around the coordinates was found, use that - if (boxAround) { - // Distinguish coordinates nearer to the left or right side of the box - var atLeft = x - boxAround.left < boxAround.right - x, atStart = atLeft == ltr; - ch = chAround + (atStart ? 0 : 1); - sticky = atStart ? "after" : "before"; - baseX = atLeft ? boxAround.left : boxAround.right; - } else { - // (Adjust for extended bound, if necessary.) - if (!ltr && (ch == end || ch == begin)) { ch++; } - // To determine which side to associate with, get the box to the - // left of the character and compare it's vertical position to the - // coordinates - sticky = ch == 0 ? "after" : ch == lineObj.text.length ? "before" : - (measureCharPrepared(cm, preparedMeasure, ch - (ltr ? 1 : 0)).bottom + widgetHeight <= y) == ltr ? - "after" : "before"; - // Now get accurate coordinates for this place, in order to get a - // base X position - var coords = cursorCoords(cm, Pos(lineNo, ch, sticky), "line", lineObj, preparedMeasure); - baseX = coords.left; - outside = y < coords.top ? -1 : y >= coords.bottom ? 1 : 0; - } - - ch = skipExtendingChars(lineObj.text, ch, 1); - return PosWithInfo(lineNo, ch, sticky, outside, x - baseX) - } - - function coordsBidiPart(cm, lineObj, lineNo, preparedMeasure, order, x, y) { - // Bidi parts are sorted left-to-right, and in a non-line-wrapping - // situation, we can take this ordering to correspond to the visual - // ordering. This finds the first part whose end is after the given - // coordinates. - var index = findFirst(function (i) { - var part = order[i], ltr = part.level != 1; - return boxIsAfter(cursorCoords(cm, Pos(lineNo, ltr ? part.to : part.from, ltr ? "before" : "after"), - "line", lineObj, preparedMeasure), x, y, true) - }, 0, order.length - 1); - var part = order[index]; - // If this isn't the first part, the part's start is also after - // the coordinates, and the coordinates aren't on the same line as - // that start, move one part back. - if (index > 0) { - var ltr = part.level != 1; - var start = cursorCoords(cm, Pos(lineNo, ltr ? part.from : part.to, ltr ? "after" : "before"), - "line", lineObj, preparedMeasure); - if (boxIsAfter(start, x, y, true) && start.top > y) - { part = order[index - 1]; } - } - return part - } - - function coordsBidiPartWrapped(cm, lineObj, _lineNo, preparedMeasure, order, x, y) { - // In a wrapped line, rtl text on wrapping boundaries can do things - // that don't correspond to the ordering in our `order` array at - // all, so a binary search doesn't work, and we want to return a - // part that only spans one line so that the binary search in - // coordsCharInner is safe. As such, we first find the extent of the - // wrapped line, and then do a flat search in which we discard any - // spans that aren't on the line. - var ref = wrappedLineExtent(cm, lineObj, preparedMeasure, y); - var begin = ref.begin; - var end = ref.end; - if (/\s/.test(lineObj.text.charAt(end - 1))) { end--; } - var part = null, closestDist = null; - for (var i = 0; i < order.length; i++) { - var p = order[i]; - if (p.from >= end || p.to <= begin) { continue } - var ltr = p.level != 1; - var endX = measureCharPrepared(cm, preparedMeasure, ltr ? Math.min(end, p.to) - 1 : Math.max(begin, p.from)).right; - // Weigh against spans ending before this, so that they are only - // picked if nothing ends after - var dist = endX < x ? x - endX + 1e9 : endX - x; - if (!part || closestDist > dist) { - part = p; - closestDist = dist; - } - } - if (!part) { part = order[order.length - 1]; } - // Clip the part to the wrapped line. - if (part.from < begin) { part = {from: begin, to: part.to, level: part.level}; } - if (part.to > end) { part = {from: part.from, to: end, level: part.level}; } - return part - } - - var measureText; - // Compute the default text height. - function textHeight(display) { - if (display.cachedTextHeight != null) { return display.cachedTextHeight } - if (measureText == null) { - measureText = elt("pre", null, "CodeMirror-line-like"); - // Measure a bunch of lines, for browsers that compute - // fractional heights. - for (var i = 0; i < 49; ++i) { - measureText.appendChild(document.createTextNode("x")); - measureText.appendChild(elt("br")); - } - measureText.appendChild(document.createTextNode("x")); - } - removeChildrenAndAdd(display.measure, measureText); - var height = measureText.offsetHeight / 50; - if (height > 3) { display.cachedTextHeight = height; } - removeChildren(display.measure); - return height || 1 - } - - // Compute the default character width. - function charWidth(display) { - if (display.cachedCharWidth != null) { return display.cachedCharWidth } - var anchor = elt("span", "xxxxxxxxxx"); - var pre = elt("pre", [anchor], "CodeMirror-line-like"); - removeChildrenAndAdd(display.measure, pre); - var rect = anchor.getBoundingClientRect(), width = (rect.right - rect.left) / 10; - if (width > 2) { display.cachedCharWidth = width; } - return width || 10 - } - - // Do a bulk-read of the DOM positions and sizes needed to draw the - // view, so that we don't interleave reading and writing to the DOM. - function getDimensions(cm) { - var d = cm.display, left = {}, width = {}; - var gutterLeft = d.gutters.clientLeft; - for (var n = d.gutters.firstChild, i = 0; n; n = n.nextSibling, ++i) { - var id = cm.display.gutterSpecs[i].className; - left[id] = n.offsetLeft + n.clientLeft + gutterLeft; - width[id] = n.clientWidth; - } - return {fixedPos: compensateForHScroll(d), - gutterTotalWidth: d.gutters.offsetWidth, - gutterLeft: left, - gutterWidth: width, - wrapperWidth: d.wrapper.clientWidth} - } - - // Computes display.scroller.scrollLeft + display.gutters.offsetWidth, - // but using getBoundingClientRect to get a sub-pixel-accurate - // result. - function compensateForHScroll(display) { - return display.scroller.getBoundingClientRect().left - display.sizer.getBoundingClientRect().left - } - - // Returns a function that estimates the height of a line, to use as - // first approximation until the line becomes visible (and is thus - // properly measurable). - function estimateHeight(cm) { - var th = textHeight(cm.display), wrapping = cm.options.lineWrapping; - var perLine = wrapping && Math.max(5, cm.display.scroller.clientWidth / charWidth(cm.display) - 3); - return function (line) { - if (lineIsHidden(cm.doc, line)) { return 0 } - - var widgetsHeight = 0; - if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) { - if (line.widgets[i].height) { widgetsHeight += line.widgets[i].height; } - } } - - if (wrapping) - { return widgetsHeight + (Math.ceil(line.text.length / perLine) || 1) * th } - else - { return widgetsHeight + th } - } - } - - function estimateLineHeights(cm) { - var doc = cm.doc, est = estimateHeight(cm); - doc.iter(function (line) { - var estHeight = est(line); - if (estHeight != line.height) { updateLineHeight(line, estHeight); } - }); - } - - // Given a mouse event, find the corresponding position. If liberal - // is false, it checks whether a gutter or scrollbar was clicked, - // and returns null if it was. forRect is used by rectangular - // selections, and tries to estimate a character position even for - // coordinates beyond the right of the text. - function posFromMouse(cm, e, liberal, forRect) { - var display = cm.display; - if (!liberal && e_target(e).getAttribute("cm-not-content") == "true") { return null } - - var x, y, space = display.lineSpace.getBoundingClientRect(); - // Fails unpredictably on IE[67] when mouse is dragged around quickly. - try { x = e.clientX - space.left; y = e.clientY - space.top; } - catch (e$1) { return null } - var coords = coordsChar(cm, x, y), line; - if (forRect && coords.xRel > 0 && (line = getLine(cm.doc, coords.line).text).length == coords.ch) { - var colDiff = countColumn(line, line.length, cm.options.tabSize) - line.length; - coords = Pos(coords.line, Math.max(0, Math.round((x - paddingH(cm.display).left) / charWidth(cm.display)) - colDiff)); - } - return coords - } - - // Find the view element corresponding to a given line. Return null - // when the line isn't visible. - function findViewIndex(cm, n) { - if (n >= cm.display.viewTo) { return null } - n -= cm.display.viewFrom; - if (n < 0) { return null } - var view = cm.display.view; - for (var i = 0; i < view.length; i++) { - n -= view[i].size; - if (n < 0) { return i } - } - } - - // Updates the display.view data structure for a given change to the - // document. From and to are in pre-change coordinates. Lendiff is - // the amount of lines added or subtracted by the change. This is - // used for changes that span multiple lines, or change the way - // lines are divided into visual lines. regLineChange (below) - // registers single-line changes. - function regChange(cm, from, to, lendiff) { - if (from == null) { from = cm.doc.first; } - if (to == null) { to = cm.doc.first + cm.doc.size; } - if (!lendiff) { lendiff = 0; } - - var display = cm.display; - if (lendiff && to < display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers > from)) - { display.updateLineNumbers = from; } - - cm.curOp.viewChanged = true; - - if (from >= display.viewTo) { // Change after - if (sawCollapsedSpans && visualLineNo(cm.doc, from) < display.viewTo) - { resetView(cm); } - } else if (to <= display.viewFrom) { // Change before - if (sawCollapsedSpans && visualLineEndNo(cm.doc, to + lendiff) > display.viewFrom) { - resetView(cm); - } else { - display.viewFrom += lendiff; - display.viewTo += lendiff; - } - } else if (from <= display.viewFrom && to >= display.viewTo) { // Full overlap - resetView(cm); - } else if (from <= display.viewFrom) { // Top overlap - var cut = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cut) { - display.view = display.view.slice(cut.index); - display.viewFrom = cut.lineN; - display.viewTo += lendiff; - } else { - resetView(cm); - } - } else if (to >= display.viewTo) { // Bottom overlap - var cut$1 = viewCuttingPoint(cm, from, from, -1); - if (cut$1) { - display.view = display.view.slice(0, cut$1.index); - display.viewTo = cut$1.lineN; - } else { - resetView(cm); - } - } else { // Gap in the middle - var cutTop = viewCuttingPoint(cm, from, from, -1); - var cutBot = viewCuttingPoint(cm, to, to + lendiff, 1); - if (cutTop && cutBot) { - display.view = display.view.slice(0, cutTop.index) - .concat(buildViewArray(cm, cutTop.lineN, cutBot.lineN)) - .concat(display.view.slice(cutBot.index)); - display.viewTo += lendiff; - } else { - resetView(cm); - } - } - - var ext = display.externalMeasured; - if (ext) { - if (to < ext.lineN) - { ext.lineN += lendiff; } - else if (from < ext.lineN + ext.size) - { display.externalMeasured = null; } - } - } - - // Register a change to a single line. Type must be one of "text", - // "gutter", "class", "widget" - function regLineChange(cm, line, type) { - cm.curOp.viewChanged = true; - var display = cm.display, ext = cm.display.externalMeasured; - if (ext && line >= ext.lineN && line < ext.lineN + ext.size) - { display.externalMeasured = null; } - - if (line < display.viewFrom || line >= display.viewTo) { return } - var lineView = display.view[findViewIndex(cm, line)]; - if (lineView.node == null) { return } - var arr = lineView.changes || (lineView.changes = []); - if (indexOf(arr, type) == -1) { arr.push(type); } - } - - // Clear the view. - function resetView(cm) { - cm.display.viewFrom = cm.display.viewTo = cm.doc.first; - cm.display.view = []; - cm.display.viewOffset = 0; - } - - function viewCuttingPoint(cm, oldN, newN, dir) { - var index = findViewIndex(cm, oldN), diff, view = cm.display.view; - if (!sawCollapsedSpans || newN == cm.doc.first + cm.doc.size) - { return {index: index, lineN: newN} } - var n = cm.display.viewFrom; - for (var i = 0; i < index; i++) - { n += view[i].size; } - if (n != oldN) { - if (dir > 0) { - if (index == view.length - 1) { return null } - diff = (n + view[index].size) - oldN; - index++; - } else { - diff = n - oldN; - } - oldN += diff; newN += diff; - } - while (visualLineNo(cm.doc, newN) != newN) { - if (index == (dir < 0 ? 0 : view.length - 1)) { return null } - newN += dir * view[index - (dir < 0 ? 1 : 0)].size; - index += dir; - } - return {index: index, lineN: newN} - } - - // Force the view to cover a given range, adding empty view element - // or clipping off existing ones as needed. - function adjustView(cm, from, to) { - var display = cm.display, view = display.view; - if (view.length == 0 || from >= display.viewTo || to <= display.viewFrom) { - display.view = buildViewArray(cm, from, to); - display.viewFrom = from; - } else { - if (display.viewFrom > from) - { display.view = buildViewArray(cm, from, display.viewFrom).concat(display.view); } - else if (display.viewFrom < from) - { display.view = display.view.slice(findViewIndex(cm, from)); } - display.viewFrom = from; - if (display.viewTo < to) - { display.view = display.view.concat(buildViewArray(cm, display.viewTo, to)); } - else if (display.viewTo > to) - { display.view = display.view.slice(0, findViewIndex(cm, to)); } - } - display.viewTo = to; - } - - // Count the number of lines in the view whose DOM representation is - // out of date (or nonexistent). - function countDirtyView(cm) { - var view = cm.display.view, dirty = 0; - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (!lineView.hidden && (!lineView.node || lineView.changes)) { ++dirty; } - } - return dirty - } - - function updateSelection(cm) { - cm.display.input.showSelection(cm.display.input.prepareSelection()); - } - - function prepareSelection(cm, primary) { - if ( primary === void 0 ) primary = true; - - var doc = cm.doc, result = {}; - var curFragment = result.cursors = document.createDocumentFragment(); - var selFragment = result.selection = document.createDocumentFragment(); - - for (var i = 0; i < doc.sel.ranges.length; i++) { - if (!primary && i == doc.sel.primIndex) { continue } - var range = doc.sel.ranges[i]; - if (range.from().line >= cm.display.viewTo || range.to().line < cm.display.viewFrom) { continue } - var collapsed = range.empty(); - if (collapsed || cm.options.showCursorWhenSelecting) - { drawSelectionCursor(cm, range.head, curFragment); } - if (!collapsed) - { drawSelectionRange(cm, range, selFragment); } - } - return result - } - - // Draws a cursor for the given range - function drawSelectionCursor(cm, head, output) { - var pos = cursorCoords(cm, head, "div", null, null, !cm.options.singleCursorHeightPerLine); - - var cursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor")); - cursor.style.left = pos.left + "px"; - cursor.style.top = pos.top + "px"; - cursor.style.height = Math.max(0, pos.bottom - pos.top) * cm.options.cursorHeight + "px"; - - if (pos.other) { - // Secondary cursor, shown when on a 'jump' in bi-directional text - var otherCursor = output.appendChild(elt("div", "\u00a0", "CodeMirror-cursor CodeMirror-secondarycursor")); - otherCursor.style.display = ""; - otherCursor.style.left = pos.other.left + "px"; - otherCursor.style.top = pos.other.top + "px"; - otherCursor.style.height = (pos.other.bottom - pos.other.top) * .85 + "px"; - } - } - - function cmpCoords(a, b) { return a.top - b.top || a.left - b.left } - - // Draws the given range as a highlighted selection - function drawSelectionRange(cm, range, output) { - var display = cm.display, doc = cm.doc; - var fragment = document.createDocumentFragment(); - var padding = paddingH(cm.display), leftSide = padding.left; - var rightSide = Math.max(display.sizerWidth, displayWidth(cm) - display.sizer.offsetLeft) - padding.right; - var docLTR = doc.direction == "ltr"; - - function add(left, top, width, bottom) { - if (top < 0) { top = 0; } - top = Math.round(top); - bottom = Math.round(bottom); - fragment.appendChild(elt("div", null, "CodeMirror-selected", ("position: absolute; left: " + left + "px;\n top: " + top + "px; width: " + (width == null ? rightSide - left : width) + "px;\n height: " + (bottom - top) + "px"))); - } - - function drawForLine(line, fromArg, toArg) { - var lineObj = getLine(doc, line); - var lineLen = lineObj.text.length; - var start, end; - function coords(ch, bias) { - return charCoords(cm, Pos(line, ch), "div", lineObj, bias) - } - - function wrapX(pos, dir, side) { - var extent = wrappedLineExtentChar(cm, lineObj, null, pos); - var prop = (dir == "ltr") == (side == "after") ? "left" : "right"; - var ch = side == "after" ? extent.begin : extent.end - (/\s/.test(lineObj.text.charAt(extent.end - 1)) ? 2 : 1); - return coords(ch, prop)[prop] - } - - var order = getOrder(lineObj, doc.direction); - iterateBidiSections(order, fromArg || 0, toArg == null ? lineLen : toArg, function (from, to, dir, i) { - var ltr = dir == "ltr"; - var fromPos = coords(from, ltr ? "left" : "right"); - var toPos = coords(to - 1, ltr ? "right" : "left"); - - var openStart = fromArg == null && from == 0, openEnd = toArg == null && to == lineLen; - var first = i == 0, last = !order || i == order.length - 1; - if (toPos.top - fromPos.top <= 3) { // Single line - var openLeft = (docLTR ? openStart : openEnd) && first; - var openRight = (docLTR ? openEnd : openStart) && last; - var left = openLeft ? leftSide : (ltr ? fromPos : toPos).left; - var right = openRight ? rightSide : (ltr ? toPos : fromPos).right; - add(left, fromPos.top, right - left, fromPos.bottom); - } else { // Multiple lines - var topLeft, topRight, botLeft, botRight; - if (ltr) { - topLeft = docLTR && openStart && first ? leftSide : fromPos.left; - topRight = docLTR ? rightSide : wrapX(from, dir, "before"); - botLeft = docLTR ? leftSide : wrapX(to, dir, "after"); - botRight = docLTR && openEnd && last ? rightSide : toPos.right; - } else { - topLeft = !docLTR ? leftSide : wrapX(from, dir, "before"); - topRight = !docLTR && openStart && first ? rightSide : fromPos.right; - botLeft = !docLTR && openEnd && last ? leftSide : toPos.left; - botRight = !docLTR ? rightSide : wrapX(to, dir, "after"); - } - add(topLeft, fromPos.top, topRight - topLeft, fromPos.bottom); - if (fromPos.bottom < toPos.top) { add(leftSide, fromPos.bottom, null, toPos.top); } - add(botLeft, toPos.top, botRight - botLeft, toPos.bottom); - } - - if (!start || cmpCoords(fromPos, start) < 0) { start = fromPos; } - if (cmpCoords(toPos, start) < 0) { start = toPos; } - if (!end || cmpCoords(fromPos, end) < 0) { end = fromPos; } - if (cmpCoords(toPos, end) < 0) { end = toPos; } - }); - return {start: start, end: end} - } - - var sFrom = range.from(), sTo = range.to(); - if (sFrom.line == sTo.line) { - drawForLine(sFrom.line, sFrom.ch, sTo.ch); - } else { - var fromLine = getLine(doc, sFrom.line), toLine = getLine(doc, sTo.line); - var singleVLine = visualLine(fromLine) == visualLine(toLine); - var leftEnd = drawForLine(sFrom.line, sFrom.ch, singleVLine ? fromLine.text.length + 1 : null).end; - var rightStart = drawForLine(sTo.line, singleVLine ? 0 : null, sTo.ch).start; - if (singleVLine) { - if (leftEnd.top < rightStart.top - 2) { - add(leftEnd.right, leftEnd.top, null, leftEnd.bottom); - add(leftSide, rightStart.top, rightStart.left, rightStart.bottom); - } else { - add(leftEnd.right, leftEnd.top, rightStart.left - leftEnd.right, leftEnd.bottom); - } - } - if (leftEnd.bottom < rightStart.top) - { add(leftSide, leftEnd.bottom, null, rightStart.top); } - } - - output.appendChild(fragment); - } - - // Cursor-blinking - function restartBlink(cm) { - if (!cm.state.focused) { return } - var display = cm.display; - clearInterval(display.blinker); - var on = true; - display.cursorDiv.style.visibility = ""; - if (cm.options.cursorBlinkRate > 0) - { display.blinker = setInterval(function () { - if (!cm.hasFocus()) { onBlur(cm); } - display.cursorDiv.style.visibility = (on = !on) ? "" : "hidden"; - }, cm.options.cursorBlinkRate); } - else if (cm.options.cursorBlinkRate < 0) - { display.cursorDiv.style.visibility = "hidden"; } - } - - function ensureFocus(cm) { - if (!cm.hasFocus()) { - cm.display.input.focus(); - if (!cm.state.focused) { onFocus(cm); } - } - } - - function delayBlurEvent(cm) { - cm.state.delayingBlurEvent = true; - setTimeout(function () { if (cm.state.delayingBlurEvent) { - cm.state.delayingBlurEvent = false; - if (cm.state.focused) { onBlur(cm); } - } }, 100); - } - - function onFocus(cm, e) { - if (cm.state.delayingBlurEvent && !cm.state.draggingText) { cm.state.delayingBlurEvent = false; } - - if (cm.options.readOnly == "nocursor") { return } - if (!cm.state.focused) { - signal(cm, "focus", cm, e); - cm.state.focused = true; - addClass(cm.display.wrapper, "CodeMirror-focused"); - // This test prevents this from firing when a context - // menu is closed (since the input reset would kill the - // select-all detection hack) - if (!cm.curOp && cm.display.selForContextMenu != cm.doc.sel) { - cm.display.input.reset(); - if (webkit) { setTimeout(function () { return cm.display.input.reset(true); }, 20); } // Issue #1730 - } - cm.display.input.receivedFocus(); - } - restartBlink(cm); - } - function onBlur(cm, e) { - if (cm.state.delayingBlurEvent) { return } - - if (cm.state.focused) { - signal(cm, "blur", cm, e); - cm.state.focused = false; - rmClass(cm.display.wrapper, "CodeMirror-focused"); - } - clearInterval(cm.display.blinker); - setTimeout(function () { if (!cm.state.focused) { cm.display.shift = false; } }, 150); - } - - // Read the actual heights of the rendered lines, and update their - // stored heights to match. - function updateHeightsInViewport(cm) { - var display = cm.display; - var prevBottom = display.lineDiv.offsetTop; - for (var i = 0; i < display.view.length; i++) { - var cur = display.view[i], wrapping = cm.options.lineWrapping; - var height = (void 0), width = 0; - if (cur.hidden) { continue } - if (ie && ie_version < 8) { - var bot = cur.node.offsetTop + cur.node.offsetHeight; - height = bot - prevBottom; - prevBottom = bot; - } else { - var box = cur.node.getBoundingClientRect(); - height = box.bottom - box.top; - // Check that lines don't extend past the right of the current - // editor width - if (!wrapping && cur.text.firstChild) - { width = cur.text.firstChild.getBoundingClientRect().right - box.left - 1; } - } - var diff = cur.line.height - height; - if (diff > .005 || diff < -.005) { - updateLineHeight(cur.line, height); - updateWidgetHeight(cur.line); - if (cur.rest) { for (var j = 0; j < cur.rest.length; j++) - { updateWidgetHeight(cur.rest[j]); } } - } - if (width > cm.display.sizerWidth) { - var chWidth = Math.ceil(width / charWidth(cm.display)); - if (chWidth > cm.display.maxLineLength) { - cm.display.maxLineLength = chWidth; - cm.display.maxLine = cur.line; - cm.display.maxLineChanged = true; - } - } - } - } - - // Read and store the height of line widgets associated with the - // given line. - function updateWidgetHeight(line) { - if (line.widgets) { for (var i = 0; i < line.widgets.length; ++i) { - var w = line.widgets[i], parent = w.node.parentNode; - if (parent) { w.height = parent.offsetHeight; } - } } - } - - // Compute the lines that are visible in a given viewport (defaults - // the the current scroll position). viewport may contain top, - // height, and ensure (see op.scrollToPos) properties. - function visibleLines(display, doc, viewport) { - var top = viewport && viewport.top != null ? Math.max(0, viewport.top) : display.scroller.scrollTop; - top = Math.floor(top - paddingTop(display)); - var bottom = viewport && viewport.bottom != null ? viewport.bottom : top + display.wrapper.clientHeight; - - var from = lineAtHeight(doc, top), to = lineAtHeight(doc, bottom); - // Ensure is a {from: {line, ch}, to: {line, ch}} object, and - // forces those lines into the viewport (if possible). - if (viewport && viewport.ensure) { - var ensureFrom = viewport.ensure.from.line, ensureTo = viewport.ensure.to.line; - if (ensureFrom < from) { - from = ensureFrom; - to = lineAtHeight(doc, heightAtLine(getLine(doc, ensureFrom)) + display.wrapper.clientHeight); - } else if (Math.min(ensureTo, doc.lastLine()) >= to) { - from = lineAtHeight(doc, heightAtLine(getLine(doc, ensureTo)) - display.wrapper.clientHeight); - to = ensureTo; - } - } - return {from: from, to: Math.max(to, from + 1)} - } - - // SCROLLING THINGS INTO VIEW - - // If an editor sits on the top or bottom of the window, partially - // scrolled out of view, this ensures that the cursor is visible. - function maybeScrollWindow(cm, rect) { - if (signalDOMEvent(cm, "scrollCursorIntoView")) { return } - - var display = cm.display, box = display.sizer.getBoundingClientRect(), doScroll = null; - if (rect.top + box.top < 0) { doScroll = true; } - else if (rect.bottom + box.top > (window.innerHeight || document.documentElement.clientHeight)) { doScroll = false; } - if (doScroll != null && !phantom) { - var scrollNode = elt("div", "\u200b", null, ("position: absolute;\n top: " + (rect.top - display.viewOffset - paddingTop(cm.display)) + "px;\n height: " + (rect.bottom - rect.top + scrollGap(cm) + display.barHeight) + "px;\n left: " + (rect.left) + "px; width: " + (Math.max(2, rect.right - rect.left)) + "px;")); - cm.display.lineSpace.appendChild(scrollNode); - scrollNode.scrollIntoView(doScroll); - cm.display.lineSpace.removeChild(scrollNode); - } - } - - // Scroll a given position into view (immediately), verifying that - // it actually became visible (as line heights are accurately - // measured, the position of something may 'drift' during drawing). - function scrollPosIntoView(cm, pos, end, margin) { - if (margin == null) { margin = 0; } - var rect; - if (!cm.options.lineWrapping && pos == end) { - // Set pos and end to the cursor positions around the character pos sticks to - // If pos.sticky == "before", that is around pos.ch - 1, otherwise around pos.ch - // If pos == Pos(_, 0, "before"), pos and end are unchanged - pos = pos.ch ? Pos(pos.line, pos.sticky == "before" ? pos.ch - 1 : pos.ch, "after") : pos; - end = pos.sticky == "before" ? Pos(pos.line, pos.ch + 1, "before") : pos; - } - for (var limit = 0; limit < 5; limit++) { - var changed = false; - var coords = cursorCoords(cm, pos); - var endCoords = !end || end == pos ? coords : cursorCoords(cm, end); - rect = {left: Math.min(coords.left, endCoords.left), - top: Math.min(coords.top, endCoords.top) - margin, - right: Math.max(coords.left, endCoords.left), - bottom: Math.max(coords.bottom, endCoords.bottom) + margin}; - var scrollPos = calculateScrollPos(cm, rect); - var startTop = cm.doc.scrollTop, startLeft = cm.doc.scrollLeft; - if (scrollPos.scrollTop != null) { - updateScrollTop(cm, scrollPos.scrollTop); - if (Math.abs(cm.doc.scrollTop - startTop) > 1) { changed = true; } - } - if (scrollPos.scrollLeft != null) { - setScrollLeft(cm, scrollPos.scrollLeft); - if (Math.abs(cm.doc.scrollLeft - startLeft) > 1) { changed = true; } - } - if (!changed) { break } - } - return rect - } - - // Scroll a given set of coordinates into view (immediately). - function scrollIntoView(cm, rect) { - var scrollPos = calculateScrollPos(cm, rect); - if (scrollPos.scrollTop != null) { updateScrollTop(cm, scrollPos.scrollTop); } - if (scrollPos.scrollLeft != null) { setScrollLeft(cm, scrollPos.scrollLeft); } - } - - // Calculate a new scroll position needed to scroll the given - // rectangle into view. Returns an object with scrollTop and - // scrollLeft properties. When these are undefined, the - // vertical/horizontal position does not need to be adjusted. - function calculateScrollPos(cm, rect) { - var display = cm.display, snapMargin = textHeight(cm.display); - if (rect.top < 0) { rect.top = 0; } - var screentop = cm.curOp && cm.curOp.scrollTop != null ? cm.curOp.scrollTop : display.scroller.scrollTop; - var screen = displayHeight(cm), result = {}; - if (rect.bottom - rect.top > screen) { rect.bottom = rect.top + screen; } - var docBottom = cm.doc.height + paddingVert(display); - var atTop = rect.top < snapMargin, atBottom = rect.bottom > docBottom - snapMargin; - if (rect.top < screentop) { - result.scrollTop = atTop ? 0 : rect.top; - } else if (rect.bottom > screentop + screen) { - var newTop = Math.min(rect.top, (atBottom ? docBottom : rect.bottom) - screen); - if (newTop != screentop) { result.scrollTop = newTop; } - } - - var gutterSpace = cm.options.fixedGutter ? 0 : display.gutters.offsetWidth; - var screenleft = cm.curOp && cm.curOp.scrollLeft != null ? cm.curOp.scrollLeft : display.scroller.scrollLeft - gutterSpace; - var screenw = displayWidth(cm) - display.gutters.offsetWidth; - var tooWide = rect.right - rect.left > screenw; - if (tooWide) { rect.right = rect.left + screenw; } - if (rect.left < 10) - { result.scrollLeft = 0; } - else if (rect.left < screenleft) - { result.scrollLeft = Math.max(0, rect.left + gutterSpace - (tooWide ? 0 : 10)); } - else if (rect.right > screenw + screenleft - 3) - { result.scrollLeft = rect.right + (tooWide ? 0 : 10) - screenw; } - return result - } - - // Store a relative adjustment to the scroll position in the current - // operation (to be applied when the operation finishes). - function addToScrollTop(cm, top) { - if (top == null) { return } - resolveScrollToPos(cm); - cm.curOp.scrollTop = (cm.curOp.scrollTop == null ? cm.doc.scrollTop : cm.curOp.scrollTop) + top; - } - - // Make sure that at the end of the operation the current cursor is - // shown. - function ensureCursorVisible(cm) { - resolveScrollToPos(cm); - var cur = cm.getCursor(); - cm.curOp.scrollToPos = {from: cur, to: cur, margin: cm.options.cursorScrollMargin}; - } - - function scrollToCoords(cm, x, y) { - if (x != null || y != null) { resolveScrollToPos(cm); } - if (x != null) { cm.curOp.scrollLeft = x; } - if (y != null) { cm.curOp.scrollTop = y; } - } - - function scrollToRange(cm, range) { - resolveScrollToPos(cm); - cm.curOp.scrollToPos = range; - } - - // When an operation has its scrollToPos property set, and another - // scroll action is applied before the end of the operation, this - // 'simulates' scrolling that position into view in a cheap way, so - // that the effect of intermediate scroll commands is not ignored. - function resolveScrollToPos(cm) { - var range = cm.curOp.scrollToPos; - if (range) { - cm.curOp.scrollToPos = null; - var from = estimateCoords(cm, range.from), to = estimateCoords(cm, range.to); - scrollToCoordsRange(cm, from, to, range.margin); - } - } - - function scrollToCoordsRange(cm, from, to, margin) { - var sPos = calculateScrollPos(cm, { - left: Math.min(from.left, to.left), - top: Math.min(from.top, to.top) - margin, - right: Math.max(from.right, to.right), - bottom: Math.max(from.bottom, to.bottom) + margin - }); - scrollToCoords(cm, sPos.scrollLeft, sPos.scrollTop); - } - - // Sync the scrollable area and scrollbars, ensure the viewport - // covers the visible area. - function updateScrollTop(cm, val) { - if (Math.abs(cm.doc.scrollTop - val) < 2) { return } - if (!gecko) { updateDisplaySimple(cm, {top: val}); } - setScrollTop(cm, val, true); - if (gecko) { updateDisplaySimple(cm); } - startWorker(cm, 100); - } - - function setScrollTop(cm, val, forceScroll) { - val = Math.max(0, Math.min(cm.display.scroller.scrollHeight - cm.display.scroller.clientHeight, val)); - if (cm.display.scroller.scrollTop == val && !forceScroll) { return } - cm.doc.scrollTop = val; - cm.display.scrollbars.setScrollTop(val); - if (cm.display.scroller.scrollTop != val) { cm.display.scroller.scrollTop = val; } - } - - // Sync scroller and scrollbar, ensure the gutter elements are - // aligned. - function setScrollLeft(cm, val, isScroller, forceScroll) { - val = Math.max(0, Math.min(val, cm.display.scroller.scrollWidth - cm.display.scroller.clientWidth)); - if ((isScroller ? val == cm.doc.scrollLeft : Math.abs(cm.doc.scrollLeft - val) < 2) && !forceScroll) { return } - cm.doc.scrollLeft = val; - alignHorizontally(cm); - if (cm.display.scroller.scrollLeft != val) { cm.display.scroller.scrollLeft = val; } - cm.display.scrollbars.setScrollLeft(val); - } - - // SCROLLBARS - - // Prepare DOM reads needed to update the scrollbars. Done in one - // shot to minimize update/measure roundtrips. - function measureForScrollbars(cm) { - var d = cm.display, gutterW = d.gutters.offsetWidth; - var docH = Math.round(cm.doc.height + paddingVert(cm.display)); - return { - clientHeight: d.scroller.clientHeight, - viewHeight: d.wrapper.clientHeight, - scrollWidth: d.scroller.scrollWidth, clientWidth: d.scroller.clientWidth, - viewWidth: d.wrapper.clientWidth, - barLeft: cm.options.fixedGutter ? gutterW : 0, - docHeight: docH, - scrollHeight: docH + scrollGap(cm) + d.barHeight, - nativeBarWidth: d.nativeBarWidth, - gutterWidth: gutterW - } - } - - var NativeScrollbars = function(place, scroll, cm) { - this.cm = cm; - var vert = this.vert = elt("div", [elt("div", null, null, "min-width: 1px")], "CodeMirror-vscrollbar"); - var horiz = this.horiz = elt("div", [elt("div", null, null, "height: 100%; min-height: 1px")], "CodeMirror-hscrollbar"); - vert.tabIndex = horiz.tabIndex = -1; - place(vert); place(horiz); - - on(vert, "scroll", function () { - if (vert.clientHeight) { scroll(vert.scrollTop, "vertical"); } - }); - on(horiz, "scroll", function () { - if (horiz.clientWidth) { scroll(horiz.scrollLeft, "horizontal"); } - }); - - this.checkedZeroWidth = false; - // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). - if (ie && ie_version < 8) { this.horiz.style.minHeight = this.vert.style.minWidth = "18px"; } - }; - - NativeScrollbars.prototype.update = function (measure) { - var needsH = measure.scrollWidth > measure.clientWidth + 1; - var needsV = measure.scrollHeight > measure.clientHeight + 1; - var sWidth = measure.nativeBarWidth; - - if (needsV) { - this.vert.style.display = "block"; - this.vert.style.bottom = needsH ? sWidth + "px" : "0"; - var totalHeight = measure.viewHeight - (needsH ? sWidth : 0); - // A bug in IE8 can cause this value to be negative, so guard it. - this.vert.firstChild.style.height = - Math.max(0, measure.scrollHeight - measure.clientHeight + totalHeight) + "px"; - } else { - this.vert.style.display = ""; - this.vert.firstChild.style.height = "0"; - } - - if (needsH) { - this.horiz.style.display = "block"; - this.horiz.style.right = needsV ? sWidth + "px" : "0"; - this.horiz.style.left = measure.barLeft + "px"; - var totalWidth = measure.viewWidth - measure.barLeft - (needsV ? sWidth : 0); - this.horiz.firstChild.style.width = - Math.max(0, measure.scrollWidth - measure.clientWidth + totalWidth) + "px"; - } else { - this.horiz.style.display = ""; - this.horiz.firstChild.style.width = "0"; - } - - if (!this.checkedZeroWidth && measure.clientHeight > 0) { - if (sWidth == 0) { this.zeroWidthHack(); } - this.checkedZeroWidth = true; - } - - return {right: needsV ? sWidth : 0, bottom: needsH ? sWidth : 0} - }; - - NativeScrollbars.prototype.setScrollLeft = function (pos) { - if (this.horiz.scrollLeft != pos) { this.horiz.scrollLeft = pos; } - if (this.disableHoriz) { this.enableZeroWidthBar(this.horiz, this.disableHoriz, "horiz"); } - }; - - NativeScrollbars.prototype.setScrollTop = function (pos) { - if (this.vert.scrollTop != pos) { this.vert.scrollTop = pos; } - if (this.disableVert) { this.enableZeroWidthBar(this.vert, this.disableVert, "vert"); } - }; - - NativeScrollbars.prototype.zeroWidthHack = function () { - var w = mac && !mac_geMountainLion ? "12px" : "18px"; - this.horiz.style.height = this.vert.style.width = w; - this.horiz.style.pointerEvents = this.vert.style.pointerEvents = "none"; - this.disableHoriz = new Delayed; - this.disableVert = new Delayed; - }; - - NativeScrollbars.prototype.enableZeroWidthBar = function (bar, delay, type) { - bar.style.pointerEvents = "auto"; - function maybeDisable() { - // To find out whether the scrollbar is still visible, we - // check whether the element under the pixel in the bottom - // right corner of the scrollbar box is the scrollbar box - // itself (when the bar is still visible) or its filler child - // (when the bar is hidden). If it is still visible, we keep - // it enabled, if it's hidden, we disable pointer events. - var box = bar.getBoundingClientRect(); - var elt = type == "vert" ? document.elementFromPoint(box.right - 1, (box.top + box.bottom) / 2) - : document.elementFromPoint((box.right + box.left) / 2, box.bottom - 1); - if (elt != bar) { bar.style.pointerEvents = "none"; } - else { delay.set(1000, maybeDisable); } - } - delay.set(1000, maybeDisable); - }; - - NativeScrollbars.prototype.clear = function () { - var parent = this.horiz.parentNode; - parent.removeChild(this.horiz); - parent.removeChild(this.vert); - }; - - var NullScrollbars = function () {}; - - NullScrollbars.prototype.update = function () { return {bottom: 0, right: 0} }; - NullScrollbars.prototype.setScrollLeft = function () {}; - NullScrollbars.prototype.setScrollTop = function () {}; - NullScrollbars.prototype.clear = function () {}; - - function updateScrollbars(cm, measure) { - if (!measure) { measure = measureForScrollbars(cm); } - var startWidth = cm.display.barWidth, startHeight = cm.display.barHeight; - updateScrollbarsInner(cm, measure); - for (var i = 0; i < 4 && startWidth != cm.display.barWidth || startHeight != cm.display.barHeight; i++) { - if (startWidth != cm.display.barWidth && cm.options.lineWrapping) - { updateHeightsInViewport(cm); } - updateScrollbarsInner(cm, measureForScrollbars(cm)); - startWidth = cm.display.barWidth; startHeight = cm.display.barHeight; - } - } - - // Re-synchronize the fake scrollbars with the actual size of the - // content. - function updateScrollbarsInner(cm, measure) { - var d = cm.display; - var sizes = d.scrollbars.update(measure); - - d.sizer.style.paddingRight = (d.barWidth = sizes.right) + "px"; - d.sizer.style.paddingBottom = (d.barHeight = sizes.bottom) + "px"; - d.heightForcer.style.borderBottom = sizes.bottom + "px solid transparent"; - - if (sizes.right && sizes.bottom) { - d.scrollbarFiller.style.display = "block"; - d.scrollbarFiller.style.height = sizes.bottom + "px"; - d.scrollbarFiller.style.width = sizes.right + "px"; - } else { d.scrollbarFiller.style.display = ""; } - if (sizes.bottom && cm.options.coverGutterNextToScrollbar && cm.options.fixedGutter) { - d.gutterFiller.style.display = "block"; - d.gutterFiller.style.height = sizes.bottom + "px"; - d.gutterFiller.style.width = measure.gutterWidth + "px"; - } else { d.gutterFiller.style.display = ""; } - } - - var scrollbarModel = {"native": NativeScrollbars, "null": NullScrollbars}; - - function initScrollbars(cm) { - if (cm.display.scrollbars) { - cm.display.scrollbars.clear(); - if (cm.display.scrollbars.addClass) - { rmClass(cm.display.wrapper, cm.display.scrollbars.addClass); } - } - - cm.display.scrollbars = new scrollbarModel[cm.options.scrollbarStyle](function (node) { - cm.display.wrapper.insertBefore(node, cm.display.scrollbarFiller); - // Prevent clicks in the scrollbars from killing focus - on(node, "mousedown", function () { - if (cm.state.focused) { setTimeout(function () { return cm.display.input.focus(); }, 0); } - }); - node.setAttribute("cm-not-content", "true"); - }, function (pos, axis) { - if (axis == "horizontal") { setScrollLeft(cm, pos); } - else { updateScrollTop(cm, pos); } - }, cm); - if (cm.display.scrollbars.addClass) - { addClass(cm.display.wrapper, cm.display.scrollbars.addClass); } - } - - // Operations are used to wrap a series of changes to the editor - // state in such a way that each change won't have to update the - // cursor and display (which would be awkward, slow, and - // error-prone). Instead, display updates are batched and then all - // combined and executed at once. - - var nextOpId = 0; - // Start a new operation. - function startOperation(cm) { - cm.curOp = { - cm: cm, - viewChanged: false, // Flag that indicates that lines might need to be redrawn - startHeight: cm.doc.height, // Used to detect need to update scrollbar - forceUpdate: false, // Used to force a redraw - updateInput: 0, // Whether to reset the input textarea - typing: false, // Whether this reset should be careful to leave existing text (for compositing) - changeObjs: null, // Accumulated changes, for firing change events - cursorActivityHandlers: null, // Set of handlers to fire cursorActivity on - cursorActivityCalled: 0, // Tracks which cursorActivity handlers have been called already - selectionChanged: false, // Whether the selection needs to be redrawn - updateMaxLine: false, // Set when the widest line needs to be determined anew - scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet - scrollToPos: null, // Used to scroll to a specific position - focus: false, - id: ++nextOpId // Unique ID - }; - pushOperation(cm.curOp); - } - - // Finish an operation, updating the display and signalling delayed events - function endOperation(cm) { - var op = cm.curOp; - if (op) { finishOperation(op, function (group) { - for (var i = 0; i < group.ops.length; i++) - { group.ops[i].cm.curOp = null; } - endOperations(group); - }); } - } - - // The DOM updates done when an operation finishes are batched so - // that the minimum number of relayouts are required. - function endOperations(group) { - var ops = group.ops; - for (var i = 0; i < ops.length; i++) // Read DOM - { endOperation_R1(ops[i]); } - for (var i$1 = 0; i$1 < ops.length; i$1++) // Write DOM (maybe) - { endOperation_W1(ops[i$1]); } - for (var i$2 = 0; i$2 < ops.length; i$2++) // Read DOM - { endOperation_R2(ops[i$2]); } - for (var i$3 = 0; i$3 < ops.length; i$3++) // Write DOM (maybe) - { endOperation_W2(ops[i$3]); } - for (var i$4 = 0; i$4 < ops.length; i$4++) // Read DOM - { endOperation_finish(ops[i$4]); } - } - - function endOperation_R1(op) { - var cm = op.cm, display = cm.display; - maybeClipScrollbars(cm); - if (op.updateMaxLine) { findMaxLine(cm); } - - op.mustUpdate = op.viewChanged || op.forceUpdate || op.scrollTop != null || - op.scrollToPos && (op.scrollToPos.from.line < display.viewFrom || - op.scrollToPos.to.line >= display.viewTo) || - display.maxLineChanged && cm.options.lineWrapping; - op.update = op.mustUpdate && - new DisplayUpdate(cm, op.mustUpdate && {top: op.scrollTop, ensure: op.scrollToPos}, op.forceUpdate); - } - - function endOperation_W1(op) { - op.updatedDisplay = op.mustUpdate && updateDisplayIfNeeded(op.cm, op.update); - } - - function endOperation_R2(op) { - var cm = op.cm, display = cm.display; - if (op.updatedDisplay) { updateHeightsInViewport(cm); } - - op.barMeasure = measureForScrollbars(cm); - - // If the max line changed since it was last measured, measure it, - // and ensure the document's width matches it. - // updateDisplay_W2 will use these properties to do the actual resizing - if (display.maxLineChanged && !cm.options.lineWrapping) { - op.adjustWidthTo = measureChar(cm, display.maxLine, display.maxLine.text.length).left + 3; - cm.display.sizerWidth = op.adjustWidthTo; - op.barMeasure.scrollWidth = - Math.max(display.scroller.clientWidth, display.sizer.offsetLeft + op.adjustWidthTo + scrollGap(cm) + cm.display.barWidth); - op.maxScrollLeft = Math.max(0, display.sizer.offsetLeft + op.adjustWidthTo - displayWidth(cm)); - } - - if (op.updatedDisplay || op.selectionChanged) - { op.preparedSelection = display.input.prepareSelection(); } - } - - function endOperation_W2(op) { - var cm = op.cm; - - if (op.adjustWidthTo != null) { - cm.display.sizer.style.minWidth = op.adjustWidthTo + "px"; - if (op.maxScrollLeft < cm.doc.scrollLeft) - { setScrollLeft(cm, Math.min(cm.display.scroller.scrollLeft, op.maxScrollLeft), true); } - cm.display.maxLineChanged = false; - } - - var takeFocus = op.focus && op.focus == activeElt(); - if (op.preparedSelection) - { cm.display.input.showSelection(op.preparedSelection, takeFocus); } - if (op.updatedDisplay || op.startHeight != cm.doc.height) - { updateScrollbars(cm, op.barMeasure); } - if (op.updatedDisplay) - { setDocumentHeight(cm, op.barMeasure); } - - if (op.selectionChanged) { restartBlink(cm); } - - if (cm.state.focused && op.updateInput) - { cm.display.input.reset(op.typing); } - if (takeFocus) { ensureFocus(op.cm); } - } - - function endOperation_finish(op) { - var cm = op.cm, display = cm.display, doc = cm.doc; - - if (op.updatedDisplay) { postUpdateDisplay(cm, op.update); } - - // Abort mouse wheel delta measurement, when scrolling explicitly - if (display.wheelStartX != null && (op.scrollTop != null || op.scrollLeft != null || op.scrollToPos)) - { display.wheelStartX = display.wheelStartY = null; } - - // Propagate the scroll position to the actual DOM scroller - if (op.scrollTop != null) { setScrollTop(cm, op.scrollTop, op.forceScroll); } - - if (op.scrollLeft != null) { setScrollLeft(cm, op.scrollLeft, true, true); } - // If we need to scroll a specific position into view, do so. - if (op.scrollToPos) { - var rect = scrollPosIntoView(cm, clipPos(doc, op.scrollToPos.from), - clipPos(doc, op.scrollToPos.to), op.scrollToPos.margin); - maybeScrollWindow(cm, rect); - } - - // Fire events for markers that are hidden/unidden by editing or - // undoing - var hidden = op.maybeHiddenMarkers, unhidden = op.maybeUnhiddenMarkers; - if (hidden) { for (var i = 0; i < hidden.length; ++i) - { if (!hidden[i].lines.length) { signal(hidden[i], "hide"); } } } - if (unhidden) { for (var i$1 = 0; i$1 < unhidden.length; ++i$1) - { if (unhidden[i$1].lines.length) { signal(unhidden[i$1], "unhide"); } } } - - if (display.wrapper.offsetHeight) - { doc.scrollTop = cm.display.scroller.scrollTop; } - - // Fire change events, and delayed event handlers - if (op.changeObjs) - { signal(cm, "changes", cm, op.changeObjs); } - if (op.update) - { op.update.finish(); } - } - - // Run the given function in an operation - function runInOp(cm, f) { - if (cm.curOp) { return f() } - startOperation(cm); - try { return f() } - finally { endOperation(cm); } - } - // Wraps a function in an operation. Returns the wrapped function. - function operation(cm, f) { - return function() { - if (cm.curOp) { return f.apply(cm, arguments) } - startOperation(cm); - try { return f.apply(cm, arguments) } - finally { endOperation(cm); } - } - } - // Used to add methods to editor and doc instances, wrapping them in - // operations. - function methodOp(f) { - return function() { - if (this.curOp) { return f.apply(this, arguments) } - startOperation(this); - try { return f.apply(this, arguments) } - finally { endOperation(this); } - } - } - function docMethodOp(f) { - return function() { - var cm = this.cm; - if (!cm || cm.curOp) { return f.apply(this, arguments) } - startOperation(cm); - try { return f.apply(this, arguments) } - finally { endOperation(cm); } - } - } - - // HIGHLIGHT WORKER - - function startWorker(cm, time) { - if (cm.doc.highlightFrontier < cm.display.viewTo) - { cm.state.highlight.set(time, bind(highlightWorker, cm)); } - } - - function highlightWorker(cm) { - var doc = cm.doc; - if (doc.highlightFrontier >= cm.display.viewTo) { return } - var end = +new Date + cm.options.workTime; - var context = getContextBefore(cm, doc.highlightFrontier); - var changedLines = []; - - doc.iter(context.line, Math.min(doc.first + doc.size, cm.display.viewTo + 500), function (line) { - if (context.line >= cm.display.viewFrom) { // Visible - var oldStyles = line.styles; - var resetState = line.text.length > cm.options.maxHighlightLength ? copyState(doc.mode, context.state) : null; - var highlighted = highlightLine(cm, line, context, true); - if (resetState) { context.state = resetState; } - line.styles = highlighted.styles; - var oldCls = line.styleClasses, newCls = highlighted.classes; - if (newCls) { line.styleClasses = newCls; } - else if (oldCls) { line.styleClasses = null; } - var ischange = !oldStyles || oldStyles.length != line.styles.length || - oldCls != newCls && (!oldCls || !newCls || oldCls.bgClass != newCls.bgClass || oldCls.textClass != newCls.textClass); - for (var i = 0; !ischange && i < oldStyles.length; ++i) { ischange = oldStyles[i] != line.styles[i]; } - if (ischange) { changedLines.push(context.line); } - line.stateAfter = context.save(); - context.nextLine(); - } else { - if (line.text.length <= cm.options.maxHighlightLength) - { processLine(cm, line.text, context); } - line.stateAfter = context.line % 5 == 0 ? context.save() : null; - context.nextLine(); - } - if (+new Date > end) { - startWorker(cm, cm.options.workDelay); - return true - } - }); - doc.highlightFrontier = context.line; - doc.modeFrontier = Math.max(doc.modeFrontier, context.line); - if (changedLines.length) { runInOp(cm, function () { - for (var i = 0; i < changedLines.length; i++) - { regLineChange(cm, changedLines[i], "text"); } - }); } - } - - // DISPLAY DRAWING - - var DisplayUpdate = function(cm, viewport, force) { - var display = cm.display; - - this.viewport = viewport; - // Store some values that we'll need later (but don't want to force a relayout for) - this.visible = visibleLines(display, cm.doc, viewport); - this.editorIsHidden = !display.wrapper.offsetWidth; - this.wrapperHeight = display.wrapper.clientHeight; - this.wrapperWidth = display.wrapper.clientWidth; - this.oldDisplayWidth = displayWidth(cm); - this.force = force; - this.dims = getDimensions(cm); - this.events = []; - }; - - DisplayUpdate.prototype.signal = function (emitter, type) { - if (hasHandler(emitter, type)) - { this.events.push(arguments); } - }; - DisplayUpdate.prototype.finish = function () { - for (var i = 0; i < this.events.length; i++) - { signal.apply(null, this.events[i]); } - }; - - function maybeClipScrollbars(cm) { - var display = cm.display; - if (!display.scrollbarsClipped && display.scroller.offsetWidth) { - display.nativeBarWidth = display.scroller.offsetWidth - display.scroller.clientWidth; - display.heightForcer.style.height = scrollGap(cm) + "px"; - display.sizer.style.marginBottom = -display.nativeBarWidth + "px"; - display.sizer.style.borderRightWidth = scrollGap(cm) + "px"; - display.scrollbarsClipped = true; - } - } - - function selectionSnapshot(cm) { - if (cm.hasFocus()) { return null } - var active = activeElt(); - if (!active || !contains(cm.display.lineDiv, active)) { return null } - var result = {activeElt: active}; - if (window.getSelection) { - var sel = window.getSelection(); - if (sel.anchorNode && sel.extend && contains(cm.display.lineDiv, sel.anchorNode)) { - result.anchorNode = sel.anchorNode; - result.anchorOffset = sel.anchorOffset; - result.focusNode = sel.focusNode; - result.focusOffset = sel.focusOffset; - } - } - return result - } - - function restoreSelection(snapshot) { - if (!snapshot || !snapshot.activeElt || snapshot.activeElt == activeElt()) { return } - snapshot.activeElt.focus(); - if (!/^(INPUT|TEXTAREA)$/.test(snapshot.activeElt.nodeName) && - snapshot.anchorNode && contains(document.body, snapshot.anchorNode) && contains(document.body, snapshot.focusNode)) { - var sel = window.getSelection(), range = document.createRange(); - range.setEnd(snapshot.anchorNode, snapshot.anchorOffset); - range.collapse(false); - sel.removeAllRanges(); - sel.addRange(range); - sel.extend(snapshot.focusNode, snapshot.focusOffset); - } - } - - // Does the actual updating of the line display. Bails out - // (returning false) when there is nothing to be done and forced is - // false. - function updateDisplayIfNeeded(cm, update) { - var display = cm.display, doc = cm.doc; - - if (update.editorIsHidden) { - resetView(cm); - return false - } - - // Bail out if the visible area is already rendered and nothing changed. - if (!update.force && - update.visible.from >= display.viewFrom && update.visible.to <= display.viewTo && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo) && - display.renderedView == display.view && countDirtyView(cm) == 0) - { return false } - - if (maybeUpdateLineNumberWidth(cm)) { - resetView(cm); - update.dims = getDimensions(cm); - } - - // Compute a suitable new viewport (from & to) - var end = doc.first + doc.size; - var from = Math.max(update.visible.from - cm.options.viewportMargin, doc.first); - var to = Math.min(end, update.visible.to + cm.options.viewportMargin); - if (display.viewFrom < from && from - display.viewFrom < 20) { from = Math.max(doc.first, display.viewFrom); } - if (display.viewTo > to && display.viewTo - to < 20) { to = Math.min(end, display.viewTo); } - if (sawCollapsedSpans) { - from = visualLineNo(cm.doc, from); - to = visualLineEndNo(cm.doc, to); - } - - var different = from != display.viewFrom || to != display.viewTo || - display.lastWrapHeight != update.wrapperHeight || display.lastWrapWidth != update.wrapperWidth; - adjustView(cm, from, to); - - display.viewOffset = heightAtLine(getLine(cm.doc, display.viewFrom)); - // Position the mover div to align with the current scroll position - cm.display.mover.style.top = display.viewOffset + "px"; - - var toUpdate = countDirtyView(cm); - if (!different && toUpdate == 0 && !update.force && display.renderedView == display.view && - (display.updateLineNumbers == null || display.updateLineNumbers >= display.viewTo)) - { return false } - - // For big changes, we hide the enclosing element during the - // update, since that speeds up the operations on most browsers. - var selSnapshot = selectionSnapshot(cm); - if (toUpdate > 4) { display.lineDiv.style.display = "none"; } - patchDisplay(cm, display.updateLineNumbers, update.dims); - if (toUpdate > 4) { display.lineDiv.style.display = ""; } - display.renderedView = display.view; - // There might have been a widget with a focused element that got - // hidden or updated, if so re-focus it. - restoreSelection(selSnapshot); - - // Prevent selection and cursors from interfering with the scroll - // width and height. - removeChildren(display.cursorDiv); - removeChildren(display.selectionDiv); - display.gutters.style.height = display.sizer.style.minHeight = 0; - - if (different) { - display.lastWrapHeight = update.wrapperHeight; - display.lastWrapWidth = update.wrapperWidth; - startWorker(cm, 400); - } - - display.updateLineNumbers = null; - - return true - } - - function postUpdateDisplay(cm, update) { - var viewport = update.viewport; - - for (var first = true;; first = false) { - if (!first || !cm.options.lineWrapping || update.oldDisplayWidth == displayWidth(cm)) { - // Clip forced viewport to actual scrollable area. - if (viewport && viewport.top != null) - { viewport = {top: Math.min(cm.doc.height + paddingVert(cm.display) - displayHeight(cm), viewport.top)}; } - // Updated line heights might result in the drawn area not - // actually covering the viewport. Keep looping until it does. - update.visible = visibleLines(cm.display, cm.doc, viewport); - if (update.visible.from >= cm.display.viewFrom && update.visible.to <= cm.display.viewTo) - { break } - } else if (first) { - update.visible = visibleLines(cm.display, cm.doc, viewport); - } - if (!updateDisplayIfNeeded(cm, update)) { break } - updateHeightsInViewport(cm); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - updateScrollbars(cm, barMeasure); - setDocumentHeight(cm, barMeasure); - update.force = false; - } - - update.signal(cm, "update", cm); - if (cm.display.viewFrom != cm.display.reportedViewFrom || cm.display.viewTo != cm.display.reportedViewTo) { - update.signal(cm, "viewportChange", cm, cm.display.viewFrom, cm.display.viewTo); - cm.display.reportedViewFrom = cm.display.viewFrom; cm.display.reportedViewTo = cm.display.viewTo; - } - } - - function updateDisplaySimple(cm, viewport) { - var update = new DisplayUpdate(cm, viewport); - if (updateDisplayIfNeeded(cm, update)) { - updateHeightsInViewport(cm); - postUpdateDisplay(cm, update); - var barMeasure = measureForScrollbars(cm); - updateSelection(cm); - updateScrollbars(cm, barMeasure); - setDocumentHeight(cm, barMeasure); - update.finish(); - } - } - - // Sync the actual display DOM structure with display.view, removing - // nodes for lines that are no longer in view, and creating the ones - // that are not there yet, and updating the ones that are out of - // date. - function patchDisplay(cm, updateNumbersFrom, dims) { - var display = cm.display, lineNumbers = cm.options.lineNumbers; - var container = display.lineDiv, cur = container.firstChild; - - function rm(node) { - var next = node.nextSibling; - // Works around a throw-scroll bug in OS X Webkit - if (webkit && mac && cm.display.currentWheelTarget == node) - { node.style.display = "none"; } - else - { node.parentNode.removeChild(node); } - return next - } - - var view = display.view, lineN = display.viewFrom; - // Loop over the elements in the view, syncing cur (the DOM nodes - // in display.lineDiv) with the view as we go. - for (var i = 0; i < view.length; i++) { - var lineView = view[i]; - if (lineView.hidden) ; else if (!lineView.node || lineView.node.parentNode != container) { // Not drawn yet - var node = buildLineElement(cm, lineView, lineN, dims); - container.insertBefore(node, cur); - } else { // Already drawn - while (cur != lineView.node) { cur = rm(cur); } - var updateNumber = lineNumbers && updateNumbersFrom != null && - updateNumbersFrom <= lineN && lineView.lineNumber; - if (lineView.changes) { - if (indexOf(lineView.changes, "gutter") > -1) { updateNumber = false; } - updateLineForChanges(cm, lineView, lineN, dims); - } - if (updateNumber) { - removeChildren(lineView.lineNumber); - lineView.lineNumber.appendChild(document.createTextNode(lineNumberFor(cm.options, lineN))); - } - cur = lineView.node.nextSibling; - } - lineN += lineView.size; - } - while (cur) { cur = rm(cur); } - } - - function updateGutterSpace(display) { - var width = display.gutters.offsetWidth; - display.sizer.style.marginLeft = width + "px"; - } - - function setDocumentHeight(cm, measure) { - cm.display.sizer.style.minHeight = measure.docHeight + "px"; - cm.display.heightForcer.style.top = measure.docHeight + "px"; - cm.display.gutters.style.height = (measure.docHeight + cm.display.barHeight + scrollGap(cm)) + "px"; - } - - // Re-align line numbers and gutter marks to compensate for - // horizontal scrolling. - function alignHorizontally(cm) { - var display = cm.display, view = display.view; - if (!display.alignWidgets && (!display.gutters.firstChild || !cm.options.fixedGutter)) { return } - var comp = compensateForHScroll(display) - display.scroller.scrollLeft + cm.doc.scrollLeft; - var gutterW = display.gutters.offsetWidth, left = comp + "px"; - for (var i = 0; i < view.length; i++) { if (!view[i].hidden) { - if (cm.options.fixedGutter) { - if (view[i].gutter) - { view[i].gutter.style.left = left; } - if (view[i].gutterBackground) - { view[i].gutterBackground.style.left = left; } - } - var align = view[i].alignable; - if (align) { for (var j = 0; j < align.length; j++) - { align[j].style.left = left; } } - } } - if (cm.options.fixedGutter) - { display.gutters.style.left = (comp + gutterW) + "px"; } - } - - // Used to ensure that the line number gutter is still the right - // size for the current document size. Returns true when an update - // is needed. - function maybeUpdateLineNumberWidth(cm) { - if (!cm.options.lineNumbers) { return false } - var doc = cm.doc, last = lineNumberFor(cm.options, doc.first + doc.size - 1), display = cm.display; - if (last.length != display.lineNumChars) { - var test = display.measure.appendChild(elt("div", [elt("div", last)], - "CodeMirror-linenumber CodeMirror-gutter-elt")); - var innerW = test.firstChild.offsetWidth, padding = test.offsetWidth - innerW; - display.lineGutter.style.width = ""; - display.lineNumInnerWidth = Math.max(innerW, display.lineGutter.offsetWidth - padding) + 1; - display.lineNumWidth = display.lineNumInnerWidth + padding; - display.lineNumChars = display.lineNumInnerWidth ? last.length : -1; - display.lineGutter.style.width = display.lineNumWidth + "px"; - updateGutterSpace(cm.display); - return true - } - return false - } - - function getGutters(gutters, lineNumbers) { - var result = [], sawLineNumbers = false; - for (var i = 0; i < gutters.length; i++) { - var name = gutters[i], style = null; - if (typeof name != "string") { style = name.style; name = name.className; } - if (name == "CodeMirror-linenumbers") { - if (!lineNumbers) { continue } - else { sawLineNumbers = true; } - } - result.push({className: name, style: style}); - } - if (lineNumbers && !sawLineNumbers) { result.push({className: "CodeMirror-linenumbers", style: null}); } - return result - } - - // Rebuild the gutter elements, ensure the margin to the left of the - // code matches their width. - function renderGutters(display) { - var gutters = display.gutters, specs = display.gutterSpecs; - removeChildren(gutters); - display.lineGutter = null; - for (var i = 0; i < specs.length; ++i) { - var ref = specs[i]; - var className = ref.className; - var style = ref.style; - var gElt = gutters.appendChild(elt("div", null, "CodeMirror-gutter " + className)); - if (style) { gElt.style.cssText = style; } - if (className == "CodeMirror-linenumbers") { - display.lineGutter = gElt; - gElt.style.width = (display.lineNumWidth || 1) + "px"; - } - } - gutters.style.display = specs.length ? "" : "none"; - updateGutterSpace(display); - } - - function updateGutters(cm) { - renderGutters(cm.display); - regChange(cm); - alignHorizontally(cm); - } - - // The display handles the DOM integration, both for input reading - // and content drawing. It holds references to DOM nodes and - // display-related state. - - function Display(place, doc, input, options) { - var d = this; - this.input = input; - - // Covers bottom-right square when both scrollbars are present. - d.scrollbarFiller = elt("div", null, "CodeMirror-scrollbar-filler"); - d.scrollbarFiller.setAttribute("cm-not-content", "true"); - // Covers bottom of gutter when coverGutterNextToScrollbar is on - // and h scrollbar is present. - d.gutterFiller = elt("div", null, "CodeMirror-gutter-filler"); - d.gutterFiller.setAttribute("cm-not-content", "true"); - // Will contain the actual code, positioned to cover the viewport. - d.lineDiv = eltP("div", null, "CodeMirror-code"); - // Elements are added to these to represent selection and cursors. - d.selectionDiv = elt("div", null, null, "position: relative; z-index: 1"); - d.cursorDiv = elt("div", null, "CodeMirror-cursors"); - // A visibility: hidden element used to find the size of things. - d.measure = elt("div", null, "CodeMirror-measure"); - // When lines outside of the viewport are measured, they are drawn in this. - d.lineMeasure = elt("div", null, "CodeMirror-measure"); - // Wraps everything that needs to exist inside the vertically-padded coordinate system - d.lineSpace = eltP("div", [d.measure, d.lineMeasure, d.selectionDiv, d.cursorDiv, d.lineDiv], - null, "position: relative; outline: none"); - var lines = eltP("div", [d.lineSpace], "CodeMirror-lines"); - // Moved around its parent to cover visible view. - d.mover = elt("div", [lines], null, "position: relative"); - // Set to the height of the document, allowing scrolling. - d.sizer = elt("div", [d.mover], "CodeMirror-sizer"); - d.sizerWidth = null; - // Behavior of elts with overflow: auto and padding is - // inconsistent across browsers. This is used to ensure the - // scrollable area is big enough. - d.heightForcer = elt("div", null, null, "position: absolute; height: " + scrollerGap + "px; width: 1px;"); - // Will contain the gutters, if any. - d.gutters = elt("div", null, "CodeMirror-gutters"); - d.lineGutter = null; - // Actual scrollable element. - d.scroller = elt("div", [d.sizer, d.heightForcer, d.gutters], "CodeMirror-scroll"); - d.scroller.setAttribute("tabIndex", "-1"); - // The element in which the editor lives. - d.wrapper = elt("div", [d.scrollbarFiller, d.gutterFiller, d.scroller], "CodeMirror"); - - // Work around IE7 z-index bug (not perfect, hence IE7 not really being supported) - if (ie && ie_version < 8) { d.gutters.style.zIndex = -1; d.scroller.style.paddingRight = 0; } - if (!webkit && !(gecko && mobile)) { d.scroller.draggable = true; } - - if (place) { - if (place.appendChild) { place.appendChild(d.wrapper); } - else { place(d.wrapper); } - } - - // Current rendered range (may be bigger than the view window). - d.viewFrom = d.viewTo = doc.first; - d.reportedViewFrom = d.reportedViewTo = doc.first; - // Information about the rendered lines. - d.view = []; - d.renderedView = null; - // Holds info about a single rendered line when it was rendered - // for measurement, while not in view. - d.externalMeasured = null; - // Empty space (in pixels) above the view - d.viewOffset = 0; - d.lastWrapHeight = d.lastWrapWidth = 0; - d.updateLineNumbers = null; - - d.nativeBarWidth = d.barHeight = d.barWidth = 0; - d.scrollbarsClipped = false; - - // Used to only resize the line number gutter when necessary (when - // the amount of lines crosses a boundary that makes its width change) - d.lineNumWidth = d.lineNumInnerWidth = d.lineNumChars = null; - // Set to true when a non-horizontal-scrolling line widget is - // added. As an optimization, line widget aligning is skipped when - // this is false. - d.alignWidgets = false; - - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - - // Tracks the maximum line length so that the horizontal scrollbar - // can be kept static when scrolling. - d.maxLine = null; - d.maxLineLength = 0; - d.maxLineChanged = false; - - // Used for measuring wheel scrolling granularity - d.wheelDX = d.wheelDY = d.wheelStartX = d.wheelStartY = null; - - // True when shift is held down. - d.shift = false; - - // Used to track whether anything happened since the context menu - // was opened. - d.selForContextMenu = null; - - d.activeTouch = null; - - d.gutterSpecs = getGutters(options.gutters, options.lineNumbers); - renderGutters(d); - - input.init(d); - } - - // Since the delta values reported on mouse wheel events are - // unstandardized between browsers and even browser versions, and - // generally horribly unpredictable, this code starts by measuring - // the scroll effect that the first few mouse wheel events have, - // and, from that, detects the way it can convert deltas to pixel - // offsets afterwards. - // - // The reason we want to know the amount a wheel event will scroll - // is that it gives us a chance to update the display before the - // actual scrolling happens, reducing flickering. - - var wheelSamples = 0, wheelPixelsPerUnit = null; - // Fill in a browser-detected starting value on browsers where we - // know one. These don't have to be accurate -- the result of them - // being wrong would just be a slight flicker on the first wheel - // scroll (if it is large enough). - if (ie) { wheelPixelsPerUnit = -.53; } - else if (gecko) { wheelPixelsPerUnit = 15; } - else if (chrome) { wheelPixelsPerUnit = -.7; } - else if (safari) { wheelPixelsPerUnit = -1/3; } - - function wheelEventDelta(e) { - var dx = e.wheelDeltaX, dy = e.wheelDeltaY; - if (dx == null && e.detail && e.axis == e.HORIZONTAL_AXIS) { dx = e.detail; } - if (dy == null && e.detail && e.axis == e.VERTICAL_AXIS) { dy = e.detail; } - else if (dy == null) { dy = e.wheelDelta; } - return {x: dx, y: dy} - } - function wheelEventPixels(e) { - var delta = wheelEventDelta(e); - delta.x *= wheelPixelsPerUnit; - delta.y *= wheelPixelsPerUnit; - return delta - } - - function onScrollWheel(cm, e) { - var delta = wheelEventDelta(e), dx = delta.x, dy = delta.y; - - var display = cm.display, scroll = display.scroller; - // Quit if there's nothing to scroll here - var canScrollX = scroll.scrollWidth > scroll.clientWidth; - var canScrollY = scroll.scrollHeight > scroll.clientHeight; - if (!(dx && canScrollX || dy && canScrollY)) { return } - - // Webkit browsers on OS X abort momentum scrolls when the target - // of the scroll event is removed from the scrollable element. - // This hack (see related code in patchDisplay) makes sure the - // element is kept around. - if (dy && mac && webkit) { - outer: for (var cur = e.target, view = display.view; cur != scroll; cur = cur.parentNode) { - for (var i = 0; i < view.length; i++) { - if (view[i].node == cur) { - cm.display.currentWheelTarget = cur; - break outer - } - } - } - } - - // On some browsers, horizontal scrolling will cause redraws to - // happen before the gutter has been realigned, causing it to - // wriggle around in a most unseemly way. When we have an - // estimated pixels/delta value, we just handle horizontal - // scrolling entirely here. It'll be slightly off from native, but - // better than glitching out. - if (dx && !gecko && !presto && wheelPixelsPerUnit != null) { - if (dy && canScrollY) - { updateScrollTop(cm, Math.max(0, scroll.scrollTop + dy * wheelPixelsPerUnit)); } - setScrollLeft(cm, Math.max(0, scroll.scrollLeft + dx * wheelPixelsPerUnit)); - // Only prevent default scrolling if vertical scrolling is - // actually possible. Otherwise, it causes vertical scroll - // jitter on OSX trackpads when deltaX is small and deltaY - // is large (issue #3579) - if (!dy || (dy && canScrollY)) - { e_preventDefault(e); } - display.wheelStartX = null; // Abort measurement, if in progress - return - } - - // 'Project' the visible viewport to cover the area that is being - // scrolled into view (if we know enough to estimate it). - if (dy && wheelPixelsPerUnit != null) { - var pixels = dy * wheelPixelsPerUnit; - var top = cm.doc.scrollTop, bot = top + display.wrapper.clientHeight; - if (pixels < 0) { top = Math.max(0, top + pixels - 50); } - else { bot = Math.min(cm.doc.height, bot + pixels + 50); } - updateDisplaySimple(cm, {top: top, bottom: bot}); - } - - if (wheelSamples < 20) { - if (display.wheelStartX == null) { - display.wheelStartX = scroll.scrollLeft; display.wheelStartY = scroll.scrollTop; - display.wheelDX = dx; display.wheelDY = dy; - setTimeout(function () { - if (display.wheelStartX == null) { return } - var movedX = scroll.scrollLeft - display.wheelStartX; - var movedY = scroll.scrollTop - display.wheelStartY; - var sample = (movedY && display.wheelDY && movedY / display.wheelDY) || - (movedX && display.wheelDX && movedX / display.wheelDX); - display.wheelStartX = display.wheelStartY = null; - if (!sample) { return } - wheelPixelsPerUnit = (wheelPixelsPerUnit * wheelSamples + sample) / (wheelSamples + 1); - ++wheelSamples; - }, 200); - } else { - display.wheelDX += dx; display.wheelDY += dy; - } - } - } - - // Selection objects are immutable. A new one is created every time - // the selection changes. A selection is one or more non-overlapping - // (and non-touching) ranges, sorted, and an integer that indicates - // which one is the primary selection (the one that's scrolled into - // view, that getCursor returns, etc). - var Selection = function(ranges, primIndex) { - this.ranges = ranges; - this.primIndex = primIndex; - }; - - Selection.prototype.primary = function () { return this.ranges[this.primIndex] }; - - Selection.prototype.equals = function (other) { - if (other == this) { return true } - if (other.primIndex != this.primIndex || other.ranges.length != this.ranges.length) { return false } - for (var i = 0; i < this.ranges.length; i++) { - var here = this.ranges[i], there = other.ranges[i]; - if (!equalCursorPos(here.anchor, there.anchor) || !equalCursorPos(here.head, there.head)) { return false } - } - return true - }; - - Selection.prototype.deepCopy = function () { - var out = []; - for (var i = 0; i < this.ranges.length; i++) - { out[i] = new Range(copyPos(this.ranges[i].anchor), copyPos(this.ranges[i].head)); } - return new Selection(out, this.primIndex) - }; - - Selection.prototype.somethingSelected = function () { - for (var i = 0; i < this.ranges.length; i++) - { if (!this.ranges[i].empty()) { return true } } - return false - }; - - Selection.prototype.contains = function (pos, end) { - if (!end) { end = pos; } - for (var i = 0; i < this.ranges.length; i++) { - var range = this.ranges[i]; - if (cmp(end, range.from()) >= 0 && cmp(pos, range.to()) <= 0) - { return i } - } - return -1 - }; - - var Range = function(anchor, head) { - this.anchor = anchor; this.head = head; - }; - - Range.prototype.from = function () { return minPos(this.anchor, this.head) }; - Range.prototype.to = function () { return maxPos(this.anchor, this.head) }; - Range.prototype.empty = function () { return this.head.line == this.anchor.line && this.head.ch == this.anchor.ch }; - - // Take an unsorted, potentially overlapping set of ranges, and - // build a selection out of it. 'Consumes' ranges array (modifying - // it). - function normalizeSelection(cm, ranges, primIndex) { - var mayTouch = cm && cm.options.selectionsMayTouch; - var prim = ranges[primIndex]; - ranges.sort(function (a, b) { return cmp(a.from(), b.from()); }); - primIndex = indexOf(ranges, prim); - for (var i = 1; i < ranges.length; i++) { - var cur = ranges[i], prev = ranges[i - 1]; - var diff = cmp(prev.to(), cur.from()); - if (mayTouch && !cur.empty() ? diff > 0 : diff >= 0) { - var from = minPos(prev.from(), cur.from()), to = maxPos(prev.to(), cur.to()); - var inv = prev.empty() ? cur.from() == cur.head : prev.from() == prev.head; - if (i <= primIndex) { --primIndex; } - ranges.splice(--i, 2, new Range(inv ? to : from, inv ? from : to)); - } - } - return new Selection(ranges, primIndex) - } - - function simpleSelection(anchor, head) { - return new Selection([new Range(anchor, head || anchor)], 0) - } - - // Compute the position of the end of a change (its 'to' property - // refers to the pre-change end). - function changeEnd(change) { - if (!change.text) { return change.to } - return Pos(change.from.line + change.text.length - 1, - lst(change.text).length + (change.text.length == 1 ? change.from.ch : 0)) - } - - // Adjust a position to refer to the post-change position of the - // same text, or the end of the change if the change covers it. - function adjustForChange(pos, change) { - if (cmp(pos, change.from) < 0) { return pos } - if (cmp(pos, change.to) <= 0) { return changeEnd(change) } - - var line = pos.line + change.text.length - (change.to.line - change.from.line) - 1, ch = pos.ch; - if (pos.line == change.to.line) { ch += changeEnd(change).ch - change.to.ch; } - return Pos(line, ch) - } - - function computeSelAfterChange(doc, change) { - var out = []; - for (var i = 0; i < doc.sel.ranges.length; i++) { - var range = doc.sel.ranges[i]; - out.push(new Range(adjustForChange(range.anchor, change), - adjustForChange(range.head, change))); - } - return normalizeSelection(doc.cm, out, doc.sel.primIndex) - } - - function offsetPos(pos, old, nw) { - if (pos.line == old.line) - { return Pos(nw.line, pos.ch - old.ch + nw.ch) } - else - { return Pos(nw.line + (pos.line - old.line), pos.ch) } - } - - // Used by replaceSelections to allow moving the selection to the - // start or around the replaced test. Hint may be "start" or "around". - function computeReplacedSel(doc, changes, hint) { - var out = []; - var oldPrev = Pos(doc.first, 0), newPrev = oldPrev; - for (var i = 0; i < changes.length; i++) { - var change = changes[i]; - var from = offsetPos(change.from, oldPrev, newPrev); - var to = offsetPos(changeEnd(change), oldPrev, newPrev); - oldPrev = change.to; - newPrev = to; - if (hint == "around") { - var range = doc.sel.ranges[i], inv = cmp(range.head, range.anchor) < 0; - out[i] = new Range(inv ? to : from, inv ? from : to); - } else { - out[i] = new Range(from, from); - } - } - return new Selection(out, doc.sel.primIndex) - } - - // Used to get the editor into a consistent state again when options change. - - function loadMode(cm) { - cm.doc.mode = getMode(cm.options, cm.doc.modeOption); - resetModeState(cm); - } - - function resetModeState(cm) { - cm.doc.iter(function (line) { - if (line.stateAfter) { line.stateAfter = null; } - if (line.styles) { line.styles = null; } - }); - cm.doc.modeFrontier = cm.doc.highlightFrontier = cm.doc.first; - startWorker(cm, 100); - cm.state.modeGen++; - if (cm.curOp) { regChange(cm); } - } - - // DOCUMENT DATA STRUCTURE - - // By default, updates that start and end at the beginning of a line - // are treated specially, in order to make the association of line - // widgets and marker elements with the text behave more intuitive. - function isWholeLineUpdate(doc, change) { - return change.from.ch == 0 && change.to.ch == 0 && lst(change.text) == "" && - (!doc.cm || doc.cm.options.wholeLineUpdateBefore) - } - - // Perform a change on the document data structure. - function updateDoc(doc, change, markedSpans, estimateHeight) { - function spansFor(n) {return markedSpans ? markedSpans[n] : null} - function update(line, text, spans) { - updateLine(line, text, spans, estimateHeight); - signalLater(line, "change", line, change); - } - function linesFor(start, end) { - var result = []; - for (var i = start; i < end; ++i) - { result.push(new Line(text[i], spansFor(i), estimateHeight)); } - return result - } - - var from = change.from, to = change.to, text = change.text; - var firstLine = getLine(doc, from.line), lastLine = getLine(doc, to.line); - var lastText = lst(text), lastSpans = spansFor(text.length - 1), nlines = to.line - from.line; - - // Adjust the line structure - if (change.full) { - doc.insert(0, linesFor(0, text.length)); - doc.remove(text.length, doc.size - text.length); - } else if (isWholeLineUpdate(doc, change)) { - // This is a whole-line replace. Treated specially to make - // sure line objects move the way they are supposed to. - var added = linesFor(0, text.length - 1); - update(lastLine, lastLine.text, lastSpans); - if (nlines) { doc.remove(from.line, nlines); } - if (added.length) { doc.insert(from.line, added); } - } else if (firstLine == lastLine) { - if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + lastText + firstLine.text.slice(to.ch), lastSpans); - } else { - var added$1 = linesFor(1, text.length - 1); - added$1.push(new Line(lastText + firstLine.text.slice(to.ch), lastSpans, estimateHeight)); - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - doc.insert(from.line + 1, added$1); - } - } else if (text.length == 1) { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0] + lastLine.text.slice(to.ch), spansFor(0)); - doc.remove(from.line + 1, nlines); - } else { - update(firstLine, firstLine.text.slice(0, from.ch) + text[0], spansFor(0)); - update(lastLine, lastText + lastLine.text.slice(to.ch), lastSpans); - var added$2 = linesFor(1, text.length - 1); - if (nlines > 1) { doc.remove(from.line + 1, nlines - 1); } - doc.insert(from.line + 1, added$2); - } - - signalLater(doc, "change", doc, change); - } - - // Call f for all linked documents. - function linkedDocs(doc, f, sharedHistOnly) { - function propagate(doc, skip, sharedHist) { - if (doc.linked) { for (var i = 0; i < doc.linked.length; ++i) { - var rel = doc.linked[i]; - if (rel.doc == skip) { continue } - var shared = sharedHist && rel.sharedHist; - if (sharedHistOnly && !shared) { continue } - f(rel.doc, shared); - propagate(rel.doc, doc, shared); - } } - } - propagate(doc, null, true); - } - - // Attach a document to an editor. - function attachDoc(cm, doc) { - if (doc.cm) { throw new Error("This document is already in use.") } - cm.doc = doc; - doc.cm = cm; - estimateLineHeights(cm); - loadMode(cm); - setDirectionClass(cm); - if (!cm.options.lineWrapping) { findMaxLine(cm); } - cm.options.mode = doc.modeOption; - regChange(cm); - } - - function setDirectionClass(cm) { - (cm.doc.direction == "rtl" ? addClass : rmClass)(cm.display.lineDiv, "CodeMirror-rtl"); - } - - function directionChanged(cm) { - runInOp(cm, function () { - setDirectionClass(cm); - regChange(cm); - }); - } - - function History(startGen) { - // Arrays of change events and selections. Doing something adds an - // event to done and clears undo. Undoing moves events from done - // to undone, redoing moves them in the other direction. - this.done = []; this.undone = []; - this.undoDepth = Infinity; - // Used to track when changes can be merged into a single undo - // event - this.lastModTime = this.lastSelTime = 0; - this.lastOp = this.lastSelOp = null; - this.lastOrigin = this.lastSelOrigin = null; - // Used by the isClean() method - this.generation = this.maxGeneration = startGen || 1; - } - - // Create a history change event from an updateDoc-style change - // object. - function historyChangeFromChange(doc, change) { - var histChange = {from: copyPos(change.from), to: changeEnd(change), text: getBetween(doc, change.from, change.to)}; - attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); - linkedDocs(doc, function (doc) { return attachLocalSpans(doc, histChange, change.from.line, change.to.line + 1); }, true); - return histChange - } - - // Pop all selection events off the end of a history array. Stop at - // a change event. - function clearSelectionEvents(array) { - while (array.length) { - var last = lst(array); - if (last.ranges) { array.pop(); } - else { break } - } - } - - // Find the top change event in the history. Pop off selection - // events that are in the way. - function lastChangeEvent(hist, force) { - if (force) { - clearSelectionEvents(hist.done); - return lst(hist.done) - } else if (hist.done.length && !lst(hist.done).ranges) { - return lst(hist.done) - } else if (hist.done.length > 1 && !hist.done[hist.done.length - 2].ranges) { - hist.done.pop(); - return lst(hist.done) - } - } - - // Register a change in the history. Merges changes that are within - // a single operation, or are close together with an origin that - // allows merging (starting with "+") into a single event. - function addChangeToHistory(doc, change, selAfter, opId) { - var hist = doc.history; - hist.undone.length = 0; - var time = +new Date, cur; - var last; - - if ((hist.lastOp == opId || - hist.lastOrigin == change.origin && change.origin && - ((change.origin.charAt(0) == "+" && hist.lastModTime > time - (doc.cm ? doc.cm.options.historyEventDelay : 500)) || - change.origin.charAt(0) == "*")) && - (cur = lastChangeEvent(hist, hist.lastOp == opId))) { - // Merge this change into the last event - last = lst(cur.changes); - if (cmp(change.from, change.to) == 0 && cmp(change.from, last.to) == 0) { - // Optimized case for simple insertion -- don't want to add - // new changesets for every character typed - last.to = changeEnd(change); - } else { - // Add new sub-event - cur.changes.push(historyChangeFromChange(doc, change)); - } - } else { - // Can not be merged, start a new event. - var before = lst(hist.done); - if (!before || !before.ranges) - { pushSelectionToHistory(doc.sel, hist.done); } - cur = {changes: [historyChangeFromChange(doc, change)], - generation: hist.generation}; - hist.done.push(cur); - while (hist.done.length > hist.undoDepth) { - hist.done.shift(); - if (!hist.done[0].ranges) { hist.done.shift(); } - } - } - hist.done.push(selAfter); - hist.generation = ++hist.maxGeneration; - hist.lastModTime = hist.lastSelTime = time; - hist.lastOp = hist.lastSelOp = opId; - hist.lastOrigin = hist.lastSelOrigin = change.origin; - - if (!last) { signal(doc, "historyAdded"); } - } - - function selectionEventCanBeMerged(doc, origin, prev, sel) { - var ch = origin.charAt(0); - return ch == "*" || - ch == "+" && - prev.ranges.length == sel.ranges.length && - prev.somethingSelected() == sel.somethingSelected() && - new Date - doc.history.lastSelTime <= (doc.cm ? doc.cm.options.historyEventDelay : 500) - } - - // Called whenever the selection changes, sets the new selection as - // the pending selection in the history, and pushes the old pending - // selection into the 'done' array when it was significantly - // different (in number of selected ranges, emptiness, or time). - function addSelectionToHistory(doc, sel, opId, options) { - var hist = doc.history, origin = options && options.origin; - - // A new event is started when the previous origin does not match - // the current, or the origins don't allow matching. Origins - // starting with * are always merged, those starting with + are - // merged when similar and close together in time. - if (opId == hist.lastSelOp || - (origin && hist.lastSelOrigin == origin && - (hist.lastModTime == hist.lastSelTime && hist.lastOrigin == origin || - selectionEventCanBeMerged(doc, origin, lst(hist.done), sel)))) - { hist.done[hist.done.length - 1] = sel; } - else - { pushSelectionToHistory(sel, hist.done); } - - hist.lastSelTime = +new Date; - hist.lastSelOrigin = origin; - hist.lastSelOp = opId; - if (options && options.clearRedo !== false) - { clearSelectionEvents(hist.undone); } - } - - function pushSelectionToHistory(sel, dest) { - var top = lst(dest); - if (!(top && top.ranges && top.equals(sel))) - { dest.push(sel); } - } - - // Used to store marked span information in the history. - function attachLocalSpans(doc, change, from, to) { - var existing = change["spans_" + doc.id], n = 0; - doc.iter(Math.max(doc.first, from), Math.min(doc.first + doc.size, to), function (line) { - if (line.markedSpans) - { (existing || (existing = change["spans_" + doc.id] = {}))[n] = line.markedSpans; } - ++n; - }); - } - - // When un/re-doing restores text containing marked spans, those - // that have been explicitly cleared should not be restored. - function removeClearedSpans(spans) { - if (!spans) { return null } - var out; - for (var i = 0; i < spans.length; ++i) { - if (spans[i].marker.explicitlyCleared) { if (!out) { out = spans.slice(0, i); } } - else if (out) { out.push(spans[i]); } - } - return !out ? spans : out.length ? out : null - } - - // Retrieve and filter the old marked spans stored in a change event. - function getOldSpans(doc, change) { - var found = change["spans_" + doc.id]; - if (!found) { return null } - var nw = []; - for (var i = 0; i < change.text.length; ++i) - { nw.push(removeClearedSpans(found[i])); } - return nw - } - - // Used for un/re-doing changes from the history. Combines the - // result of computing the existing spans with the set of spans that - // existed in the history (so that deleting around a span and then - // undoing brings back the span). - function mergeOldSpans(doc, change) { - var old = getOldSpans(doc, change); - var stretched = stretchSpansOverChange(doc, change); - if (!old) { return stretched } - if (!stretched) { return old } - - for (var i = 0; i < old.length; ++i) { - var oldCur = old[i], stretchCur = stretched[i]; - if (oldCur && stretchCur) { - spans: for (var j = 0; j < stretchCur.length; ++j) { - var span = stretchCur[j]; - for (var k = 0; k < oldCur.length; ++k) - { if (oldCur[k].marker == span.marker) { continue spans } } - oldCur.push(span); - } - } else if (stretchCur) { - old[i] = stretchCur; - } - } - return old - } - - // Used both to provide a JSON-safe object in .getHistory, and, when - // detaching a document, to split the history in two - function copyHistoryArray(events, newGroup, instantiateSel) { - var copy = []; - for (var i = 0; i < events.length; ++i) { - var event = events[i]; - if (event.ranges) { - copy.push(instantiateSel ? Selection.prototype.deepCopy.call(event) : event); - continue - } - var changes = event.changes, newChanges = []; - copy.push({changes: newChanges}); - for (var j = 0; j < changes.length; ++j) { - var change = changes[j], m = (void 0); - newChanges.push({from: change.from, to: change.to, text: change.text}); - if (newGroup) { for (var prop in change) { if (m = prop.match(/^spans_(\d+)$/)) { - if (indexOf(newGroup, Number(m[1])) > -1) { - lst(newChanges)[prop] = change[prop]; - delete change[prop]; - } - } } } - } - } - return copy - } - - // The 'scroll' parameter given to many of these indicated whether - // the new cursor position should be scrolled into view after - // modifying the selection. - - // If shift is held or the extend flag is set, extends a range to - // include a given position (and optionally a second position). - // Otherwise, simply returns the range between the given positions. - // Used for cursor motion and such. - function extendRange(range, head, other, extend) { - if (extend) { - var anchor = range.anchor; - if (other) { - var posBefore = cmp(head, anchor) < 0; - if (posBefore != (cmp(other, anchor) < 0)) { - anchor = head; - head = other; - } else if (posBefore != (cmp(head, other) < 0)) { - head = other; - } - } - return new Range(anchor, head) - } else { - return new Range(other || head, head) - } - } - - // Extend the primary selection range, discard the rest. - function extendSelection(doc, head, other, options, extend) { - if (extend == null) { extend = doc.cm && (doc.cm.display.shift || doc.extend); } - setSelection(doc, new Selection([extendRange(doc.sel.primary(), head, other, extend)], 0), options); - } - - // Extend all selections (pos is an array of selections with length - // equal the number of selections) - function extendSelections(doc, heads, options) { - var out = []; - var extend = doc.cm && (doc.cm.display.shift || doc.extend); - for (var i = 0; i < doc.sel.ranges.length; i++) - { out[i] = extendRange(doc.sel.ranges[i], heads[i], null, extend); } - var newSel = normalizeSelection(doc.cm, out, doc.sel.primIndex); - setSelection(doc, newSel, options); - } - - // Updates a single range in the selection. - function replaceOneSelection(doc, i, range, options) { - var ranges = doc.sel.ranges.slice(0); - ranges[i] = range; - setSelection(doc, normalizeSelection(doc.cm, ranges, doc.sel.primIndex), options); - } - - // Reset the selection to a single range. - function setSimpleSelection(doc, anchor, head, options) { - setSelection(doc, simpleSelection(anchor, head), options); - } - - // Give beforeSelectionChange handlers a change to influence a - // selection update. - function filterSelectionChange(doc, sel, options) { - var obj = { - ranges: sel.ranges, - update: function(ranges) { - this.ranges = []; - for (var i = 0; i < ranges.length; i++) - { this.ranges[i] = new Range(clipPos(doc, ranges[i].anchor), - clipPos(doc, ranges[i].head)); } - }, - origin: options && options.origin - }; - signal(doc, "beforeSelectionChange", doc, obj); - if (doc.cm) { signal(doc.cm, "beforeSelectionChange", doc.cm, obj); } - if (obj.ranges != sel.ranges) { return normalizeSelection(doc.cm, obj.ranges, obj.ranges.length - 1) } - else { return sel } - } - - function setSelectionReplaceHistory(doc, sel, options) { - var done = doc.history.done, last = lst(done); - if (last && last.ranges) { - done[done.length - 1] = sel; - setSelectionNoUndo(doc, sel, options); - } else { - setSelection(doc, sel, options); - } - } - - // Set a new selection. - function setSelection(doc, sel, options) { - setSelectionNoUndo(doc, sel, options); - addSelectionToHistory(doc, doc.sel, doc.cm ? doc.cm.curOp.id : NaN, options); - } - - function setSelectionNoUndo(doc, sel, options) { - if (hasHandler(doc, "beforeSelectionChange") || doc.cm && hasHandler(doc.cm, "beforeSelectionChange")) - { sel = filterSelectionChange(doc, sel, options); } - - var bias = options && options.bias || - (cmp(sel.primary().head, doc.sel.primary().head) < 0 ? -1 : 1); - setSelectionInner(doc, skipAtomicInSelection(doc, sel, bias, true)); - - if (!(options && options.scroll === false) && doc.cm) - { ensureCursorVisible(doc.cm); } - } - - function setSelectionInner(doc, sel) { - if (sel.equals(doc.sel)) { return } - - doc.sel = sel; - - if (doc.cm) { - doc.cm.curOp.updateInput = 1; - doc.cm.curOp.selectionChanged = true; - signalCursorActivity(doc.cm); - } - signalLater(doc, "cursorActivity", doc); - } - - // Verify that the selection does not partially select any atomic - // marked ranges. - function reCheckSelection(doc) { - setSelectionInner(doc, skipAtomicInSelection(doc, doc.sel, null, false)); - } - - // Return a selection that does not partially select any atomic - // ranges. - function skipAtomicInSelection(doc, sel, bias, mayClear) { - var out; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - var old = sel.ranges.length == doc.sel.ranges.length && doc.sel.ranges[i]; - var newAnchor = skipAtomic(doc, range.anchor, old && old.anchor, bias, mayClear); - var newHead = skipAtomic(doc, range.head, old && old.head, bias, mayClear); - if (out || newAnchor != range.anchor || newHead != range.head) { - if (!out) { out = sel.ranges.slice(0, i); } - out[i] = new Range(newAnchor, newHead); - } - } - return out ? normalizeSelection(doc.cm, out, sel.primIndex) : sel - } - - function skipAtomicInner(doc, pos, oldPos, dir, mayClear) { - var line = getLine(doc, pos.line); - if (line.markedSpans) { for (var i = 0; i < line.markedSpans.length; ++i) { - var sp = line.markedSpans[i], m = sp.marker; - - // Determine if we should prevent the cursor being placed to the left/right of an atomic marker - // Historically this was determined using the inclusiveLeft/Right option, but the new way to control it - // is with selectLeft/Right - var preventCursorLeft = ("selectLeft" in m) ? !m.selectLeft : m.inclusiveLeft; - var preventCursorRight = ("selectRight" in m) ? !m.selectRight : m.inclusiveRight; - - if ((sp.from == null || (preventCursorLeft ? sp.from <= pos.ch : sp.from < pos.ch)) && - (sp.to == null || (preventCursorRight ? sp.to >= pos.ch : sp.to > pos.ch))) { - if (mayClear) { - signal(m, "beforeCursorEnter"); - if (m.explicitlyCleared) { - if (!line.markedSpans) { break } - else {--i; continue} - } - } - if (!m.atomic) { continue } - - if (oldPos) { - var near = m.find(dir < 0 ? 1 : -1), diff = (void 0); - if (dir < 0 ? preventCursorRight : preventCursorLeft) - { near = movePos(doc, near, -dir, near && near.line == pos.line ? line : null); } - if (near && near.line == pos.line && (diff = cmp(near, oldPos)) && (dir < 0 ? diff < 0 : diff > 0)) - { return skipAtomicInner(doc, near, pos, dir, mayClear) } - } - - var far = m.find(dir < 0 ? -1 : 1); - if (dir < 0 ? preventCursorLeft : preventCursorRight) - { far = movePos(doc, far, dir, far.line == pos.line ? line : null); } - return far ? skipAtomicInner(doc, far, pos, dir, mayClear) : null - } - } } - return pos - } - - // Ensure a given position is not inside an atomic range. - function skipAtomic(doc, pos, oldPos, bias, mayClear) { - var dir = bias || 1; - var found = skipAtomicInner(doc, pos, oldPos, dir, mayClear) || - (!mayClear && skipAtomicInner(doc, pos, oldPos, dir, true)) || - skipAtomicInner(doc, pos, oldPos, -dir, mayClear) || - (!mayClear && skipAtomicInner(doc, pos, oldPos, -dir, true)); - if (!found) { - doc.cantEdit = true; - return Pos(doc.first, 0) - } - return found - } - - function movePos(doc, pos, dir, line) { - if (dir < 0 && pos.ch == 0) { - if (pos.line > doc.first) { return clipPos(doc, Pos(pos.line - 1)) } - else { return null } - } else if (dir > 0 && pos.ch == (line || getLine(doc, pos.line)).text.length) { - if (pos.line < doc.first + doc.size - 1) { return Pos(pos.line + 1, 0) } - else { return null } - } else { - return new Pos(pos.line, pos.ch + dir) - } - } - - function selectAll(cm) { - cm.setSelection(Pos(cm.firstLine(), 0), Pos(cm.lastLine()), sel_dontScroll); - } - - // UPDATING - - // Allow "beforeChange" event handlers to influence a change - function filterChange(doc, change, update) { - var obj = { - canceled: false, - from: change.from, - to: change.to, - text: change.text, - origin: change.origin, - cancel: function () { return obj.canceled = true; } - }; - if (update) { obj.update = function (from, to, text, origin) { - if (from) { obj.from = clipPos(doc, from); } - if (to) { obj.to = clipPos(doc, to); } - if (text) { obj.text = text; } - if (origin !== undefined) { obj.origin = origin; } - }; } - signal(doc, "beforeChange", doc, obj); - if (doc.cm) { signal(doc.cm, "beforeChange", doc.cm, obj); } - - if (obj.canceled) { - if (doc.cm) { doc.cm.curOp.updateInput = 2; } - return null - } - return {from: obj.from, to: obj.to, text: obj.text, origin: obj.origin} - } - - // Apply a change to a document, and add it to the document's - // history, and propagating it to all linked documents. - function makeChange(doc, change, ignoreReadOnly) { - if (doc.cm) { - if (!doc.cm.curOp) { return operation(doc.cm, makeChange)(doc, change, ignoreReadOnly) } - if (doc.cm.state.suppressEdits) { return } - } - - if (hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange")) { - change = filterChange(doc, change, true); - if (!change) { return } - } - - // Possibly split or suppress the update based on the presence - // of read-only spans in its range. - var split = sawReadOnlySpans && !ignoreReadOnly && removeReadOnlyRanges(doc, change.from, change.to); - if (split) { - for (var i = split.length - 1; i >= 0; --i) - { makeChangeInner(doc, {from: split[i].from, to: split[i].to, text: i ? [""] : change.text, origin: change.origin}); } - } else { - makeChangeInner(doc, change); - } - } - - function makeChangeInner(doc, change) { - if (change.text.length == 1 && change.text[0] == "" && cmp(change.from, change.to) == 0) { return } - var selAfter = computeSelAfterChange(doc, change); - addChangeToHistory(doc, change, selAfter, doc.cm ? doc.cm.curOp.id : NaN); - - makeChangeSingleDoc(doc, change, selAfter, stretchSpansOverChange(doc, change)); - var rebased = []; - - linkedDocs(doc, function (doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, stretchSpansOverChange(doc, change)); - }); - } - - // Revert a change stored in a document's history. - function makeChangeFromHistory(doc, type, allowSelectionOnly) { - var suppress = doc.cm && doc.cm.state.suppressEdits; - if (suppress && !allowSelectionOnly) { return } - - var hist = doc.history, event, selAfter = doc.sel; - var source = type == "undo" ? hist.done : hist.undone, dest = type == "undo" ? hist.undone : hist.done; - - // Verify that there is a useable event (so that ctrl-z won't - // needlessly clear selection events) - var i = 0; - for (; i < source.length; i++) { - event = source[i]; - if (allowSelectionOnly ? event.ranges && !event.equals(doc.sel) : !event.ranges) - { break } - } - if (i == source.length) { return } - hist.lastOrigin = hist.lastSelOrigin = null; - - for (;;) { - event = source.pop(); - if (event.ranges) { - pushSelectionToHistory(event, dest); - if (allowSelectionOnly && !event.equals(doc.sel)) { - setSelection(doc, event, {clearRedo: false}); - return - } - selAfter = event; - } else if (suppress) { - source.push(event); - return - } else { break } - } - - // Build up a reverse change object to add to the opposite history - // stack (redo when undoing, and vice versa). - var antiChanges = []; - pushSelectionToHistory(selAfter, dest); - dest.push({changes: antiChanges, generation: hist.generation}); - hist.generation = event.generation || ++hist.maxGeneration; - - var filter = hasHandler(doc, "beforeChange") || doc.cm && hasHandler(doc.cm, "beforeChange"); - - var loop = function ( i ) { - var change = event.changes[i]; - change.origin = type; - if (filter && !filterChange(doc, change, false)) { - source.length = 0; - return {} - } - - antiChanges.push(historyChangeFromChange(doc, change)); - - var after = i ? computeSelAfterChange(doc, change) : lst(source); - makeChangeSingleDoc(doc, change, after, mergeOldSpans(doc, change)); - if (!i && doc.cm) { doc.cm.scrollIntoView({from: change.from, to: changeEnd(change)}); } - var rebased = []; - - // Propagate to the linked documents - linkedDocs(doc, function (doc, sharedHist) { - if (!sharedHist && indexOf(rebased, doc.history) == -1) { - rebaseHist(doc.history, change); - rebased.push(doc.history); - } - makeChangeSingleDoc(doc, change, null, mergeOldSpans(doc, change)); - }); - }; - - for (var i$1 = event.changes.length - 1; i$1 >= 0; --i$1) { - var returned = loop( i$1 ); - - if ( returned ) return returned.v; - } - } - - // Sub-views need their line numbers shifted when text is added - // above or below them in the parent document. - function shiftDoc(doc, distance) { - if (distance == 0) { return } - doc.first += distance; - doc.sel = new Selection(map(doc.sel.ranges, function (range) { return new Range( - Pos(range.anchor.line + distance, range.anchor.ch), - Pos(range.head.line + distance, range.head.ch) - ); }), doc.sel.primIndex); - if (doc.cm) { - regChange(doc.cm, doc.first, doc.first - distance, distance); - for (var d = doc.cm.display, l = d.viewFrom; l < d.viewTo; l++) - { regLineChange(doc.cm, l, "gutter"); } - } - } - - // More lower-level change function, handling only a single document - // (not linked ones). - function makeChangeSingleDoc(doc, change, selAfter, spans) { - if (doc.cm && !doc.cm.curOp) - { return operation(doc.cm, makeChangeSingleDoc)(doc, change, selAfter, spans) } - - if (change.to.line < doc.first) { - shiftDoc(doc, change.text.length - 1 - (change.to.line - change.from.line)); - return - } - if (change.from.line > doc.lastLine()) { return } - - // Clip the change to the size of this doc - if (change.from.line < doc.first) { - var shift = change.text.length - 1 - (doc.first - change.from.line); - shiftDoc(doc, shift); - change = {from: Pos(doc.first, 0), to: Pos(change.to.line + shift, change.to.ch), - text: [lst(change.text)], origin: change.origin}; - } - var last = doc.lastLine(); - if (change.to.line > last) { - change = {from: change.from, to: Pos(last, getLine(doc, last).text.length), - text: [change.text[0]], origin: change.origin}; - } - - change.removed = getBetween(doc, change.from, change.to); - - if (!selAfter) { selAfter = computeSelAfterChange(doc, change); } - if (doc.cm) { makeChangeSingleDocInEditor(doc.cm, change, spans); } - else { updateDoc(doc, change, spans); } - setSelectionNoUndo(doc, selAfter, sel_dontScroll); - - if (doc.cantEdit && skipAtomic(doc, Pos(doc.firstLine(), 0))) - { doc.cantEdit = false; } - } - - // Handle the interaction of a change to a document with the editor - // that this document is part of. - function makeChangeSingleDocInEditor(cm, change, spans) { - var doc = cm.doc, display = cm.display, from = change.from, to = change.to; - - var recomputeMaxLength = false, checkWidthStart = from.line; - if (!cm.options.lineWrapping) { - checkWidthStart = lineNo(visualLine(getLine(doc, from.line))); - doc.iter(checkWidthStart, to.line + 1, function (line) { - if (line == display.maxLine) { - recomputeMaxLength = true; - return true - } - }); - } - - if (doc.sel.contains(change.from, change.to) > -1) - { signalCursorActivity(cm); } - - updateDoc(doc, change, spans, estimateHeight(cm)); - - if (!cm.options.lineWrapping) { - doc.iter(checkWidthStart, from.line + change.text.length, function (line) { - var len = lineLength(line); - if (len > display.maxLineLength) { - display.maxLine = line; - display.maxLineLength = len; - display.maxLineChanged = true; - recomputeMaxLength = false; - } - }); - if (recomputeMaxLength) { cm.curOp.updateMaxLine = true; } - } - - retreatFrontier(doc, from.line); - startWorker(cm, 400); - - var lendiff = change.text.length - (to.line - from.line) - 1; - // Remember that these lines changed, for updating the display - if (change.full) - { regChange(cm); } - else if (from.line == to.line && change.text.length == 1 && !isWholeLineUpdate(cm.doc, change)) - { regLineChange(cm, from.line, "text"); } - else - { regChange(cm, from.line, to.line + 1, lendiff); } - - var changesHandler = hasHandler(cm, "changes"), changeHandler = hasHandler(cm, "change"); - if (changeHandler || changesHandler) { - var obj = { - from: from, to: to, - text: change.text, - removed: change.removed, - origin: change.origin - }; - if (changeHandler) { signalLater(cm, "change", cm, obj); } - if (changesHandler) { (cm.curOp.changeObjs || (cm.curOp.changeObjs = [])).push(obj); } - } - cm.display.selForContextMenu = null; - } - - function replaceRange(doc, code, from, to, origin) { - var assign; - - if (!to) { to = from; } - if (cmp(to, from) < 0) { (assign = [to, from], from = assign[0], to = assign[1]); } - if (typeof code == "string") { code = doc.splitLines(code); } - makeChange(doc, {from: from, to: to, text: code, origin: origin}); - } - - // Rebasing/resetting history to deal with externally-sourced changes - - function rebaseHistSelSingle(pos, from, to, diff) { - if (to < pos.line) { - pos.line += diff; - } else if (from < pos.line) { - pos.line = from; - pos.ch = 0; - } - } - - // Tries to rebase an array of history events given a change in the - // document. If the change touches the same lines as the event, the - // event, and everything 'behind' it, is discarded. If the change is - // before the event, the event's positions are updated. Uses a - // copy-on-write scheme for the positions, to avoid having to - // reallocate them all on every rebase, but also avoid problems with - // shared position objects being unsafely updated. - function rebaseHistArray(array, from, to, diff) { - for (var i = 0; i < array.length; ++i) { - var sub = array[i], ok = true; - if (sub.ranges) { - if (!sub.copied) { sub = array[i] = sub.deepCopy(); sub.copied = true; } - for (var j = 0; j < sub.ranges.length; j++) { - rebaseHistSelSingle(sub.ranges[j].anchor, from, to, diff); - rebaseHistSelSingle(sub.ranges[j].head, from, to, diff); - } - continue - } - for (var j$1 = 0; j$1 < sub.changes.length; ++j$1) { - var cur = sub.changes[j$1]; - if (to < cur.from.line) { - cur.from = Pos(cur.from.line + diff, cur.from.ch); - cur.to = Pos(cur.to.line + diff, cur.to.ch); - } else if (from <= cur.to.line) { - ok = false; - break - } - } - if (!ok) { - array.splice(0, i + 1); - i = 0; - } - } - } - - function rebaseHist(hist, change) { - var from = change.from.line, to = change.to.line, diff = change.text.length - (to - from) - 1; - rebaseHistArray(hist.done, from, to, diff); - rebaseHistArray(hist.undone, from, to, diff); - } - - // Utility for applying a change to a line by handle or number, - // returning the number and optionally registering the line as - // changed. - function changeLine(doc, handle, changeType, op) { - var no = handle, line = handle; - if (typeof handle == "number") { line = getLine(doc, clipLine(doc, handle)); } - else { no = lineNo(handle); } - if (no == null) { return null } - if (op(line, no) && doc.cm) { regLineChange(doc.cm, no, changeType); } - return line - } - - // The document is represented as a BTree consisting of leaves, with - // chunk of lines in them, and branches, with up to ten leaves or - // other branch nodes below them. The top node is always a branch - // node, and is the document object itself (meaning it has - // additional methods and properties). - // - // All nodes have parent links. The tree is used both to go from - // line numbers to line objects, and to go from objects to numbers. - // It also indexes by height, and is used to convert between height - // and line object, and to find the total height of the document. - // - // See also http://marijnhaverbeke.nl/blog/codemirror-line-tree.html - - function LeafChunk(lines) { - this.lines = lines; - this.parent = null; - var height = 0; - for (var i = 0; i < lines.length; ++i) { - lines[i].parent = this; - height += lines[i].height; - } - this.height = height; - } - - LeafChunk.prototype = { - chunkSize: function() { return this.lines.length }, - - // Remove the n lines at offset 'at'. - removeInner: function(at, n) { - for (var i = at, e = at + n; i < e; ++i) { - var line = this.lines[i]; - this.height -= line.height; - cleanUpLine(line); - signalLater(line, "delete"); - } - this.lines.splice(at, n); - }, - - // Helper used to collapse a small branch into a single leaf. - collapse: function(lines) { - lines.push.apply(lines, this.lines); - }, - - // Insert the given array of lines at offset 'at', count them as - // having the given height. - insertInner: function(at, lines, height) { - this.height += height; - this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); - for (var i = 0; i < lines.length; ++i) { lines[i].parent = this; } - }, - - // Used to iterate over a part of the tree. - iterN: function(at, n, op) { - for (var e = at + n; at < e; ++at) - { if (op(this.lines[at])) { return true } } - } - }; - - function BranchChunk(children) { - this.children = children; - var size = 0, height = 0; - for (var i = 0; i < children.length; ++i) { - var ch = children[i]; - size += ch.chunkSize(); height += ch.height; - ch.parent = this; - } - this.size = size; - this.height = height; - this.parent = null; - } - - BranchChunk.prototype = { - chunkSize: function() { return this.size }, - - removeInner: function(at, n) { - this.size -= n; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var rm = Math.min(n, sz - at), oldHeight = child.height; - child.removeInner(at, rm); - this.height -= oldHeight - child.height; - if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } - if ((n -= rm) == 0) { break } - at = 0; - } else { at -= sz; } - } - // If the result is smaller than 25 lines, ensure that it is a - // single leaf node. - if (this.size - n < 25 && - (this.children.length > 1 || !(this.children[0] instanceof LeafChunk))) { - var lines = []; - this.collapse(lines); - this.children = [new LeafChunk(lines)]; - this.children[0].parent = this; - } - }, - - collapse: function(lines) { - for (var i = 0; i < this.children.length; ++i) { this.children[i].collapse(lines); } - }, - - insertInner: function(at, lines, height) { - this.size += lines.length; - this.height += height; - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at <= sz) { - child.insertInner(at, lines, height); - if (child.lines && child.lines.length > 50) { - // To avoid memory thrashing when child.lines is huge (e.g. first view of a large file), it's never spliced. - // Instead, small slices are taken. They're taken in order because sequential memory accesses are fastest. - var remaining = child.lines.length % 25 + 25; - for (var pos = remaining; pos < child.lines.length;) { - var leaf = new LeafChunk(child.lines.slice(pos, pos += 25)); - child.height -= leaf.height; - this.children.splice(++i, 0, leaf); - leaf.parent = this; - } - child.lines = child.lines.slice(0, remaining); - this.maybeSpill(); - } - break - } - at -= sz; - } - }, - - // When a node has grown, check whether it should be split. - maybeSpill: function() { - if (this.children.length <= 10) { return } - var me = this; - do { - var spilled = me.children.splice(me.children.length - 5, 5); - var sibling = new BranchChunk(spilled); - if (!me.parent) { // Become the parent node - var copy = new BranchChunk(me.children); - copy.parent = me; - me.children = [copy, sibling]; - me = copy; - } else { - me.size -= sibling.size; - me.height -= sibling.height; - var myIndex = indexOf(me.parent.children, me); - me.parent.children.splice(myIndex + 1, 0, sibling); - } - sibling.parent = me.parent; - } while (me.children.length > 10) - me.parent.maybeSpill(); - }, - - iterN: function(at, n, op) { - for (var i = 0; i < this.children.length; ++i) { - var child = this.children[i], sz = child.chunkSize(); - if (at < sz) { - var used = Math.min(n, sz - at); - if (child.iterN(at, used, op)) { return true } - if ((n -= used) == 0) { break } - at = 0; - } else { at -= sz; } - } - } - }; - - // Line widgets are block elements displayed above or below a line. - - var LineWidget = function(doc, node, options) { - if (options) { for (var opt in options) { if (options.hasOwnProperty(opt)) - { this[opt] = options[opt]; } } } - this.doc = doc; - this.node = node; - }; - - LineWidget.prototype.clear = function () { - var cm = this.doc.cm, ws = this.line.widgets, line = this.line, no = lineNo(line); - if (no == null || !ws) { return } - for (var i = 0; i < ws.length; ++i) { if (ws[i] == this) { ws.splice(i--, 1); } } - if (!ws.length) { line.widgets = null; } - var height = widgetHeight(this); - updateLineHeight(line, Math.max(0, line.height - height)); - if (cm) { - runInOp(cm, function () { - adjustScrollWhenAboveVisible(cm, line, -height); - regLineChange(cm, no, "widget"); - }); - signalLater(cm, "lineWidgetCleared", cm, this, no); - } - }; - - LineWidget.prototype.changed = function () { - var this$1 = this; - - var oldH = this.height, cm = this.doc.cm, line = this.line; - this.height = null; - var diff = widgetHeight(this) - oldH; - if (!diff) { return } - if (!lineIsHidden(this.doc, line)) { updateLineHeight(line, line.height + diff); } - if (cm) { - runInOp(cm, function () { - cm.curOp.forceUpdate = true; - adjustScrollWhenAboveVisible(cm, line, diff); - signalLater(cm, "lineWidgetChanged", cm, this$1, lineNo(line)); - }); - } - }; - eventMixin(LineWidget); - - function adjustScrollWhenAboveVisible(cm, line, diff) { - if (heightAtLine(line) < ((cm.curOp && cm.curOp.scrollTop) || cm.doc.scrollTop)) - { addToScrollTop(cm, diff); } - } - - function addLineWidget(doc, handle, node, options) { - var widget = new LineWidget(doc, node, options); - var cm = doc.cm; - if (cm && widget.noHScroll) { cm.display.alignWidgets = true; } - changeLine(doc, handle, "widget", function (line) { - var widgets = line.widgets || (line.widgets = []); - if (widget.insertAt == null) { widgets.push(widget); } - else { widgets.splice(Math.min(widgets.length, Math.max(0, widget.insertAt)), 0, widget); } - widget.line = line; - if (cm && !lineIsHidden(doc, line)) { - var aboveVisible = heightAtLine(line) < doc.scrollTop; - updateLineHeight(line, line.height + widgetHeight(widget)); - if (aboveVisible) { addToScrollTop(cm, widget.height); } - cm.curOp.forceUpdate = true; - } - return true - }); - if (cm) { signalLater(cm, "lineWidgetAdded", cm, widget, typeof handle == "number" ? handle : lineNo(handle)); } - return widget - } - - // TEXTMARKERS - - // Created with markText and setBookmark methods. A TextMarker is a - // handle that can be used to clear or find a marked position in the - // document. Line objects hold arrays (markedSpans) containing - // {from, to, marker} object pointing to such marker objects, and - // indicating that such a marker is present on that line. Multiple - // lines may point to the same marker when it spans across lines. - // The spans will have null for their from/to properties when the - // marker continues beyond the start/end of the line. Markers have - // links back to the lines they currently touch. - - // Collapsed markers have unique ids, in order to be able to order - // them, which is needed for uniquely determining an outer marker - // when they overlap (they may nest, but not partially overlap). - var nextMarkerId = 0; - - var TextMarker = function(doc, type) { - this.lines = []; - this.type = type; - this.doc = doc; - this.id = ++nextMarkerId; - }; - - // Clear the marker. - TextMarker.prototype.clear = function () { - if (this.explicitlyCleared) { return } - var cm = this.doc.cm, withOp = cm && !cm.curOp; - if (withOp) { startOperation(cm); } - if (hasHandler(this, "clear")) { - var found = this.find(); - if (found) { signalLater(this, "clear", found.from, found.to); } - } - var min = null, max = null; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (cm && !this.collapsed) { regLineChange(cm, lineNo(line), "text"); } - else if (cm) { - if (span.to != null) { max = lineNo(line); } - if (span.from != null) { min = lineNo(line); } - } - line.markedSpans = removeMarkedSpan(line.markedSpans, span); - if (span.from == null && this.collapsed && !lineIsHidden(this.doc, line) && cm) - { updateLineHeight(line, textHeight(cm.display)); } - } - if (cm && this.collapsed && !cm.options.lineWrapping) { for (var i$1 = 0; i$1 < this.lines.length; ++i$1) { - var visual = visualLine(this.lines[i$1]), len = lineLength(visual); - if (len > cm.display.maxLineLength) { - cm.display.maxLine = visual; - cm.display.maxLineLength = len; - cm.display.maxLineChanged = true; - } - } } - - if (min != null && cm && this.collapsed) { regChange(cm, min, max + 1); } - this.lines.length = 0; - this.explicitlyCleared = true; - if (this.atomic && this.doc.cantEdit) { - this.doc.cantEdit = false; - if (cm) { reCheckSelection(cm.doc); } - } - if (cm) { signalLater(cm, "markerCleared", cm, this, min, max); } - if (withOp) { endOperation(cm); } - if (this.parent) { this.parent.clear(); } - }; - - // Find the position of the marker in the document. Returns a {from, - // to} object by default. Side can be passed to get a specific side - // -- 0 (both), -1 (left), or 1 (right). When lineObj is true, the - // Pos objects returned contain a line object, rather than a line - // number (used to prevent looking up the same line twice). - TextMarker.prototype.find = function (side, lineObj) { - if (side == null && this.type == "bookmark") { side = 1; } - var from, to; - for (var i = 0; i < this.lines.length; ++i) { - var line = this.lines[i]; - var span = getMarkedSpanFor(line.markedSpans, this); - if (span.from != null) { - from = Pos(lineObj ? line : lineNo(line), span.from); - if (side == -1) { return from } - } - if (span.to != null) { - to = Pos(lineObj ? line : lineNo(line), span.to); - if (side == 1) { return to } - } - } - return from && {from: from, to: to} - }; - - // Signals that the marker's widget changed, and surrounding layout - // should be recomputed. - TextMarker.prototype.changed = function () { - var this$1 = this; - - var pos = this.find(-1, true), widget = this, cm = this.doc.cm; - if (!pos || !cm) { return } - runInOp(cm, function () { - var line = pos.line, lineN = lineNo(pos.line); - var view = findViewForLine(cm, lineN); - if (view) { - clearLineMeasurementCacheFor(view); - cm.curOp.selectionChanged = cm.curOp.forceUpdate = true; - } - cm.curOp.updateMaxLine = true; - if (!lineIsHidden(widget.doc, line) && widget.height != null) { - var oldHeight = widget.height; - widget.height = null; - var dHeight = widgetHeight(widget) - oldHeight; - if (dHeight) - { updateLineHeight(line, line.height + dHeight); } - } - signalLater(cm, "markerChanged", cm, this$1); - }); - }; - - TextMarker.prototype.attachLine = function (line) { - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp; - if (!op.maybeHiddenMarkers || indexOf(op.maybeHiddenMarkers, this) == -1) - { (op.maybeUnhiddenMarkers || (op.maybeUnhiddenMarkers = [])).push(this); } - } - this.lines.push(line); - }; - - TextMarker.prototype.detachLine = function (line) { - this.lines.splice(indexOf(this.lines, line), 1); - if (!this.lines.length && this.doc.cm) { - var op = this.doc.cm.curOp - ;(op.maybeHiddenMarkers || (op.maybeHiddenMarkers = [])).push(this); - } - }; - eventMixin(TextMarker); - - // Create a marker, wire it up to the right lines, and - function markText(doc, from, to, options, type) { - // Shared markers (across linked documents) are handled separately - // (markTextShared will call out to this again, once per - // document). - if (options && options.shared) { return markTextShared(doc, from, to, options, type) } - // Ensure we are in an operation. - if (doc.cm && !doc.cm.curOp) { return operation(doc.cm, markText)(doc, from, to, options, type) } - - var marker = new TextMarker(doc, type), diff = cmp(from, to); - if (options) { copyObj(options, marker, false); } - // Don't connect empty markers unless clearWhenEmpty is false - if (diff > 0 || diff == 0 && marker.clearWhenEmpty !== false) - { return marker } - if (marker.replacedWith) { - // Showing up as a widget implies collapsed (widget replaces text) - marker.collapsed = true; - marker.widgetNode = eltP("span", [marker.replacedWith], "CodeMirror-widget"); - if (!options.handleMouseEvents) { marker.widgetNode.setAttribute("cm-ignore-events", "true"); } - if (options.insertLeft) { marker.widgetNode.insertLeft = true; } - } - if (marker.collapsed) { - if (conflictingCollapsedRange(doc, from.line, from, to, marker) || - from.line != to.line && conflictingCollapsedRange(doc, to.line, from, to, marker)) - { throw new Error("Inserting collapsed marker partially overlapping an existing one") } - seeCollapsedSpans(); - } - - if (marker.addToHistory) - { addChangeToHistory(doc, {from: from, to: to, origin: "markText"}, doc.sel, NaN); } - - var curLine = from.line, cm = doc.cm, updateMaxLine; - doc.iter(curLine, to.line + 1, function (line) { - if (cm && marker.collapsed && !cm.options.lineWrapping && visualLine(line) == cm.display.maxLine) - { updateMaxLine = true; } - if (marker.collapsed && curLine != from.line) { updateLineHeight(line, 0); } - addMarkedSpan(line, new MarkedSpan(marker, - curLine == from.line ? from.ch : null, - curLine == to.line ? to.ch : null)); - ++curLine; - }); - // lineIsHidden depends on the presence of the spans, so needs a second pass - if (marker.collapsed) { doc.iter(from.line, to.line + 1, function (line) { - if (lineIsHidden(doc, line)) { updateLineHeight(line, 0); } - }); } - - if (marker.clearOnEnter) { on(marker, "beforeCursorEnter", function () { return marker.clear(); }); } - - if (marker.readOnly) { - seeReadOnlySpans(); - if (doc.history.done.length || doc.history.undone.length) - { doc.clearHistory(); } - } - if (marker.collapsed) { - marker.id = ++nextMarkerId; - marker.atomic = true; - } - if (cm) { - // Sync editor state - if (updateMaxLine) { cm.curOp.updateMaxLine = true; } - if (marker.collapsed) - { regChange(cm, from.line, to.line + 1); } - else if (marker.className || marker.startStyle || marker.endStyle || marker.css || - marker.attributes || marker.title) - { for (var i = from.line; i <= to.line; i++) { regLineChange(cm, i, "text"); } } - if (marker.atomic) { reCheckSelection(cm.doc); } - signalLater(cm, "markerAdded", cm, marker); - } - return marker - } - - // SHARED TEXTMARKERS - - // A shared marker spans multiple linked documents. It is - // implemented as a meta-marker-object controlling multiple normal - // markers. - var SharedTextMarker = function(markers, primary) { - this.markers = markers; - this.primary = primary; - for (var i = 0; i < markers.length; ++i) - { markers[i].parent = this; } - }; - - SharedTextMarker.prototype.clear = function () { - if (this.explicitlyCleared) { return } - this.explicitlyCleared = true; - for (var i = 0; i < this.markers.length; ++i) - { this.markers[i].clear(); } - signalLater(this, "clear"); - }; - - SharedTextMarker.prototype.find = function (side, lineObj) { - return this.primary.find(side, lineObj) - }; - eventMixin(SharedTextMarker); - - function markTextShared(doc, from, to, options, type) { - options = copyObj(options); - options.shared = false; - var markers = [markText(doc, from, to, options, type)], primary = markers[0]; - var widget = options.widgetNode; - linkedDocs(doc, function (doc) { - if (widget) { options.widgetNode = widget.cloneNode(true); } - markers.push(markText(doc, clipPos(doc, from), clipPos(doc, to), options, type)); - for (var i = 0; i < doc.linked.length; ++i) - { if (doc.linked[i].isParent) { return } } - primary = lst(markers); - }); - return new SharedTextMarker(markers, primary) - } - - function findSharedMarkers(doc) { - return doc.findMarks(Pos(doc.first, 0), doc.clipPos(Pos(doc.lastLine())), function (m) { return m.parent; }) - } - - function copySharedMarkers(doc, markers) { - for (var i = 0; i < markers.length; i++) { - var marker = markers[i], pos = marker.find(); - var mFrom = doc.clipPos(pos.from), mTo = doc.clipPos(pos.to); - if (cmp(mFrom, mTo)) { - var subMark = markText(doc, mFrom, mTo, marker.primary, marker.primary.type); - marker.markers.push(subMark); - subMark.parent = marker; - } - } - } - - function detachSharedMarkers(markers) { - var loop = function ( i ) { - var marker = markers[i], linked = [marker.primary.doc]; - linkedDocs(marker.primary.doc, function (d) { return linked.push(d); }); - for (var j = 0; j < marker.markers.length; j++) { - var subMarker = marker.markers[j]; - if (indexOf(linked, subMarker.doc) == -1) { - subMarker.parent = null; - marker.markers.splice(j--, 1); - } - } - }; - - for (var i = 0; i < markers.length; i++) loop( i ); - } - - var nextDocId = 0; - var Doc = function(text, mode, firstLine, lineSep, direction) { - if (!(this instanceof Doc)) { return new Doc(text, mode, firstLine, lineSep, direction) } - if (firstLine == null) { firstLine = 0; } - - BranchChunk.call(this, [new LeafChunk([new Line("", null)])]); - this.first = firstLine; - this.scrollTop = this.scrollLeft = 0; - this.cantEdit = false; - this.cleanGeneration = 1; - this.modeFrontier = this.highlightFrontier = firstLine; - var start = Pos(firstLine, 0); - this.sel = simpleSelection(start); - this.history = new History(null); - this.id = ++nextDocId; - this.modeOption = mode; - this.lineSep = lineSep; - this.direction = (direction == "rtl") ? "rtl" : "ltr"; - this.extend = false; - - if (typeof text == "string") { text = this.splitLines(text); } - updateDoc(this, {from: start, to: start, text: text}); - setSelection(this, simpleSelection(start), sel_dontScroll); - }; - - Doc.prototype = createObj(BranchChunk.prototype, { - constructor: Doc, - // Iterate over the document. Supports two forms -- with only one - // argument, it calls that for each line in the document. With - // three, it iterates over the range given by the first two (with - // the second being non-inclusive). - iter: function(from, to, op) { - if (op) { this.iterN(from - this.first, to - from, op); } - else { this.iterN(this.first, this.first + this.size, from); } - }, - - // Non-public interface for adding and removing lines. - insert: function(at, lines) { - var height = 0; - for (var i = 0; i < lines.length; ++i) { height += lines[i].height; } - this.insertInner(at - this.first, lines, height); - }, - remove: function(at, n) { this.removeInner(at - this.first, n); }, - - // From here, the methods are part of the public interface. Most - // are also available from CodeMirror (editor) instances. - - getValue: function(lineSep) { - var lines = getLines(this, this.first, this.first + this.size); - if (lineSep === false) { return lines } - return lines.join(lineSep || this.lineSeparator()) - }, - setValue: docMethodOp(function(code) { - var top = Pos(this.first, 0), last = this.first + this.size - 1; - makeChange(this, {from: top, to: Pos(last, getLine(this, last).text.length), - text: this.splitLines(code), origin: "setValue", full: true}, true); - if (this.cm) { scrollToCoords(this.cm, 0, 0); } - setSelection(this, simpleSelection(top), sel_dontScroll); - }), - replaceRange: function(code, from, to, origin) { - from = clipPos(this, from); - to = to ? clipPos(this, to) : from; - replaceRange(this, code, from, to, origin); - }, - getRange: function(from, to, lineSep) { - var lines = getBetween(this, clipPos(this, from), clipPos(this, to)); - if (lineSep === false) { return lines } - return lines.join(lineSep || this.lineSeparator()) - }, - - getLine: function(line) {var l = this.getLineHandle(line); return l && l.text}, - - getLineHandle: function(line) {if (isLine(this, line)) { return getLine(this, line) }}, - getLineNumber: function(line) {return lineNo(line)}, - - getLineHandleVisualStart: function(line) { - if (typeof line == "number") { line = getLine(this, line); } - return visualLine(line) - }, - - lineCount: function() {return this.size}, - firstLine: function() {return this.first}, - lastLine: function() {return this.first + this.size - 1}, - - clipPos: function(pos) {return clipPos(this, pos)}, - - getCursor: function(start) { - var range = this.sel.primary(), pos; - if (start == null || start == "head") { pos = range.head; } - else if (start == "anchor") { pos = range.anchor; } - else if (start == "end" || start == "to" || start === false) { pos = range.to(); } - else { pos = range.from(); } - return pos - }, - listSelections: function() { return this.sel.ranges }, - somethingSelected: function() {return this.sel.somethingSelected()}, - - setCursor: docMethodOp(function(line, ch, options) { - setSimpleSelection(this, clipPos(this, typeof line == "number" ? Pos(line, ch || 0) : line), null, options); - }), - setSelection: docMethodOp(function(anchor, head, options) { - setSimpleSelection(this, clipPos(this, anchor), clipPos(this, head || anchor), options); - }), - extendSelection: docMethodOp(function(head, other, options) { - extendSelection(this, clipPos(this, head), other && clipPos(this, other), options); - }), - extendSelections: docMethodOp(function(heads, options) { - extendSelections(this, clipPosArray(this, heads), options); - }), - extendSelectionsBy: docMethodOp(function(f, options) { - var heads = map(this.sel.ranges, f); - extendSelections(this, clipPosArray(this, heads), options); - }), - setSelections: docMethodOp(function(ranges, primary, options) { - if (!ranges.length) { return } - var out = []; - for (var i = 0; i < ranges.length; i++) - { out[i] = new Range(clipPos(this, ranges[i].anchor), - clipPos(this, ranges[i].head)); } - if (primary == null) { primary = Math.min(ranges.length - 1, this.sel.primIndex); } - setSelection(this, normalizeSelection(this.cm, out, primary), options); - }), - addSelection: docMethodOp(function(anchor, head, options) { - var ranges = this.sel.ranges.slice(0); - ranges.push(new Range(clipPos(this, anchor), clipPos(this, head || anchor))); - setSelection(this, normalizeSelection(this.cm, ranges, ranges.length - 1), options); - }), - - getSelection: function(lineSep) { - var ranges = this.sel.ranges, lines; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - lines = lines ? lines.concat(sel) : sel; - } - if (lineSep === false) { return lines } - else { return lines.join(lineSep || this.lineSeparator()) } - }, - getSelections: function(lineSep) { - var parts = [], ranges = this.sel.ranges; - for (var i = 0; i < ranges.length; i++) { - var sel = getBetween(this, ranges[i].from(), ranges[i].to()); - if (lineSep !== false) { sel = sel.join(lineSep || this.lineSeparator()); } - parts[i] = sel; - } - return parts - }, - replaceSelection: function(code, collapse, origin) { - var dup = []; - for (var i = 0; i < this.sel.ranges.length; i++) - { dup[i] = code; } - this.replaceSelections(dup, collapse, origin || "+input"); - }, - replaceSelections: docMethodOp(function(code, collapse, origin) { - var changes = [], sel = this.sel; - for (var i = 0; i < sel.ranges.length; i++) { - var range = sel.ranges[i]; - changes[i] = {from: range.from(), to: range.to(), text: this.splitLines(code[i]), origin: origin}; - } - var newSel = collapse && collapse != "end" && computeReplacedSel(this, changes, collapse); - for (var i$1 = changes.length - 1; i$1 >= 0; i$1--) - { makeChange(this, changes[i$1]); } - if (newSel) { setSelectionReplaceHistory(this, newSel); } - else if (this.cm) { ensureCursorVisible(this.cm); } - }), - undo: docMethodOp(function() {makeChangeFromHistory(this, "undo");}), - redo: docMethodOp(function() {makeChangeFromHistory(this, "redo");}), - undoSelection: docMethodOp(function() {makeChangeFromHistory(this, "undo", true);}), - redoSelection: docMethodOp(function() {makeChangeFromHistory(this, "redo", true);}), - - setExtending: function(val) {this.extend = val;}, - getExtending: function() {return this.extend}, - - historySize: function() { - var hist = this.history, done = 0, undone = 0; - for (var i = 0; i < hist.done.length; i++) { if (!hist.done[i].ranges) { ++done; } } - for (var i$1 = 0; i$1 < hist.undone.length; i$1++) { if (!hist.undone[i$1].ranges) { ++undone; } } - return {undo: done, redo: undone} - }, - clearHistory: function() { - var this$1 = this; - - this.history = new History(this.history.maxGeneration); - linkedDocs(this, function (doc) { return doc.history = this$1.history; }, true); - }, - - markClean: function() { - this.cleanGeneration = this.changeGeneration(true); - }, - changeGeneration: function(forceSplit) { - if (forceSplit) - { this.history.lastOp = this.history.lastSelOp = this.history.lastOrigin = null; } - return this.history.generation - }, - isClean: function (gen) { - return this.history.generation == (gen || this.cleanGeneration) - }, - - getHistory: function() { - return {done: copyHistoryArray(this.history.done), - undone: copyHistoryArray(this.history.undone)} - }, - setHistory: function(histData) { - var hist = this.history = new History(this.history.maxGeneration); - hist.done = copyHistoryArray(histData.done.slice(0), null, true); - hist.undone = copyHistoryArray(histData.undone.slice(0), null, true); - }, - - setGutterMarker: docMethodOp(function(line, gutterID, value) { - return changeLine(this, line, "gutter", function (line) { - var markers = line.gutterMarkers || (line.gutterMarkers = {}); - markers[gutterID] = value; - if (!value && isEmpty(markers)) { line.gutterMarkers = null; } - return true - }) - }), - - clearGutter: docMethodOp(function(gutterID) { - var this$1 = this; - - this.iter(function (line) { - if (line.gutterMarkers && line.gutterMarkers[gutterID]) { - changeLine(this$1, line, "gutter", function () { - line.gutterMarkers[gutterID] = null; - if (isEmpty(line.gutterMarkers)) { line.gutterMarkers = null; } - return true - }); - } - }); - }), - - lineInfo: function(line) { - var n; - if (typeof line == "number") { - if (!isLine(this, line)) { return null } - n = line; - line = getLine(this, line); - if (!line) { return null } - } else { - n = lineNo(line); - if (n == null) { return null } - } - return {line: n, handle: line, text: line.text, gutterMarkers: line.gutterMarkers, - textClass: line.textClass, bgClass: line.bgClass, wrapClass: line.wrapClass, - widgets: line.widgets} - }, - - addLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - if (!line[prop]) { line[prop] = cls; } - else if (classTest(cls).test(line[prop])) { return false } - else { line[prop] += " " + cls; } - return true - }) - }), - removeLineClass: docMethodOp(function(handle, where, cls) { - return changeLine(this, handle, where == "gutter" ? "gutter" : "class", function (line) { - var prop = where == "text" ? "textClass" - : where == "background" ? "bgClass" - : where == "gutter" ? "gutterClass" : "wrapClass"; - var cur = line[prop]; - if (!cur) { return false } - else if (cls == null) { line[prop] = null; } - else { - var found = cur.match(classTest(cls)); - if (!found) { return false } - var end = found.index + found[0].length; - line[prop] = cur.slice(0, found.index) + (!found.index || end == cur.length ? "" : " ") + cur.slice(end) || null; - } - return true - }) - }), - - addLineWidget: docMethodOp(function(handle, node, options) { - return addLineWidget(this, handle, node, options) - }), - removeLineWidget: function(widget) { widget.clear(); }, - - markText: function(from, to, options) { - return markText(this, clipPos(this, from), clipPos(this, to), options, options && options.type || "range") - }, - setBookmark: function(pos, options) { - var realOpts = {replacedWith: options && (options.nodeType == null ? options.widget : options), - insertLeft: options && options.insertLeft, - clearWhenEmpty: false, shared: options && options.shared, - handleMouseEvents: options && options.handleMouseEvents}; - pos = clipPos(this, pos); - return markText(this, pos, pos, realOpts, "bookmark") - }, - findMarksAt: function(pos) { - pos = clipPos(this, pos); - var markers = [], spans = getLine(this, pos.line).markedSpans; - if (spans) { for (var i = 0; i < spans.length; ++i) { - var span = spans[i]; - if ((span.from == null || span.from <= pos.ch) && - (span.to == null || span.to >= pos.ch)) - { markers.push(span.marker.parent || span.marker); } - } } - return markers - }, - findMarks: function(from, to, filter) { - from = clipPos(this, from); to = clipPos(this, to); - var found = [], lineNo = from.line; - this.iter(from.line, to.line + 1, function (line) { - var spans = line.markedSpans; - if (spans) { for (var i = 0; i < spans.length; i++) { - var span = spans[i]; - if (!(span.to != null && lineNo == from.line && from.ch >= span.to || - span.from == null && lineNo != from.line || - span.from != null && lineNo == to.line && span.from >= to.ch) && - (!filter || filter(span.marker))) - { found.push(span.marker.parent || span.marker); } - } } - ++lineNo; - }); - return found - }, - getAllMarks: function() { - var markers = []; - this.iter(function (line) { - var sps = line.markedSpans; - if (sps) { for (var i = 0; i < sps.length; ++i) - { if (sps[i].from != null) { markers.push(sps[i].marker); } } } - }); - return markers - }, - - posFromIndex: function(off) { - var ch, lineNo = this.first, sepSize = this.lineSeparator().length; - this.iter(function (line) { - var sz = line.text.length + sepSize; - if (sz > off) { ch = off; return true } - off -= sz; - ++lineNo; - }); - return clipPos(this, Pos(lineNo, ch)) - }, - indexFromPos: function (coords) { - coords = clipPos(this, coords); - var index = coords.ch; - if (coords.line < this.first || coords.ch < 0) { return 0 } - var sepSize = this.lineSeparator().length; - this.iter(this.first, coords.line, function (line) { // iter aborts when callback returns a truthy value - index += line.text.length + sepSize; - }); - return index - }, - - copy: function(copyHistory) { - var doc = new Doc(getLines(this, this.first, this.first + this.size), - this.modeOption, this.first, this.lineSep, this.direction); - doc.scrollTop = this.scrollTop; doc.scrollLeft = this.scrollLeft; - doc.sel = this.sel; - doc.extend = false; - if (copyHistory) { - doc.history.undoDepth = this.history.undoDepth; - doc.setHistory(this.getHistory()); - } - return doc - }, - - linkedDoc: function(options) { - if (!options) { options = {}; } - var from = this.first, to = this.first + this.size; - if (options.from != null && options.from > from) { from = options.from; } - if (options.to != null && options.to < to) { to = options.to; } - var copy = new Doc(getLines(this, from, to), options.mode || this.modeOption, from, this.lineSep, this.direction); - if (options.sharedHist) { copy.history = this.history - ; }(this.linked || (this.linked = [])).push({doc: copy, sharedHist: options.sharedHist}); - copy.linked = [{doc: this, isParent: true, sharedHist: options.sharedHist}]; - copySharedMarkers(copy, findSharedMarkers(this)); - return copy - }, - unlinkDoc: function(other) { - if (other instanceof CodeMirror) { other = other.doc; } - if (this.linked) { for (var i = 0; i < this.linked.length; ++i) { - var link = this.linked[i]; - if (link.doc != other) { continue } - this.linked.splice(i, 1); - other.unlinkDoc(this); - detachSharedMarkers(findSharedMarkers(this)); - break - } } - // If the histories were shared, split them again - if (other.history == this.history) { - var splitIds = [other.id]; - linkedDocs(other, function (doc) { return splitIds.push(doc.id); }, true); - other.history = new History(null); - other.history.done = copyHistoryArray(this.history.done, splitIds); - other.history.undone = copyHistoryArray(this.history.undone, splitIds); - } - }, - iterLinkedDocs: function(f) {linkedDocs(this, f);}, - - getMode: function() {return this.mode}, - getEditor: function() {return this.cm}, - - splitLines: function(str) { - if (this.lineSep) { return str.split(this.lineSep) } - return splitLinesAuto(str) - }, - lineSeparator: function() { return this.lineSep || "\n" }, - - setDirection: docMethodOp(function (dir) { - if (dir != "rtl") { dir = "ltr"; } - if (dir == this.direction) { return } - this.direction = dir; - this.iter(function (line) { return line.order = null; }); - if (this.cm) { directionChanged(this.cm); } - }) - }); - - // Public alias. - Doc.prototype.eachLine = Doc.prototype.iter; - - // Kludge to work around strange IE behavior where it'll sometimes - // re-fire a series of drag-related events right after the drop (#1551) - var lastDrop = 0; - - function onDrop(e) { - var cm = this; - clearDragCursor(cm); - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) - { return } - e_preventDefault(e); - if (ie) { lastDrop = +new Date; } - var pos = posFromMouse(cm, e, true), files = e.dataTransfer.files; - if (!pos || cm.isReadOnly()) { return } - // Might be a file drop, in which case we simply extract the text - // and insert it. - if (files && files.length && window.FileReader && window.File) { - var n = files.length, text = Array(n), read = 0; - var markAsReadAndPasteIfAllFilesAreRead = function () { - if (++read == n) { - operation(cm, function () { - pos = clipPos(cm.doc, pos); - var change = {from: pos, to: pos, - text: cm.doc.splitLines( - text.filter(function (t) { return t != null; }).join(cm.doc.lineSeparator())), - origin: "paste"}; - makeChange(cm.doc, change); - setSelectionReplaceHistory(cm.doc, simpleSelection(clipPos(cm.doc, pos), clipPos(cm.doc, changeEnd(change)))); - })(); - } - }; - var readTextFromFile = function (file, i) { - if (cm.options.allowDropFileTypes && - indexOf(cm.options.allowDropFileTypes, file.type) == -1) { - markAsReadAndPasteIfAllFilesAreRead(); - return - } - var reader = new FileReader; - reader.onerror = function () { return markAsReadAndPasteIfAllFilesAreRead(); }; - reader.onload = function () { - var content = reader.result; - if (/[\x00-\x08\x0e-\x1f]{2}/.test(content)) { - markAsReadAndPasteIfAllFilesAreRead(); - return - } - text[i] = content; - markAsReadAndPasteIfAllFilesAreRead(); - }; - reader.readAsText(file); - }; - for (var i = 0; i < files.length; i++) { readTextFromFile(files[i], i); } - } else { // Normal drop - // Don't do a replace if the drop happened inside of the selected text. - if (cm.state.draggingText && cm.doc.sel.contains(pos) > -1) { - cm.state.draggingText(e); - // Ensure the editor is re-focused - setTimeout(function () { return cm.display.input.focus(); }, 20); - return - } - try { - var text$1 = e.dataTransfer.getData("Text"); - if (text$1) { - var selected; - if (cm.state.draggingText && !cm.state.draggingText.copy) - { selected = cm.listSelections(); } - setSelectionNoUndo(cm.doc, simpleSelection(pos, pos)); - if (selected) { for (var i$1 = 0; i$1 < selected.length; ++i$1) - { replaceRange(cm.doc, "", selected[i$1].anchor, selected[i$1].head, "drag"); } } - cm.replaceSelection(text$1, "around", "paste"); - cm.display.input.focus(); - } - } - catch(e$1){} - } - } - - function onDragStart(cm, e) { - if (ie && (!cm.state.draggingText || +new Date - lastDrop < 100)) { e_stop(e); return } - if (signalDOMEvent(cm, e) || eventInWidget(cm.display, e)) { return } - - e.dataTransfer.setData("Text", cm.getSelection()); - e.dataTransfer.effectAllowed = "copyMove"; - - // Use dummy image instead of default browsers image. - // Recent Safari (~6.0.2) have a tendency to segfault when this happens, so we don't do it there. - if (e.dataTransfer.setDragImage && !safari) { - var img = elt("img", null, null, "position: fixed; left: 0; top: 0;"); - img.src = "data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="; - if (presto) { - img.width = img.height = 1; - cm.display.wrapper.appendChild(img); - // Force a relayout, or Opera won't use our image for some obscure reason - img._top = img.offsetTop; - } - e.dataTransfer.setDragImage(img, 0, 0); - if (presto) { img.parentNode.removeChild(img); } - } - } - - function onDragOver(cm, e) { - var pos = posFromMouse(cm, e); - if (!pos) { return } - var frag = document.createDocumentFragment(); - drawSelectionCursor(cm, pos, frag); - if (!cm.display.dragCursor) { - cm.display.dragCursor = elt("div", null, "CodeMirror-cursors CodeMirror-dragcursors"); - cm.display.lineSpace.insertBefore(cm.display.dragCursor, cm.display.cursorDiv); - } - removeChildrenAndAdd(cm.display.dragCursor, frag); - } - - function clearDragCursor(cm) { - if (cm.display.dragCursor) { - cm.display.lineSpace.removeChild(cm.display.dragCursor); - cm.display.dragCursor = null; - } - } - - // These must be handled carefully, because naively registering a - // handler for each editor will cause the editors to never be - // garbage collected. - - function forEachCodeMirror(f) { - if (!document.getElementsByClassName) { return } - var byClass = document.getElementsByClassName("CodeMirror"), editors = []; - for (var i = 0; i < byClass.length; i++) { - var cm = byClass[i].CodeMirror; - if (cm) { editors.push(cm); } - } - if (editors.length) { editors[0].operation(function () { - for (var i = 0; i < editors.length; i++) { f(editors[i]); } - }); } - } - - var globalsRegistered = false; - function ensureGlobalHandlers() { - if (globalsRegistered) { return } - registerGlobalHandlers(); - globalsRegistered = true; - } - function registerGlobalHandlers() { - // When the window resizes, we need to refresh active editors. - var resizeTimer; - on(window, "resize", function () { - if (resizeTimer == null) { resizeTimer = setTimeout(function () { - resizeTimer = null; - forEachCodeMirror(onResize); - }, 100); } - }); - // When the window loses focus, we want to show the editor as blurred - on(window, "blur", function () { return forEachCodeMirror(onBlur); }); - } - // Called when the window resizes - function onResize(cm) { - var d = cm.display; - // Might be a text scaling operation, clear size caches. - d.cachedCharWidth = d.cachedTextHeight = d.cachedPaddingH = null; - d.scrollbarsClipped = false; - cm.setSize(); - } - - var keyNames = { - 3: "Pause", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", - 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", - 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", - 46: "Delete", 59: ";", 61: "=", 91: "Mod", 92: "Mod", 93: "Mod", - 106: "*", 107: "=", 109: "-", 110: ".", 111: "/", 145: "ScrollLock", - 173: "-", 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", - 221: "]", 222: "'", 224: "Mod", 63232: "Up", 63233: "Down", 63234: "Left", 63235: "Right", 63272: "Delete", - 63273: "Home", 63275: "End", 63276: "PageUp", 63277: "PageDown", 63302: "Insert" - }; - - // Number keys - for (var i = 0; i < 10; i++) { keyNames[i + 48] = keyNames[i + 96] = String(i); } - // Alphabetic keys - for (var i$1 = 65; i$1 <= 90; i$1++) { keyNames[i$1] = String.fromCharCode(i$1); } - // Function keys - for (var i$2 = 1; i$2 <= 12; i$2++) { keyNames[i$2 + 111] = keyNames[i$2 + 63235] = "F" + i$2; } - - var keyMap = {}; - - keyMap.basic = { - "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", - "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", - "Delete": "delCharAfter", "Backspace": "delCharBefore", "Shift-Backspace": "delCharBefore", - "Tab": "defaultTab", "Shift-Tab": "indentAuto", - "Enter": "newlineAndIndent", "Insert": "toggleOverwrite", - "Esc": "singleSelection" - }; - // Note that the save and find-related commands aren't defined by - // default. User code or addons can define them. Unknown commands - // are simply ignored. - keyMap.pcDefault = { - "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", - "Ctrl-Home": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Up": "goLineUp", "Ctrl-Down": "goLineDown", - "Ctrl-Left": "goGroupLeft", "Ctrl-Right": "goGroupRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", - "Ctrl-Backspace": "delGroupBefore", "Ctrl-Delete": "delGroupAfter", "Ctrl-S": "save", "Ctrl-F": "find", - "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", - "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", - "Ctrl-U": "undoSelection", "Shift-Ctrl-U": "redoSelection", "Alt-U": "redoSelection", - "fallthrough": "basic" - }; - // Very basic readline/emacs-style bindings, which are standard on Mac. - keyMap.emacsy = { - "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", - "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", - "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharAfter", "Ctrl-H": "delCharBefore", - "Alt-D": "delWordAfter", "Alt-Backspace": "delWordBefore", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars", - "Ctrl-O": "openLine" - }; - keyMap.macDefault = { - "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", - "Cmd-Home": "goDocStart", "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goGroupLeft", - "Alt-Right": "goGroupRight", "Cmd-Left": "goLineLeft", "Cmd-Right": "goLineRight", "Alt-Backspace": "delGroupBefore", - "Ctrl-Alt-Backspace": "delGroupAfter", "Alt-Delete": "delGroupAfter", "Cmd-S": "save", "Cmd-F": "find", - "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", - "Cmd-[": "indentLess", "Cmd-]": "indentMore", "Cmd-Backspace": "delWrappedLineLeft", "Cmd-Delete": "delWrappedLineRight", - "Cmd-U": "undoSelection", "Shift-Cmd-U": "redoSelection", "Ctrl-Up": "goDocStart", "Ctrl-Down": "goDocEnd", - "fallthrough": ["basic", "emacsy"] - }; - keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; - - // KEYMAP DISPATCH - - function normalizeKeyName(name) { - var parts = name.split(/-(?!$)/); - name = parts[parts.length - 1]; - var alt, ctrl, shift, cmd; - for (var i = 0; i < parts.length - 1; i++) { - var mod = parts[i]; - if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } - else if (/^a(lt)?$/i.test(mod)) { alt = true; } - else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } - else if (/^s(hift)?$/i.test(mod)) { shift = true; } - else { throw new Error("Unrecognized modifier name: " + mod) } - } - if (alt) { name = "Alt-" + name; } - if (ctrl) { name = "Ctrl-" + name; } - if (cmd) { name = "Cmd-" + name; } - if (shift) { name = "Shift-" + name; } - return name - } - - // This is a kludge to keep keymaps mostly working as raw objects - // (backwards compatibility) while at the same time support features - // like normalization and multi-stroke key bindings. It compiles a - // new normalized keymap, and then updates the old object to reflect - // this. - function normalizeKeyMap(keymap) { - var copy = {}; - for (var keyname in keymap) { if (keymap.hasOwnProperty(keyname)) { - var value = keymap[keyname]; - if (/^(name|fallthrough|(de|at)tach)$/.test(keyname)) { continue } - if (value == "...") { delete keymap[keyname]; continue } - - var keys = map(keyname.split(" "), normalizeKeyName); - for (var i = 0; i < keys.length; i++) { - var val = (void 0), name = (void 0); - if (i == keys.length - 1) { - name = keys.join(" "); - val = value; - } else { - name = keys.slice(0, i + 1).join(" "); - val = "..."; - } - var prev = copy[name]; - if (!prev) { copy[name] = val; } - else if (prev != val) { throw new Error("Inconsistent bindings for " + name) } - } - delete keymap[keyname]; - } } - for (var prop in copy) { keymap[prop] = copy[prop]; } - return keymap - } - - function lookupKey(key, map, handle, context) { - map = getKeyMap(map); - var found = map.call ? map.call(key, context) : map[key]; - if (found === false) { return "nothing" } - if (found === "...") { return "multi" } - if (found != null && handle(found)) { return "handled" } - - if (map.fallthrough) { - if (Object.prototype.toString.call(map.fallthrough) != "[object Array]") - { return lookupKey(key, map.fallthrough, handle, context) } - for (var i = 0; i < map.fallthrough.length; i++) { - var result = lookupKey(key, map.fallthrough[i], handle, context); - if (result) { return result } - } - } - } - - // Modifier key presses don't count as 'real' key presses for the - // purpose of keymap fallthrough. - function isModifierKey(value) { - var name = typeof value == "string" ? value : keyNames[value.keyCode]; - return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod" - } - - function addModifierNames(name, event, noShift) { - var base = name; - if (event.altKey && base != "Alt") { name = "Alt-" + name; } - if ((flipCtrlCmd ? event.metaKey : event.ctrlKey) && base != "Ctrl") { name = "Ctrl-" + name; } - if ((flipCtrlCmd ? event.ctrlKey : event.metaKey) && base != "Mod") { name = "Cmd-" + name; } - if (!noShift && event.shiftKey && base != "Shift") { name = "Shift-" + name; } - return name - } - - // Look up the name of a key as indicated by an event object. - function keyName(event, noShift) { - if (presto && event.keyCode == 34 && event["char"]) { return false } - var name = keyNames[event.keyCode]; - if (name == null || event.altGraphKey) { return false } - // Ctrl-ScrollLock has keyCode 3, same as Ctrl-Pause, - // so we'll use event.code when available (Chrome 48+, FF 38+, Safari 10.1+) - if (event.keyCode == 3 && event.code) { name = event.code; } - return addModifierNames(name, event, noShift) - } - - function getKeyMap(val) { - return typeof val == "string" ? keyMap[val] : val - } - - // Helper for deleting text near the selection(s), used to implement - // backspace, delete, and similar functionality. - function deleteNearSelection(cm, compute) { - var ranges = cm.doc.sel.ranges, kill = []; - // Build up a set of ranges to kill first, merging overlapping - // ranges. - for (var i = 0; i < ranges.length; i++) { - var toKill = compute(ranges[i]); - while (kill.length && cmp(toKill.from, lst(kill).to) <= 0) { - var replaced = kill.pop(); - if (cmp(replaced.from, toKill.from) < 0) { - toKill.from = replaced.from; - break - } - } - kill.push(toKill); - } - // Next, remove those actual ranges. - runInOp(cm, function () { - for (var i = kill.length - 1; i >= 0; i--) - { replaceRange(cm.doc, "", kill[i].from, kill[i].to, "+delete"); } - ensureCursorVisible(cm); - }); - } - - function moveCharLogically(line, ch, dir) { - var target = skipExtendingChars(line.text, ch + dir, dir); - return target < 0 || target > line.text.length ? null : target - } - - function moveLogically(line, start, dir) { - var ch = moveCharLogically(line, start.ch, dir); - return ch == null ? null : new Pos(start.line, ch, dir < 0 ? "after" : "before") - } - - function endOfLine(visually, cm, lineObj, lineNo, dir) { - if (visually) { - if (cm.doc.direction == "rtl") { dir = -dir; } - var order = getOrder(lineObj, cm.doc.direction); - if (order) { - var part = dir < 0 ? lst(order) : order[0]; - var moveInStorageOrder = (dir < 0) == (part.level == 1); - var sticky = moveInStorageOrder ? "after" : "before"; - var ch; - // With a wrapped rtl chunk (possibly spanning multiple bidi parts), - // it could be that the last bidi part is not on the last visual line, - // since visual lines contain content order-consecutive chunks. - // Thus, in rtl, we are looking for the first (content-order) character - // in the rtl chunk that is on the last line (that is, the same line - // as the last (content-order) character). - if (part.level > 0 || cm.doc.direction == "rtl") { - var prep = prepareMeasureForLine(cm, lineObj); - ch = dir < 0 ? lineObj.text.length - 1 : 0; - var targetTop = measureCharPrepared(cm, prep, ch).top; - ch = findFirst(function (ch) { return measureCharPrepared(cm, prep, ch).top == targetTop; }, (dir < 0) == (part.level == 1) ? part.from : part.to - 1, ch); - if (sticky == "before") { ch = moveCharLogically(lineObj, ch, 1); } - } else { ch = dir < 0 ? part.to : part.from; } - return new Pos(lineNo, ch, sticky) - } - } - return new Pos(lineNo, dir < 0 ? lineObj.text.length : 0, dir < 0 ? "before" : "after") - } - - function moveVisually(cm, line, start, dir) { - var bidi = getOrder(line, cm.doc.direction); - if (!bidi) { return moveLogically(line, start, dir) } - if (start.ch >= line.text.length) { - start.ch = line.text.length; - start.sticky = "before"; - } else if (start.ch <= 0) { - start.ch = 0; - start.sticky = "after"; - } - var partPos = getBidiPartAt(bidi, start.ch, start.sticky), part = bidi[partPos]; - if (cm.doc.direction == "ltr" && part.level % 2 == 0 && (dir > 0 ? part.to > start.ch : part.from < start.ch)) { - // Case 1: We move within an ltr part in an ltr editor. Even with wrapped lines, - // nothing interesting happens. - return moveLogically(line, start, dir) - } - - var mv = function (pos, dir) { return moveCharLogically(line, pos instanceof Pos ? pos.ch : pos, dir); }; - var prep; - var getWrappedLineExtent = function (ch) { - if (!cm.options.lineWrapping) { return {begin: 0, end: line.text.length} } - prep = prep || prepareMeasureForLine(cm, line); - return wrappedLineExtentChar(cm, line, prep, ch) - }; - var wrappedLineExtent = getWrappedLineExtent(start.sticky == "before" ? mv(start, -1) : start.ch); - - if (cm.doc.direction == "rtl" || part.level == 1) { - var moveInStorageOrder = (part.level == 1) == (dir < 0); - var ch = mv(start, moveInStorageOrder ? 1 : -1); - if (ch != null && (!moveInStorageOrder ? ch >= part.from && ch >= wrappedLineExtent.begin : ch <= part.to && ch <= wrappedLineExtent.end)) { - // Case 2: We move within an rtl part or in an rtl editor on the same visual line - var sticky = moveInStorageOrder ? "before" : "after"; - return new Pos(start.line, ch, sticky) - } - } - - // Case 3: Could not move within this bidi part in this visual line, so leave - // the current bidi part - - var searchInVisualLine = function (partPos, dir, wrappedLineExtent) { - var getRes = function (ch, moveInStorageOrder) { return moveInStorageOrder - ? new Pos(start.line, mv(ch, 1), "before") - : new Pos(start.line, ch, "after"); }; - - for (; partPos >= 0 && partPos < bidi.length; partPos += dir) { - var part = bidi[partPos]; - var moveInStorageOrder = (dir > 0) == (part.level != 1); - var ch = moveInStorageOrder ? wrappedLineExtent.begin : mv(wrappedLineExtent.end, -1); - if (part.from <= ch && ch < part.to) { return getRes(ch, moveInStorageOrder) } - ch = moveInStorageOrder ? part.from : mv(part.to, -1); - if (wrappedLineExtent.begin <= ch && ch < wrappedLineExtent.end) { return getRes(ch, moveInStorageOrder) } - } - }; - - // Case 3a: Look for other bidi parts on the same visual line - var res = searchInVisualLine(partPos + dir, dir, wrappedLineExtent); - if (res) { return res } - - // Case 3b: Look for other bidi parts on the next visual line - var nextCh = dir > 0 ? wrappedLineExtent.end : mv(wrappedLineExtent.begin, -1); - if (nextCh != null && !(dir > 0 && nextCh == line.text.length)) { - res = searchInVisualLine(dir > 0 ? 0 : bidi.length - 1, dir, getWrappedLineExtent(nextCh)); - if (res) { return res } - } - - // Case 4: Nowhere to move - return null - } - - // Commands are parameter-less actions that can be performed on an - // editor, mostly used for keybindings. - var commands = { - selectAll: selectAll, - singleSelection: function (cm) { return cm.setSelection(cm.getCursor("anchor"), cm.getCursor("head"), sel_dontScroll); }, - killLine: function (cm) { return deleteNearSelection(cm, function (range) { - if (range.empty()) { - var len = getLine(cm.doc, range.head.line).text.length; - if (range.head.ch == len && range.head.line < cm.lastLine()) - { return {from: range.head, to: Pos(range.head.line + 1, 0)} } - else - { return {from: range.head, to: Pos(range.head.line, len)} } - } else { - return {from: range.from(), to: range.to()} - } - }); }, - deleteLine: function (cm) { return deleteNearSelection(cm, function (range) { return ({ - from: Pos(range.from().line, 0), - to: clipPos(cm.doc, Pos(range.to().line + 1, 0)) - }); }); }, - delLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { return ({ - from: Pos(range.from().line, 0), to: range.from() - }); }); }, - delWrappedLineLeft: function (cm) { return deleteNearSelection(cm, function (range) { - var top = cm.charCoords(range.head, "div").top + 5; - var leftPos = cm.coordsChar({left: 0, top: top}, "div"); - return {from: leftPos, to: range.from()} - }); }, - delWrappedLineRight: function (cm) { return deleteNearSelection(cm, function (range) { - var top = cm.charCoords(range.head, "div").top + 5; - var rightPos = cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div"); - return {from: range.from(), to: rightPos } - }); }, - undo: function (cm) { return cm.undo(); }, - redo: function (cm) { return cm.redo(); }, - undoSelection: function (cm) { return cm.undoSelection(); }, - redoSelection: function (cm) { return cm.redoSelection(); }, - goDocStart: function (cm) { return cm.extendSelection(Pos(cm.firstLine(), 0)); }, - goDocEnd: function (cm) { return cm.extendSelection(Pos(cm.lastLine())); }, - goLineStart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStart(cm, range.head.line); }, - {origin: "+move", bias: 1} - ); }, - goLineStartSmart: function (cm) { return cm.extendSelectionsBy(function (range) { return lineStartSmart(cm, range.head); }, - {origin: "+move", bias: 1} - ); }, - goLineEnd: function (cm) { return cm.extendSelectionsBy(function (range) { return lineEnd(cm, range.head.line); }, - {origin: "+move", bias: -1} - ); }, - goLineRight: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.cursorCoords(range.head, "div").top + 5; - return cm.coordsChar({left: cm.display.lineDiv.offsetWidth + 100, top: top}, "div") - }, sel_move); }, - goLineLeft: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.cursorCoords(range.head, "div").top + 5; - return cm.coordsChar({left: 0, top: top}, "div") - }, sel_move); }, - goLineLeftSmart: function (cm) { return cm.extendSelectionsBy(function (range) { - var top = cm.cursorCoords(range.head, "div").top + 5; - var pos = cm.coordsChar({left: 0, top: top}, "div"); - if (pos.ch < cm.getLine(pos.line).search(/\S/)) { return lineStartSmart(cm, range.head) } - return pos - }, sel_move); }, - goLineUp: function (cm) { return cm.moveV(-1, "line"); }, - goLineDown: function (cm) { return cm.moveV(1, "line"); }, - goPageUp: function (cm) { return cm.moveV(-1, "page"); }, - goPageDown: function (cm) { return cm.moveV(1, "page"); }, - goCharLeft: function (cm) { return cm.moveH(-1, "char"); }, - goCharRight: function (cm) { return cm.moveH(1, "char"); }, - goColumnLeft: function (cm) { return cm.moveH(-1, "column"); }, - goColumnRight: function (cm) { return cm.moveH(1, "column"); }, - goWordLeft: function (cm) { return cm.moveH(-1, "word"); }, - goGroupRight: function (cm) { return cm.moveH(1, "group"); }, - goGroupLeft: function (cm) { return cm.moveH(-1, "group"); }, - goWordRight: function (cm) { return cm.moveH(1, "word"); }, - delCharBefore: function (cm) { return cm.deleteH(-1, "codepoint"); }, - delCharAfter: function (cm) { return cm.deleteH(1, "char"); }, - delWordBefore: function (cm) { return cm.deleteH(-1, "word"); }, - delWordAfter: function (cm) { return cm.deleteH(1, "word"); }, - delGroupBefore: function (cm) { return cm.deleteH(-1, "group"); }, - delGroupAfter: function (cm) { return cm.deleteH(1, "group"); }, - indentAuto: function (cm) { return cm.indentSelection("smart"); }, - indentMore: function (cm) { return cm.indentSelection("add"); }, - indentLess: function (cm) { return cm.indentSelection("subtract"); }, - insertTab: function (cm) { return cm.replaceSelection("\t"); }, - insertSoftTab: function (cm) { - var spaces = [], ranges = cm.listSelections(), tabSize = cm.options.tabSize; - for (var i = 0; i < ranges.length; i++) { - var pos = ranges[i].from(); - var col = countColumn(cm.getLine(pos.line), pos.ch, tabSize); - spaces.push(spaceStr(tabSize - col % tabSize)); - } - cm.replaceSelections(spaces); - }, - defaultTab: function (cm) { - if (cm.somethingSelected()) { cm.indentSelection("add"); } - else { cm.execCommand("insertTab"); } - }, - // Swap the two chars left and right of each selection's head. - // Move cursor behind the two swapped characters afterwards. - // - // Doesn't consider line feeds a character. - // Doesn't scan more than one line above to find a character. - // Doesn't do anything on an empty line. - // Doesn't do anything with non-empty selections. - transposeChars: function (cm) { return runInOp(cm, function () { - var ranges = cm.listSelections(), newSel = []; - for (var i = 0; i < ranges.length; i++) { - if (!ranges[i].empty()) { continue } - var cur = ranges[i].head, line = getLine(cm.doc, cur.line).text; - if (line) { - if (cur.ch == line.length) { cur = new Pos(cur.line, cur.ch - 1); } - if (cur.ch > 0) { - cur = new Pos(cur.line, cur.ch + 1); - cm.replaceRange(line.charAt(cur.ch - 1) + line.charAt(cur.ch - 2), - Pos(cur.line, cur.ch - 2), cur, "+transpose"); - } else if (cur.line > cm.doc.first) { - var prev = getLine(cm.doc, cur.line - 1).text; - if (prev) { - cur = new Pos(cur.line, 1); - cm.replaceRange(line.charAt(0) + cm.doc.lineSeparator() + - prev.charAt(prev.length - 1), - Pos(cur.line - 1, prev.length - 1), cur, "+transpose"); - } - } - } - newSel.push(new Range(cur, cur)); - } - cm.setSelections(newSel); - }); }, - newlineAndIndent: function (cm) { return runInOp(cm, function () { - var sels = cm.listSelections(); - for (var i = sels.length - 1; i >= 0; i--) - { cm.replaceRange(cm.doc.lineSeparator(), sels[i].anchor, sels[i].head, "+input"); } - sels = cm.listSelections(); - for (var i$1 = 0; i$1 < sels.length; i$1++) - { cm.indentLine(sels[i$1].from().line, null, true); } - ensureCursorVisible(cm); - }); }, - openLine: function (cm) { return cm.replaceSelection("\n", "start"); }, - toggleOverwrite: function (cm) { return cm.toggleOverwrite(); } - }; - - - function lineStart(cm, lineN) { - var line = getLine(cm.doc, lineN); - var visual = visualLine(line); - if (visual != line) { lineN = lineNo(visual); } - return endOfLine(true, cm, visual, lineN, 1) - } - function lineEnd(cm, lineN) { - var line = getLine(cm.doc, lineN); - var visual = visualLineEnd(line); - if (visual != line) { lineN = lineNo(visual); } - return endOfLine(true, cm, line, lineN, -1) - } - function lineStartSmart(cm, pos) { - var start = lineStart(cm, pos.line); - var line = getLine(cm.doc, start.line); - var order = getOrder(line, cm.doc.direction); - if (!order || order[0].level == 0) { - var firstNonWS = Math.max(start.ch, line.text.search(/\S/)); - var inWS = pos.line == start.line && pos.ch <= firstNonWS && pos.ch; - return Pos(start.line, inWS ? 0 : firstNonWS, start.sticky) - } - return start - } - - // Run a handler that was bound to a key. - function doHandleBinding(cm, bound, dropShift) { - if (typeof bound == "string") { - bound = commands[bound]; - if (!bound) { return false } - } - // Ensure previous input has been read, so that the handler sees a - // consistent view of the document - cm.display.input.ensurePolled(); - var prevShift = cm.display.shift, done = false; - try { - if (cm.isReadOnly()) { cm.state.suppressEdits = true; } - if (dropShift) { cm.display.shift = false; } - done = bound(cm) != Pass; - } finally { - cm.display.shift = prevShift; - cm.state.suppressEdits = false; - } - return done - } - - function lookupKeyForEditor(cm, name, handle) { - for (var i = 0; i < cm.state.keyMaps.length; i++) { - var result = lookupKey(name, cm.state.keyMaps[i], handle, cm); - if (result) { return result } - } - return (cm.options.extraKeys && lookupKey(name, cm.options.extraKeys, handle, cm)) - || lookupKey(name, cm.options.keyMap, handle, cm) - } - - // Note that, despite the name, this function is also used to check - // for bound mouse clicks. - - var stopSeq = new Delayed; - - function dispatchKey(cm, name, e, handle) { - var seq = cm.state.keySeq; - if (seq) { - if (isModifierKey(name)) { return "handled" } - if (/\'$/.test(name)) - { cm.state.keySeq = null; } - else - { stopSeq.set(50, function () { - if (cm.state.keySeq == seq) { - cm.state.keySeq = null; - cm.display.input.reset(); - } - }); } - if (dispatchKeyInner(cm, seq + " " + name, e, handle)) { return true } - } - return dispatchKeyInner(cm, name, e, handle) - } - - function dispatchKeyInner(cm, name, e, handle) { - var result = lookupKeyForEditor(cm, name, handle); - - if (result == "multi") - { cm.state.keySeq = name; } - if (result == "handled") - { signalLater(cm, "keyHandled", cm, name, e); } - - if (result == "handled" || result == "multi") { - e_preventDefault(e); - restartBlink(cm); - } - - return !!result - } - - // Handle a key from the keydown event. - function handleKeyBinding(cm, e) { - var name = keyName(e, true); - if (!name) { return false } - - if (e.shiftKey && !cm.state.keySeq) { - // First try to resolve full name (including 'Shift-'). Failing - // that, see if there is a cursor-motion command (starting with - // 'go') bound to the keyname without 'Shift-'. - return dispatchKey(cm, "Shift-" + name, e, function (b) { return doHandleBinding(cm, b, true); }) - || dispatchKey(cm, name, e, function (b) { - if (typeof b == "string" ? /^go[A-Z]/.test(b) : b.motion) - { return doHandleBinding(cm, b) } - }) - } else { - return dispatchKey(cm, name, e, function (b) { return doHandleBinding(cm, b); }) - } - } - - // Handle a key from the keypress event - function handleCharBinding(cm, e, ch) { - return dispatchKey(cm, "'" + ch + "'", e, function (b) { return doHandleBinding(cm, b, true); }) - } - - var lastStoppedKey = null; - function onKeyDown(e) { - var cm = this; - if (e.target && e.target != cm.display.input.getField()) { return } - cm.curOp.focus = activeElt(); - if (signalDOMEvent(cm, e)) { return } - // IE does strange things with escape. - if (ie && ie_version < 11 && e.keyCode == 27) { e.returnValue = false; } - var code = e.keyCode; - cm.display.shift = code == 16 || e.shiftKey; - var handled = handleKeyBinding(cm, e); - if (presto) { - lastStoppedKey = handled ? code : null; - // Opera has no cut event... we try to at least catch the key combo - if (!handled && code == 88 && !hasCopyEvent && (mac ? e.metaKey : e.ctrlKey)) - { cm.replaceSelection("", null, "cut"); } - } - if (gecko && !mac && !handled && code == 46 && e.shiftKey && !e.ctrlKey && document.execCommand) - { document.execCommand("cut"); } - - // Turn mouse into crosshair when Alt is held on Mac. - if (code == 18 && !/\bCodeMirror-crosshair\b/.test(cm.display.lineDiv.className)) - { showCrossHair(cm); } - } - - function showCrossHair(cm) { - var lineDiv = cm.display.lineDiv; - addClass(lineDiv, "CodeMirror-crosshair"); - - function up(e) { - if (e.keyCode == 18 || !e.altKey) { - rmClass(lineDiv, "CodeMirror-crosshair"); - off(document, "keyup", up); - off(document, "mouseover", up); - } - } - on(document, "keyup", up); - on(document, "mouseover", up); - } - - function onKeyUp(e) { - if (e.keyCode == 16) { this.doc.sel.shift = false; } - signalDOMEvent(this, e); - } - - function onKeyPress(e) { - var cm = this; - if (e.target && e.target != cm.display.input.getField()) { return } - if (eventInWidget(cm.display, e) || signalDOMEvent(cm, e) || e.ctrlKey && !e.altKey || mac && e.metaKey) { return } - var keyCode = e.keyCode, charCode = e.charCode; - if (presto && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return} - if ((presto && (!e.which || e.which < 10)) && handleKeyBinding(cm, e)) { return } - var ch = String.fromCharCode(charCode == null ? keyCode : charCode); - // Some browsers fire keypress events for backspace - if (ch == "\x08") { return } - if (handleCharBinding(cm, e, ch)) { return } - cm.display.input.onKeyPress(e); - } - - var DOUBLECLICK_DELAY = 400; - - var PastClick = function(time, pos, button) { - this.time = time; - this.pos = pos; - this.button = button; - }; - - PastClick.prototype.compare = function (time, pos, button) { - return this.time + DOUBLECLICK_DELAY > time && - cmp(pos, this.pos) == 0 && button == this.button - }; - - var lastClick, lastDoubleClick; - function clickRepeat(pos, button) { - var now = +new Date; - if (lastDoubleClick && lastDoubleClick.compare(now, pos, button)) { - lastClick = lastDoubleClick = null; - return "triple" - } else if (lastClick && lastClick.compare(now, pos, button)) { - lastDoubleClick = new PastClick(now, pos, button); - lastClick = null; - return "double" - } else { - lastClick = new PastClick(now, pos, button); - lastDoubleClick = null; - return "single" - } - } - - // A mouse down can be a single click, double click, triple click, - // start of selection drag, start of text drag, new cursor - // (ctrl-click), rectangle drag (alt-drag), or xwin - // middle-click-paste. Or it might be a click on something we should - // not interfere with, such as a scrollbar or widget. - function onMouseDown(e) { - var cm = this, display = cm.display; - if (signalDOMEvent(cm, e) || display.activeTouch && display.input.supportsTouch()) { return } - display.input.ensurePolled(); - display.shift = e.shiftKey; - - if (eventInWidget(display, e)) { - if (!webkit) { - // Briefly turn off draggability, to allow widgets to do - // normal dragging things. - display.scroller.draggable = false; - setTimeout(function () { return display.scroller.draggable = true; }, 100); - } - return - } - if (clickInGutter(cm, e)) { return } - var pos = posFromMouse(cm, e), button = e_button(e), repeat = pos ? clickRepeat(pos, button) : "single"; - window.focus(); - - // #3261: make sure, that we're not starting a second selection - if (button == 1 && cm.state.selectingText) - { cm.state.selectingText(e); } - - if (pos && handleMappedButton(cm, button, pos, repeat, e)) { return } - - if (button == 1) { - if (pos) { leftButtonDown(cm, pos, repeat, e); } - else if (e_target(e) == display.scroller) { e_preventDefault(e); } - } else if (button == 2) { - if (pos) { extendSelection(cm.doc, pos); } - setTimeout(function () { return display.input.focus(); }, 20); - } else if (button == 3) { - if (captureRightClick) { cm.display.input.onContextMenu(e); } - else { delayBlurEvent(cm); } - } - } - - function handleMappedButton(cm, button, pos, repeat, event) { - var name = "Click"; - if (repeat == "double") { name = "Double" + name; } - else if (repeat == "triple") { name = "Triple" + name; } - name = (button == 1 ? "Left" : button == 2 ? "Middle" : "Right") + name; - - return dispatchKey(cm, addModifierNames(name, event), event, function (bound) { - if (typeof bound == "string") { bound = commands[bound]; } - if (!bound) { return false } - var done = false; - try { - if (cm.isReadOnly()) { cm.state.suppressEdits = true; } - done = bound(cm, pos) != Pass; - } finally { - cm.state.suppressEdits = false; - } - return done - }) - } - - function configureMouse(cm, repeat, event) { - var option = cm.getOption("configureMouse"); - var value = option ? option(cm, repeat, event) : {}; - if (value.unit == null) { - var rect = chromeOS ? event.shiftKey && event.metaKey : event.altKey; - value.unit = rect ? "rectangle" : repeat == "single" ? "char" : repeat == "double" ? "word" : "line"; - } - if (value.extend == null || cm.doc.extend) { value.extend = cm.doc.extend || event.shiftKey; } - if (value.addNew == null) { value.addNew = mac ? event.metaKey : event.ctrlKey; } - if (value.moveOnDrag == null) { value.moveOnDrag = !(mac ? event.altKey : event.ctrlKey); } - return value - } - - function leftButtonDown(cm, pos, repeat, event) { - if (ie) { setTimeout(bind(ensureFocus, cm), 0); } - else { cm.curOp.focus = activeElt(); } - - var behavior = configureMouse(cm, repeat, event); - - var sel = cm.doc.sel, contained; - if (cm.options.dragDrop && dragAndDrop && !cm.isReadOnly() && - repeat == "single" && (contained = sel.contains(pos)) > -1 && - (cmp((contained = sel.ranges[contained]).from(), pos) < 0 || pos.xRel > 0) && - (cmp(contained.to(), pos) > 0 || pos.xRel < 0)) - { leftButtonStartDrag(cm, event, pos, behavior); } - else - { leftButtonSelect(cm, event, pos, behavior); } - } - - // Start a text drag. When it ends, see if any dragging actually - // happen, and treat as a click if it didn't. - function leftButtonStartDrag(cm, event, pos, behavior) { - var display = cm.display, moved = false; - var dragEnd = operation(cm, function (e) { - if (webkit) { display.scroller.draggable = false; } - cm.state.draggingText = false; - if (cm.state.delayingBlurEvent) { - if (cm.hasFocus()) { cm.state.delayingBlurEvent = false; } - else { delayBlurEvent(cm); } - } - off(display.wrapper.ownerDocument, "mouseup", dragEnd); - off(display.wrapper.ownerDocument, "mousemove", mouseMove); - off(display.scroller, "dragstart", dragStart); - off(display.scroller, "drop", dragEnd); - if (!moved) { - e_preventDefault(e); - if (!behavior.addNew) - { extendSelection(cm.doc, pos, null, null, behavior.extend); } - // Work around unexplainable focus problem in IE9 (#2127) and Chrome (#3081) - if ((webkit && !safari) || ie && ie_version == 9) - { setTimeout(function () {display.wrapper.ownerDocument.body.focus({preventScroll: true}); display.input.focus();}, 20); } - else - { display.input.focus(); } - } - }); - var mouseMove = function(e2) { - moved = moved || Math.abs(event.clientX - e2.clientX) + Math.abs(event.clientY - e2.clientY) >= 10; - }; - var dragStart = function () { return moved = true; }; - // Let the drag handler handle this. - if (webkit) { display.scroller.draggable = true; } - cm.state.draggingText = dragEnd; - dragEnd.copy = !behavior.moveOnDrag; - on(display.wrapper.ownerDocument, "mouseup", dragEnd); - on(display.wrapper.ownerDocument, "mousemove", mouseMove); - on(display.scroller, "dragstart", dragStart); - on(display.scroller, "drop", dragEnd); - - cm.state.delayingBlurEvent = true; - setTimeout(function () { return display.input.focus(); }, 20); - // IE's approach to draggable - if (display.scroller.dragDrop) { display.scroller.dragDrop(); } - } - - function rangeForUnit(cm, pos, unit) { - if (unit == "char") { return new Range(pos, pos) } - if (unit == "word") { return cm.findWordAt(pos) } - if (unit == "line") { return new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))) } - var result = unit(cm, pos); - return new Range(result.from, result.to) - } - - // Normal selection, as opposed to text dragging. - function leftButtonSelect(cm, event, start, behavior) { - if (ie) { delayBlurEvent(cm); } - var display = cm.display, doc = cm.doc; - e_preventDefault(event); - - var ourRange, ourIndex, startSel = doc.sel, ranges = startSel.ranges; - if (behavior.addNew && !behavior.extend) { - ourIndex = doc.sel.contains(start); - if (ourIndex > -1) - { ourRange = ranges[ourIndex]; } - else - { ourRange = new Range(start, start); } - } else { - ourRange = doc.sel.primary(); - ourIndex = doc.sel.primIndex; - } - - if (behavior.unit == "rectangle") { - if (!behavior.addNew) { ourRange = new Range(start, start); } - start = posFromMouse(cm, event, true, true); - ourIndex = -1; - } else { - var range = rangeForUnit(cm, start, behavior.unit); - if (behavior.extend) - { ourRange = extendRange(ourRange, range.anchor, range.head, behavior.extend); } - else - { ourRange = range; } - } - - if (!behavior.addNew) { - ourIndex = 0; - setSelection(doc, new Selection([ourRange], 0), sel_mouse); - startSel = doc.sel; - } else if (ourIndex == -1) { - ourIndex = ranges.length; - setSelection(doc, normalizeSelection(cm, ranges.concat([ourRange]), ourIndex), - {scroll: false, origin: "*mouse"}); - } else if (ranges.length > 1 && ranges[ourIndex].empty() && behavior.unit == "char" && !behavior.extend) { - setSelection(doc, normalizeSelection(cm, ranges.slice(0, ourIndex).concat(ranges.slice(ourIndex + 1)), 0), - {scroll: false, origin: "*mouse"}); - startSel = doc.sel; - } else { - replaceOneSelection(doc, ourIndex, ourRange, sel_mouse); - } - - var lastPos = start; - function extendTo(pos) { - if (cmp(lastPos, pos) == 0) { return } - lastPos = pos; - - if (behavior.unit == "rectangle") { - var ranges = [], tabSize = cm.options.tabSize; - var startCol = countColumn(getLine(doc, start.line).text, start.ch, tabSize); - var posCol = countColumn(getLine(doc, pos.line).text, pos.ch, tabSize); - var left = Math.min(startCol, posCol), right = Math.max(startCol, posCol); - for (var line = Math.min(start.line, pos.line), end = Math.min(cm.lastLine(), Math.max(start.line, pos.line)); - line <= end; line++) { - var text = getLine(doc, line).text, leftPos = findColumn(text, left, tabSize); - if (left == right) - { ranges.push(new Range(Pos(line, leftPos), Pos(line, leftPos))); } - else if (text.length > leftPos) - { ranges.push(new Range(Pos(line, leftPos), Pos(line, findColumn(text, right, tabSize)))); } - } - if (!ranges.length) { ranges.push(new Range(start, start)); } - setSelection(doc, normalizeSelection(cm, startSel.ranges.slice(0, ourIndex).concat(ranges), ourIndex), - {origin: "*mouse", scroll: false}); - cm.scrollIntoView(pos); - } else { - var oldRange = ourRange; - var range = rangeForUnit(cm, pos, behavior.unit); - var anchor = oldRange.anchor, head; - if (cmp(range.anchor, anchor) > 0) { - head = range.head; - anchor = minPos(oldRange.from(), range.anchor); - } else { - head = range.anchor; - anchor = maxPos(oldRange.to(), range.head); - } - var ranges$1 = startSel.ranges.slice(0); - ranges$1[ourIndex] = bidiSimplify(cm, new Range(clipPos(doc, anchor), head)); - setSelection(doc, normalizeSelection(cm, ranges$1, ourIndex), sel_mouse); - } - } - - var editorSize = display.wrapper.getBoundingClientRect(); - // Used to ensure timeout re-tries don't fire when another extend - // happened in the meantime (clearTimeout isn't reliable -- at - // least on Chrome, the timeouts still happen even when cleared, - // if the clear happens after their scheduled firing time). - var counter = 0; - - function extend(e) { - var curCount = ++counter; - var cur = posFromMouse(cm, e, true, behavior.unit == "rectangle"); - if (!cur) { return } - if (cmp(cur, lastPos) != 0) { - cm.curOp.focus = activeElt(); - extendTo(cur); - var visible = visibleLines(display, doc); - if (cur.line >= visible.to || cur.line < visible.from) - { setTimeout(operation(cm, function () {if (counter == curCount) { extend(e); }}), 150); } - } else { - var outside = e.clientY < editorSize.top ? -20 : e.clientY > editorSize.bottom ? 20 : 0; - if (outside) { setTimeout(operation(cm, function () { - if (counter != curCount) { return } - display.scroller.scrollTop += outside; - extend(e); - }), 50); } - } - } - - function done(e) { - cm.state.selectingText = false; - counter = Infinity; - // If e is null or undefined we interpret this as someone trying - // to explicitly cancel the selection rather than the user - // letting go of the mouse button. - if (e) { - e_preventDefault(e); - display.input.focus(); - } - off(display.wrapper.ownerDocument, "mousemove", move); - off(display.wrapper.ownerDocument, "mouseup", up); - doc.history.lastSelOrigin = null; - } - - var move = operation(cm, function (e) { - if (e.buttons === 0 || !e_button(e)) { done(e); } - else { extend(e); } - }); - var up = operation(cm, done); - cm.state.selectingText = up; - on(display.wrapper.ownerDocument, "mousemove", move); - on(display.wrapper.ownerDocument, "mouseup", up); - } - - // Used when mouse-selecting to adjust the anchor to the proper side - // of a bidi jump depending on the visual position of the head. - function bidiSimplify(cm, range) { - var anchor = range.anchor; - var head = range.head; - var anchorLine = getLine(cm.doc, anchor.line); - if (cmp(anchor, head) == 0 && anchor.sticky == head.sticky) { return range } - var order = getOrder(anchorLine); - if (!order) { return range } - var index = getBidiPartAt(order, anchor.ch, anchor.sticky), part = order[index]; - if (part.from != anchor.ch && part.to != anchor.ch) { return range } - var boundary = index + ((part.from == anchor.ch) == (part.level != 1) ? 0 : 1); - if (boundary == 0 || boundary == order.length) { return range } - - // Compute the relative visual position of the head compared to the - // anchor (<0 is to the left, >0 to the right) - var leftSide; - if (head.line != anchor.line) { - leftSide = (head.line - anchor.line) * (cm.doc.direction == "ltr" ? 1 : -1) > 0; - } else { - var headIndex = getBidiPartAt(order, head.ch, head.sticky); - var dir = headIndex - index || (head.ch - anchor.ch) * (part.level == 1 ? -1 : 1); - if (headIndex == boundary - 1 || headIndex == boundary) - { leftSide = dir < 0; } - else - { leftSide = dir > 0; } - } - - var usePart = order[boundary + (leftSide ? -1 : 0)]; - var from = leftSide == (usePart.level == 1); - var ch = from ? usePart.from : usePart.to, sticky = from ? "after" : "before"; - return anchor.ch == ch && anchor.sticky == sticky ? range : new Range(new Pos(anchor.line, ch, sticky), head) - } - - - // Determines whether an event happened in the gutter, and fires the - // handlers for the corresponding event. - function gutterEvent(cm, e, type, prevent) { - var mX, mY; - if (e.touches) { - mX = e.touches[0].clientX; - mY = e.touches[0].clientY; - } else { - try { mX = e.clientX; mY = e.clientY; } - catch(e$1) { return false } - } - if (mX >= Math.floor(cm.display.gutters.getBoundingClientRect().right)) { return false } - if (prevent) { e_preventDefault(e); } - - var display = cm.display; - var lineBox = display.lineDiv.getBoundingClientRect(); - - if (mY > lineBox.bottom || !hasHandler(cm, type)) { return e_defaultPrevented(e) } - mY -= lineBox.top - display.viewOffset; - - for (var i = 0; i < cm.display.gutterSpecs.length; ++i) { - var g = display.gutters.childNodes[i]; - if (g && g.getBoundingClientRect().right >= mX) { - var line = lineAtHeight(cm.doc, mY); - var gutter = cm.display.gutterSpecs[i]; - signal(cm, type, cm, line, gutter.className, e); - return e_defaultPrevented(e) - } - } - } - - function clickInGutter(cm, e) { - return gutterEvent(cm, e, "gutterClick", true) - } - - // CONTEXT MENU HANDLING - - // To make the context menu work, we need to briefly unhide the - // textarea (making it as unobtrusive as possible) to let the - // right-click take effect on it. - function onContextMenu(cm, e) { - if (eventInWidget(cm.display, e) || contextMenuInGutter(cm, e)) { return } - if (signalDOMEvent(cm, e, "contextmenu")) { return } - if (!captureRightClick) { cm.display.input.onContextMenu(e); } - } - - function contextMenuInGutter(cm, e) { - if (!hasHandler(cm, "gutterContextMenu")) { return false } - return gutterEvent(cm, e, "gutterContextMenu", false) - } - - function themeChanged(cm) { - cm.display.wrapper.className = cm.display.wrapper.className.replace(/\s*cm-s-\S+/g, "") + - cm.options.theme.replace(/(^|\s)\s*/g, " cm-s-"); - clearCaches(cm); - } - - var Init = {toString: function(){return "CodeMirror.Init"}}; - - var defaults = {}; - var optionHandlers = {}; - - function defineOptions(CodeMirror) { - var optionHandlers = CodeMirror.optionHandlers; - - function option(name, deflt, handle, notOnInit) { - CodeMirror.defaults[name] = deflt; - if (handle) { optionHandlers[name] = - notOnInit ? function (cm, val, old) {if (old != Init) { handle(cm, val, old); }} : handle; } - } - - CodeMirror.defineOption = option; - - // Passed to option handlers when there is no old value. - CodeMirror.Init = Init; - - // These two are, on init, called from the constructor because they - // have to be initialized before the editor can start at all. - option("value", "", function (cm, val) { return cm.setValue(val); }, true); - option("mode", null, function (cm, val) { - cm.doc.modeOption = val; - loadMode(cm); - }, true); - - option("indentUnit", 2, loadMode, true); - option("indentWithTabs", false); - option("smartIndent", true); - option("tabSize", 4, function (cm) { - resetModeState(cm); - clearCaches(cm); - regChange(cm); - }, true); - - option("lineSeparator", null, function (cm, val) { - cm.doc.lineSep = val; - if (!val) { return } - var newBreaks = [], lineNo = cm.doc.first; - cm.doc.iter(function (line) { - for (var pos = 0;;) { - var found = line.text.indexOf(val, pos); - if (found == -1) { break } - pos = found + val.length; - newBreaks.push(Pos(lineNo, found)); - } - lineNo++; - }); - for (var i = newBreaks.length - 1; i >= 0; i--) - { replaceRange(cm.doc, val, newBreaks[i], Pos(newBreaks[i].line, newBreaks[i].ch + val.length)); } - }); - option("specialChars", /[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g, function (cm, val, old) { - cm.state.specialChars = new RegExp(val.source + (val.test("\t") ? "" : "|\t"), "g"); - if (old != Init) { cm.refresh(); } - }); - option("specialCharPlaceholder", defaultSpecialCharPlaceholder, function (cm) { return cm.refresh(); }, true); - option("electricChars", true); - option("inputStyle", mobile ? "contenteditable" : "textarea", function () { - throw new Error("inputStyle can not (yet) be changed in a running editor") // FIXME - }, true); - option("spellcheck", false, function (cm, val) { return cm.getInputField().spellcheck = val; }, true); - option("autocorrect", false, function (cm, val) { return cm.getInputField().autocorrect = val; }, true); - option("autocapitalize", false, function (cm, val) { return cm.getInputField().autocapitalize = val; }, true); - option("rtlMoveVisually", !windows); - option("wholeLineUpdateBefore", true); - - option("theme", "default", function (cm) { - themeChanged(cm); - updateGutters(cm); - }, true); - option("keyMap", "default", function (cm, val, old) { - var next = getKeyMap(val); - var prev = old != Init && getKeyMap(old); - if (prev && prev.detach) { prev.detach(cm, next); } - if (next.attach) { next.attach(cm, prev || null); } - }); - option("extraKeys", null); - option("configureMouse", null); - - option("lineWrapping", false, wrappingChanged, true); - option("gutters", [], function (cm, val) { - cm.display.gutterSpecs = getGutters(val, cm.options.lineNumbers); - updateGutters(cm); - }, true); - option("fixedGutter", true, function (cm, val) { - cm.display.gutters.style.left = val ? compensateForHScroll(cm.display) + "px" : "0"; - cm.refresh(); - }, true); - option("coverGutterNextToScrollbar", false, function (cm) { return updateScrollbars(cm); }, true); - option("scrollbarStyle", "native", function (cm) { - initScrollbars(cm); - updateScrollbars(cm); - cm.display.scrollbars.setScrollTop(cm.doc.scrollTop); - cm.display.scrollbars.setScrollLeft(cm.doc.scrollLeft); - }, true); - option("lineNumbers", false, function (cm, val) { - cm.display.gutterSpecs = getGutters(cm.options.gutters, val); - updateGutters(cm); - }, true); - option("firstLineNumber", 1, updateGutters, true); - option("lineNumberFormatter", function (integer) { return integer; }, updateGutters, true); - option("showCursorWhenSelecting", false, updateSelection, true); - - option("resetSelectionOnContextMenu", true); - option("lineWiseCopyCut", true); - option("pasteLinesPerSelection", true); - option("selectionsMayTouch", false); - - option("readOnly", false, function (cm, val) { - if (val == "nocursor") { - onBlur(cm); - cm.display.input.blur(); - } - cm.display.input.readOnlyChanged(val); - }); - - option("screenReaderLabel", null, function (cm, val) { - val = (val === '') ? null : val; - cm.display.input.screenReaderLabelChanged(val); - }); - - option("disableInput", false, function (cm, val) {if (!val) { cm.display.input.reset(); }}, true); - option("dragDrop", true, dragDropChanged); - option("allowDropFileTypes", null); - - option("cursorBlinkRate", 530); - option("cursorScrollMargin", 0); - option("cursorHeight", 1, updateSelection, true); - option("singleCursorHeightPerLine", true, updateSelection, true); - option("workTime", 100); - option("workDelay", 100); - option("flattenSpans", true, resetModeState, true); - option("addModeClass", false, resetModeState, true); - option("pollInterval", 100); - option("undoDepth", 200, function (cm, val) { return cm.doc.history.undoDepth = val; }); - option("historyEventDelay", 1250); - option("viewportMargin", 10, function (cm) { return cm.refresh(); }, true); - option("maxHighlightLength", 10000, resetModeState, true); - option("moveInputWithCursor", true, function (cm, val) { - if (!val) { cm.display.input.resetPosition(); } - }); - - option("tabindex", null, function (cm, val) { return cm.display.input.getField().tabIndex = val || ""; }); - option("autofocus", null); - option("direction", "ltr", function (cm, val) { return cm.doc.setDirection(val); }, true); - option("phrases", null); - } - - function dragDropChanged(cm, value, old) { - var wasOn = old && old != Init; - if (!value != !wasOn) { - var funcs = cm.display.dragFunctions; - var toggle = value ? on : off; - toggle(cm.display.scroller, "dragstart", funcs.start); - toggle(cm.display.scroller, "dragenter", funcs.enter); - toggle(cm.display.scroller, "dragover", funcs.over); - toggle(cm.display.scroller, "dragleave", funcs.leave); - toggle(cm.display.scroller, "drop", funcs.drop); - } - } - - function wrappingChanged(cm) { - if (cm.options.lineWrapping) { - addClass(cm.display.wrapper, "CodeMirror-wrap"); - cm.display.sizer.style.minWidth = ""; - cm.display.sizerWidth = null; - } else { - rmClass(cm.display.wrapper, "CodeMirror-wrap"); - findMaxLine(cm); - } - estimateLineHeights(cm); - regChange(cm); - clearCaches(cm); - setTimeout(function () { return updateScrollbars(cm); }, 100); - } - - // A CodeMirror instance represents an editor. This is the object - // that user code is usually dealing with. - - function CodeMirror(place, options) { - var this$1 = this; - - if (!(this instanceof CodeMirror)) { return new CodeMirror(place, options) } - - this.options = options = options ? copyObj(options) : {}; - // Determine effective options based on given values and defaults. - copyObj(defaults, options, false); - - var doc = options.value; - if (typeof doc == "string") { doc = new Doc(doc, options.mode, null, options.lineSeparator, options.direction); } - else if (options.mode) { doc.modeOption = options.mode; } - this.doc = doc; - - var input = new CodeMirror.inputStyles[options.inputStyle](this); - var display = this.display = new Display(place, doc, input, options); - display.wrapper.CodeMirror = this; - themeChanged(this); - if (options.lineWrapping) - { this.display.wrapper.className += " CodeMirror-wrap"; } - initScrollbars(this); - - this.state = { - keyMaps: [], // stores maps added by addKeyMap - overlays: [], // highlighting overlays, as added by addOverlay - modeGen: 0, // bumped when mode/overlay changes, used to invalidate highlighting info - overwrite: false, - delayingBlurEvent: false, - focused: false, - suppressEdits: false, // used to disable editing during key handlers when in readOnly mode - pasteIncoming: -1, cutIncoming: -1, // help recognize paste/cut edits in input.poll - selectingText: false, - draggingText: false, - highlight: new Delayed(), // stores highlight worker timeout - keySeq: null, // Unfinished key sequence - specialChars: null - }; - - if (options.autofocus && !mobile) { display.input.focus(); } - - // Override magic textarea content restore that IE sometimes does - // on our hidden textarea on reload - if (ie && ie_version < 11) { setTimeout(function () { return this$1.display.input.reset(true); }, 20); } - - registerEventHandlers(this); - ensureGlobalHandlers(); - - startOperation(this); - this.curOp.forceUpdate = true; - attachDoc(this, doc); - - if ((options.autofocus && !mobile) || this.hasFocus()) - { setTimeout(function () { - if (this$1.hasFocus() && !this$1.state.focused) { onFocus(this$1); } - }, 20); } - else - { onBlur(this); } - - for (var opt in optionHandlers) { if (optionHandlers.hasOwnProperty(opt)) - { optionHandlers[opt](this, options[opt], Init); } } - maybeUpdateLineNumberWidth(this); - if (options.finishInit) { options.finishInit(this); } - for (var i = 0; i < initHooks.length; ++i) { initHooks[i](this); } - endOperation(this); - // Suppress optimizelegibility in Webkit, since it breaks text - // measuring on line wrapping boundaries. - if (webkit && options.lineWrapping && - getComputedStyle(display.lineDiv).textRendering == "optimizelegibility") - { display.lineDiv.style.textRendering = "auto"; } - } - - // The default configuration options. - CodeMirror.defaults = defaults; - // Functions to run when options are changed. - CodeMirror.optionHandlers = optionHandlers; - - // Attach the necessary event handlers when initializing the editor - function registerEventHandlers(cm) { - var d = cm.display; - on(d.scroller, "mousedown", operation(cm, onMouseDown)); - // Older IE's will not fire a second mousedown for a double click - if (ie && ie_version < 11) - { on(d.scroller, "dblclick", operation(cm, function (e) { - if (signalDOMEvent(cm, e)) { return } - var pos = posFromMouse(cm, e); - if (!pos || clickInGutter(cm, e) || eventInWidget(cm.display, e)) { return } - e_preventDefault(e); - var word = cm.findWordAt(pos); - extendSelection(cm.doc, word.anchor, word.head); - })); } - else - { on(d.scroller, "dblclick", function (e) { return signalDOMEvent(cm, e) || e_preventDefault(e); }); } - // Some browsers fire contextmenu *after* opening the menu, at - // which point we can't mess with it anymore. Context menu is - // handled in onMouseDown for these browsers. - on(d.scroller, "contextmenu", function (e) { return onContextMenu(cm, e); }); - on(d.input.getField(), "contextmenu", function (e) { - if (!d.scroller.contains(e.target)) { onContextMenu(cm, e); } - }); - - // Used to suppress mouse event handling when a touch happens - var touchFinished, prevTouch = {end: 0}; - function finishTouch() { - if (d.activeTouch) { - touchFinished = setTimeout(function () { return d.activeTouch = null; }, 1000); - prevTouch = d.activeTouch; - prevTouch.end = +new Date; - } - } - function isMouseLikeTouchEvent(e) { - if (e.touches.length != 1) { return false } - var touch = e.touches[0]; - return touch.radiusX <= 1 && touch.radiusY <= 1 - } - function farAway(touch, other) { - if (other.left == null) { return true } - var dx = other.left - touch.left, dy = other.top - touch.top; - return dx * dx + dy * dy > 20 * 20 - } - on(d.scroller, "touchstart", function (e) { - if (!signalDOMEvent(cm, e) && !isMouseLikeTouchEvent(e) && !clickInGutter(cm, e)) { - d.input.ensurePolled(); - clearTimeout(touchFinished); - var now = +new Date; - d.activeTouch = {start: now, moved: false, - prev: now - prevTouch.end <= 300 ? prevTouch : null}; - if (e.touches.length == 1) { - d.activeTouch.left = e.touches[0].pageX; - d.activeTouch.top = e.touches[0].pageY; - } - } - }); - on(d.scroller, "touchmove", function () { - if (d.activeTouch) { d.activeTouch.moved = true; } - }); - on(d.scroller, "touchend", function (e) { - var touch = d.activeTouch; - if (touch && !eventInWidget(d, e) && touch.left != null && - !touch.moved && new Date - touch.start < 300) { - var pos = cm.coordsChar(d.activeTouch, "page"), range; - if (!touch.prev || farAway(touch, touch.prev)) // Single tap - { range = new Range(pos, pos); } - else if (!touch.prev.prev || farAway(touch, touch.prev.prev)) // Double tap - { range = cm.findWordAt(pos); } - else // Triple tap - { range = new Range(Pos(pos.line, 0), clipPos(cm.doc, Pos(pos.line + 1, 0))); } - cm.setSelection(range.anchor, range.head); - cm.focus(); - e_preventDefault(e); - } - finishTouch(); - }); - on(d.scroller, "touchcancel", finishTouch); - - // Sync scrolling between fake scrollbars and real scrollable - // area, ensure viewport is updated when scrolling. - on(d.scroller, "scroll", function () { - if (d.scroller.clientHeight) { - updateScrollTop(cm, d.scroller.scrollTop); - setScrollLeft(cm, d.scroller.scrollLeft, true); - signal(cm, "scroll", cm); - } - }); - - // Listen to wheel events in order to try and update the viewport on time. - on(d.scroller, "mousewheel", function (e) { return onScrollWheel(cm, e); }); - on(d.scroller, "DOMMouseScroll", function (e) { return onScrollWheel(cm, e); }); - - // Prevent wrapper from ever scrolling - on(d.wrapper, "scroll", function () { return d.wrapper.scrollTop = d.wrapper.scrollLeft = 0; }); - - d.dragFunctions = { - enter: function (e) {if (!signalDOMEvent(cm, e)) { e_stop(e); }}, - over: function (e) {if (!signalDOMEvent(cm, e)) { onDragOver(cm, e); e_stop(e); }}, - start: function (e) { return onDragStart(cm, e); }, - drop: operation(cm, onDrop), - leave: function (e) {if (!signalDOMEvent(cm, e)) { clearDragCursor(cm); }} - }; - - var inp = d.input.getField(); - on(inp, "keyup", function (e) { return onKeyUp.call(cm, e); }); - on(inp, "keydown", operation(cm, onKeyDown)); - on(inp, "keypress", operation(cm, onKeyPress)); - on(inp, "focus", function (e) { return onFocus(cm, e); }); - on(inp, "blur", function (e) { return onBlur(cm, e); }); - } - - var initHooks = []; - CodeMirror.defineInitHook = function (f) { return initHooks.push(f); }; - - // Indent the given line. The how parameter can be "smart", - // "add"/null, "subtract", or "prev". When aggressive is false - // (typically set to true for forced single-line indents), empty - // lines are not indented, and places where the mode returns Pass - // are left alone. - function indentLine(cm, n, how, aggressive) { - var doc = cm.doc, state; - if (how == null) { how = "add"; } - if (how == "smart") { - // Fall back to "prev" when the mode doesn't have an indentation - // method. - if (!doc.mode.indent) { how = "prev"; } - else { state = getContextBefore(cm, n).state; } - } - - var tabSize = cm.options.tabSize; - var line = getLine(doc, n), curSpace = countColumn(line.text, null, tabSize); - if (line.stateAfter) { line.stateAfter = null; } - var curSpaceString = line.text.match(/^\s*/)[0], indentation; - if (!aggressive && !/\S/.test(line.text)) { - indentation = 0; - how = "not"; - } else if (how == "smart") { - indentation = doc.mode.indent(state, line.text.slice(curSpaceString.length), line.text); - if (indentation == Pass || indentation > 150) { - if (!aggressive) { return } - how = "prev"; - } - } - if (how == "prev") { - if (n > doc.first) { indentation = countColumn(getLine(doc, n-1).text, null, tabSize); } - else { indentation = 0; } - } else if (how == "add") { - indentation = curSpace + cm.options.indentUnit; - } else if (how == "subtract") { - indentation = curSpace - cm.options.indentUnit; - } else if (typeof how == "number") { - indentation = curSpace + how; - } - indentation = Math.max(0, indentation); - - var indentString = "", pos = 0; - if (cm.options.indentWithTabs) - { for (var i = Math.floor(indentation / tabSize); i; --i) {pos += tabSize; indentString += "\t";} } - if (pos < indentation) { indentString += spaceStr(indentation - pos); } - - if (indentString != curSpaceString) { - replaceRange(doc, indentString, Pos(n, 0), Pos(n, curSpaceString.length), "+input"); - line.stateAfter = null; - return true - } else { - // Ensure that, if the cursor was in the whitespace at the start - // of the line, it is moved to the end of that space. - for (var i$1 = 0; i$1 < doc.sel.ranges.length; i$1++) { - var range = doc.sel.ranges[i$1]; - if (range.head.line == n && range.head.ch < curSpaceString.length) { - var pos$1 = Pos(n, curSpaceString.length); - replaceOneSelection(doc, i$1, new Range(pos$1, pos$1)); - break - } - } - } - } - - // This will be set to a {lineWise: bool, text: [string]} object, so - // that, when pasting, we know what kind of selections the copied - // text was made out of. - var lastCopied = null; - - function setLastCopied(newLastCopied) { - lastCopied = newLastCopied; - } - - function applyTextInput(cm, inserted, deleted, sel, origin) { - var doc = cm.doc; - cm.display.shift = false; - if (!sel) { sel = doc.sel; } - - var recent = +new Date - 200; - var paste = origin == "paste" || cm.state.pasteIncoming > recent; - var textLines = splitLinesAuto(inserted), multiPaste = null; - // When pasting N lines into N selections, insert one line per selection - if (paste && sel.ranges.length > 1) { - if (lastCopied && lastCopied.text.join("\n") == inserted) { - if (sel.ranges.length % lastCopied.text.length == 0) { - multiPaste = []; - for (var i = 0; i < lastCopied.text.length; i++) - { multiPaste.push(doc.splitLines(lastCopied.text[i])); } - } - } else if (textLines.length == sel.ranges.length && cm.options.pasteLinesPerSelection) { - multiPaste = map(textLines, function (l) { return [l]; }); - } - } - - var updateInput = cm.curOp.updateInput; - // Normal behavior is to insert the new text into every selection - for (var i$1 = sel.ranges.length - 1; i$1 >= 0; i$1--) { - var range = sel.ranges[i$1]; - var from = range.from(), to = range.to(); - if (range.empty()) { - if (deleted && deleted > 0) // Handle deletion - { from = Pos(from.line, from.ch - deleted); } - else if (cm.state.overwrite && !paste) // Handle overwrite - { to = Pos(to.line, Math.min(getLine(doc, to.line).text.length, to.ch + lst(textLines).length)); } - else if (paste && lastCopied && lastCopied.lineWise && lastCopied.text.join("\n") == textLines.join("\n")) - { from = to = Pos(from.line, 0); } - } - var changeEvent = {from: from, to: to, text: multiPaste ? multiPaste[i$1 % multiPaste.length] : textLines, - origin: origin || (paste ? "paste" : cm.state.cutIncoming > recent ? "cut" : "+input")}; - makeChange(cm.doc, changeEvent); - signalLater(cm, "inputRead", cm, changeEvent); - } - if (inserted && !paste) - { triggerElectric(cm, inserted); } - - ensureCursorVisible(cm); - if (cm.curOp.updateInput < 2) { cm.curOp.updateInput = updateInput; } - cm.curOp.typing = true; - cm.state.pasteIncoming = cm.state.cutIncoming = -1; - } - - function handlePaste(e, cm) { - var pasted = e.clipboardData && e.clipboardData.getData("Text"); - if (pasted) { - e.preventDefault(); - if (!cm.isReadOnly() && !cm.options.disableInput) - { runInOp(cm, function () { return applyTextInput(cm, pasted, 0, null, "paste"); }); } - return true - } - } - - function triggerElectric(cm, inserted) { - // When an 'electric' character is inserted, immediately trigger a reindent - if (!cm.options.electricChars || !cm.options.smartIndent) { return } - var sel = cm.doc.sel; - - for (var i = sel.ranges.length - 1; i >= 0; i--) { - var range = sel.ranges[i]; - if (range.head.ch > 100 || (i && sel.ranges[i - 1].head.line == range.head.line)) { continue } - var mode = cm.getModeAt(range.head); - var indented = false; - if (mode.electricChars) { - for (var j = 0; j < mode.electricChars.length; j++) - { if (inserted.indexOf(mode.electricChars.charAt(j)) > -1) { - indented = indentLine(cm, range.head.line, "smart"); - break - } } - } else if (mode.electricInput) { - if (mode.electricInput.test(getLine(cm.doc, range.head.line).text.slice(0, range.head.ch))) - { indented = indentLine(cm, range.head.line, "smart"); } - } - if (indented) { signalLater(cm, "electricInput", cm, range.head.line); } - } - } - - function copyableRanges(cm) { - var text = [], ranges = []; - for (var i = 0; i < cm.doc.sel.ranges.length; i++) { - var line = cm.doc.sel.ranges[i].head.line; - var lineRange = {anchor: Pos(line, 0), head: Pos(line + 1, 0)}; - ranges.push(lineRange); - text.push(cm.getRange(lineRange.anchor, lineRange.head)); - } - return {text: text, ranges: ranges} - } - - function disableBrowserMagic(field, spellcheck, autocorrect, autocapitalize) { - field.setAttribute("autocorrect", autocorrect ? "" : "off"); - field.setAttribute("autocapitalize", autocapitalize ? "" : "off"); - field.setAttribute("spellcheck", !!spellcheck); - } - - function hiddenTextarea() { - var te = elt("textarea", null, null, "position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"); - var div = elt("div", [te], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); - // The textarea is kept positioned near the cursor to prevent the - // fact that it'll be scrolled into view on input from scrolling - // our fake cursor out of view. On webkit, when wrap=off, paste is - // very slow. So make the area wide instead. - if (webkit) { te.style.width = "1000px"; } - else { te.setAttribute("wrap", "off"); } - // If border: 0; -- iOS fails to open keyboard (issue #1287) - if (ios) { te.style.border = "1px solid black"; } - disableBrowserMagic(te); - return div - } - - // The publicly visible API. Note that methodOp(f) means - // 'wrap f in an operation, performed on its `this` parameter'. - - // This is not the complete set of editor methods. Most of the - // methods defined on the Doc type are also injected into - // CodeMirror.prototype, for backwards compatibility and - // convenience. - - function addEditorMethods(CodeMirror) { - var optionHandlers = CodeMirror.optionHandlers; - - var helpers = CodeMirror.helpers = {}; - - CodeMirror.prototype = { - constructor: CodeMirror, - focus: function(){window.focus(); this.display.input.focus();}, - - setOption: function(option, value) { - var options = this.options, old = options[option]; - if (options[option] == value && option != "mode") { return } - options[option] = value; - if (optionHandlers.hasOwnProperty(option)) - { operation(this, optionHandlers[option])(this, value, old); } - signal(this, "optionChange", this, option); - }, - - getOption: function(option) {return this.options[option]}, - getDoc: function() {return this.doc}, - - addKeyMap: function(map, bottom) { - this.state.keyMaps[bottom ? "push" : "unshift"](getKeyMap(map)); - }, - removeKeyMap: function(map) { - var maps = this.state.keyMaps; - for (var i = 0; i < maps.length; ++i) - { if (maps[i] == map || maps[i].name == map) { - maps.splice(i, 1); - return true - } } - }, - - addOverlay: methodOp(function(spec, options) { - var mode = spec.token ? spec : CodeMirror.getMode(this.options, spec); - if (mode.startState) { throw new Error("Overlays may not be stateful.") } - insertSorted(this.state.overlays, - {mode: mode, modeSpec: spec, opaque: options && options.opaque, - priority: (options && options.priority) || 0}, - function (overlay) { return overlay.priority; }); - this.state.modeGen++; - regChange(this); - }), - removeOverlay: methodOp(function(spec) { - var overlays = this.state.overlays; - for (var i = 0; i < overlays.length; ++i) { - var cur = overlays[i].modeSpec; - if (cur == spec || typeof spec == "string" && cur.name == spec) { - overlays.splice(i, 1); - this.state.modeGen++; - regChange(this); - return - } - } - }), - - indentLine: methodOp(function(n, dir, aggressive) { - if (typeof dir != "string" && typeof dir != "number") { - if (dir == null) { dir = this.options.smartIndent ? "smart" : "prev"; } - else { dir = dir ? "add" : "subtract"; } - } - if (isLine(this.doc, n)) { indentLine(this, n, dir, aggressive); } - }), - indentSelection: methodOp(function(how) { - var ranges = this.doc.sel.ranges, end = -1; - for (var i = 0; i < ranges.length; i++) { - var range = ranges[i]; - if (!range.empty()) { - var from = range.from(), to = range.to(); - var start = Math.max(end, from.line); - end = Math.min(this.lastLine(), to.line - (to.ch ? 0 : 1)) + 1; - for (var j = start; j < end; ++j) - { indentLine(this, j, how); } - var newRanges = this.doc.sel.ranges; - if (from.ch == 0 && ranges.length == newRanges.length && newRanges[i].from().ch > 0) - { replaceOneSelection(this.doc, i, new Range(from, newRanges[i].to()), sel_dontScroll); } - } else if (range.head.line > end) { - indentLine(this, range.head.line, how, true); - end = range.head.line; - if (i == this.doc.sel.primIndex) { ensureCursorVisible(this); } - } - } - }), - - // Fetch the parser token for a given character. Useful for hacks - // that want to inspect the mode state (say, for completion). - getTokenAt: function(pos, precise) { - return takeToken(this, pos, precise) - }, - - getLineTokens: function(line, precise) { - return takeToken(this, Pos(line), precise, true) - }, - - getTokenTypeAt: function(pos) { - pos = clipPos(this.doc, pos); - var styles = getLineStyles(this, getLine(this.doc, pos.line)); - var before = 0, after = (styles.length - 1) / 2, ch = pos.ch; - var type; - if (ch == 0) { type = styles[2]; } - else { for (;;) { - var mid = (before + after) >> 1; - if ((mid ? styles[mid * 2 - 1] : 0) >= ch) { after = mid; } - else if (styles[mid * 2 + 1] < ch) { before = mid + 1; } - else { type = styles[mid * 2 + 2]; break } - } } - var cut = type ? type.indexOf("overlay ") : -1; - return cut < 0 ? type : cut == 0 ? null : type.slice(0, cut - 1) - }, - - getModeAt: function(pos) { - var mode = this.doc.mode; - if (!mode.innerMode) { return mode } - return CodeMirror.innerMode(mode, this.getTokenAt(pos).state).mode - }, - - getHelper: function(pos, type) { - return this.getHelpers(pos, type)[0] - }, - - getHelpers: function(pos, type) { - var found = []; - if (!helpers.hasOwnProperty(type)) { return found } - var help = helpers[type], mode = this.getModeAt(pos); - if (typeof mode[type] == "string") { - if (help[mode[type]]) { found.push(help[mode[type]]); } - } else if (mode[type]) { - for (var i = 0; i < mode[type].length; i++) { - var val = help[mode[type][i]]; - if (val) { found.push(val); } - } - } else if (mode.helperType && help[mode.helperType]) { - found.push(help[mode.helperType]); - } else if (help[mode.name]) { - found.push(help[mode.name]); - } - for (var i$1 = 0; i$1 < help._global.length; i$1++) { - var cur = help._global[i$1]; - if (cur.pred(mode, this) && indexOf(found, cur.val) == -1) - { found.push(cur.val); } - } - return found - }, - - getStateAfter: function(line, precise) { - var doc = this.doc; - line = clipLine(doc, line == null ? doc.first + doc.size - 1: line); - return getContextBefore(this, line + 1, precise).state - }, - - cursorCoords: function(start, mode) { - var pos, range = this.doc.sel.primary(); - if (start == null) { pos = range.head; } - else if (typeof start == "object") { pos = clipPos(this.doc, start); } - else { pos = start ? range.from() : range.to(); } - return cursorCoords(this, pos, mode || "page") - }, - - charCoords: function(pos, mode) { - return charCoords(this, clipPos(this.doc, pos), mode || "page") - }, - - coordsChar: function(coords, mode) { - coords = fromCoordSystem(this, coords, mode || "page"); - return coordsChar(this, coords.left, coords.top) - }, - - lineAtHeight: function(height, mode) { - height = fromCoordSystem(this, {top: height, left: 0}, mode || "page").top; - return lineAtHeight(this.doc, height + this.display.viewOffset) - }, - heightAtLine: function(line, mode, includeWidgets) { - var end = false, lineObj; - if (typeof line == "number") { - var last = this.doc.first + this.doc.size - 1; - if (line < this.doc.first) { line = this.doc.first; } - else if (line > last) { line = last; end = true; } - lineObj = getLine(this.doc, line); - } else { - lineObj = line; - } - return intoCoordSystem(this, lineObj, {top: 0, left: 0}, mode || "page", includeWidgets || end).top + - (end ? this.doc.height - heightAtLine(lineObj) : 0) - }, - - defaultTextHeight: function() { return textHeight(this.display) }, - defaultCharWidth: function() { return charWidth(this.display) }, - - getViewport: function() { return {from: this.display.viewFrom, to: this.display.viewTo}}, - - addWidget: function(pos, node, scroll, vert, horiz) { - var display = this.display; - pos = cursorCoords(this, clipPos(this.doc, pos)); - var top = pos.bottom, left = pos.left; - node.style.position = "absolute"; - node.setAttribute("cm-ignore-events", "true"); - this.display.input.setUneditable(node); - display.sizer.appendChild(node); - if (vert == "over") { - top = pos.top; - } else if (vert == "above" || vert == "near") { - var vspace = Math.max(display.wrapper.clientHeight, this.doc.height), - hspace = Math.max(display.sizer.clientWidth, display.lineSpace.clientWidth); - // Default to positioning above (if specified and possible); otherwise default to positioning below - if ((vert == 'above' || pos.bottom + node.offsetHeight > vspace) && pos.top > node.offsetHeight) - { top = pos.top - node.offsetHeight; } - else if (pos.bottom + node.offsetHeight <= vspace) - { top = pos.bottom; } - if (left + node.offsetWidth > hspace) - { left = hspace - node.offsetWidth; } - } - node.style.top = top + "px"; - node.style.left = node.style.right = ""; - if (horiz == "right") { - left = display.sizer.clientWidth - node.offsetWidth; - node.style.right = "0px"; - } else { - if (horiz == "left") { left = 0; } - else if (horiz == "middle") { left = (display.sizer.clientWidth - node.offsetWidth) / 2; } - node.style.left = left + "px"; - } - if (scroll) - { scrollIntoView(this, {left: left, top: top, right: left + node.offsetWidth, bottom: top + node.offsetHeight}); } - }, - - triggerOnKeyDown: methodOp(onKeyDown), - triggerOnKeyPress: methodOp(onKeyPress), - triggerOnKeyUp: onKeyUp, - triggerOnMouseDown: methodOp(onMouseDown), - - execCommand: function(cmd) { - if (commands.hasOwnProperty(cmd)) - { return commands[cmd].call(null, this) } - }, - - triggerElectric: methodOp(function(text) { triggerElectric(this, text); }), - - findPosH: function(from, amount, unit, visually) { - var dir = 1; - if (amount < 0) { dir = -1; amount = -amount; } - var cur = clipPos(this.doc, from); - for (var i = 0; i < amount; ++i) { - cur = findPosH(this.doc, cur, dir, unit, visually); - if (cur.hitSide) { break } - } - return cur - }, - - moveH: methodOp(function(dir, unit) { - var this$1 = this; - - this.extendSelectionsBy(function (range) { - if (this$1.display.shift || this$1.doc.extend || range.empty()) - { return findPosH(this$1.doc, range.head, dir, unit, this$1.options.rtlMoveVisually) } - else - { return dir < 0 ? range.from() : range.to() } - }, sel_move); - }), - - deleteH: methodOp(function(dir, unit) { - var sel = this.doc.sel, doc = this.doc; - if (sel.somethingSelected()) - { doc.replaceSelection("", null, "+delete"); } - else - { deleteNearSelection(this, function (range) { - var other = findPosH(doc, range.head, dir, unit, false); - return dir < 0 ? {from: other, to: range.head} : {from: range.head, to: other} - }); } - }), - - findPosV: function(from, amount, unit, goalColumn) { - var dir = 1, x = goalColumn; - if (amount < 0) { dir = -1; amount = -amount; } - var cur = clipPos(this.doc, from); - for (var i = 0; i < amount; ++i) { - var coords = cursorCoords(this, cur, "div"); - if (x == null) { x = coords.left; } - else { coords.left = x; } - cur = findPosV(this, coords, dir, unit); - if (cur.hitSide) { break } - } - return cur - }, - - moveV: methodOp(function(dir, unit) { - var this$1 = this; - - var doc = this.doc, goals = []; - var collapse = !this.display.shift && !doc.extend && doc.sel.somethingSelected(); - doc.extendSelectionsBy(function (range) { - if (collapse) - { return dir < 0 ? range.from() : range.to() } - var headPos = cursorCoords(this$1, range.head, "div"); - if (range.goalColumn != null) { headPos.left = range.goalColumn; } - goals.push(headPos.left); - var pos = findPosV(this$1, headPos, dir, unit); - if (unit == "page" && range == doc.sel.primary()) - { addToScrollTop(this$1, charCoords(this$1, pos, "div").top - headPos.top); } - return pos - }, sel_move); - if (goals.length) { for (var i = 0; i < doc.sel.ranges.length; i++) - { doc.sel.ranges[i].goalColumn = goals[i]; } } - }), - - // Find the word at the given position (as returned by coordsChar). - findWordAt: function(pos) { - var doc = this.doc, line = getLine(doc, pos.line).text; - var start = pos.ch, end = pos.ch; - if (line) { - var helper = this.getHelper(pos, "wordChars"); - if ((pos.sticky == "before" || end == line.length) && start) { --start; } else { ++end; } - var startChar = line.charAt(start); - var check = isWordChar(startChar, helper) - ? function (ch) { return isWordChar(ch, helper); } - : /\s/.test(startChar) ? function (ch) { return /\s/.test(ch); } - : function (ch) { return (!/\s/.test(ch) && !isWordChar(ch)); }; - while (start > 0 && check(line.charAt(start - 1))) { --start; } - while (end < line.length && check(line.charAt(end))) { ++end; } - } - return new Range(Pos(pos.line, start), Pos(pos.line, end)) - }, - - toggleOverwrite: function(value) { - if (value != null && value == this.state.overwrite) { return } - if (this.state.overwrite = !this.state.overwrite) - { addClass(this.display.cursorDiv, "CodeMirror-overwrite"); } - else - { rmClass(this.display.cursorDiv, "CodeMirror-overwrite"); } - - signal(this, "overwriteToggle", this, this.state.overwrite); - }, - hasFocus: function() { return this.display.input.getField() == activeElt() }, - isReadOnly: function() { return !!(this.options.readOnly || this.doc.cantEdit) }, - - scrollTo: methodOp(function (x, y) { scrollToCoords(this, x, y); }), - getScrollInfo: function() { - var scroller = this.display.scroller; - return {left: scroller.scrollLeft, top: scroller.scrollTop, - height: scroller.scrollHeight - scrollGap(this) - this.display.barHeight, - width: scroller.scrollWidth - scrollGap(this) - this.display.barWidth, - clientHeight: displayHeight(this), clientWidth: displayWidth(this)} - }, - - scrollIntoView: methodOp(function(range, margin) { - if (range == null) { - range = {from: this.doc.sel.primary().head, to: null}; - if (margin == null) { margin = this.options.cursorScrollMargin; } - } else if (typeof range == "number") { - range = {from: Pos(range, 0), to: null}; - } else if (range.from == null) { - range = {from: range, to: null}; - } - if (!range.to) { range.to = range.from; } - range.margin = margin || 0; - - if (range.from.line != null) { - scrollToRange(this, range); - } else { - scrollToCoordsRange(this, range.from, range.to, range.margin); - } - }), - - setSize: methodOp(function(width, height) { - var this$1 = this; - - var interpret = function (val) { return typeof val == "number" || /^\d+$/.test(String(val)) ? val + "px" : val; }; - if (width != null) { this.display.wrapper.style.width = interpret(width); } - if (height != null) { this.display.wrapper.style.height = interpret(height); } - if (this.options.lineWrapping) { clearLineMeasurementCache(this); } - var lineNo = this.display.viewFrom; - this.doc.iter(lineNo, this.display.viewTo, function (line) { - if (line.widgets) { for (var i = 0; i < line.widgets.length; i++) - { if (line.widgets[i].noHScroll) { regLineChange(this$1, lineNo, "widget"); break } } } - ++lineNo; - }); - this.curOp.forceUpdate = true; - signal(this, "refresh", this); - }), - - operation: function(f){return runInOp(this, f)}, - startOperation: function(){return startOperation(this)}, - endOperation: function(){return endOperation(this)}, - - refresh: methodOp(function() { - var oldHeight = this.display.cachedTextHeight; - regChange(this); - this.curOp.forceUpdate = true; - clearCaches(this); - scrollToCoords(this, this.doc.scrollLeft, this.doc.scrollTop); - updateGutterSpace(this.display); - if (oldHeight == null || Math.abs(oldHeight - textHeight(this.display)) > .5 || this.options.lineWrapping) - { estimateLineHeights(this); } - signal(this, "refresh", this); - }), - - swapDoc: methodOp(function(doc) { - var old = this.doc; - old.cm = null; - // Cancel the current text selection if any (#5821) - if (this.state.selectingText) { this.state.selectingText(); } - attachDoc(this, doc); - clearCaches(this); - this.display.input.reset(); - scrollToCoords(this, doc.scrollLeft, doc.scrollTop); - this.curOp.forceScroll = true; - signalLater(this, "swapDoc", this, old); - return old - }), - - phrase: function(phraseText) { - var phrases = this.options.phrases; - return phrases && Object.prototype.hasOwnProperty.call(phrases, phraseText) ? phrases[phraseText] : phraseText - }, - - getInputField: function(){return this.display.input.getField()}, - getWrapperElement: function(){return this.display.wrapper}, - getScrollerElement: function(){return this.display.scroller}, - getGutterElement: function(){return this.display.gutters} - }; - eventMixin(CodeMirror); - - CodeMirror.registerHelper = function(type, name, value) { - if (!helpers.hasOwnProperty(type)) { helpers[type] = CodeMirror[type] = {_global: []}; } - helpers[type][name] = value; - }; - CodeMirror.registerGlobalHelper = function(type, name, predicate, value) { - CodeMirror.registerHelper(type, name, value); - helpers[type]._global.push({pred: predicate, val: value}); - }; - } - - // Used for horizontal relative motion. Dir is -1 or 1 (left or - // right), unit can be "codepoint", "char", "column" (like char, but - // doesn't cross line boundaries), "word" (across next word), or - // "group" (to the start of next group of word or - // non-word-non-whitespace chars). The visually param controls - // whether, in right-to-left text, direction 1 means to move towards - // the next index in the string, or towards the character to the right - // of the current position. The resulting position will have a - // hitSide=true property if it reached the end of the document. - function findPosH(doc, pos, dir, unit, visually) { - var oldPos = pos; - var origDir = dir; - var lineObj = getLine(doc, pos.line); - var lineDir = visually && doc.direction == "rtl" ? -dir : dir; - function findNextLine() { - var l = pos.line + lineDir; - if (l < doc.first || l >= doc.first + doc.size) { return false } - pos = new Pos(l, pos.ch, pos.sticky); - return lineObj = getLine(doc, l) - } - function moveOnce(boundToLine) { - var next; - if (unit == "codepoint") { - var ch = lineObj.text.charCodeAt(pos.ch + (unit > 0 ? 0 : -1)); - if (isNaN(ch)) { next = null; } - else { next = new Pos(pos.line, Math.max(0, Math.min(lineObj.text.length, pos.ch + dir * (ch >= 0xD800 && ch < 0xDC00 ? 2 : 1))), - -dir); } - } else if (visually) { - next = moveVisually(doc.cm, lineObj, pos, dir); - } else { - next = moveLogically(lineObj, pos, dir); - } - if (next == null) { - if (!boundToLine && findNextLine()) - { pos = endOfLine(visually, doc.cm, lineObj, pos.line, lineDir); } - else - { return false } - } else { - pos = next; - } - return true - } - - if (unit == "char" || unit == "codepoint") { - moveOnce(); - } else if (unit == "column") { - moveOnce(true); - } else if (unit == "word" || unit == "group") { - var sawType = null, group = unit == "group"; - var helper = doc.cm && doc.cm.getHelper(pos, "wordChars"); - for (var first = true;; first = false) { - if (dir < 0 && !moveOnce(!first)) { break } - var cur = lineObj.text.charAt(pos.ch) || "\n"; - var type = isWordChar(cur, helper) ? "w" - : group && cur == "\n" ? "n" - : !group || /\s/.test(cur) ? null - : "p"; - if (group && !first && !type) { type = "s"; } - if (sawType && sawType != type) { - if (dir < 0) {dir = 1; moveOnce(); pos.sticky = "after";} - break - } - - if (type) { sawType = type; } - if (dir > 0 && !moveOnce(!first)) { break } - } - } - var result = skipAtomic(doc, pos, oldPos, origDir, true); - if (equalCursorPos(oldPos, result)) { result.hitSide = true; } - return result - } - - // For relative vertical movement. Dir may be -1 or 1. Unit can be - // "page" or "line". The resulting position will have a hitSide=true - // property if it reached the end of the document. - function findPosV(cm, pos, dir, unit) { - var doc = cm.doc, x = pos.left, y; - if (unit == "page") { - var pageSize = Math.min(cm.display.wrapper.clientHeight, window.innerHeight || document.documentElement.clientHeight); - var moveAmount = Math.max(pageSize - .5 * textHeight(cm.display), 3); - y = (dir > 0 ? pos.bottom : pos.top) + dir * moveAmount; - - } else if (unit == "line") { - y = dir > 0 ? pos.bottom + 3 : pos.top - 3; - } - var target; - for (;;) { - target = coordsChar(cm, x, y); - if (!target.outside) { break } - if (dir < 0 ? y <= 0 : y >= doc.height) { target.hitSide = true; break } - y += dir * 5; - } - return target - } - - // CONTENTEDITABLE INPUT STYLE - - var ContentEditableInput = function(cm) { - this.cm = cm; - this.lastAnchorNode = this.lastAnchorOffset = this.lastFocusNode = this.lastFocusOffset = null; - this.polling = new Delayed(); - this.composing = null; - this.gracePeriod = false; - this.readDOMTimeout = null; - }; - - ContentEditableInput.prototype.init = function (display) { - var this$1 = this; - - var input = this, cm = input.cm; - var div = input.div = display.lineDiv; - disableBrowserMagic(div, cm.options.spellcheck, cm.options.autocorrect, cm.options.autocapitalize); - - function belongsToInput(e) { - for (var t = e.target; t; t = t.parentNode) { - if (t == div) { return true } - if (/\bCodeMirror-(?:line)?widget\b/.test(t.className)) { break } - } - return false - } - - on(div, "paste", function (e) { - if (!belongsToInput(e) || signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } - // IE doesn't fire input events, so we schedule a read for the pasted content in this way - if (ie_version <= 11) { setTimeout(operation(cm, function () { return this$1.updateFromDOM(); }), 20); } - }); - - on(div, "compositionstart", function (e) { - this$1.composing = {data: e.data, done: false}; - }); - on(div, "compositionupdate", function (e) { - if (!this$1.composing) { this$1.composing = {data: e.data, done: false}; } - }); - on(div, "compositionend", function (e) { - if (this$1.composing) { - if (e.data != this$1.composing.data) { this$1.readFromDOMSoon(); } - this$1.composing.done = true; - } - }); - - on(div, "touchstart", function () { return input.forceCompositionEnd(); }); - - on(div, "input", function () { - if (!this$1.composing) { this$1.readFromDOMSoon(); } - }); - - function onCopyCut(e) { - if (!belongsToInput(e) || signalDOMEvent(cm, e)) { return } - if (cm.somethingSelected()) { - setLastCopied({lineWise: false, text: cm.getSelections()}); - if (e.type == "cut") { cm.replaceSelection("", null, "cut"); } - } else if (!cm.options.lineWiseCopyCut) { - return - } else { - var ranges = copyableRanges(cm); - setLastCopied({lineWise: true, text: ranges.text}); - if (e.type == "cut") { - cm.operation(function () { - cm.setSelections(ranges.ranges, 0, sel_dontScroll); - cm.replaceSelection("", null, "cut"); - }); - } - } - if (e.clipboardData) { - e.clipboardData.clearData(); - var content = lastCopied.text.join("\n"); - // iOS exposes the clipboard API, but seems to discard content inserted into it - e.clipboardData.setData("Text", content); - if (e.clipboardData.getData("Text") == content) { - e.preventDefault(); - return - } - } - // Old-fashioned briefly-focus-a-textarea hack - var kludge = hiddenTextarea(), te = kludge.firstChild; - cm.display.lineSpace.insertBefore(kludge, cm.display.lineSpace.firstChild); - te.value = lastCopied.text.join("\n"); - var hadFocus = document.activeElement; - selectInput(te); - setTimeout(function () { - cm.display.lineSpace.removeChild(kludge); - hadFocus.focus(); - if (hadFocus == div) { input.showPrimarySelection(); } - }, 50); - } - on(div, "copy", onCopyCut); - on(div, "cut", onCopyCut); - }; - - ContentEditableInput.prototype.screenReaderLabelChanged = function (label) { - // Label for screenreaders, accessibility - if(label) { - this.div.setAttribute('aria-label', label); - } else { - this.div.removeAttribute('aria-label'); - } - }; - - ContentEditableInput.prototype.prepareSelection = function () { - var result = prepareSelection(this.cm, false); - result.focus = document.activeElement == this.div; - return result - }; - - ContentEditableInput.prototype.showSelection = function (info, takeFocus) { - if (!info || !this.cm.display.view.length) { return } - if (info.focus || takeFocus) { this.showPrimarySelection(); } - this.showMultipleSelections(info); - }; - - ContentEditableInput.prototype.getSelection = function () { - return this.cm.display.wrapper.ownerDocument.getSelection() - }; - - ContentEditableInput.prototype.showPrimarySelection = function () { - var sel = this.getSelection(), cm = this.cm, prim = cm.doc.sel.primary(); - var from = prim.from(), to = prim.to(); - - if (cm.display.viewTo == cm.display.viewFrom || from.line >= cm.display.viewTo || to.line < cm.display.viewFrom) { - sel.removeAllRanges(); - return - } - - var curAnchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); - var curFocus = domToPos(cm, sel.focusNode, sel.focusOffset); - if (curAnchor && !curAnchor.bad && curFocus && !curFocus.bad && - cmp(minPos(curAnchor, curFocus), from) == 0 && - cmp(maxPos(curAnchor, curFocus), to) == 0) - { return } - - var view = cm.display.view; - var start = (from.line >= cm.display.viewFrom && posToDOM(cm, from)) || - {node: view[0].measure.map[2], offset: 0}; - var end = to.line < cm.display.viewTo && posToDOM(cm, to); - if (!end) { - var measure = view[view.length - 1].measure; - var map = measure.maps ? measure.maps[measure.maps.length - 1] : measure.map; - end = {node: map[map.length - 1], offset: map[map.length - 2] - map[map.length - 3]}; - } - - if (!start || !end) { - sel.removeAllRanges(); - return - } - - var old = sel.rangeCount && sel.getRangeAt(0), rng; - try { rng = range(start.node, start.offset, end.offset, end.node); } - catch(e) {} // Our model of the DOM might be outdated, in which case the range we try to set can be impossible - if (rng) { - if (!gecko && cm.state.focused) { - sel.collapse(start.node, start.offset); - if (!rng.collapsed) { - sel.removeAllRanges(); - sel.addRange(rng); - } - } else { - sel.removeAllRanges(); - sel.addRange(rng); - } - if (old && sel.anchorNode == null) { sel.addRange(old); } - else if (gecko) { this.startGracePeriod(); } - } - this.rememberSelection(); - }; - - ContentEditableInput.prototype.startGracePeriod = function () { - var this$1 = this; - - clearTimeout(this.gracePeriod); - this.gracePeriod = setTimeout(function () { - this$1.gracePeriod = false; - if (this$1.selectionChanged()) - { this$1.cm.operation(function () { return this$1.cm.curOp.selectionChanged = true; }); } - }, 20); - }; - - ContentEditableInput.prototype.showMultipleSelections = function (info) { - removeChildrenAndAdd(this.cm.display.cursorDiv, info.cursors); - removeChildrenAndAdd(this.cm.display.selectionDiv, info.selection); - }; - - ContentEditableInput.prototype.rememberSelection = function () { - var sel = this.getSelection(); - this.lastAnchorNode = sel.anchorNode; this.lastAnchorOffset = sel.anchorOffset; - this.lastFocusNode = sel.focusNode; this.lastFocusOffset = sel.focusOffset; - }; - - ContentEditableInput.prototype.selectionInEditor = function () { - var sel = this.getSelection(); - if (!sel.rangeCount) { return false } - var node = sel.getRangeAt(0).commonAncestorContainer; - return contains(this.div, node) - }; - - ContentEditableInput.prototype.focus = function () { - if (this.cm.options.readOnly != "nocursor") { - if (!this.selectionInEditor() || document.activeElement != this.div) - { this.showSelection(this.prepareSelection(), true); } - this.div.focus(); - } - }; - ContentEditableInput.prototype.blur = function () { this.div.blur(); }; - ContentEditableInput.prototype.getField = function () { return this.div }; - - ContentEditableInput.prototype.supportsTouch = function () { return true }; - - ContentEditableInput.prototype.receivedFocus = function () { - var input = this; - if (this.selectionInEditor()) - { this.pollSelection(); } - else - { runInOp(this.cm, function () { return input.cm.curOp.selectionChanged = true; }); } - - function poll() { - if (input.cm.state.focused) { - input.pollSelection(); - input.polling.set(input.cm.options.pollInterval, poll); - } - } - this.polling.set(this.cm.options.pollInterval, poll); - }; - - ContentEditableInput.prototype.selectionChanged = function () { - var sel = this.getSelection(); - return sel.anchorNode != this.lastAnchorNode || sel.anchorOffset != this.lastAnchorOffset || - sel.focusNode != this.lastFocusNode || sel.focusOffset != this.lastFocusOffset - }; - - ContentEditableInput.prototype.pollSelection = function () { - if (this.readDOMTimeout != null || this.gracePeriod || !this.selectionChanged()) { return } - var sel = this.getSelection(), cm = this.cm; - // On Android Chrome (version 56, at least), backspacing into an - // uneditable block element will put the cursor in that element, - // and then, because it's not editable, hide the virtual keyboard. - // Because Android doesn't allow us to actually detect backspace - // presses in a sane way, this code checks for when that happens - // and simulates a backspace press in this case. - if (android && chrome && this.cm.display.gutterSpecs.length && isInGutter(sel.anchorNode)) { - this.cm.triggerOnKeyDown({type: "keydown", keyCode: 8, preventDefault: Math.abs}); - this.blur(); - this.focus(); - return - } - if (this.composing) { return } - this.rememberSelection(); - var anchor = domToPos(cm, sel.anchorNode, sel.anchorOffset); - var head = domToPos(cm, sel.focusNode, sel.focusOffset); - if (anchor && head) { runInOp(cm, function () { - setSelection(cm.doc, simpleSelection(anchor, head), sel_dontScroll); - if (anchor.bad || head.bad) { cm.curOp.selectionChanged = true; } - }); } - }; - - ContentEditableInput.prototype.pollContent = function () { - if (this.readDOMTimeout != null) { - clearTimeout(this.readDOMTimeout); - this.readDOMTimeout = null; - } - - var cm = this.cm, display = cm.display, sel = cm.doc.sel.primary(); - var from = sel.from(), to = sel.to(); - if (from.ch == 0 && from.line > cm.firstLine()) - { from = Pos(from.line - 1, getLine(cm.doc, from.line - 1).length); } - if (to.ch == getLine(cm.doc, to.line).text.length && to.line < cm.lastLine()) - { to = Pos(to.line + 1, 0); } - if (from.line < display.viewFrom || to.line > display.viewTo - 1) { return false } - - var fromIndex, fromLine, fromNode; - if (from.line == display.viewFrom || (fromIndex = findViewIndex(cm, from.line)) == 0) { - fromLine = lineNo(display.view[0].line); - fromNode = display.view[0].node; - } else { - fromLine = lineNo(display.view[fromIndex].line); - fromNode = display.view[fromIndex - 1].node.nextSibling; - } - var toIndex = findViewIndex(cm, to.line); - var toLine, toNode; - if (toIndex == display.view.length - 1) { - toLine = display.viewTo - 1; - toNode = display.lineDiv.lastChild; - } else { - toLine = lineNo(display.view[toIndex + 1].line) - 1; - toNode = display.view[toIndex + 1].node.previousSibling; - } - - if (!fromNode) { return false } - var newText = cm.doc.splitLines(domTextBetween(cm, fromNode, toNode, fromLine, toLine)); - var oldText = getBetween(cm.doc, Pos(fromLine, 0), Pos(toLine, getLine(cm.doc, toLine).text.length)); - while (newText.length > 1 && oldText.length > 1) { - if (lst(newText) == lst(oldText)) { newText.pop(); oldText.pop(); toLine--; } - else if (newText[0] == oldText[0]) { newText.shift(); oldText.shift(); fromLine++; } - else { break } - } - - var cutFront = 0, cutEnd = 0; - var newTop = newText[0], oldTop = oldText[0], maxCutFront = Math.min(newTop.length, oldTop.length); - while (cutFront < maxCutFront && newTop.charCodeAt(cutFront) == oldTop.charCodeAt(cutFront)) - { ++cutFront; } - var newBot = lst(newText), oldBot = lst(oldText); - var maxCutEnd = Math.min(newBot.length - (newText.length == 1 ? cutFront : 0), - oldBot.length - (oldText.length == 1 ? cutFront : 0)); - while (cutEnd < maxCutEnd && - newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) - { ++cutEnd; } - // Try to move start of change to start of selection if ambiguous - if (newText.length == 1 && oldText.length == 1 && fromLine == from.line) { - while (cutFront && cutFront > from.ch && - newBot.charCodeAt(newBot.length - cutEnd - 1) == oldBot.charCodeAt(oldBot.length - cutEnd - 1)) { - cutFront--; - cutEnd++; - } - } - - newText[newText.length - 1] = newBot.slice(0, newBot.length - cutEnd).replace(/^\u200b+/, ""); - newText[0] = newText[0].slice(cutFront).replace(/\u200b+$/, ""); - - var chFrom = Pos(fromLine, cutFront); - var chTo = Pos(toLine, oldText.length ? lst(oldText).length - cutEnd : 0); - if (newText.length > 1 || newText[0] || cmp(chFrom, chTo)) { - replaceRange(cm.doc, newText, chFrom, chTo, "+input"); - return true - } - }; - - ContentEditableInput.prototype.ensurePolled = function () { - this.forceCompositionEnd(); - }; - ContentEditableInput.prototype.reset = function () { - this.forceCompositionEnd(); - }; - ContentEditableInput.prototype.forceCompositionEnd = function () { - if (!this.composing) { return } - clearTimeout(this.readDOMTimeout); - this.composing = null; - this.updateFromDOM(); - this.div.blur(); - this.div.focus(); - }; - ContentEditableInput.prototype.readFromDOMSoon = function () { - var this$1 = this; - - if (this.readDOMTimeout != null) { return } - this.readDOMTimeout = setTimeout(function () { - this$1.readDOMTimeout = null; - if (this$1.composing) { - if (this$1.composing.done) { this$1.composing = null; } - else { return } - } - this$1.updateFromDOM(); - }, 80); - }; - - ContentEditableInput.prototype.updateFromDOM = function () { - var this$1 = this; - - if (this.cm.isReadOnly() || !this.pollContent()) - { runInOp(this.cm, function () { return regChange(this$1.cm); }); } - }; - - ContentEditableInput.prototype.setUneditable = function (node) { - node.contentEditable = "false"; - }; - - ContentEditableInput.prototype.onKeyPress = function (e) { - if (e.charCode == 0 || this.composing) { return } - e.preventDefault(); - if (!this.cm.isReadOnly()) - { operation(this.cm, applyTextInput)(this.cm, String.fromCharCode(e.charCode == null ? e.keyCode : e.charCode), 0); } - }; - - ContentEditableInput.prototype.readOnlyChanged = function (val) { - this.div.contentEditable = String(val != "nocursor"); - }; - - ContentEditableInput.prototype.onContextMenu = function () {}; - ContentEditableInput.prototype.resetPosition = function () {}; - - ContentEditableInput.prototype.needsContentAttribute = true; - - function posToDOM(cm, pos) { - var view = findViewForLine(cm, pos.line); - if (!view || view.hidden) { return null } - var line = getLine(cm.doc, pos.line); - var info = mapFromLineView(view, line, pos.line); - - var order = getOrder(line, cm.doc.direction), side = "left"; - if (order) { - var partPos = getBidiPartAt(order, pos.ch); - side = partPos % 2 ? "right" : "left"; - } - var result = nodeAndOffsetInLineMap(info.map, pos.ch, side); - result.offset = result.collapse == "right" ? result.end : result.start; - return result - } - - function isInGutter(node) { - for (var scan = node; scan; scan = scan.parentNode) - { if (/CodeMirror-gutter-wrapper/.test(scan.className)) { return true } } - return false - } - - function badPos(pos, bad) { if (bad) { pos.bad = true; } return pos } - - function domTextBetween(cm, from, to, fromLine, toLine) { - var text = "", closing = false, lineSep = cm.doc.lineSeparator(), extraLinebreak = false; - function recognizeMarker(id) { return function (marker) { return marker.id == id; } } - function close() { - if (closing) { - text += lineSep; - if (extraLinebreak) { text += lineSep; } - closing = extraLinebreak = false; - } - } - function addText(str) { - if (str) { - close(); - text += str; - } - } - function walk(node) { - if (node.nodeType == 1) { - var cmText = node.getAttribute("cm-text"); - if (cmText) { - addText(cmText); - return - } - var markerID = node.getAttribute("cm-marker"), range; - if (markerID) { - var found = cm.findMarks(Pos(fromLine, 0), Pos(toLine + 1, 0), recognizeMarker(+markerID)); - if (found.length && (range = found[0].find(0))) - { addText(getBetween(cm.doc, range.from, range.to).join(lineSep)); } - return - } - if (node.getAttribute("contenteditable") == "false") { return } - var isBlock = /^(pre|div|p|li|table|br)$/i.test(node.nodeName); - if (!/^br$/i.test(node.nodeName) && node.textContent.length == 0) { return } - - if (isBlock) { close(); } - for (var i = 0; i < node.childNodes.length; i++) - { walk(node.childNodes[i]); } - - if (/^(pre|p)$/i.test(node.nodeName)) { extraLinebreak = true; } - if (isBlock) { closing = true; } - } else if (node.nodeType == 3) { - addText(node.nodeValue.replace(/\u200b/g, "").replace(/\u00a0/g, " ")); - } - } - for (;;) { - walk(from); - if (from == to) { break } - from = from.nextSibling; - extraLinebreak = false; - } - return text - } - - function domToPos(cm, node, offset) { - var lineNode; - if (node == cm.display.lineDiv) { - lineNode = cm.display.lineDiv.childNodes[offset]; - if (!lineNode) { return badPos(cm.clipPos(Pos(cm.display.viewTo - 1)), true) } - node = null; offset = 0; - } else { - for (lineNode = node;; lineNode = lineNode.parentNode) { - if (!lineNode || lineNode == cm.display.lineDiv) { return null } - if (lineNode.parentNode && lineNode.parentNode == cm.display.lineDiv) { break } - } - } - for (var i = 0; i < cm.display.view.length; i++) { - var lineView = cm.display.view[i]; - if (lineView.node == lineNode) - { return locateNodeInLineView(lineView, node, offset) } - } - } - - function locateNodeInLineView(lineView, node, offset) { - var wrapper = lineView.text.firstChild, bad = false; - if (!node || !contains(wrapper, node)) { return badPos(Pos(lineNo(lineView.line), 0), true) } - if (node == wrapper) { - bad = true; - node = wrapper.childNodes[offset]; - offset = 0; - if (!node) { - var line = lineView.rest ? lst(lineView.rest) : lineView.line; - return badPos(Pos(lineNo(line), line.text.length), bad) - } - } - - var textNode = node.nodeType == 3 ? node : null, topNode = node; - if (!textNode && node.childNodes.length == 1 && node.firstChild.nodeType == 3) { - textNode = node.firstChild; - if (offset) { offset = textNode.nodeValue.length; } - } - while (topNode.parentNode != wrapper) { topNode = topNode.parentNode; } - var measure = lineView.measure, maps = measure.maps; - - function find(textNode, topNode, offset) { - for (var i = -1; i < (maps ? maps.length : 0); i++) { - var map = i < 0 ? measure.map : maps[i]; - for (var j = 0; j < map.length; j += 3) { - var curNode = map[j + 2]; - if (curNode == textNode || curNode == topNode) { - var line = lineNo(i < 0 ? lineView.line : lineView.rest[i]); - var ch = map[j] + offset; - if (offset < 0 || curNode != textNode) { ch = map[j + (offset ? 1 : 0)]; } - return Pos(line, ch) - } - } - } - } - var found = find(textNode, topNode, offset); - if (found) { return badPos(found, bad) } - - // FIXME this is all really shaky. might handle the few cases it needs to handle, but likely to cause problems - for (var after = topNode.nextSibling, dist = textNode ? textNode.nodeValue.length - offset : 0; after; after = after.nextSibling) { - found = find(after, after.firstChild, 0); - if (found) - { return badPos(Pos(found.line, found.ch - dist), bad) } - else - { dist += after.textContent.length; } - } - for (var before = topNode.previousSibling, dist$1 = offset; before; before = before.previousSibling) { - found = find(before, before.firstChild, -1); - if (found) - { return badPos(Pos(found.line, found.ch + dist$1), bad) } - else - { dist$1 += before.textContent.length; } - } - } - - // TEXTAREA INPUT STYLE - - var TextareaInput = function(cm) { - this.cm = cm; - // See input.poll and input.reset - this.prevInput = ""; - - // Flag that indicates whether we expect input to appear real soon - // now (after some event like 'keypress' or 'input') and are - // polling intensively. - this.pollingFast = false; - // Self-resetting timeout for the poller - this.polling = new Delayed(); - // Used to work around IE issue with selection being forgotten when focus moves away from textarea - this.hasSelection = false; - this.composing = null; - }; - - TextareaInput.prototype.init = function (display) { - var this$1 = this; - - var input = this, cm = this.cm; - this.createField(display); - var te = this.textarea; - - display.wrapper.insertBefore(this.wrapper, display.wrapper.firstChild); - - // Needed to hide big blue blinking cursor on Mobile Safari (doesn't seem to work in iOS 8 anymore) - if (ios) { te.style.width = "0px"; } - - on(te, "input", function () { - if (ie && ie_version >= 9 && this$1.hasSelection) { this$1.hasSelection = null; } - input.poll(); - }); - - on(te, "paste", function (e) { - if (signalDOMEvent(cm, e) || handlePaste(e, cm)) { return } - - cm.state.pasteIncoming = +new Date; - input.fastPoll(); - }); - - function prepareCopyCut(e) { - if (signalDOMEvent(cm, e)) { return } - if (cm.somethingSelected()) { - setLastCopied({lineWise: false, text: cm.getSelections()}); - } else if (!cm.options.lineWiseCopyCut) { - return - } else { - var ranges = copyableRanges(cm); - setLastCopied({lineWise: true, text: ranges.text}); - if (e.type == "cut") { - cm.setSelections(ranges.ranges, null, sel_dontScroll); - } else { - input.prevInput = ""; - te.value = ranges.text.join("\n"); - selectInput(te); - } - } - if (e.type == "cut") { cm.state.cutIncoming = +new Date; } - } - on(te, "cut", prepareCopyCut); - on(te, "copy", prepareCopyCut); - - on(display.scroller, "paste", function (e) { - if (eventInWidget(display, e) || signalDOMEvent(cm, e)) { return } - if (!te.dispatchEvent) { - cm.state.pasteIncoming = +new Date; - input.focus(); - return - } - - // Pass the `paste` event to the textarea so it's handled by its event listener. - var event = new Event("paste"); - event.clipboardData = e.clipboardData; - te.dispatchEvent(event); - }); - - // Prevent normal selection in the editor (we handle our own) - on(display.lineSpace, "selectstart", function (e) { - if (!eventInWidget(display, e)) { e_preventDefault(e); } - }); - - on(te, "compositionstart", function () { - var start = cm.getCursor("from"); - if (input.composing) { input.composing.range.clear(); } - input.composing = { - start: start, - range: cm.markText(start, cm.getCursor("to"), {className: "CodeMirror-composing"}) - }; - }); - on(te, "compositionend", function () { - if (input.composing) { - input.poll(); - input.composing.range.clear(); - input.composing = null; - } - }); - }; - - TextareaInput.prototype.createField = function (_display) { - // Wraps and hides input textarea - this.wrapper = hiddenTextarea(); - // The semihidden textarea that is focused when the editor is - // focused, and receives input. - this.textarea = this.wrapper.firstChild; - }; - - TextareaInput.prototype.screenReaderLabelChanged = function (label) { - // Label for screenreaders, accessibility - if(label) { - this.textarea.setAttribute('aria-label', label); - } else { - this.textarea.removeAttribute('aria-label'); - } - }; - - TextareaInput.prototype.prepareSelection = function () { - // Redraw the selection and/or cursor - var cm = this.cm, display = cm.display, doc = cm.doc; - var result = prepareSelection(cm); - - // Move the hidden textarea near the cursor to prevent scrolling artifacts - if (cm.options.moveInputWithCursor) { - var headPos = cursorCoords(cm, doc.sel.primary().head, "div"); - var wrapOff = display.wrapper.getBoundingClientRect(), lineOff = display.lineDiv.getBoundingClientRect(); - result.teTop = Math.max(0, Math.min(display.wrapper.clientHeight - 10, - headPos.top + lineOff.top - wrapOff.top)); - result.teLeft = Math.max(0, Math.min(display.wrapper.clientWidth - 10, - headPos.left + lineOff.left - wrapOff.left)); - } - - return result - }; - - TextareaInput.prototype.showSelection = function (drawn) { - var cm = this.cm, display = cm.display; - removeChildrenAndAdd(display.cursorDiv, drawn.cursors); - removeChildrenAndAdd(display.selectionDiv, drawn.selection); - if (drawn.teTop != null) { - this.wrapper.style.top = drawn.teTop + "px"; - this.wrapper.style.left = drawn.teLeft + "px"; - } - }; - - // Reset the input to correspond to the selection (or to be empty, - // when not typing and nothing is selected) - TextareaInput.prototype.reset = function (typing) { - if (this.contextMenuPending || this.composing) { return } - var cm = this.cm; - if (cm.somethingSelected()) { - this.prevInput = ""; - var content = cm.getSelection(); - this.textarea.value = content; - if (cm.state.focused) { selectInput(this.textarea); } - if (ie && ie_version >= 9) { this.hasSelection = content; } - } else if (!typing) { - this.prevInput = this.textarea.value = ""; - if (ie && ie_version >= 9) { this.hasSelection = null; } - } - }; - - TextareaInput.prototype.getField = function () { return this.textarea }; - - TextareaInput.prototype.supportsTouch = function () { return false }; - - TextareaInput.prototype.focus = function () { - if (this.cm.options.readOnly != "nocursor" && (!mobile || activeElt() != this.textarea)) { - try { this.textarea.focus(); } - catch (e) {} // IE8 will throw if the textarea is display: none or not in DOM - } - }; - - TextareaInput.prototype.blur = function () { this.textarea.blur(); }; - - TextareaInput.prototype.resetPosition = function () { - this.wrapper.style.top = this.wrapper.style.left = 0; - }; - - TextareaInput.prototype.receivedFocus = function () { this.slowPoll(); }; - - // Poll for input changes, using the normal rate of polling. This - // runs as long as the editor is focused. - TextareaInput.prototype.slowPoll = function () { - var this$1 = this; - - if (this.pollingFast) { return } - this.polling.set(this.cm.options.pollInterval, function () { - this$1.poll(); - if (this$1.cm.state.focused) { this$1.slowPoll(); } - }); - }; - - // When an event has just come in that is likely to add or change - // something in the input textarea, we poll faster, to ensure that - // the change appears on the screen quickly. - TextareaInput.prototype.fastPoll = function () { - var missed = false, input = this; - input.pollingFast = true; - function p() { - var changed = input.poll(); - if (!changed && !missed) {missed = true; input.polling.set(60, p);} - else {input.pollingFast = false; input.slowPoll();} - } - input.polling.set(20, p); - }; - - // Read input from the textarea, and update the document to match. - // When something is selected, it is present in the textarea, and - // selected (unless it is huge, in which case a placeholder is - // used). When nothing is selected, the cursor sits after previously - // seen text (can be empty), which is stored in prevInput (we must - // not reset the textarea when typing, because that breaks IME). - TextareaInput.prototype.poll = function () { - var this$1 = this; - - var cm = this.cm, input = this.textarea, prevInput = this.prevInput; - // Since this is called a *lot*, try to bail out as cheaply as - // possible when it is clear that nothing happened. hasSelection - // will be the case when there is a lot of text in the textarea, - // in which case reading its value would be expensive. - if (this.contextMenuPending || !cm.state.focused || - (hasSelection(input) && !prevInput && !this.composing) || - cm.isReadOnly() || cm.options.disableInput || cm.state.keySeq) - { return false } - - var text = input.value; - // If nothing changed, bail. - if (text == prevInput && !cm.somethingSelected()) { return false } - // Work around nonsensical selection resetting in IE9/10, and - // inexplicable appearance of private area unicode characters on - // some key combos in Mac (#2689). - if (ie && ie_version >= 9 && this.hasSelection === text || - mac && /[\uf700-\uf7ff]/.test(text)) { - cm.display.input.reset(); - return false - } - - if (cm.doc.sel == cm.display.selForContextMenu) { - var first = text.charCodeAt(0); - if (first == 0x200b && !prevInput) { prevInput = "\u200b"; } - if (first == 0x21da) { this.reset(); return this.cm.execCommand("undo") } - } - // Find the part of the input that is actually new - var same = 0, l = Math.min(prevInput.length, text.length); - while (same < l && prevInput.charCodeAt(same) == text.charCodeAt(same)) { ++same; } - - runInOp(cm, function () { - applyTextInput(cm, text.slice(same), prevInput.length - same, - null, this$1.composing ? "*compose" : null); - - // Don't leave long text in the textarea, since it makes further polling slow - if (text.length > 1000 || text.indexOf("\n") > -1) { input.value = this$1.prevInput = ""; } - else { this$1.prevInput = text; } - - if (this$1.composing) { - this$1.composing.range.clear(); - this$1.composing.range = cm.markText(this$1.composing.start, cm.getCursor("to"), - {className: "CodeMirror-composing"}); - } - }); - return true - }; - - TextareaInput.prototype.ensurePolled = function () { - if (this.pollingFast && this.poll()) { this.pollingFast = false; } - }; - - TextareaInput.prototype.onKeyPress = function () { - if (ie && ie_version >= 9) { this.hasSelection = null; } - this.fastPoll(); - }; - - TextareaInput.prototype.onContextMenu = function (e) { - var input = this, cm = input.cm, display = cm.display, te = input.textarea; - if (input.contextMenuPending) { input.contextMenuPending(); } - var pos = posFromMouse(cm, e), scrollPos = display.scroller.scrollTop; - if (!pos || presto) { return } // Opera is difficult. - - // Reset the current text selection only if the click is done outside of the selection - // and 'resetSelectionOnContextMenu' option is true. - var reset = cm.options.resetSelectionOnContextMenu; - if (reset && cm.doc.sel.contains(pos) == -1) - { operation(cm, setSelection)(cm.doc, simpleSelection(pos), sel_dontScroll); } - - var oldCSS = te.style.cssText, oldWrapperCSS = input.wrapper.style.cssText; - var wrapperBox = input.wrapper.offsetParent.getBoundingClientRect(); - input.wrapper.style.cssText = "position: static"; - te.style.cssText = "position: absolute; width: 30px; height: 30px;\n top: " + (e.clientY - wrapperBox.top - 5) + "px; left: " + (e.clientX - wrapperBox.left - 5) + "px;\n z-index: 1000; background: " + (ie ? "rgba(255, 255, 255, .05)" : "transparent") + ";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; - var oldScrollY; - if (webkit) { oldScrollY = window.scrollY; } // Work around Chrome issue (#2712) - display.input.focus(); - if (webkit) { window.scrollTo(null, oldScrollY); } - display.input.reset(); - // Adds "Select all" to context menu in FF - if (!cm.somethingSelected()) { te.value = input.prevInput = " "; } - input.contextMenuPending = rehide; - display.selForContextMenu = cm.doc.sel; - clearTimeout(display.detectingSelectAll); - - // Select-all will be greyed out if there's nothing to select, so - // this adds a zero-width space so that we can later check whether - // it got selected. - function prepareSelectAllHack() { - if (te.selectionStart != null) { - var selected = cm.somethingSelected(); - var extval = "\u200b" + (selected ? te.value : ""); - te.value = "\u21da"; // Used to catch context-menu undo - te.value = extval; - input.prevInput = selected ? "" : "\u200b"; - te.selectionStart = 1; te.selectionEnd = extval.length; - // Re-set this, in case some other handler touched the - // selection in the meantime. - display.selForContextMenu = cm.doc.sel; - } - } - function rehide() { - if (input.contextMenuPending != rehide) { return } - input.contextMenuPending = false; - input.wrapper.style.cssText = oldWrapperCSS; - te.style.cssText = oldCSS; - if (ie && ie_version < 9) { display.scrollbars.setScrollTop(display.scroller.scrollTop = scrollPos); } - - // Try to detect the user choosing select-all - if (te.selectionStart != null) { - if (!ie || (ie && ie_version < 9)) { prepareSelectAllHack(); } - var i = 0, poll = function () { - if (display.selForContextMenu == cm.doc.sel && te.selectionStart == 0 && - te.selectionEnd > 0 && input.prevInput == "\u200b") { - operation(cm, selectAll)(cm); - } else if (i++ < 10) { - display.detectingSelectAll = setTimeout(poll, 500); - } else { - display.selForContextMenu = null; - display.input.reset(); - } - }; - display.detectingSelectAll = setTimeout(poll, 200); - } - } - - if (ie && ie_version >= 9) { prepareSelectAllHack(); } - if (captureRightClick) { - e_stop(e); - var mouseup = function () { - off(window, "mouseup", mouseup); - setTimeout(rehide, 20); - }; - on(window, "mouseup", mouseup); - } else { - setTimeout(rehide, 50); - } - }; - - TextareaInput.prototype.readOnlyChanged = function (val) { - if (!val) { this.reset(); } - this.textarea.disabled = val == "nocursor"; - this.textarea.readOnly = !!val; - }; - - TextareaInput.prototype.setUneditable = function () {}; - - TextareaInput.prototype.needsContentAttribute = false; - - function fromTextArea(textarea, options) { - options = options ? copyObj(options) : {}; - options.value = textarea.value; - if (!options.tabindex && textarea.tabIndex) - { options.tabindex = textarea.tabIndex; } - if (!options.placeholder && textarea.placeholder) - { options.placeholder = textarea.placeholder; } - // Set autofocus to true if this textarea is focused, or if it has - // autofocus and no other element is focused. - if (options.autofocus == null) { - var hasFocus = activeElt(); - options.autofocus = hasFocus == textarea || - textarea.getAttribute("autofocus") != null && hasFocus == document.body; - } - - function save() {textarea.value = cm.getValue();} - - var realSubmit; - if (textarea.form) { - on(textarea.form, "submit", save); - // Deplorable hack to make the submit method do the right thing. - if (!options.leaveSubmitMethodAlone) { - var form = textarea.form; - realSubmit = form.submit; - try { - var wrappedSubmit = form.submit = function () { - save(); - form.submit = realSubmit; - form.submit(); - form.submit = wrappedSubmit; - }; - } catch(e) {} - } - } - - options.finishInit = function (cm) { - cm.save = save; - cm.getTextArea = function () { return textarea; }; - cm.toTextArea = function () { - cm.toTextArea = isNaN; // Prevent this from being ran twice - save(); - textarea.parentNode.removeChild(cm.getWrapperElement()); - textarea.style.display = ""; - if (textarea.form) { - off(textarea.form, "submit", save); - if (!options.leaveSubmitMethodAlone && typeof textarea.form.submit == "function") - { textarea.form.submit = realSubmit; } - } - }; - }; - - textarea.style.display = "none"; - var cm = CodeMirror(function (node) { return textarea.parentNode.insertBefore(node, textarea.nextSibling); }, - options); - return cm - } - - function addLegacyProps(CodeMirror) { - CodeMirror.off = off; - CodeMirror.on = on; - CodeMirror.wheelEventPixels = wheelEventPixels; - CodeMirror.Doc = Doc; - CodeMirror.splitLines = splitLinesAuto; - CodeMirror.countColumn = countColumn; - CodeMirror.findColumn = findColumn; - CodeMirror.isWordChar = isWordCharBasic; - CodeMirror.Pass = Pass; - CodeMirror.signal = signal; - CodeMirror.Line = Line; - CodeMirror.changeEnd = changeEnd; - CodeMirror.scrollbarModel = scrollbarModel; - CodeMirror.Pos = Pos; - CodeMirror.cmpPos = cmp; - CodeMirror.modes = modes; - CodeMirror.mimeModes = mimeModes; - CodeMirror.resolveMode = resolveMode; - CodeMirror.getMode = getMode; - CodeMirror.modeExtensions = modeExtensions; - CodeMirror.extendMode = extendMode; - CodeMirror.copyState = copyState; - CodeMirror.startState = startState; - CodeMirror.innerMode = innerMode; - CodeMirror.commands = commands; - CodeMirror.keyMap = keyMap; - CodeMirror.keyName = keyName; - CodeMirror.isModifierKey = isModifierKey; - CodeMirror.lookupKey = lookupKey; - CodeMirror.normalizeKeyMap = normalizeKeyMap; - CodeMirror.StringStream = StringStream; - CodeMirror.SharedTextMarker = SharedTextMarker; - CodeMirror.TextMarker = TextMarker; - CodeMirror.LineWidget = LineWidget; - CodeMirror.e_preventDefault = e_preventDefault; - CodeMirror.e_stopPropagation = e_stopPropagation; - CodeMirror.e_stop = e_stop; - CodeMirror.addClass = addClass; - CodeMirror.contains = contains; - CodeMirror.rmClass = rmClass; - CodeMirror.keyNames = keyNames; - } - - // EDITOR CONSTRUCTOR - - defineOptions(CodeMirror); - - addEditorMethods(CodeMirror); - - // Set up methods on CodeMirror's prototype to redirect to the editor's document. - var dontDelegate = "iter insert remove copy getEditor constructor".split(" "); - for (var prop in Doc.prototype) { if (Doc.prototype.hasOwnProperty(prop) && indexOf(dontDelegate, prop) < 0) - { CodeMirror.prototype[prop] = (function(method) { - return function() {return method.apply(this.doc, arguments)} - })(Doc.prototype[prop]); } } - - eventMixin(Doc); - CodeMirror.inputStyles = {"textarea": TextareaInput, "contenteditable": ContentEditableInput}; - - // Extra arguments are stored as the mode's dependencies, which is - // used by (legacy) mechanisms like loadmode.js to automatically - // load a mode. (Preferred mechanism is the require/define calls.) - CodeMirror.defineMode = function(name/*, mode, …*/) { - if (!CodeMirror.defaults.mode && name != "null") { CodeMirror.defaults.mode = name; } - defineMode.apply(this, arguments); - }; - - CodeMirror.defineMIME = defineMIME; - - // Minimal default mode. - CodeMirror.defineMode("null", function () { return ({token: function (stream) { return stream.skipToEnd(); }}); }); - CodeMirror.defineMIME("text/plain", "null"); - - // EXTENSIONS - - CodeMirror.defineExtension = function (name, func) { - CodeMirror.prototype[name] = func; - }; - CodeMirror.defineDocExtension = function (name, func) { - Doc.prototype[name] = func; - }; - - CodeMirror.fromTextArea = fromTextArea; - - addLegacyProps(CodeMirror); - - CodeMirror.version = "5.58.3"; - - return CodeMirror; - -}))); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).CodeMirror=t()}(this,function(){"use strict";var e=navigator.userAgent,t=navigator.platform,d=/gecko\/\d/i.test(e),n=/MSIE \d/.test(e),r=/Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(e),i=/Edge\/(\d+)/.exec(e),w=n||r||i,v=w&&(n?document.documentMode||6:+(i||r)[1]),f=!i&&/WebKit\//.test(e),r=f&&/Qt\/\d+\.\d+/.test(e),o=!i&&/Chrome\//.test(e),p=/Opera\//.test(e),c=/Apple Computer/.test(navigator.vendor),l=/Mac OS X 1\d\D([8-9]|\d\d)\D/.test(e),u=/PhantomJS/.test(e),s=!i&&/AppleWebKit/.test(e)&&/Mobile\/\w+/.test(e),a=/Android/.test(e),h=s||a||/webOS|BlackBerry|Opera Mini|Opera Mobi|IEMobile/i.test(e),g=s||/Mac/.test(t),m=/\bCrOS\b/.test(e),y=/win/i.test(t),e=p&&e.match(/Version\/(\d*\.\d*)/);(e=e&&Number(e[1]))&&15<=e&&(f=!(p=!1));var b=g&&(r||p&&(null==e||e<12.11)),x=d||w&&9<=v;function C(e){return new RegExp("(^|\\s)"+e+"(?:$|\\s)\\s*")}var S,L=function(e,t){var n=e.className,r=C(t).exec(n);r&&(t=n.slice(r.index+r[0].length),e.className=n.slice(0,r.index)+(t?r[1]+t:""))};function k(e){for(var t=e.childNodes.length;0<t;--t)e.removeChild(e.firstChild);return e}function T(e,t){return k(e).appendChild(t)}function M(e,t,n,r){var i=document.createElement(e);if(n&&(i.className=n),r&&(i.style.cssText=r),"string"==typeof t)i.appendChild(document.createTextNode(t));else if(t)for(var o=0;o<t.length;++o)i.appendChild(t[o]);return i}function N(e,t,n,r){r=M(e,t,n,r);return r.setAttribute("role","presentation"),r}function A(e,t){if(3==t.nodeType&&(t=t.parentNode),e.contains)return e.contains(t);do{if(11==t.nodeType&&(t=t.host),t==e)return!0}while(t=t.parentNode)}function O(){var t;try{t=document.activeElement}catch(e){t=document.body||null}for(;t&&t.shadowRoot&&t.shadowRoot.activeElement;)t=t.shadowRoot.activeElement;return t}function D(e,t){var n=e.className;C(t).test(n)||(e.className+=(n?" ":"")+t)}function W(e,t){for(var n=e.split(" "),r=0;r<n.length;r++)n[r]&&!C(n[r]).test(t)&&(t+=" "+n[r]);return t}S=document.createRange?function(e,t,n,r){var i=document.createRange();return i.setEnd(r||e,n),i.setStart(e,t),i}:function(e,t,n){var r=document.body.createTextRange();try{r.moveToElementText(e.parentNode)}catch(e){return r}return r.collapse(!0),r.moveEnd("character",n),r.moveStart("character",t),r};var H=function(e){e.select()};function F(e){var t=Array.prototype.slice.call(arguments,1);return function(){return e.apply(null,t)}}function E(e,t,n){for(var r in t=t||{},e)!e.hasOwnProperty(r)||!1===n&&t.hasOwnProperty(r)||(t[r]=e[r]);return t}function P(e,t,n,r,i){null==t&&-1==(t=e.search(/[^\s\u00a0]/))&&(t=e.length);for(var o=r||0,l=i||0;;){var s=e.indexOf("\t",o);if(s<0||t<=s)return l+(t-o);l+=s-o,l+=n-l%n,o=s+1}}s?H=function(e){e.selectionStart=0,e.selectionEnd=e.value.length}:w&&(H=function(e){try{e.select()}catch(e){}});var I=function(){this.id=null,this.f=null,this.time=0,this.handler=F(this.onTimeout,this)};function R(e,t){for(var n=0;n<e.length;++n)if(e[n]==t)return n;return-1}I.prototype.onTimeout=function(e){e.id=0,e.time<=+new Date?e.f():setTimeout(e.handler,e.time-+new Date)},I.prototype.set=function(e,t){this.f=t;t=+new Date+e;(!this.id||t<this.time)&&(clearTimeout(this.id),this.id=setTimeout(this.handler,e),this.time=t)};var z=50,B={toString:function(){return"CodeMirror.Pass"}},G={scroll:!1},U={origin:"*mouse"},V={origin:"+move"};function K(e,t,n){for(var r=0,i=0;;){var o=e.indexOf("\t",r);-1==o&&(o=e.length);var l=o-r;if(o==e.length||t<=i+l)return r+Math.min(l,t-i);if(i+=o-r,r=o+1,t<=(i+=n-i%n))return r}}var j=[""];function X(e){for(;j.length<=e;)j.push(Y(j)+" ");return j[e]}function Y(e){return e[e.length-1]}function _(e,t){for(var n=[],r=0;r<e.length;r++)n[r]=t(e[r],r);return n}function $(){}function q(e,t){e=Object.create?Object.create(e):($.prototype=e,new $);return t&&E(t,e),e}var Z=/[\u00df\u0587\u0590-\u05f4\u0600-\u06ff\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc\uac00-\ud7af]/;function Q(e){return/\w/.test(e)||"€"<e&&(e.toUpperCase()!=e.toLowerCase()||Z.test(e))}function J(e,t){return t?!!(-1<t.source.indexOf("\\w")&&Q(e))||t.test(e):Q(e)}function ee(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t])return;return 1}var te=/[\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065e\u0670\u06d6-\u06dc\u06de-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0900-\u0902\u093c\u0941-\u0948\u094d\u0951-\u0955\u0962\u0963\u0981\u09bc\u09be\u09c1-\u09c4\u09cd\u09d7\u09e2\u09e3\u0a01\u0a02\u0a3c\u0a41\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81\u0a82\u0abc\u0ac1-\u0ac5\u0ac7\u0ac8\u0acd\u0ae2\u0ae3\u0b01\u0b3c\u0b3e\u0b3f\u0b41-\u0b44\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe\u0bc0\u0bcd\u0bd7\u0c3e-\u0c40\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0cbc\u0cbf\u0cc2\u0cc6\u0ccc\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d3e\u0d41-\u0d44\u0d4d\u0d57\u0d62\u0d63\u0dca\u0dcf\u0dd2-\u0dd4\u0dd6\u0ddf\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f71-\u0f7e\u0f80-\u0f84\u0f86\u0f87\u0f90-\u0f97\u0f99-\u0fbc\u0fc6\u102d-\u1030\u1032-\u1037\u1039\u103a\u103d\u103e\u1058\u1059\u105e-\u1060\u1071-\u1074\u1082\u1085\u1086\u108d\u109d\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b7-\u17bd\u17c6\u17c9-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u1922\u1927\u1928\u1932\u1939-\u193b\u1a17\u1a18\u1a56\u1a58-\u1a5e\u1a60\u1a62\u1a65-\u1a6c\u1a73-\u1a7c\u1a7f\u1b00-\u1b03\u1b34\u1b36-\u1b3a\u1b3c\u1b42\u1b6b-\u1b73\u1b80\u1b81\u1ba2-\u1ba5\u1ba8\u1ba9\u1c2c-\u1c33\u1c36\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce0\u1ce2-\u1ce8\u1ced\u1dc0-\u1de6\u1dfd-\u1dff\u200c\u200d\u20d0-\u20f0\u2cef-\u2cf1\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua67c\ua67d\ua6f0\ua6f1\ua802\ua806\ua80b\ua825\ua826\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua951\ua980-\ua982\ua9b3\ua9b6-\ua9b9\ua9bc\uaa29-\uaa2e\uaa31\uaa32\uaa35\uaa36\uaa43\uaa4c\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uabe5\uabe8\uabed\udc00-\udfff\ufb1e\ufe00-\ufe0f\ufe20-\ufe26\uff9e\uff9f]/;function ne(e){return 768<=e.charCodeAt(0)&&te.test(e)}function re(e,t,n){for(;(n<0?0<t:t<e.length)&&ne(e.charAt(t));)t+=n;return t}function ie(e,t,n){for(var r=n<t?-1:1;;){if(t==n)return t;var i=(t+n)/2,i=r<0?Math.ceil(i):Math.floor(i);if(i==t)return e(i)?t:n;e(i)?n=i:t=i+r}}var oe=null;function le(e,t,n){var r;oe=null;for(var i=0;i<e.length;++i){var o=e[i];if(o.from<t&&o.to>t)return i;o.to==t&&(o.from!=o.to&&"before"==n?r=i:oe=i),o.from==t&&(o.from!=o.to&&"before"!=n?r=i:oe=i)}return null!=r?r:oe}var se,ae,ue,ce,he,de,fe,pe=(se="bbbbbbbbbtstwsbbbbbbbbbbbbbbssstwNN%%%NNNNNN,N,N1111111111NNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNNNLLLLLLLLLLLLLLLLLLLLLLLLLLNNNNbbbbbbsbbbbbbbbbbbbbbbbbbbbbbbbbb,N%%%%NNNNLNNNNN%%11NLNNN1LNNNNNLLLLLLLLLLLLLLLLLLLLLLLNLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLN",ae="nnnnnnNNr%%r,rNNmmmmmmmmmmmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmmmmmmmmmmmmmmmnnnnnnnnnn%nnrrrmrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrmmmmmmmnNmmmmmmrrmmNmmmmrr1111111111",ue=/[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/,ce=/[stwN]/,he=/[LRr]/,de=/[Lb1n]/,fe=/[1n]/,function(e,t){var n="ltr"==t?"L":"R";if(0==e.length||"ltr"==t&&!ue.test(e))return!1;for(var r,i=e.length,o=[],l=0;l<i;++l)o.push((r=e.charCodeAt(l))<=247?se.charAt(r):1424<=r&&r<=1524?"R":1536<=r&&r<=1785?ae.charAt(r-1536):1774<=r&&r<=2220?"r":8192<=r&&r<=8203?"w":8204==r?"b":"L");for(var s=0,a=n;s<i;++s){var u=o[s];"m"==u?o[s]=a:a=u}for(var c=0,h=n;c<i;++c){var d=o[c];"1"==d&&"r"==h?o[c]="n":he.test(d)&&"r"==(h=d)&&(o[c]="R")}for(var f=1,p=o[0];f<i-1;++f){var g=o[f];"+"==g&&"1"==p&&"1"==o[f+1]?o[f]="1":","!=g||p!=o[f+1]||"1"!=p&&"n"!=p||(o[f]=p),p=g}for(var m=0;m<i;++m){var v=o[m];if(","==v)o[m]="N";else if("%"==v){for(var y=void 0,y=m+1;y<i&&"%"==o[y];++y);for(var b=m&&"!"==o[m-1]||y<i&&"1"==o[y]?"1":"N",w=m;w<y;++w)o[w]=b;m=y-1}}for(var x=0,C=n;x<i;++x){var S=o[x];"L"==C&&"1"==S?o[x]="L":he.test(S)&&(C=S)}for(var L=0;L<i;++L)if(ce.test(o[L])){for(var k=void 0,k=L+1;k<i&&ce.test(o[k]);++k);for(var T="L"==(L?o[L-1]:n),M=T==("L"==(k<i?o[k]:n))?T?"L":"R":n,N=L;N<k;++N)o[N]=M;L=k-1}for(var A,O=[],D=0;D<i;)if(de.test(o[D])){var W=D;for(++D;D<i&&de.test(o[D]);++D);O.push(new ge(0,W,D))}else{var H=D,F=O.length,E="rtl"==t?1:0;for(++D;D<i&&"L"!=o[D];++D);for(var P=H;P<D;)if(fe.test(o[P])){H<P&&(O.splice(F,0,new ge(1,H,P)),F+=E);var I=P;for(++P;P<D&&fe.test(o[P]);++P);O.splice(F,0,new ge(2,I,P)),F+=E,H=P}else++P;H<D&&O.splice(F,0,new ge(1,H,D))}return"ltr"==t&&(1==O[0].level&&(A=e.match(/^\s+/))&&(O[0].from=A[0].length,O.unshift(new ge(0,0,A[0].length))),1==Y(O).level&&(A=e.match(/\s+$/))&&(Y(O).to-=A[0].length,O.push(new ge(0,i-A[0].length,i)))),"rtl"==t?O.reverse():O});function ge(e,t,n){this.level=e,this.from=t,this.to=n}function me(e,t){var n=e.order;return null==n&&(n=e.order=pe(e.text,t)),n}var ve=[],ye=function(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent?e.attachEvent("on"+t,n):(e=e._handlers||(e._handlers={}))[t]=(e[t]||ve).concat(n)};function be(e,t){return e._handlers&&e._handlers[t]||ve}function we(e,t,n){var r;e.removeEventListener?e.removeEventListener(t,n,!1):e.detachEvent?e.detachEvent("on"+t,n):!(e=(r=e._handlers)&&r[t])||-1<(n=R(e,n))&&(r[t]=e.slice(0,n).concat(e.slice(n+1)))}function xe(e,t){var n=be(e,t);if(n.length)for(var r=Array.prototype.slice.call(arguments,2),i=0;i<n.length;++i)n[i].apply(null,r)}function Ce(e,t,n){return"string"==typeof t&&(t={type:t,preventDefault:function(){this.defaultPrevented=!0}}),xe(e,n||t.type,e,t),Ne(t)||t.codemirrorIgnore}function Se(e){var t=e._handlers&&e._handlers.cursorActivity;if(t)for(var n=e.curOp.cursorActivityHandlers||(e.curOp.cursorActivityHandlers=[]),r=0;r<t.length;++r)-1==R(n,t[r])&&n.push(t[r])}function Le(e,t){return 0<be(e,t).length}function ke(e){e.prototype.on=function(e,t){ye(this,e,t)},e.prototype.off=function(e,t){we(this,e,t)}}function Te(e){e.preventDefault?e.preventDefault():e.returnValue=!1}function Me(e){e.stopPropagation?e.stopPropagation():e.cancelBubble=!0}function Ne(e){return null!=e.defaultPrevented?e.defaultPrevented:0==e.returnValue}function Ae(e){Te(e),Me(e)}function Oe(e){return e.target||e.srcElement}function De(e){var t=e.which;return null==t&&(1&e.button?t=1:2&e.button?t=3:4&e.button&&(t=2)),g&&e.ctrlKey&&1==t&&(t=3),t}var We,He,Fe=function(){if(w&&v<9)return!1;var e=M("div");return"draggable"in e||"dragDrop"in e}();var Ee=3!="\n\nb".split(/\n/).length?function(e){for(var t=0,n=[],r=e.length;t<=r;){var i=e.indexOf("\n",t);-1==i&&(i=e.length);var o=e.slice(t,"\r"==e.charAt(i-1)?i-1:i),l=o.indexOf("\r");-1!=l?(n.push(o.slice(0,l)),t+=l+1):(n.push(o),t=i+1)}return n}:function(e){return e.split(/\r\n?|\n/)},Pe=window.getSelection?function(e){try{return e.selectionStart!=e.selectionEnd}catch(e){return!1}}:function(e){var t;try{t=e.ownerDocument.selection.createRange()}catch(e){}return!(!t||t.parentElement()!=e)&&0!=t.compareEndPoints("StartToEnd",t)},Ie="oncopy"in(r=M("div"))||(r.setAttribute("oncopy","return;"),"function"==typeof r.oncopy),Re=null;var ze={},Be={};function Ge(e){if("string"==typeof e&&Be.hasOwnProperty(e))e=Be[e];else if(e&&"string"==typeof e.name&&Be.hasOwnProperty(e.name)){var t=Be[e.name];"string"==typeof t&&(t={name:t}),(e=q(t,e)).name=t.name}else{if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+xml$/.test(e))return Ge("application/xml");if("string"==typeof e&&/^[\w\-]+\/[\w\-]+\+json$/.test(e))return Ge("application/json")}return"string"==typeof e?{name:e}:e||{name:"null"}}function Ue(e,t){t=Ge(t);var n=ze[t.name];if(!n)return Ue(e,"text/plain");var r=n(e,t);if(Ve.hasOwnProperty(t.name)){var i,o=Ve[t.name];for(i in o)o.hasOwnProperty(i)&&(r.hasOwnProperty(i)&&(r["_"+i]=r[i]),r[i]=o[i])}if(r.name=t.name,t.helperType&&(r.helperType=t.helperType),t.modeProps)for(var l in t.modeProps)r[l]=t.modeProps[l];return r}var Ve={};function Ke(e,t){E(t,Ve.hasOwnProperty(e)?Ve[e]:Ve[e]={})}function je(e,t){if(!0===t)return t;if(e.copyState)return e.copyState(t);var n,r={};for(n in t){var i=t[n];i instanceof Array&&(i=i.concat([])),r[n]=i}return r}function Xe(e,t){for(var n;e.innerMode&&(n=e.innerMode(t))&&n.mode!=e;)t=n.state,e=n.mode;return n||{mode:e,state:t}}function Ye(e,t,n){return!e.startState||e.startState(t,n)}var _e=function(e,t,n){this.pos=this.start=0,this.string=e,this.tabSize=t||8,this.lastColumnPos=this.lastColumnValue=0,this.lineStart=0,this.lineOracle=n};function $e(e,t){if((t-=e.first)<0||t>=e.size)throw new Error("There is no line "+(t+e.first)+" in the document.");for(var n=e;!n.lines;)for(var r=0;;++r){var i=n.children[r],o=i.chunkSize();if(t<o){n=i;break}t-=o}return n.lines[t]}function qe(e,t,n){var r=[],i=t.line;return e.iter(t.line,n.line+1,function(e){e=e.text;i==n.line&&(e=e.slice(0,n.ch)),i==t.line&&(e=e.slice(t.ch)),r.push(e),++i}),r}function Ze(e,t,n){var r=[];return e.iter(t,n,function(e){r.push(e.text)}),r}function Qe(e,t){var n=t-e.height;if(n)for(var r=e;r;r=r.parent)r.height+=n}function Je(e){if(null==e.parent)return null;for(var t=e.parent,n=R(t.lines,e),r=t.parent;r;r=(t=r).parent)for(var i=0;r.children[i]!=t;++i)n+=r.children[i].chunkSize();return n+t.first}function et(e,t){var n=e.first;e:do{for(var r=0;r<e.children.length;++r){var i=e.children[r],o=i.height;if(t<o){e=i;continue e}t-=o,n+=i.chunkSize()}return n}while(!e.lines);for(var l=0;l<e.lines.length;++l){var s=e.lines[l].height;if(t<s)break;t-=s}return n+l}function tt(e,t){return t>=e.first&&t<e.first+e.size}function nt(e,t){return String(e.lineNumberFormatter(t+e.firstLineNumber))}function rt(e,t,n){if(void 0===n&&(n=null),!(this instanceof rt))return new rt(e,t,n);this.line=e,this.ch=t,this.sticky=n}function it(e,t){return e.line-t.line||e.ch-t.ch}function ot(e,t){return e.sticky==t.sticky&&0==it(e,t)}function lt(e){return rt(e.line,e.ch)}function st(e,t){return it(e,t)<0?t:e}function at(e,t){return it(e,t)<0?e:t}function ut(e,t){return Math.max(e.first,Math.min(t,e.first+e.size-1))}function ct(e,t){if(t.line<e.first)return rt(e.first,0);var n=e.first+e.size-1;return t.line>n?rt(n,$e(e,n).text.length):(e=$e(e,(n=t).line).text.length,null==(t=n.ch)||e<t?rt(n.line,e):t<0?rt(n.line,0):n)}function ht(e,t){for(var n=[],r=0;r<t.length;r++)n[r]=ct(e,t[r]);return n}_e.prototype.eol=function(){return this.pos>=this.string.length},_e.prototype.sol=function(){return this.pos==this.lineStart},_e.prototype.peek=function(){return this.string.charAt(this.pos)||void 0},_e.prototype.next=function(){if(this.pos<this.string.length)return this.string.charAt(this.pos++)},_e.prototype.eat=function(e){var t=this.string.charAt(this.pos),e="string"==typeof e?t==e:t&&(e.test?e.test(t):e(t));if(e)return++this.pos,t},_e.prototype.eatWhile=function(e){for(var t=this.pos;this.eat(e););return this.pos>t},_e.prototype.eatSpace=function(){for(var e=this.pos;/[\s\u00a0]/.test(this.string.charAt(this.pos));)++this.pos;return this.pos>e},_e.prototype.skipToEnd=function(){this.pos=this.string.length},_e.prototype.skipTo=function(e){e=this.string.indexOf(e,this.pos);if(-1<e)return this.pos=e,!0},_e.prototype.backUp=function(e){this.pos-=e},_e.prototype.column=function(){return this.lastColumnPos<this.start&&(this.lastColumnValue=P(this.string,this.start,this.tabSize,this.lastColumnPos,this.lastColumnValue),this.lastColumnPos=this.start),this.lastColumnValue-(this.lineStart?P(this.string,this.lineStart,this.tabSize):0)},_e.prototype.indentation=function(){return P(this.string,null,this.tabSize)-(this.lineStart?P(this.string,this.lineStart,this.tabSize):0)},_e.prototype.match=function(e,t,n){if("string"!=typeof e){var r=this.string.slice(this.pos).match(e);return r&&0<r.index?null:(r&&!1!==t&&(this.pos+=r[0].length),r)}r=function(e){return n?e.toLowerCase():e};if(r(this.string.substr(this.pos,e.length))==r(e))return!1!==t&&(this.pos+=e.length),!0},_e.prototype.current=function(){return this.string.slice(this.start,this.pos)},_e.prototype.hideFirstChars=function(e,t){this.lineStart+=e;try{return t()}finally{this.lineStart-=e}},_e.prototype.lookAhead=function(e){var t=this.lineOracle;return t&&t.lookAhead(e)},_e.prototype.baseToken=function(){var e=this.lineOracle;return e&&e.baseToken(this.pos)};var dt=function(e,t){this.state=e,this.lookAhead=t},ft=function(e,t,n,r){this.state=t,this.doc=e,this.line=n,this.maxLookAhead=r||0,this.baseTokens=null,this.baseTokenPos=1};function pt(t,n,r,e){var a=[t.state.modeGen],i={};St(t,n.text,t.doc.mode,r,function(e,t){return a.push(e,t)},i,e);for(var u=r.state,o=0;o<t.state.overlays.length;++o)!function(e){r.baseTokens=a;var o=t.state.overlays[e],l=1,s=0;r.state=!0,St(t,n.text,o.mode,r,function(e,t){for(var n=l;s<e;){var r=a[l];e<r&&a.splice(l,1,e,a[l+1],r),l+=2,s=Math.min(e,r)}if(t)if(o.opaque)a.splice(n,l-n,e,"overlay "+t),l=n+2;else for(;n<l;n+=2){var i=a[n+1];a[n+1]=(i?i+" ":"")+"overlay "+t}},i),r.state=u,r.baseTokens=null,r.baseTokenPos=1}(o);return{styles:a,classes:i.bgClass||i.textClass?i:null}}function gt(e,t,n){var r,i,o;return t.styles&&t.styles[0]==e.state.modeGen||(r=mt(e,Je(t)),i=t.text.length>e.options.maxHighlightLength&&je(e.doc.mode,r.state),o=pt(e,t,r),i&&(r.state=i),t.stateAfter=r.save(!i),t.styles=o.styles,o.classes?t.styleClasses=o.classes:t.styleClasses&&(t.styleClasses=null),n===e.doc.highlightFrontier&&(e.doc.modeFrontier=Math.max(e.doc.modeFrontier,++e.doc.highlightFrontier))),t.styles}function mt(n,r,e){var t=n.doc,i=n.display;if(!t.mode.startState)return new ft(t,!0,r);var o=function(e,t,n){for(var r,i,o=e.doc,l=n?-1:t-(e.doc.mode.innerMode?1e3:100),s=t;l<s;--s){if(s<=o.first)return o.first;var a=$e(o,s-1),u=a.stateAfter;if(u&&(!n||s+(u instanceof dt?u.lookAhead:0)<=o.modeFrontier))return s;a=P(a.text,null,e.options.tabSize);(null==i||a<r)&&(i=s-1,r=a)}return i}(n,r,e),l=o>t.first&&$e(t,o-1).stateAfter,s=l?ft.fromSaved(t,l,o):new ft(t,Ye(t.mode),o);return t.iter(o,r,function(e){vt(n,e.text,s);var t=s.line;e.stateAfter=t==r-1||t%5==0||t>=i.viewFrom&&t<i.viewTo?s.save():null,s.nextLine()}),e&&(t.modeFrontier=s.line),s}function vt(e,t,n,r){var i=e.doc.mode,o=new _e(t,e.options.tabSize,n);for(o.start=o.pos=r||0,""==t&&yt(i,n.state);!o.eol();)bt(i,o,n.state),o.start=o.pos}function yt(e,t){if(e.blankLine)return e.blankLine(t);if(e.innerMode){t=Xe(e,t);return t.mode.blankLine?t.mode.blankLine(t.state):void 0}}function bt(e,t,n,r){for(var i=0;i<10;i++){r&&(r[0]=Xe(e,n).mode);var o=e.token(t,n);if(t.pos>t.start)return o}throw new Error("Mode "+e.name+" failed to advance stream.")}ft.prototype.lookAhead=function(e){var t=this.doc.getLine(this.line+e);return null!=t&&e>this.maxLookAhead&&(this.maxLookAhead=e),t},ft.prototype.baseToken=function(e){if(!this.baseTokens)return null;for(;this.baseTokens[this.baseTokenPos]<=e;)this.baseTokenPos+=2;var t=this.baseTokens[this.baseTokenPos+1];return{type:t&&t.replace(/( |^)overlay .*/,""),size:this.baseTokens[this.baseTokenPos]-e}},ft.prototype.nextLine=function(){this.line++,0<this.maxLookAhead&&this.maxLookAhead--},ft.fromSaved=function(e,t,n){return t instanceof dt?new ft(e,je(e.mode,t.state),n,t.lookAhead):new ft(e,je(e.mode,t),n)},ft.prototype.save=function(e){e=!1!==e?je(this.doc.mode,this.state):this.state;return 0<this.maxLookAhead?new dt(e,this.maxLookAhead):e};var wt=function(e,t,n){this.start=e.start,this.end=e.pos,this.string=e.current(),this.type=t||null,this.state=n};function xt(e,t,n,r){var i,o,l=e.doc,s=l.mode,a=$e(l,(t=ct(l,t)).line),u=mt(e,t.line,n),c=new _e(a.text,e.options.tabSize,u);for(r&&(o=[]);(r||c.pos<t.ch)&&!c.eol();)c.start=c.pos,i=bt(s,c,u.state),r&&o.push(new wt(c,i,je(l.mode,u.state)));return r?o:new wt(c,i,u.state)}function Ct(e,t){if(e)for(;;){var n=e.match(/(?:^|\s+)line-(background-)?(\S+)/);if(!n)break;e=e.slice(0,n.index)+e.slice(n.index+n[0].length);var r=n[1]?"bgClass":"textClass";null==t[r]?t[r]=n[2]:new RegExp("(?:^|\\s)"+n[2]+"(?:$|\\s)").test(t[r])||(t[r]+=" "+n[2])}return e}function St(e,t,n,r,i,o,l){var s=n.flattenSpans;null==s&&(s=e.options.flattenSpans);var a=0,u=null,c=new _e(t,e.options.tabSize,r),h=e.options.addModeClass&&[null];for(""==t&&Ct(yt(n,r.state),o);!c.eol();){var d,f=c.pos>e.options.maxHighlightLength?(s=!1,l&&vt(e,t,r,c.pos),c.pos=t.length,null):Ct(bt(n,c,r.state,h),o);if(!h||(d=h[0].name)&&(f="m-"+(f?d+" "+f:d)),!s||u!=f){for(;a<c.start;)i(a=Math.min(c.start,a+5e3),u);u=f}c.start=c.pos}for(;a<c.pos;){var p=Math.min(c.pos,a+5e3);i(p,u),a=p}}var Lt=!1,kt=!1;function Tt(e,t,n){this.marker=e,this.from=t,this.to=n}function Mt(e,t){if(e)for(var n=0;n<e.length;++n){var r=e[n];if(r.marker==t)return r}}function Nt(e,t){if(t.full)return null;var n=tt(e,t.from.line)&&$e(e,t.from.line).markedSpans,r=tt(e,t.to.line)&&$e(e,t.to.line).markedSpans;if(!n&&!r)return null;var i=t.from.ch,o=t.to.ch,e=0==it(t.from,t.to),l=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t))&&(l.from!=t||"bookmark"!=s.type||n&&l.marker.insertLeft)||(o=null==l.to||(s.inclusiveRight?l.to>=t:l.to>t),(r=r||[]).push(new Tt(s,l.from,o?null:l.to)))}return r}(n,i,e),s=function(e,t,n){var r;if(e)for(var i=0;i<e.length;++i){var o,l=e[i],s=l.marker;!(null==l.to||(s.inclusiveRight?l.to>=t:l.to>t))&&(l.from!=t||"bookmark"!=s.type||n&&!l.marker.insertLeft)||(o=null==l.from||(s.inclusiveLeft?l.from<=t:l.from<t),(r=r||[]).push(new Tt(s,o?null:l.from-t,null==l.to?null:l.to-t)))}return r}(r,o,e),a=1==t.text.length,u=Y(t.text).length+(a?i:0);if(l)for(var c=0;c<l.length;++c){var h,d=l[c];null==d.to&&((h=Mt(s,d.marker))?a&&(d.to=null==h.to?null:h.to+u):d.to=i)}if(s)for(var f=0;f<s.length;++f){var p=s[f];null!=p.to&&(p.to+=u),null==p.from?Mt(l,p.marker)||(p.from=u,a&&(l=l||[]).push(p)):(p.from+=u,a&&(l=l||[]).push(p))}l=l&&At(l),s&&s!=l&&(s=At(s));var g=[l];if(!a){var m,v=t.text.length-2;if(0<v&&l)for(var y=0;y<l.length;++y)null==l[y].to&&(m=m||[]).push(new Tt(l[y].marker,null,null));for(var b=0;b<v;++b)g.push(m);g.push(s)}return g}function At(e){for(var t=0;t<e.length;++t){var n=e[t];null!=n.from&&n.from==n.to&&!1!==n.marker.clearWhenEmpty&&e.splice(t--,1)}return e.length?e:null}function Ot(e){var t=e.markedSpans;if(t){for(var n=0;n<t.length;++n)t[n].marker.detachLine(e);e.markedSpans=null}}function Dt(e,t){if(t){for(var n=0;n<t.length;++n)t[n].marker.attachLine(e);e.markedSpans=t}}function Wt(e){return e.inclusiveLeft?-1:0}function Ht(e){return e.inclusiveRight?1:0}function Ft(e,t){var n=e.lines.length-t.lines.length;if(0!=n)return n;var r=e.find(),i=t.find(),n=it(r.from,i.from)||Wt(e)-Wt(t);if(n)return-n;i=it(r.to,i.to)||Ht(e)-Ht(t);return i||t.id-e.id}function Et(e,t){var n,r=kt&&e.markedSpans;if(r)for(var i,o=0;o<r.length;++o)(i=r[o]).marker.collapsed&&null==(t?i.from:i.to)&&(!n||Ft(n,i.marker)<0)&&(n=i.marker);return n}function Pt(e){return Et(e,!0)}function It(e){return Et(e,!1)}function Rt(e,t,n,r,i){var t=$e(e,t),o=kt&&t.markedSpans;if(o)for(var l=0;l<o.length;++l){var s=o[l];if(s.marker.collapsed){var a=s.marker.find(0),u=it(a.from,n)||Wt(s.marker)-Wt(i),c=it(a.to,r)||Ht(s.marker)-Ht(i);if(!(0<=u&&c<=0||u<=0&&0<=c)&&(u<=0&&(s.marker.inclusiveRight&&i.inclusiveLeft?0<=it(a.to,n):0<it(a.to,n))||0<=u&&(s.marker.inclusiveRight&&i.inclusiveLeft?it(a.from,r)<=0:it(a.from,r)<0)))return 1}}}function zt(e){for(var t;t=Pt(e);)e=t.find(-1,!0).line;return e}function Bt(e,t){var n=$e(e,t),e=zt(n);return n==e?t:Je(e)}function Gt(e,t){if(t>e.lastLine())return t;var n,r=$e(e,t);if(!Ut(e,r))return t;for(;n=It(r);)r=n.find(1,!0).line;return Je(r)+1}function Ut(e,t){var n=kt&&t.markedSpans;if(n)for(var r,i=0;i<n.length;++i)if((r=n[i]).marker.collapsed){if(null==r.from)return!0;if(!r.marker.widgetNode&&0==r.from&&r.marker.inclusiveLeft&&function e(t,n,r){if(null==r.to){var i=r.marker.find(1,!0);return e(t,i.line,Mt(i.line.markedSpans,r.marker))}if(r.marker.inclusiveRight&&r.to==n.text.length)return!0;for(var o=void 0,l=0;l<n.markedSpans.length;++l)if((o=n.markedSpans[l]).marker.collapsed&&!o.marker.widgetNode&&o.from==r.to&&(null==o.to||o.to!=r.from)&&(o.marker.inclusiveLeft||r.marker.inclusiveRight)&&e(t,n,o))return!0}(e,t,r))return!0}}function Vt(e){for(var t=0,n=(e=zt(e)).parent,r=0;r<n.lines.length;++r){var i=n.lines[r];if(i==e)break;t+=i.height}for(var o=n.parent;o;o=(n=o).parent)for(var l=0;l<o.children.length;++l){var s=o.children[l];if(s==n)break;t+=s.height}return t}function Kt(e){if(0==e.height)return 0;for(var t,n=e.text.length,r=e;t=Pt(r);){var i=t.find(0,!0),r=i.from.line;n+=i.from.ch-i.to.ch}for(r=e;t=It(r);){var o=t.find(0,!0);n-=r.text.length-o.from.ch,n+=(r=o.to.line).text.length-o.to.ch}return n}function jt(e){var n=e.display,e=e.doc;n.maxLine=$e(e,e.first),n.maxLineLength=Kt(n.maxLine),n.maxLineChanged=!0,e.iter(function(e){var t=Kt(e);t>n.maxLineLength&&(n.maxLineLength=t,n.maxLine=e)})}var Xt=function(e,t,n){this.text=e,Dt(this,t),this.height=n?n(this):1};Xt.prototype.lineNo=function(){return Je(this)},ke(Xt);var Yt={},_t={};function $t(e,t){if(!e||/^\s*$/.test(e))return null;t=t.addModeClass?_t:Yt;return t[e]||(t[e]=e.replace(/\S+/g,"cm-$&"))}function qt(e,t){var n=N("span",null,null,f?"padding-right: .1px":null),r={pre:N("pre",[n],"CodeMirror-line"),content:n,col:0,pos:0,cm:e,trailingSpace:!1,splitSpaces:e.getOption("lineWrapping")};t.measure={};for(var i=0;i<=(t.rest?t.rest.length:0);i++){var o=i?t.rest[i-1]:t.line,l=void 0;r.pos=0,r.addToken=Qt,function(e){if(null!=He)return He;var t=T(e,document.createTextNode("AخA")),n=S(t,0,1).getBoundingClientRect(),t=S(t,1,2).getBoundingClientRect();return k(e),n&&n.left!=n.right&&(He=t.right-n.right<3)}(e.display.measure)&&(l=me(o,e.doc.direction))&&(r.addToken=function(h,d){return function(e,t,n,r,i,o,l){n=n?n+" cm-force-border":"cm-force-border";for(var s=e.pos,a=s+t.length;;){for(var u=void 0,c=0;c<d.length&&!((u=d[c]).to>s&&u.from<=s);c++);if(u.to>=a)return h(e,t,n,r,i,o,l);h(e,t.slice(0,u.to-s),n,r,null,o,l),r=null,t=t.slice(u.to-s),s=u.to}}}(r.addToken,l)),r.map=[],function(e,t,n){var r=e.markedSpans,i=e.text,o=0;if(!r){for(var l=1;l<n.length;l+=2)t.addToken(t,i.slice(o,o=n[l]),$t(n[l+1],t.cm.options));return}for(var s,a,u,c,h,d,f,p=i.length,g=0,m=1,v="",y=0;;){if(y==g){u=c=h=a="",d=f=null,y=1/0;for(var b=[],w=void 0,x=0;x<r.length;++x){var C=r[x],S=C.marker;if("bookmark"==S.type&&C.from==g&&S.widgetNode)b.push(S);else if(C.from<=g&&(null==C.to||C.to>g||S.collapsed&&C.to==g&&C.from==g)){if(null!=C.to&&C.to!=g&&y>C.to&&(y=C.to,c=""),S.className&&(u+=" "+S.className),S.css&&(a=(a?a+";":"")+S.css),S.startStyle&&C.from==g&&(h+=" "+S.startStyle),S.endStyle&&C.to==y&&(w=w||[]).push(S.endStyle,C.to),S.title&&((f=f||{}).title=S.title),S.attributes)for(var L in S.attributes)(f=f||{})[L]=S.attributes[L];S.collapsed&&(!d||Ft(d.marker,S)<0)&&(d=C)}else C.from>g&&y>C.from&&(y=C.from)}if(w)for(var k=0;k<w.length;k+=2)w[k+1]==y&&(c+=" "+w[k]);if(!d||d.from==g)for(var T=0;T<b.length;++T)Jt(t,0,b[T]);if(d&&(d.from||0)==g){if(Jt(t,(null==d.to?p+1:d.to)-g,d.marker,null==d.from),null==d.to)return;d.to==g&&(d=!1)}}if(p<=g)break;for(var M=Math.min(p,y);;){if(v){var N,A=g+v.length;if(d||(N=M<A?v.slice(0,M-g):v,t.addToken(t,N,s?s+u:u,h,g+N.length==y?c:"",a,f)),M<=A){v=v.slice(M-g),g=M;break}g=A,h=""}v=i.slice(o,o=n[m++]),s=$t(n[m++],t.cm.options)}}}(o,r,gt(e,o,t!=e.display.externalMeasured&&Je(o))),o.styleClasses&&(o.styleClasses.bgClass&&(r.bgClass=W(o.styleClasses.bgClass,r.bgClass||"")),o.styleClasses.textClass&&(r.textClass=W(o.styleClasses.textClass,r.textClass||""))),0==r.map.length&&r.map.push(0,0,r.content.appendChild(function(e){null==We&&(t=M("span","​"),T(e,M("span",[t,document.createTextNode("x")])),0!=e.firstChild.offsetHeight&&(We=t.offsetWidth<=1&&2<t.offsetHeight&&!(w&&v<8)));var t=We?M("span","​"):M("span"," ",null,"display: inline-block; width: 1px; margin-right: -1px");return t.setAttribute("cm-text",""),t}(e.display.measure))),0==i?(t.measure.map=r.map,t.measure.cache={}):((t.measure.maps||(t.measure.maps=[])).push(r.map),(t.measure.caches||(t.measure.caches=[])).push({}))}return f&&(n=r.content.lastChild,(/\bcm-tab\b/.test(n.className)||n.querySelector&&n.querySelector(".cm-tab"))&&(r.content.className="cm-tab-wrap-hack")),xe(e,"renderLine",e,t.line,r.pre),r.pre.className&&(r.textClass=W(r.pre.className,r.textClass||"")),r}function Zt(e){var t=M("span","•","cm-invalidchar");return t.title="\\u"+e.charCodeAt(0).toString(16),t.setAttribute("aria-label",t.title),t}function Qt(e,t,n,r,i,o,l){if(t){var s,a=e.splitSpaces?function(e,t){if(1<e.length&&!/ /.test(e))return e;for(var n=t,r="",i=0;i<e.length;i++){var o=e.charAt(i);" "!=o||!n||i!=e.length-1&&32!=e.charCodeAt(i+1)||(o=" "),r+=o,n=" "==o}return r}(t,e.trailingSpace):t,u=e.cm.state.specialChars,c=!1;if(u.test(t)){s=document.createDocumentFragment();for(var h=0;;){u.lastIndex=h;var d=u.exec(t),f=d?d.index-h:t.length-h;if(f&&(p=document.createTextNode(a.slice(h,h+f)),w&&v<9?s.appendChild(M("span",[p])):s.appendChild(p),e.map.push(e.pos,e.pos+f,p),e.col+=f,e.pos+=f),!d)break;h+=1+f;var p=void 0;"\t"==d[0]?(f=(f=e.cm.options.tabSize)-e.col%f,(p=s.appendChild(M("span",X(f),"cm-tab"))).setAttribute("role","presentation"),p.setAttribute("cm-text","\t"),e.col+=f):("\r"==d[0]||"\n"==d[0]?(p=s.appendChild(M("span","\r"==d[0]?"␍":"␤","cm-invalidchar"))).setAttribute("cm-text",d[0]):((p=e.cm.options.specialCharPlaceholder(d[0])).setAttribute("cm-text",d[0]),w&&v<9?s.appendChild(M("span",[p])):s.appendChild(p)),e.col+=1),e.map.push(e.pos,e.pos+1,p),e.pos++}}else e.col+=t.length,s=document.createTextNode(a),e.map.push(e.pos,e.pos+t.length,s),w&&v<9&&(c=!0),e.pos+=t.length;if(e.trailingSpace=32==a.charCodeAt(t.length-1),n||r||i||c||o||l){n=n||"";r&&(n+=r),i&&(n+=i);var g=M("span",[s],n,o);if(l)for(var m in l)l.hasOwnProperty(m)&&"style"!=m&&"class"!=m&&g.setAttribute(m,l[m]);return e.content.appendChild(g)}e.content.appendChild(s)}}function Jt(e,t,n,r){var i=!r&&n.widgetNode;i&&e.map.push(e.pos,e.pos+t,i),!r&&e.cm.display.input.needsContentAttribute&&(i=i||e.content.appendChild(document.createElement("span"))).setAttribute("cm-marker",n.id),i&&(e.cm.display.input.setUneditable(i),e.content.appendChild(i)),e.pos+=t,e.trailingSpace=!1}function en(e,t,n){this.line=t,this.rest=function(e){for(var t,n;t=It(e);)e=t.find(1,!0).line,(n=n||[]).push(e);return n}(t),this.size=this.rest?Je(Y(this.rest))-n+1:1,this.node=this.text=null,this.hidden=Ut(e,t)}function tn(e,t,n){for(var r=[],i=t;i<n;i=l){var o=new en(e.doc,$e(e.doc,i),i),l=i+o.size;r.push(o)}return r}var nn=null;function rn(e,t){var n=e.ownsGroup;if(n)try{!function(e){var t=e.delayedCallbacks,n=0;do{for(;n<t.length;n++)t[n].call(null);for(var r=0;r<e.ops.length;r++){var i=e.ops[r];if(i.cursorActivityHandlers)for(;i.cursorActivityCalled<i.cursorActivityHandlers.length;)i.cursorActivityHandlers[i.cursorActivityCalled++].call(null,i.cm)}}while(n<t.length)}(n)}finally{nn=null,t(n)}}var on=null;function ln(e,t){var n=be(e,t);if(n.length){var r,i=Array.prototype.slice.call(arguments,2);nn?r=nn.delayedCallbacks:on?r=on:(r=on=[],setTimeout(sn,0));for(var o=0;o<n.length;++o)!function(e){r.push(function(){return n[e].apply(null,i)})}(o)}}function sn(){var e=on;on=null;for(var t=0;t<e.length;++t)e[t]()}function an(e,t,n,r){for(var i=0;i<t.changes.length;i++){var o=t.changes[i];"text"==o?function(e,t){var n=t.text.className,r=cn(e,t);t.text==t.node&&(t.node=r.pre);t.text.parentNode.replaceChild(r.pre,t.text),t.text=r.pre,r.bgClass!=t.bgClass||r.textClass!=t.textClass?(t.bgClass=r.bgClass,t.textClass=r.textClass,hn(e,t)):n&&(t.text.className=n)}(e,t):"gutter"==o?dn(e,t,n,r):"class"==o?hn(e,t):"widget"==o&&function(e,t,n){t.alignable&&(t.alignable=null);for(var r=C("CodeMirror-linewidget"),i=t.node.firstChild,o=void 0;i;i=o)o=i.nextSibling,r.test(i.className)&&t.node.removeChild(i);fn(e,t,n)}(e,t,r)}t.changes=null}function un(e){return e.node==e.text&&(e.node=M("div",null,null,"position: relative"),e.text.parentNode&&e.text.parentNode.replaceChild(e.node,e.text),e.node.appendChild(e.text),w&&v<8&&(e.node.style.zIndex=2)),e.node}function cn(e,t){var n=e.display.externalMeasured;return n&&n.line==t.line?(e.display.externalMeasured=null,t.measure=n.measure,n.built):qt(e,t)}function hn(e,t){var n,r;n=e,(r=(i=t).bgClass?i.bgClass+" "+(i.line.bgClass||""):i.line.bgClass)&&(r+=" CodeMirror-linebackground"),i.background?r?i.background.className=r:(i.background.parentNode.removeChild(i.background),i.background=null):r&&(e=un(i),i.background=e.insertBefore(M("div",null,r),e.firstChild),n.display.input.setUneditable(i.background)),t.line.wrapClass?un(t).className=t.line.wrapClass:t.node!=t.text&&(t.node.className="");var i=t.textClass?t.textClass+" "+(t.line.textClass||""):t.line.textClass;t.text.className=i||""}function dn(e,t,n,r){t.gutter&&(t.node.removeChild(t.gutter),t.gutter=null),t.gutterBackground&&(t.node.removeChild(t.gutterBackground),t.gutterBackground=null),t.line.gutterClass&&(o=un(t),t.gutterBackground=M("div",null,"CodeMirror-gutter-background "+t.line.gutterClass,"left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px; width: "+r.gutterTotalWidth+"px"),e.display.input.setUneditable(t.gutterBackground),o.insertBefore(t.gutterBackground,t.text));var i=t.line.gutterMarkers;if(e.options.lineNumbers||i){var o=un(t),l=t.gutter=M("div",null,"CodeMirror-gutter-wrapper","left: "+(e.options.fixedGutter?r.fixedPos:-r.gutterTotalWidth)+"px");if(e.display.input.setUneditable(l),o.insertBefore(l,t.text),t.line.gutterClass&&(l.className+=" "+t.line.gutterClass),!e.options.lineNumbers||i&&i["CodeMirror-linenumbers"]||(t.lineNumber=l.appendChild(M("div",nt(e.options,n),"CodeMirror-linenumber CodeMirror-gutter-elt","left: "+r.gutterLeft["CodeMirror-linenumbers"]+"px; width: "+e.display.lineNumInnerWidth+"px"))),i)for(var s=0;s<e.display.gutterSpecs.length;++s){var a=e.display.gutterSpecs[s].className,u=i.hasOwnProperty(a)&&i[a];u&&l.appendChild(M("div",[u],"CodeMirror-gutter-elt","left: "+r.gutterLeft[a]+"px; width: "+r.gutterWidth[a]+"px"))}}}function fn(e,t,n){if(pn(e,t.line,t,n,!0),t.rest)for(var r=0;r<t.rest.length;r++)pn(e,t.rest[r],t,n,!1)}function pn(e,t,n,r,i){if(t.widgets)for(var o=un(n),l=0,s=t.widgets;l<s.length;++l){var a=s[l],u=M("div",[a.node],"CodeMirror-linewidget"+(a.className?" "+a.className:""));a.handleMouseEvents||u.setAttribute("cm-ignore-events","true"),function(e,t,n,r){e.noHScroll&&((n.alignable||(n.alignable=[])).push(t),n=r.wrapperWidth,t.style.left=r.fixedPos+"px",e.coverGutter||(n-=r.gutterTotalWidth,t.style.paddingLeft=r.gutterTotalWidth+"px"),t.style.width=n+"px");e.coverGutter&&(t.style.zIndex=5,t.style.position="relative",e.noHScroll||(t.style.marginLeft=-r.gutterTotalWidth+"px"))}(a,u,n,r),e.display.input.setUneditable(u),i&&a.above?o.insertBefore(u,n.gutter||n.text):o.appendChild(u),ln(a,"redraw")}}function gn(e){if(null!=e.height)return e.height;var t,n=e.doc.cm;return n?(A(document.body,e.node)||(t="position: relative;",e.coverGutter&&(t+="margin-left: -"+n.display.gutters.offsetWidth+"px;"),e.noHScroll&&(t+="width: "+n.display.wrapper.clientWidth+"px;"),T(n.display.measure,M("div",[e.node],null,t))),e.height=e.node.parentNode.offsetHeight):0}function mn(e,t){for(var n=Oe(t);n!=e.wrapper;n=n.parentNode)if(!n||1==n.nodeType&&"true"==n.getAttribute("cm-ignore-events")||n.parentNode==e.sizer&&n!=e.mover)return 1}function vn(e){return e.lineSpace.offsetTop}function yn(e){return e.mover.offsetHeight-e.lineSpace.offsetHeight}function bn(e){if(e.cachedPaddingH)return e.cachedPaddingH;var t=T(e.measure,M("pre","x","CodeMirror-line-like")),t=window.getComputedStyle?window.getComputedStyle(t):t.currentStyle,t={left:parseInt(t.paddingLeft),right:parseInt(t.paddingRight)};return isNaN(t.left)||isNaN(t.right)||(e.cachedPaddingH=t),t}function wn(e){return z-e.display.nativeBarWidth}function xn(e){return e.display.scroller.clientWidth-wn(e)-e.display.barWidth}function Cn(e){return e.display.scroller.clientHeight-wn(e)-e.display.barHeight}function Sn(e,t,n){if(e.line==t)return{map:e.measure.map,cache:e.measure.cache};for(var r=0;r<e.rest.length;r++)if(e.rest[r]==t)return{map:e.measure.maps[r],cache:e.measure.caches[r]};for(var i=0;i<e.rest.length;i++)if(Je(e.rest[i])>n)return{map:e.measure.maps[i],cache:e.measure.caches[i],before:!0}}function Ln(e,t,n,r){return Mn(e,Tn(e,t),n,r)}function kn(e,t){if(t>=e.display.viewFrom&&t<e.display.viewTo)return e.display.view[er(e,t)];e=e.display.externalMeasured;return e&&t>=e.lineN&&t<e.lineN+e.size?e:void 0}function Tn(e,t){var n,r,i=Je(t),o=kn(e,i);o&&!o.text?o=null:o&&o.changes&&(an(e,o,i,$n(e)),e.curOp.forceUpdate=!0),o||(n=e,e=Je(r=zt(r=t)),(r=n.display.externalMeasured=new en(n.doc,r,e)).lineN=e,e=r.built=qt(n,r),r.text=e.pre,T(n.display.lineMeasure,e.pre),o=r);i=Sn(o,t,i);return{line:t,view:o,rect:null,map:i.map,cache:i.cache,before:i.before,hasHeights:!1}}function Mn(e,t,n,r,i){t.before&&(n=-1);var o,l=n+(r||"");return t.cache.hasOwnProperty(l)?o=t.cache[l]:(t.rect||(t.rect=t.view.text.getBoundingClientRect()),t.hasHeights||(function(e,t,n){var r=e.options.lineWrapping,e=r&&xn(e);if(!t.measure.heights||r&&t.measure.width!=e){var i=t.measure.heights=[];if(r){t.measure.width=e;for(var o=t.text.firstChild.getClientRects(),l=0;l<o.length-1;l++){var s=o[l],a=o[l+1];2<Math.abs(s.bottom-a.bottom)&&i.push((s.bottom+a.top)/2-n.top)}}i.push(n.bottom-n.top)}}(e,t.view,t.rect),t.hasHeights=!0),(o=function(e,t,n,r){var i,o=On(t.map,n,r),l=o.node,s=o.start,a=o.end,u=o.collapse;if(3==l.nodeType){for(var c=0;c<4;c++){for(;s&&ne(t.line.text.charAt(o.coverStart+s));)--s;for(;o.coverStart+a<o.coverEnd&&ne(t.line.text.charAt(o.coverStart+a));)++a;if((i=w&&v<9&&0==s&&a==o.coverEnd-o.coverStart?l.parentNode.getBoundingClientRect():function(e,t){var n=An;if("left"==t)for(var r=0;r<e.length&&(n=e[r]).left==n.right;r++);else for(var i=e.length-1;0<=i&&(n=e[i]).left==n.right;i--);return n}(S(l,s,a).getClientRects(),r)).left||i.right||0==s)break;a=s,--s,u="right"}w&&v<11&&(i=function(e,t){if(!window.screen||null==screen.logicalXDPI||screen.logicalXDPI==screen.deviceXDPI||!function(e){if(null!=Re)return Re;var e=(t=T(e,M("span","x"))).getBoundingClientRect(),t=S(t,0,1).getBoundingClientRect();return Re=1<Math.abs(e.left-t.left)}(e))return t;var n=screen.logicalXDPI/screen.deviceXDPI,e=screen.logicalYDPI/screen.deviceYDPI;return{left:t.left*n,right:t.right*n,top:t.top*e,bottom:t.bottom*e}}(e.display.measure,i))}else 0<s&&(u=r="right"),i=e.options.lineWrapping&&1<(g=l.getClientRects()).length?g["right"==r?g.length-1:0]:l.getBoundingClientRect();!(w&&v<9)||s||i&&(i.left||i.right)||(m=l.parentNode.getClientRects()[0],i=m?{left:m.left,right:m.left+_n(e.display),top:m.top,bottom:m.bottom}:An);for(var h=i.top-t.rect.top,n=i.bottom-t.rect.top,d=(h+n)/2,f=t.view.measure.heights,p=0;p<f.length-1&&!(d<f[p]);p++);var g=p?f[p-1]:0,m=f[p],m={left:("right"==u?i.right:i.left)-t.rect.left,right:("left"==u?i.left:i.right)-t.rect.left,top:g,bottom:m};i.left||i.right||(m.bogus=!0);e.options.singleCursorHeightPerLine||(m.rtop=h,m.rbottom=n);return m}(e,t,n,r)).bogus||(t.cache[l]=o)),{left:o.left,right:o.right,top:i?o.rtop:o.top,bottom:i?o.rbottom:o.bottom}}var Nn,An={left:0,right:0,top:0,bottom:0};function On(e,t,n){for(var r,i,o,l,s,a,u=0;u<e.length;u+=3)if(s=e[u],a=e[u+1],t<s?(i=0,o=1,l="left"):t<a?o=(i=t-s)+1:(u==e.length-3||t==a&&e[u+3]>t)&&(i=(o=a-s)-1,a<=t&&(l="right")),null!=i){if(r=e[u+2],s==a&&n==(r.insertLeft?"left":"right")&&(l=n),"left"==n&&0==i)for(;u&&e[u-2]==e[u-3]&&e[u-1].insertLeft;)r=e[2+(u-=3)],l="left";if("right"==n&&i==a-s)for(;u<e.length-3&&e[u+3]==e[u+4]&&!e[u+5].insertLeft;)r=e[(u+=3)+2],l="right";break}return{node:r,start:i,end:o,collapse:l,coverStart:s,coverEnd:a}}function Dn(e){if(e.measure&&(e.measure.cache={},e.measure.heights=null,e.rest))for(var t=0;t<e.rest.length;t++)e.measure.caches[t]={}}function Wn(e){e.display.externalMeasure=null,k(e.display.lineMeasure);for(var t=0;t<e.display.view.length;t++)Dn(e.display.view[t])}function Hn(e){Wn(e),e.display.cachedCharWidth=e.display.cachedTextHeight=e.display.cachedPaddingH=null,e.options.lineWrapping||(e.display.maxLineChanged=!0),e.display.lineNumChars=null}function Fn(){return o&&a?-(document.body.getBoundingClientRect().left-parseInt(getComputedStyle(document.body).marginLeft)):window.pageXOffset||(document.documentElement||document.body).scrollLeft}function En(){return o&&a?-(document.body.getBoundingClientRect().top-parseInt(getComputedStyle(document.body).marginTop)):window.pageYOffset||(document.documentElement||document.body).scrollTop}function Pn(e){var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;++n)e.widgets[n].above&&(t+=gn(e.widgets[n]));return t}function In(e,t,n,r,i){if(i||(i=Pn(t),n.top+=i,n.bottom+=i),"line"==r)return n;r=r||"local";t=Vt(t);return"local"==r?t+=vn(e.display):t-=e.display.viewOffset,"page"!=r&&"window"!=r||(t+=(e=e.display.lineSpace.getBoundingClientRect()).top+("window"==r?0:En()),r=e.left+("window"==r?0:Fn()),n.left+=r,n.right+=r),n.top+=t,n.bottom+=t,n}function Rn(e,t,n){if("div"==n)return t;var r=t.left,t=t.top;"page"==n?(r-=Fn(),t-=En()):"local"!=n&&n||(r+=(n=e.display.sizer.getBoundingClientRect()).left,t+=n.top);e=e.display.lineSpace.getBoundingClientRect();return{left:r-e.left,top:t-e.top}}function zn(e,t,n,r,i){return In(e,r=r||$e(e.doc,t.line),Ln(e,r,t.ch,i),n)}function Bn(n,e,r,i,o,l){function s(e,t){e=Mn(n,o,e,t?"right":"left",l);return t?e.left=e.right:e.right=e.left,In(n,i,e,r)}i=i||$e(n.doc,e.line),o=o||Tn(n,i);var a=me(i,n.doc.direction),t=e.ch,u=e.sticky;if(t>=i.text.length?(t=i.text.length,u="before"):t<=0&&(t=0,u="after"),!a)return s("before"==u?t-1:t,"before"==u);function c(e,t,n){return s(n?e-1:e,1==a[t].level!=n)}var h=le(a,t,u),e=oe,h=c(t,h,"before"==u);return null!=e&&(h.other=c(t,e,"before"!=u)),h}function Gn(e,t){var n=0;t=ct(e.doc,t),e.options.lineWrapping||(n=_n(e.display)*t.ch);t=$e(e.doc,t.line),e=Vt(t)+vn(e.display);return{left:n,right:n,top:e,bottom:e+t.height}}function Un(e,t,n,r,i){n=rt(e,t,n);return n.xRel=i,r&&(n.outside=r),n}function Vn(e,t,n){var r=e.doc;if((n+=e.display.viewOffset)<0)return Un(r.first,0,null,-1,-1);var i=et(r,n),o=r.first+r.size-1;if(o<i)return Un(r.first+r.size-1,$e(r,o).text.length,null,1,1);t<0&&(t=0);for(var l=$e(r,i);;){var s=function(n,e,t,r,i){i-=Vt(e);var o=Tn(n,e),l=Pn(e),s=0,a=e.text.length,u=!0,c=me(e,n.doc.direction);c&&(f=(n.options.lineWrapping?function(e,t,n,r,i,o,l){var l=Kn(e,t,r,l),s=l.begin,a=l.end;/\s/.test(t.text.charAt(a-1))&&a--;for(var u=null,c=null,h=0;h<i.length;h++){var d,f=i[h];f.from>=a||f.to<=s||(d=1!=f.level,d=Mn(e,r,d?Math.min(a,f.to)-1:Math.max(s,f.from)).right,d=d<o?o-d+1e9:d-o,(!u||d<c)&&(u=f,c=d))}u=u||i[i.length-1];u.from<s&&(u={from:s,to:u.to,level:u.level});u.to>a&&(u={from:u.from,to:a,level:u.level});return u}:function(n,r,i,o,l,s,a){var e=ie(function(e){var t=l[e],e=1!=t.level;return Xn(Bn(n,rt(i,e?t.to:t.from,e?"before":"after"),"line",r,o),s,a,!0)},0,l.length-1),t=l[e];{var u;0<e&&(u=1!=t.level,Xn(u=Bn(n,rt(i,u?t.from:t.to,u?"after":"before"),"line",r,o),s,a,!0)&&u.top>a&&(t=l[e-1]))}return t})(n,e,t,o,c,r,i),u=1!=f.level,s=u?f.from:f.to-1,a=u?f.to:f.from-1);var h=null,d=null,c=ie(function(e){var t=Mn(n,o,e);return t.top+=l,t.bottom+=l,Xn(t,r,i,!1)&&(t.top<=i&&t.left<=r&&(h=e,d=t),1)},s,a),f=!1;{var p,g;d?(p=r-d.left<d.right-r,c=h+((g=p==u)?0:1),g=g?"after":"before",p=p?d.left:d.right):(u||c!=a&&c!=s||c++,g=0==c||c!=e.text.length&&Mn(n,o,c-(u?1:0)).bottom+l<=i==u?"after":"before",u=Bn(n,rt(t,c,g),"line",e,o),p=u.left,f=i<u.top?-1:i>=u.bottom?1:0)}return c=re(e.text,c,1),Un(t,c,g,f,r-p)}(e,l,i,t,n),a=function(e,t){var n,r=kt&&e.markedSpans;if(r)for(var i=0;i<r.length;++i){var o=r[i];o.marker.collapsed&&(null==o.from||o.from<t)&&(null==o.to||o.to>t)&&(!n||Ft(n,o.marker)<0)&&(n=o.marker)}return n}(l,s.ch+(0<s.xRel||0<s.outside?1:0));if(!a)return s;a=a.find(1);if(a.line==i)return a;l=$e(r,i=a.line)}}function Kn(t,e,n,r){r-=Pn(e);var i=e.text.length,e=ie(function(e){return Mn(t,n,e-1).bottom<=r},i,0);return{begin:e,end:i=ie(function(e){return Mn(t,n,e).top>r},e,i)}}function jn(e,t,n,r){return Kn(e,t,n=n||Tn(e,t),In(e,t,Mn(e,n,r),"line").top)}function Xn(e,t,n,r){return!(e.bottom<=n)&&(e.top>n||(r?e.left:e.right)>t)}function Yn(e){if(null!=e.cachedTextHeight)return e.cachedTextHeight;if(null==Nn){Nn=M("pre",null,"CodeMirror-line-like");for(var t=0;t<49;++t)Nn.appendChild(document.createTextNode("x")),Nn.appendChild(M("br"));Nn.appendChild(document.createTextNode("x"))}T(e.measure,Nn);var n=Nn.offsetHeight/50;return 3<n&&(e.cachedTextHeight=n),k(e.measure),n||1}function _n(e){if(null!=e.cachedCharWidth)return e.cachedCharWidth;var t=M("span","xxxxxxxxxx"),n=M("pre",[t],"CodeMirror-line-like");T(e.measure,n);t=t.getBoundingClientRect(),t=(t.right-t.left)/10;return 2<t&&(e.cachedCharWidth=t),t||10}function $n(e){for(var t=e.display,n={},r={},i=t.gutters.clientLeft,o=t.gutters.firstChild,l=0;o;o=o.nextSibling,++l){var s=e.display.gutterSpecs[l].className;n[s]=o.offsetLeft+o.clientLeft+i,r[s]=o.clientWidth}return{fixedPos:qn(t),gutterTotalWidth:t.gutters.offsetWidth,gutterLeft:n,gutterWidth:r,wrapperWidth:t.wrapper.clientWidth}}function qn(e){return e.scroller.getBoundingClientRect().left-e.sizer.getBoundingClientRect().left}function Zn(r){var i=Yn(r.display),o=r.options.lineWrapping,l=o&&Math.max(5,r.display.scroller.clientWidth/_n(r.display)-3);return function(e){if(Ut(r.doc,e))return 0;var t=0;if(e.widgets)for(var n=0;n<e.widgets.length;n++)e.widgets[n].height&&(t+=e.widgets[n].height);return o?t+(Math.ceil(e.text.length/l)||1)*i:t+i}}function Qn(e){var t=e.doc,n=Zn(e);t.iter(function(e){var t=n(e);t!=e.height&&Qe(e,t)})}function Jn(e,t,n,r){var i=e.display;if(!n&&"true"==Oe(t).getAttribute("cm-not-content"))return null;var o,l,s=i.lineSpace.getBoundingClientRect();try{o=t.clientX-s.left,l=t.clientY-s.top}catch(e){return null}var a,i=Vn(e,o,l);return r&&0<i.xRel&&(a=$e(e.doc,i.line).text).length==i.ch&&(a=P(a,a.length,e.options.tabSize)-a.length,i=rt(i.line,Math.max(0,Math.round((o-bn(e.display).left)/_n(e.display))-a))),i}function er(e,t){if(t>=e.display.viewTo)return null;if((t-=e.display.viewFrom)<0)return null;for(var n=e.display.view,r=0;r<n.length;r++)if((t-=n[r].size)<0)return r}function tr(e,t,n,r){null==t&&(t=e.doc.first),null==n&&(n=e.doc.first+e.doc.size),r=r||0;var i,o,l=e.display;r&&n<l.viewTo&&(null==l.updateLineNumbers||l.updateLineNumbers>t)&&(l.updateLineNumbers=t),e.curOp.viewChanged=!0,t>=l.viewTo?kt&&Bt(e.doc,t)<l.viewTo&&rr(e):n<=l.viewFrom?kt&&Gt(e.doc,n+r)>l.viewFrom?rr(e):(l.viewFrom+=r,l.viewTo+=r):t<=l.viewFrom&&n>=l.viewTo?rr(e):t<=l.viewFrom?(i=ir(e,n,n+r,1))?(l.view=l.view.slice(i.index),l.viewFrom=i.lineN,l.viewTo+=r):rr(e):n>=l.viewTo?(o=ir(e,t,t,-1))?(l.view=l.view.slice(0,o.index),l.viewTo=o.lineN):rr(e):(i=ir(e,t,t,-1),o=ir(e,n,n+r,1),i&&o?(l.view=l.view.slice(0,i.index).concat(tn(e,i.lineN,o.lineN)).concat(l.view.slice(o.index)),l.viewTo+=r):rr(e));e=l.externalMeasured;e&&(n<e.lineN?e.lineN+=r:t<e.lineN+e.size&&(l.externalMeasured=null))}function nr(e,t,n){e.curOp.viewChanged=!0;var r=e.display,i=e.display.externalMeasured;i&&t>=i.lineN&&t<i.lineN+i.size&&(r.externalMeasured=null),t<r.viewFrom||t>=r.viewTo||(null==(t=r.view[er(e,t)]).node||-1==R(t=t.changes||(t.changes=[]),n)&&t.push(n))}function rr(e){e.display.viewFrom=e.display.viewTo=e.doc.first,e.display.view=[],e.display.viewOffset=0}function ir(e,t,n,r){var i,o=er(e,t),l=e.display.view;if(!kt||n==e.doc.first+e.doc.size)return{index:o,lineN:n};for(var s=e.display.viewFrom,a=0;a<o;a++)s+=l[a].size;if(s!=t){if(0<r){if(o==l.length-1)return null;i=s+l[o].size-t,o++}else i=s-t;t+=i,n+=i}for(;Bt(e.doc,n)!=n;){if(o==(r<0?0:l.length-1))return null;n+=r*l[o-(r<0?1:0)].size,o+=r}return{index:o,lineN:n}}function or(e){for(var t=e.display.view,n=0,r=0;r<t.length;r++){var i=t[r];i.hidden||i.node&&!i.changes||++n}return n}function lr(e){e.display.input.showSelection(e.display.input.prepareSelection())}function sr(e,t){void 0===t&&(t=!0);for(var n,r,i=e.doc,o={},l=o.cursors=document.createDocumentFragment(),s=o.selection=document.createDocumentFragment(),a=0;a<i.sel.ranges.length;a++)!t&&a==i.sel.primIndex||((n=i.sel.ranges[a]).from().line>=e.display.viewTo||n.to().line<e.display.viewFrom||(((r=n.empty())||e.options.showCursorWhenSelecting)&&ar(e,n.head,l),r||function(i,e,t){var n=i.display,o=i.doc,l=document.createDocumentFragment(),r=bn(i.display),S=r.left,L=Math.max(n.sizerWidth,xn(i)-n.sizer.offsetLeft)-r.right,k="ltr"==o.direction;function T(e,t,n,r){t<0&&(t=0),t=Math.round(t),r=Math.round(r),l.appendChild(M("div",null,"CodeMirror-selected","position: absolute; left: "+e+"px;\n top: "+t+"px; width: "+(null==n?L-e:n)+"px;\n height: "+(r-t)+"px"))}function s(n,g,m){var v,y,r=$e(o,n),b=r.text.length;function w(e,t){return zn(i,rt(n,e),"div",r,t)}function x(e,t,n){e=jn(i,r,null,e),t="ltr"==t==("after"==n)?"left":"right";return w("after"==n?e.begin:e.end-(/\s/.test(r.text.charAt(e.end-1))?2:1),t)[t]}var C=me(r,o.direction);return function(e,t,n,r){if(!e)return r(t,n,"ltr",0);for(var i=!1,o=0;o<e.length;++o){var l=e[o];(l.from<n&&l.to>t||t==n&&l.to==t)&&(r(Math.max(l.from,t),Math.min(l.to,n),1==l.level?"rtl":"ltr",o),i=!0)}i||r(t,n,"ltr")}(C,g||0,null==m?b:m,function(e,t,n,r){var i,o,l,s,a="ltr"==n,u=w(e,a?"left":"right"),c=w(t-1,a?"right":"left"),h=null==g&&0==e,d=null==m&&t==b,f=0==r,p=!C||r==C.length-1;c.top-u.top<=3?(i=(k?d:h)&&p,r=(k?h:d)&&f?S:(a?u:c).left,i=i?L:(a?c:u).right,T(r,u.top,i-r,u.bottom)):(n=a?(o=k&&h&&f?S:u.left,l=k?L:x(e,n,"before"),s=k?S:x(t,n,"after"),k&&d&&p?L:c.right):(o=k?x(e,n,"before"):S,l=!k&&h&&f?L:u.right,s=!k&&d&&p?S:c.left,k?x(t,n,"after"):L),T(o,u.top,l-o,u.bottom),u.bottom<c.top&&T(S,u.bottom,null,c.top),T(s,c.top,n-s,c.bottom)),(!v||ur(u,v)<0)&&(v=u),ur(c,v)<0&&(v=c),(!y||ur(u,y)<0)&&(y=u),ur(c,y)<0&&(y=c)}),{start:v,end:y}}var a=e.from(),n=e.to();a.line==n.line?s(a.line,a.ch,n.ch):(r=$e(o,a.line),e=$e(o,n.line),e=zt(r)==zt(e),r=s(a.line,a.ch,e?r.text.length+1:null).end,n=s(n.line,e?0:null,n.ch).start,e&&(r.top<n.top-2?(T(r.right,r.top,null,r.bottom),T(S,n.top,n.left,n.bottom)):T(r.right,r.top,n.left-r.right,r.bottom)),r.bottom<n.top&&T(S,r.bottom,null,n.top));t.appendChild(l)}(e,n,s)));return o}function ar(e,t,n){var r=Bn(e,t,"div",null,null,!e.options.singleCursorHeightPerLine),t=n.appendChild(M("div"," ","CodeMirror-cursor"));t.style.left=r.left+"px",t.style.top=r.top+"px",t.style.height=Math.max(0,r.bottom-r.top)*e.options.cursorHeight+"px",r.other&&((n=n.appendChild(M("div"," ","CodeMirror-cursor CodeMirror-secondarycursor"))).style.display="",n.style.left=r.other.left+"px",n.style.top=r.other.top+"px",n.style.height=.85*(r.other.bottom-r.other.top)+"px")}function ur(e,t){return e.top-t.top||e.left-t.left}function cr(e){var t,n;e.state.focused&&(t=e.display,clearInterval(t.blinker),n=!0,t.cursorDiv.style.visibility="",0<e.options.cursorBlinkRate?t.blinker=setInterval(function(){e.hasFocus()||pr(e),t.cursorDiv.style.visibility=(n=!n)?"":"hidden"},e.options.cursorBlinkRate):e.options.cursorBlinkRate<0&&(t.cursorDiv.style.visibility="hidden"))}function hr(e){e.hasFocus()||(e.display.input.focus(),e.state.focused||fr(e))}function dr(e){e.state.delayingBlurEvent=!0,setTimeout(function(){e.state.delayingBlurEvent&&(e.state.delayingBlurEvent=!1,e.state.focused&&pr(e))},100)}function fr(e,t){e.state.delayingBlurEvent&&!e.state.draggingText&&(e.state.delayingBlurEvent=!1),"nocursor"!=e.options.readOnly&&(e.state.focused||(xe(e,"focus",e,t),e.state.focused=!0,D(e.display.wrapper,"CodeMirror-focused"),e.curOp||e.display.selForContextMenu==e.doc.sel||(e.display.input.reset(),f&&setTimeout(function(){return e.display.input.reset(!0)},20)),e.display.input.receivedFocus()),cr(e))}function pr(e,t){e.state.delayingBlurEvent||(e.state.focused&&(xe(e,"blur",e,t),e.state.focused=!1,L(e.display.wrapper,"CodeMirror-focused")),clearInterval(e.display.blinker),setTimeout(function(){e.state.focused||(e.display.shift=!1)},150))}function gr(e){for(var t=e.display,n=t.lineDiv.offsetTop,r=0;r<t.view.length;r++){var i,o=t.view[r],l=e.options.lineWrapping,s=void 0,a=0;if(!o.hidden){w&&v<8?(s=(i=o.node.offsetTop+o.node.offsetHeight)-n,n=i):(s=(u=o.node.getBoundingClientRect()).bottom-u.top,!l&&o.text.firstChild&&(a=o.text.firstChild.getBoundingClientRect().right-u.left-1));var u=o.line.height-s;if((.005<u||u<-.005)&&(Qe(o.line,s),mr(o.line),o.rest))for(var c=0;c<o.rest.length;c++)mr(o.rest[c]);a>e.display.sizerWidth&&((a=Math.ceil(a/_n(e.display)))>e.display.maxLineLength&&(e.display.maxLineLength=a,e.display.maxLine=o.line,e.display.maxLineChanged=!0))}}}function mr(e){if(e.widgets)for(var t=0;t<e.widgets.length;++t){var n=e.widgets[t],r=n.node.parentNode;r&&(n.height=r.offsetHeight)}}function vr(e,t,n){var r=n&&null!=n.top?Math.max(0,n.top):e.scroller.scrollTop,r=Math.floor(r-vn(e)),i=n&&null!=n.bottom?n.bottom:r+e.wrapper.clientHeight,o=et(t,r),r=et(t,i);return n&&n.ensure&&(i=n.ensure.from.line,n=n.ensure.to.line,i<o?r=et(t,Vt($e(t,o=i))+e.wrapper.clientHeight):Math.min(n,t.lastLine())>=r&&(o=et(t,Vt($e(t,n))-e.wrapper.clientHeight),r=n)),{from:o,to:Math.max(r,o+1)}}function yr(e,t){var n=e.display,r=Yn(e.display);t.top<0&&(t.top=0);var i=(e.curOp&&null!=e.curOp.scrollTop?e.curOp:n.scroller).scrollTop,o=Cn(e),l={};t.bottom-t.top>o&&(t.bottom=t.top+o);var s=e.doc.height+yn(n),a=t.top<r,r=t.bottom>s-r;t.top<i?l.scrollTop=a?0:t.top:t.bottom>i+o&&((u=Math.min(t.top,(r?s:t.bottom)-o))!=i&&(l.scrollTop=u));var i=e.options.fixedGutter?0:n.gutters.offsetWidth,u=e.curOp&&null!=e.curOp.scrollLeft?e.curOp.scrollLeft:n.scroller.scrollLeft-i,e=xn(e)-n.gutters.offsetWidth,n=t.right-t.left>e;return n&&(t.right=t.left+e),t.left<10?l.scrollLeft=0:t.left<u?l.scrollLeft=Math.max(0,t.left+i-(n?0:10)):t.right>e+u-3&&(l.scrollLeft=t.right+(n?0:10)-e),l}function br(e,t){null!=t&&(Cr(e),e.curOp.scrollTop=(null==e.curOp.scrollTop?e.doc:e.curOp).scrollTop+t)}function wr(e){Cr(e);var t=e.getCursor();e.curOp.scrollToPos={from:t,to:t,margin:e.options.cursorScrollMargin}}function xr(e,t,n){null==t&&null==n||Cr(e),null!=t&&(e.curOp.scrollLeft=t),null!=n&&(e.curOp.scrollTop=n)}function Cr(e){var t=e.curOp.scrollToPos;t&&(e.curOp.scrollToPos=null,Sr(e,Gn(e,t.from),Gn(e,t.to),t.margin))}function Sr(e,t,n,r){r=yr(e,{left:Math.min(t.left,n.left),top:Math.min(t.top,n.top)-r,right:Math.max(t.right,n.right),bottom:Math.max(t.bottom,n.bottom)+r});xr(e,r.scrollLeft,r.scrollTop)}function Lr(e,t){Math.abs(e.doc.scrollTop-t)<2||(d||Kr(e,{top:t}),kr(e,t,!0),d&&Kr(e),zr(e,100))}function kr(e,t,n){t=Math.max(0,Math.min(e.display.scroller.scrollHeight-e.display.scroller.clientHeight,t)),e.display.scroller.scrollTop==t&&!n||(e.doc.scrollTop=t,e.display.scrollbars.setScrollTop(t),e.display.scroller.scrollTop!=t&&(e.display.scroller.scrollTop=t))}function Tr(e,t,n,r){t=Math.max(0,Math.min(t,e.display.scroller.scrollWidth-e.display.scroller.clientWidth)),(n?t==e.doc.scrollLeft:Math.abs(e.doc.scrollLeft-t)<2)&&!r||(e.doc.scrollLeft=t,Yr(e),e.display.scroller.scrollLeft!=t&&(e.display.scroller.scrollLeft=t),e.display.scrollbars.setScrollLeft(t))}function Mr(e){var t=e.display,n=t.gutters.offsetWidth,r=Math.round(e.doc.height+yn(e.display));return{clientHeight:t.scroller.clientHeight,viewHeight:t.wrapper.clientHeight,scrollWidth:t.scroller.scrollWidth,clientWidth:t.scroller.clientWidth,viewWidth:t.wrapper.clientWidth,barLeft:e.options.fixedGutter?n:0,docHeight:r,scrollHeight:r+wn(e)+t.barHeight,nativeBarWidth:t.nativeBarWidth,gutterWidth:n}}e=function(e,t,n){this.cm=n;var r=this.vert=M("div",[M("div",null,null,"min-width: 1px")],"CodeMirror-vscrollbar"),i=this.horiz=M("div",[M("div",null,null,"height: 100%; min-height: 1px")],"CodeMirror-hscrollbar");r.tabIndex=i.tabIndex=-1,e(r),e(i),ye(r,"scroll",function(){r.clientHeight&&t(r.scrollTop,"vertical")}),ye(i,"scroll",function(){i.clientWidth&&t(i.scrollLeft,"horizontal")}),this.checkedZeroWidth=!1,w&&v<8&&(this.horiz.style.minHeight=this.vert.style.minWidth="18px")};e.prototype.update=function(e){var t,n=e.scrollWidth>e.clientWidth+1,r=e.scrollHeight>e.clientHeight+1,i=e.nativeBarWidth;return r?(this.vert.style.display="block",this.vert.style.bottom=n?i+"px":"0",t=e.viewHeight-(n?i:0),this.vert.firstChild.style.height=Math.max(0,e.scrollHeight-e.clientHeight+t)+"px"):(this.vert.style.display="",this.vert.firstChild.style.height="0"),n?(this.horiz.style.display="block",this.horiz.style.right=r?i+"px":"0",this.horiz.style.left=e.barLeft+"px",t=e.viewWidth-e.barLeft-(r?i:0),this.horiz.firstChild.style.width=Math.max(0,e.scrollWidth-e.clientWidth+t)+"px"):(this.horiz.style.display="",this.horiz.firstChild.style.width="0"),!this.checkedZeroWidth&&0<e.clientHeight&&(0==i&&this.zeroWidthHack(),this.checkedZeroWidth=!0),{right:r?i:0,bottom:n?i:0}},e.prototype.setScrollLeft=function(e){this.horiz.scrollLeft!=e&&(this.horiz.scrollLeft=e),this.disableHoriz&&this.enableZeroWidthBar(this.horiz,this.disableHoriz,"horiz")},e.prototype.setScrollTop=function(e){this.vert.scrollTop!=e&&(this.vert.scrollTop=e),this.disableVert&&this.enableZeroWidthBar(this.vert,this.disableVert,"vert")},e.prototype.zeroWidthHack=function(){var e=g&&!l?"12px":"18px";this.horiz.style.height=this.vert.style.width=e,this.horiz.style.pointerEvents=this.vert.style.pointerEvents="none",this.disableHoriz=new I,this.disableVert=new I},e.prototype.enableZeroWidthBar=function(n,r,i){n.style.pointerEvents="auto",r.set(1e3,function e(){var t=n.getBoundingClientRect();("vert"==i?document.elementFromPoint(t.right-1,(t.top+t.bottom)/2):document.elementFromPoint((t.right+t.left)/2,t.bottom-1))!=n?n.style.pointerEvents="none":r.set(1e3,e)})},e.prototype.clear=function(){var e=this.horiz.parentNode;e.removeChild(this.horiz),e.removeChild(this.vert)};r=function(){};function Nr(e,t){t=t||Mr(e);var n=e.display.barWidth,r=e.display.barHeight;Ar(e,t);for(var i=0;i<4&&n!=e.display.barWidth||r!=e.display.barHeight;i++)n!=e.display.barWidth&&e.options.lineWrapping&&gr(e),Ar(e,Mr(e)),n=e.display.barWidth,r=e.display.barHeight}function Ar(e,t){var n=e.display,r=n.scrollbars.update(t);n.sizer.style.paddingRight=(n.barWidth=r.right)+"px",n.sizer.style.paddingBottom=(n.barHeight=r.bottom)+"px",n.heightForcer.style.borderBottom=r.bottom+"px solid transparent",r.right&&r.bottom?(n.scrollbarFiller.style.display="block",n.scrollbarFiller.style.height=r.bottom+"px",n.scrollbarFiller.style.width=r.right+"px"):n.scrollbarFiller.style.display="",r.bottom&&e.options.coverGutterNextToScrollbar&&e.options.fixedGutter?(n.gutterFiller.style.display="block",n.gutterFiller.style.height=r.bottom+"px",n.gutterFiller.style.width=t.gutterWidth+"px"):n.gutterFiller.style.display=""}r.prototype.update=function(){return{bottom:0,right:0}},r.prototype.setScrollLeft=function(){},r.prototype.setScrollTop=function(){},r.prototype.clear=function(){};var Or={native:e,null:r};function Dr(n){n.display.scrollbars&&(n.display.scrollbars.clear(),n.display.scrollbars.addClass&&L(n.display.wrapper,n.display.scrollbars.addClass)),n.display.scrollbars=new Or[n.options.scrollbarStyle](function(e){n.display.wrapper.insertBefore(e,n.display.scrollbarFiller),ye(e,"mousedown",function(){n.state.focused&&setTimeout(function(){return n.display.input.focus()},0)}),e.setAttribute("cm-not-content","true")},function(e,t){("horizontal"==t?Tr:Lr)(n,e)},n),n.display.scrollbars.addClass&&D(n.display.wrapper,n.display.scrollbars.addClass)}var Wr=0;function Hr(e){e.curOp={cm:e,viewChanged:!1,startHeight:e.doc.height,forceUpdate:!1,updateInput:0,typing:!1,changeObjs:null,cursorActivityHandlers:null,cursorActivityCalled:0,selectionChanged:!1,updateMaxLine:!1,scrollLeft:null,scrollTop:null,scrollToPos:null,focus:!1,id:++Wr},e=e.curOp,nn?nn.ops.push(e):e.ownsGroup=nn={ops:[e],delayedCallbacks:[]}}function Fr(e){e=e.curOp;e&&rn(e,function(e){for(var t=0;t<e.ops.length;t++)e.ops[t].cm.curOp=null;!function(e){for(var t=e.ops,n=0;n<t.length;n++)!function(e){var t=e.cm,n=t.display;(function(e){var t=e.display;!t.scrollbarsClipped&&t.scroller.offsetWidth&&(t.nativeBarWidth=t.scroller.offsetWidth-t.scroller.clientWidth,t.heightForcer.style.height=wn(e)+"px",t.sizer.style.marginBottom=-t.nativeBarWidth+"px",t.sizer.style.borderRightWidth=wn(e)+"px",t.scrollbarsClipped=!0)})(t),e.updateMaxLine&&jt(t);e.mustUpdate=e.viewChanged||e.forceUpdate||null!=e.scrollTop||e.scrollToPos&&(e.scrollToPos.from.line<n.viewFrom||e.scrollToPos.to.line>=n.viewTo)||n.maxLineChanged&&t.options.lineWrapping,e.update=e.mustUpdate&&new Gr(t,e.mustUpdate&&{top:e.scrollTop,ensure:e.scrollToPos},e.forceUpdate)}(t[n]);for(var r=0;r<t.length;r++)!function(e){e.updatedDisplay=e.mustUpdate&&Ur(e.cm,e.update)}(t[r]);for(var i=0;i<t.length;i++)!function(e){var t=e.cm,n=t.display;e.updatedDisplay&&gr(t);e.barMeasure=Mr(t),n.maxLineChanged&&!t.options.lineWrapping&&(e.adjustWidthTo=Ln(t,n.maxLine,n.maxLine.text.length).left+3,t.display.sizerWidth=e.adjustWidthTo,e.barMeasure.scrollWidth=Math.max(n.scroller.clientWidth,n.sizer.offsetLeft+e.adjustWidthTo+wn(t)+t.display.barWidth),e.maxScrollLeft=Math.max(0,n.sizer.offsetLeft+e.adjustWidthTo-xn(t)));(e.updatedDisplay||e.selectionChanged)&&(e.preparedSelection=n.input.prepareSelection())}(t[i]);for(var o=0;o<t.length;o++)!function(e){var t=e.cm;null!=e.adjustWidthTo&&(t.display.sizer.style.minWidth=e.adjustWidthTo+"px",e.maxScrollLeft<t.doc.scrollLeft&&Tr(t,Math.min(t.display.scroller.scrollLeft,e.maxScrollLeft),!0),t.display.maxLineChanged=!1);var n=e.focus&&e.focus==O();e.preparedSelection&&t.display.input.showSelection(e.preparedSelection,n);!e.updatedDisplay&&e.startHeight==t.doc.height||Nr(t,e.barMeasure);e.updatedDisplay&&Xr(t,e.barMeasure);e.selectionChanged&&cr(t);t.state.focused&&e.updateInput&&t.display.input.reset(e.typing);n&&hr(e.cm)}(t[o]);for(var l=0;l<t.length;l++)!function(e){var t=e.cm,n=t.display,r=t.doc;e.updatedDisplay&&Vr(t,e.update);null==n.wheelStartX||null==e.scrollTop&&null==e.scrollLeft&&!e.scrollToPos||(n.wheelStartX=n.wheelStartY=null);null!=e.scrollTop&&kr(t,e.scrollTop,e.forceScroll);null!=e.scrollLeft&&Tr(t,e.scrollLeft,!0,!0);{var i;e.scrollToPos&&(i=function(e,t,n,r){null==r&&(r=0),e.options.lineWrapping||t!=n||(n="before"==(t=t.ch?rt(t.line,"before"==t.sticky?t.ch-1:t.ch,"after"):t).sticky?rt(t.line,t.ch+1,"before"):t);for(var i=0;i<5;i++){var o,l=!1,s=Bn(e,t),a=n&&n!=t?Bn(e,n):s,u=yr(e,o={left:Math.min(s.left,a.left),top:Math.min(s.top,a.top)-r,right:Math.max(s.left,a.left),bottom:Math.max(s.bottom,a.bottom)+r}),s=e.doc.scrollTop,a=e.doc.scrollLeft;if(null!=u.scrollTop&&(Lr(e,u.scrollTop),1<Math.abs(e.doc.scrollTop-s)&&(l=!0)),null!=u.scrollLeft&&(Tr(e,u.scrollLeft),1<Math.abs(e.doc.scrollLeft-a)&&(l=!0)),!l)break}return o}(t,ct(r,e.scrollToPos.from),ct(r,e.scrollToPos.to),e.scrollToPos.margin),function(e,t){var n,r,i;Ce(e,"scrollCursorIntoView")||(r=(n=e.display).sizer.getBoundingClientRect(),i=null,t.top+r.top<0?i=!0:t.bottom+r.top>(window.innerHeight||document.documentElement.clientHeight)&&(i=!1),null==i||u||(t=M("div","​",null,"position: absolute;\n top: "+(t.top-n.viewOffset-vn(e.display))+"px;\n height: "+(t.bottom-t.top+wn(e)+n.barHeight)+"px;\n left: "+t.left+"px; width: "+Math.max(2,t.right-t.left)+"px;"),e.display.lineSpace.appendChild(t),t.scrollIntoView(i),e.display.lineSpace.removeChild(t)))}(t,i))}var o=e.maybeHiddenMarkers,l=e.maybeUnhiddenMarkers;if(o)for(var s=0;s<o.length;++s)o[s].lines.length||xe(o[s],"hide");if(l)for(var a=0;a<l.length;++a)l[a].lines.length&&xe(l[a],"unhide");n.wrapper.offsetHeight&&(r.scrollTop=t.display.scroller.scrollTop);e.changeObjs&&xe(t,"changes",t,e.changeObjs);e.update&&e.update.finish()}(t[l])}(e)})}function Er(e,t){if(e.curOp)return t();Hr(e);try{return t()}finally{Fr(e)}}function Pr(e,t){return function(){if(e.curOp)return t.apply(e,arguments);Hr(e);try{return t.apply(e,arguments)}finally{Fr(e)}}}function Ir(e){return function(){if(this.curOp)return e.apply(this,arguments);Hr(this);try{return e.apply(this,arguments)}finally{Fr(this)}}}function Rr(t){return function(){var e=this.cm;if(!e||e.curOp)return t.apply(this,arguments);Hr(e);try{return t.apply(this,arguments)}finally{Fr(e)}}}function zr(e,t){e.doc.highlightFrontier<e.display.viewTo&&e.state.highlight.set(t,F(Br,e))}function Br(l){var s,a,u,c=l.doc;c.highlightFrontier>=l.display.viewTo||(s=+new Date+l.options.workTime,a=mt(l,c.highlightFrontier),u=[],c.iter(a.line,Math.min(c.first+c.size,l.display.viewTo+500),function(e){if(a.line>=l.display.viewFrom){var t=e.styles,n=e.text.length>l.options.maxHighlightLength?je(c.mode,a.state):null,r=pt(l,e,a,!0);n&&(a.state=n),e.styles=r.styles;n=e.styleClasses,r=r.classes;r?e.styleClasses=r:n&&(e.styleClasses=null);for(var i=!t||t.length!=e.styles.length||n!=r&&(!n||!r||n.bgClass!=r.bgClass||n.textClass!=r.textClass),o=0;!i&&o<t.length;++o)i=t[o]!=e.styles[o];i&&u.push(a.line),e.stateAfter=a.save(),a.nextLine()}else e.text.length<=l.options.maxHighlightLength&&vt(l,e.text,a),e.stateAfter=a.line%5==0?a.save():null,a.nextLine();if(+new Date>s)return zr(l,l.options.workDelay),!0}),c.highlightFrontier=a.line,c.modeFrontier=Math.max(c.modeFrontier,a.line),u.length&&Er(l,function(){for(var e=0;e<u.length;e++)nr(l,u[e],"text")}))}var Gr=function(e,t,n){var r=e.display;this.viewport=t,this.visible=vr(r,e.doc,t),this.editorIsHidden=!r.wrapper.offsetWidth,this.wrapperHeight=r.wrapper.clientHeight,this.wrapperWidth=r.wrapper.clientWidth,this.oldDisplayWidth=xn(e),this.force=n,this.dims=$n(e),this.events=[]};function Ur(e,t){var n=e.display,r=e.doc;if(t.editorIsHidden)return rr(e),!1;if(!t.force&&t.visible.from>=n.viewFrom&&t.visible.to<=n.viewTo&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo)&&n.renderedView==n.view&&0==or(e))return!1;_r(e)&&(rr(e),t.dims=$n(e));var i=r.first+r.size,o=Math.max(t.visible.from-e.options.viewportMargin,r.first),l=Math.min(i,t.visible.to+e.options.viewportMargin);n.viewFrom<o&&o-n.viewFrom<20&&(o=Math.max(r.first,n.viewFrom)),n.viewTo>l&&n.viewTo-l<20&&(l=Math.min(i,n.viewTo)),kt&&(o=Bt(e.doc,o),l=Gt(e.doc,l));var s=o!=n.viewFrom||l!=n.viewTo||n.lastWrapHeight!=t.wrapperHeight||n.lastWrapWidth!=t.wrapperWidth;r=o,i=l,0==(l=(o=e).display).view.length||r>=l.viewTo||i<=l.viewFrom?(l.view=tn(o,r,i),l.viewFrom=r):(l.viewFrom>r?l.view=tn(o,r,l.viewFrom).concat(l.view):l.viewFrom<r&&(l.view=l.view.slice(er(o,r))),l.viewFrom=r,l.viewTo<i?l.view=l.view.concat(tn(o,l.viewTo,i)):l.viewTo>i&&(l.view=l.view.slice(0,er(o,i)))),l.viewTo=i,n.viewOffset=Vt($e(e.doc,n.viewFrom)),e.display.mover.style.top=n.viewOffset+"px";o=or(e);if(!s&&0==o&&!t.force&&n.renderedView==n.view&&(null==n.updateLineNumbers||n.updateLineNumbers>=n.viewTo))return!1;l=function(e){if(e.hasFocus())return null;var t=O();if(!t||!A(e.display.lineDiv,t))return null;var n={activeElt:t};return!window.getSelection||(t=window.getSelection()).anchorNode&&t.extend&&A(e.display.lineDiv,t.anchorNode)&&(n.anchorNode=t.anchorNode,n.anchorOffset=t.anchorOffset,n.focusNode=t.focusNode,n.focusOffset=t.focusOffset),n}(e);return 4<o&&(n.lineDiv.style.display="none"),function(n,e,t){var r=n.display,i=n.options.lineNumbers,o=r.lineDiv,l=o.firstChild;function s(e){var t=e.nextSibling;return f&&g&&n.display.currentWheelTarget==e?e.style.display="none":e.parentNode.removeChild(e),t}for(var a=r.view,u=r.viewFrom,c=0;c<a.length;c++){var h=a[c];if(!h.hidden)if(h.node&&h.node.parentNode==o){for(;l!=h.node;)l=s(l);var d=i&&null!=e&&e<=u&&h.lineNumber;h.changes&&(-1<R(h.changes,"gutter")&&(d=!1),an(n,h,u,t)),d&&(k(h.lineNumber),h.lineNumber.appendChild(document.createTextNode(nt(n.options,u)))),l=h.node.nextSibling}else{d=function(e,t,n,r){var i=cn(e,t);return t.text=t.node=i.pre,i.bgClass&&(t.bgClass=i.bgClass),i.textClass&&(t.textClass=i.textClass),hn(e,t),dn(e,t,n,r),fn(e,t,r),t.node}(n,h,u,t);o.insertBefore(d,l)}u+=h.size}for(;l;)l=s(l)}(e,n.updateLineNumbers,t.dims),4<o&&(n.lineDiv.style.display=""),n.renderedView=n.view,(i=l)&&i.activeElt&&i.activeElt!=O()&&(i.activeElt.focus(),!/^(INPUT|TEXTAREA)$/.test(i.activeElt.nodeName)&&i.anchorNode&&A(document.body,i.anchorNode)&&A(document.body,i.focusNode)&&(o=window.getSelection(),(l=document.createRange()).setEnd(i.anchorNode,i.anchorOffset),l.collapse(!1),o.removeAllRanges(),o.addRange(l),o.extend(i.focusNode,i.focusOffset))),k(n.cursorDiv),k(n.selectionDiv),n.gutters.style.height=n.sizer.style.minHeight=0,s&&(n.lastWrapHeight=t.wrapperHeight,n.lastWrapWidth=t.wrapperWidth,zr(e,400)),!(n.updateLineNumbers=null)}function Vr(e,t){for(var n=t.viewport,r=!0;;r=!1){if(r&&e.options.lineWrapping&&t.oldDisplayWidth!=xn(e))r&&(t.visible=vr(e.display,e.doc,n));else if(n&&null!=n.top&&(n={top:Math.min(e.doc.height+yn(e.display)-Cn(e),n.top)}),t.visible=vr(e.display,e.doc,n),t.visible.from>=e.display.viewFrom&&t.visible.to<=e.display.viewTo)break;if(!Ur(e,t))break;gr(e);var i=Mr(e);lr(e),Nr(e,i),Xr(e,i),t.force=!1}t.signal(e,"update",e),e.display.viewFrom==e.display.reportedViewFrom&&e.display.viewTo==e.display.reportedViewTo||(t.signal(e,"viewportChange",e,e.display.viewFrom,e.display.viewTo),e.display.reportedViewFrom=e.display.viewFrom,e.display.reportedViewTo=e.display.viewTo)}function Kr(e,t){var n=new Gr(e,t);Ur(e,n)&&(gr(e),Vr(e,n),t=Mr(e),lr(e),Nr(e,t),Xr(e,t),n.finish())}function jr(e){var t=e.gutters.offsetWidth;e.sizer.style.marginLeft=t+"px"}function Xr(e,t){e.display.sizer.style.minHeight=t.docHeight+"px",e.display.heightForcer.style.top=t.docHeight+"px",e.display.gutters.style.height=t.docHeight+e.display.barHeight+wn(e)+"px"}function Yr(e){var t=e.display,n=t.view;if(t.alignWidgets||t.gutters.firstChild&&e.options.fixedGutter){for(var r=qn(t)-t.scroller.scrollLeft+e.doc.scrollLeft,i=t.gutters.offsetWidth,o=r+"px",l=0;l<n.length;l++)if(!n[l].hidden){e.options.fixedGutter&&(n[l].gutter&&(n[l].gutter.style.left=o),n[l].gutterBackground&&(n[l].gutterBackground.style.left=o));var s=n[l].alignable;if(s)for(var a=0;a<s.length;a++)s[a].style.left=o}e.options.fixedGutter&&(t.gutters.style.left=r+i+"px")}}function _r(e){if(e.options.lineNumbers){var t=e.doc,n=nt(e.options,t.first+t.size-1),r=e.display;if(n.length!=r.lineNumChars){var i=r.measure.appendChild(M("div",[M("div",n)],"CodeMirror-linenumber CodeMirror-gutter-elt")),t=i.firstChild.offsetWidth,i=i.offsetWidth-t;return r.lineGutter.style.width="",r.lineNumInnerWidth=Math.max(t,r.lineGutter.offsetWidth-i)+1,r.lineNumWidth=r.lineNumInnerWidth+i,r.lineNumChars=r.lineNumInnerWidth?n.length:-1,r.lineGutter.style.width=r.lineNumWidth+"px",jr(e.display),1}}}function $r(e,t){for(var n=[],r=!1,i=0;i<e.length;i++){var o=e[i],l=null;if("string"!=typeof o&&(l=o.style,o=o.className),"CodeMirror-linenumbers"==o){if(!t)continue;r=!0}n.push({className:o,style:l})}return t&&!r&&n.push({className:"CodeMirror-linenumbers",style:null}),n}function qr(e){var t=e.gutters,n=e.gutterSpecs;k(t),e.lineGutter=null;for(var r=0;r<n.length;++r){var i=n[r],o=i.className,l=i.style,i=t.appendChild(M("div",null,"CodeMirror-gutter "+o));l&&(i.style.cssText=l),"CodeMirror-linenumbers"==o&&((e.lineGutter=i).style.width=(e.lineNumWidth||1)+"px")}t.style.display=n.length?"":"none",jr(e)}function Zr(e){qr(e.display),tr(e),Yr(e)}function Qr(e,t,n,r){var i=this;this.input=n,i.scrollbarFiller=M("div",null,"CodeMirror-scrollbar-filler"),i.scrollbarFiller.setAttribute("cm-not-content","true"),i.gutterFiller=M("div",null,"CodeMirror-gutter-filler"),i.gutterFiller.setAttribute("cm-not-content","true"),i.lineDiv=N("div",null,"CodeMirror-code"),i.selectionDiv=M("div",null,null,"position: relative; z-index: 1"),i.cursorDiv=M("div",null,"CodeMirror-cursors"),i.measure=M("div",null,"CodeMirror-measure"),i.lineMeasure=M("div",null,"CodeMirror-measure"),i.lineSpace=N("div",[i.measure,i.lineMeasure,i.selectionDiv,i.cursorDiv,i.lineDiv],null,"position: relative; outline: none");var o=N("div",[i.lineSpace],"CodeMirror-lines");i.mover=M("div",[o],null,"position: relative"),i.sizer=M("div",[i.mover],"CodeMirror-sizer"),i.sizerWidth=null,i.heightForcer=M("div",null,null,"position: absolute; height: "+z+"px; width: 1px;"),i.gutters=M("div",null,"CodeMirror-gutters"),i.lineGutter=null,i.scroller=M("div",[i.sizer,i.heightForcer,i.gutters],"CodeMirror-scroll"),i.scroller.setAttribute("tabIndex","-1"),i.wrapper=M("div",[i.scrollbarFiller,i.gutterFiller,i.scroller],"CodeMirror"),w&&v<8&&(i.gutters.style.zIndex=-1,i.scroller.style.paddingRight=0),f||d&&h||(i.scroller.draggable=!0),e&&(e.appendChild?e.appendChild(i.wrapper):e(i.wrapper)),i.viewFrom=i.viewTo=t.first,i.reportedViewFrom=i.reportedViewTo=t.first,i.view=[],i.renderedView=null,i.externalMeasured=null,i.viewOffset=0,i.lastWrapHeight=i.lastWrapWidth=0,i.updateLineNumbers=null,i.nativeBarWidth=i.barHeight=i.barWidth=0,i.scrollbarsClipped=!1,i.lineNumWidth=i.lineNumInnerWidth=i.lineNumChars=null,i.alignWidgets=!1,i.cachedCharWidth=i.cachedTextHeight=i.cachedPaddingH=null,i.maxLine=null,i.maxLineLength=0,i.maxLineChanged=!1,i.wheelDX=i.wheelDY=i.wheelStartX=i.wheelStartY=null,i.shift=!1,i.selForContextMenu=null,i.activeTouch=null,i.gutterSpecs=$r(r.gutters,r.lineNumbers),qr(i),n.init(i)}Gr.prototype.signal=function(e,t){Le(e,t)&&this.events.push(arguments)},Gr.prototype.finish=function(){for(var e=0;e<this.events.length;e++)xe.apply(null,this.events[e])};var Jr=0,ei=null;function ti(e){var t=e.wheelDeltaX,n=e.wheelDeltaY;return null==t&&e.detail&&e.axis==e.HORIZONTAL_AXIS&&(t=e.detail),null==n&&e.detail&&e.axis==e.VERTICAL_AXIS?n=e.detail:null==n&&(n=e.wheelDelta),{x:t,y:n}}function ni(e){e=ti(e);return e.x*=ei,e.y*=ei,e}function ri(e,t){var n=ti(t),r=n.x,i=n.y,o=e.display,l=o.scroller,s=l.scrollWidth>l.clientWidth,a=l.scrollHeight>l.clientHeight;if(r&&s||i&&a){if(i&&g&&f)e:for(var u=t.target,c=o.view;u!=l;u=u.parentNode)for(var h=0;h<c.length;h++)if(c[h].node==u){e.display.currentWheelTarget=u;break e}if(r&&!d&&!p&&null!=ei)return i&&a&&Lr(e,Math.max(0,l.scrollTop+i*ei)),Tr(e,Math.max(0,l.scrollLeft+r*ei)),(!i||i&&a)&&Te(t),void(o.wheelStartX=null);i&&null!=ei&&(n=i*ei,a=(s=e.doc.scrollTop)+o.wrapper.clientHeight,n<0?s=Math.max(0,s+n-50):a=Math.min(e.doc.height,a+n+50),Kr(e,{top:s,bottom:a})),Jr<20&&(null==o.wheelStartX?(o.wheelStartX=l.scrollLeft,o.wheelStartY=l.scrollTop,o.wheelDX=r,o.wheelDY=i,setTimeout(function(){var e,t;null!=o.wheelStartX&&(t=l.scrollLeft-o.wheelStartX,t=(e=l.scrollTop-o.wheelStartY)&&o.wheelDY&&e/o.wheelDY||t&&o.wheelDX&&t/o.wheelDX,o.wheelStartX=o.wheelStartY=null,t&&(ei=(ei*Jr+t)/(Jr+1),++Jr))},200)):(o.wheelDX+=r,o.wheelDY+=i))}}w?ei=-.53:d?ei=15:o?ei=-.7:c&&(ei=-1/3);var ii=function(e,t){this.ranges=e,this.primIndex=t};ii.prototype.primary=function(){return this.ranges[this.primIndex]},ii.prototype.equals=function(e){if(e==this)return!0;if(e.primIndex!=this.primIndex||e.ranges.length!=this.ranges.length)return!1;for(var t=0;t<this.ranges.length;t++){var n=this.ranges[t],r=e.ranges[t];if(!ot(n.anchor,r.anchor)||!ot(n.head,r.head))return!1}return!0},ii.prototype.deepCopy=function(){for(var e=[],t=0;t<this.ranges.length;t++)e[t]=new oi(lt(this.ranges[t].anchor),lt(this.ranges[t].head));return new ii(e,this.primIndex)},ii.prototype.somethingSelected=function(){for(var e=0;e<this.ranges.length;e++)if(!this.ranges[e].empty())return!0;return!1},ii.prototype.contains=function(e,t){t=t||e;for(var n=0;n<this.ranges.length;n++){var r=this.ranges[n];if(0<=it(t,r.from())&&it(e,r.to())<=0)return n}return-1};var oi=function(e,t){this.anchor=e,this.head=t};function li(e,t,n){var r=e&&e.options.selectionsMayTouch,e=t[n];t.sort(function(e,t){return it(e.from(),t.from())}),n=R(t,e);for(var i=1;i<t.length;i++){var o,l=t[i],s=t[i-1],a=it(s.to(),l.from());(r&&!l.empty()?0<a:0<=a)&&(o=at(s.from(),l.from()),a=st(s.to(),l.to()),s=s.empty()?l.from()==l.head:s.from()==s.head,i<=n&&--n,t.splice(--i,2,new oi(s?a:o,s?o:a)))}return new ii(t,n)}function si(e,t){return new ii([new oi(e,t||e)],0)}function ai(e){return e.text?rt(e.from.line+e.text.length-1,Y(e.text).length+(1==e.text.length?e.from.ch:0)):e.to}function ui(e,t){if(it(e,t.from)<0)return e;if(it(e,t.to)<=0)return ai(t);var n=e.line+t.text.length-(t.to.line-t.from.line)-1,r=e.ch;return e.line==t.to.line&&(r+=ai(t).ch-t.to.ch),rt(n,r)}function ci(e,t){for(var n=[],r=0;r<e.sel.ranges.length;r++){var i=e.sel.ranges[r];n.push(new oi(ui(i.anchor,t),ui(i.head,t)))}return li(e.cm,n,e.sel.primIndex)}function hi(e,t,n){return e.line==t.line?rt(n.line,e.ch-t.ch+n.ch):rt(n.line+(e.line-t.line),e.ch)}function di(e){e.doc.mode=Ue(e.options,e.doc.modeOption),fi(e)}function fi(e){e.doc.iter(function(e){e.stateAfter&&(e.stateAfter=null),e.styles&&(e.styles=null)}),e.doc.modeFrontier=e.doc.highlightFrontier=e.doc.first,zr(e,100),e.state.modeGen++,e.curOp&&tr(e)}function pi(e,t){return 0==t.from.ch&&0==t.to.ch&&""==Y(t.text)&&(!e.cm||e.cm.options.wholeLineUpdateBefore)}function gi(e,o,t,l){function i(e){return t?t[e]:null}function n(e,t,n){var r,i;r=t,i=n,t=l,(n=e).text=r,n.stateAfter&&(n.stateAfter=null),n.styles&&(n.styles=null),null!=n.order&&(n.order=null),Ot(n),Dt(n,i),(t=t?t(n):1)!=n.height&&Qe(n,t),ln(e,"change",e,o)}function r(e,t){for(var n=[],r=e;r<t;++r)n.push(new Xt(c[r],i(r),l));return n}var s,a=o.from,u=o.to,c=o.text,h=$e(e,a.line),d=$e(e,u.line),f=Y(c),p=i(c.length-1),g=u.line-a.line;o.full?(e.insert(0,r(0,c.length)),e.remove(c.length,e.size-c.length)):pi(e,o)?(s=r(0,c.length-1),n(d,d.text,p),g&&e.remove(a.line,g),s.length&&e.insert(a.line,s)):h==d?1==c.length?n(h,h.text.slice(0,a.ch)+f+h.text.slice(u.ch),p):((s=r(1,c.length-1)).push(new Xt(f+h.text.slice(u.ch),p,l)),n(h,h.text.slice(0,a.ch)+c[0],i(0)),e.insert(a.line+1,s)):1==c.length?(n(h,h.text.slice(0,a.ch)+c[0]+d.text.slice(u.ch),i(0)),e.remove(a.line+1,g)):(n(h,h.text.slice(0,a.ch)+c[0],i(0)),n(d,f+d.text.slice(u.ch),p),p=r(1,c.length-1),1<g&&e.remove(a.line+1,g-1),e.insert(a.line+1,p)),ln(e,"change",e,o)}function mi(e,s,a){!function e(t,n,r){if(t.linked)for(var i=0;i<t.linked.length;++i){var o,l=t.linked[i];l.doc!=n&&(o=r&&l.sharedHist,a&&!o||(s(l.doc,o),e(l.doc,t,o)))}}(e,null,!0)}function vi(e,t){if(t.cm)throw new Error("This document is already in use.");Qn((e.doc=t).cm=e),di(e),yi(e),e.options.lineWrapping||jt(e),e.options.mode=t.modeOption,tr(e)}function yi(e){("rtl"==e.doc.direction?D:L)(e.display.lineDiv,"CodeMirror-rtl")}function bi(e){this.done=[],this.undone=[],this.undoDepth=1/0,this.lastModTime=this.lastSelTime=0,this.lastOp=this.lastSelOp=null,this.lastOrigin=this.lastSelOrigin=null,this.generation=this.maxGeneration=e||1}function wi(e,t){var n={from:lt(t.from),to:ai(t),text:qe(e,t.from,t.to)};return ki(e,n,t.from.line,t.to.line+1),mi(e,function(e){return ki(e,n,t.from.line,t.to.line+1),0},!0),n}function xi(e){for(;e.length;){if(!Y(e).ranges)break;e.pop()}}function Ci(e,t,n,r){var i=e.history;i.undone.length=0;var o,l,s=+new Date;if((i.lastOp==r||i.lastOrigin==t.origin&&t.origin&&("+"==t.origin.charAt(0)&&i.lastModTime>s-(e.cm?e.cm.options.historyEventDelay:500)||"*"==t.origin.charAt(0)))&&(o=(a=i).lastOp==r?(xi(a.done),Y(a.done)):a.done.length&&!Y(a.done).ranges?Y(a.done):1<a.done.length&&!a.done[a.done.length-2].ranges?(a.done.pop(),Y(a.done)):void 0))l=Y(o.changes),0==it(t.from,t.to)&&0==it(t.from,l.to)?l.to=ai(t):o.changes.push(wi(e,t));else{var a=Y(i.done);for(a&&a.ranges||Li(e.sel,i.done),o={changes:[wi(e,t)],generation:i.generation},i.done.push(o);i.done.length>i.undoDepth;)i.done.shift(),i.done[0].ranges||i.done.shift()}i.done.push(n),i.generation=++i.maxGeneration,i.lastModTime=i.lastSelTime=s,i.lastOp=i.lastSelOp=r,i.lastOrigin=i.lastSelOrigin=t.origin,l||xe(e,"historyAdded")}function Si(e,t,n,r){var i,o,l,s=e.history,a=r&&r.origin;n==s.lastSelOp||a&&s.lastSelOrigin==a&&(s.lastModTime==s.lastSelTime&&s.lastOrigin==a||(i=e,o=a,l=Y(s.done),e=t,"*"==(o=o.charAt(0))||"+"==o&&l.ranges.length==e.ranges.length&&l.somethingSelected()==e.somethingSelected()&&new Date-i.history.lastSelTime<=(i.cm?i.cm.options.historyEventDelay:500)))?s.done[s.done.length-1]=t:Li(t,s.done),s.lastSelTime=+new Date,s.lastSelOrigin=a,s.lastSelOp=n,r&&!1!==r.clearRedo&&xi(s.undone)}function Li(e,t){var n=Y(t);n&&n.ranges&&n.equals(e)||t.push(e)}function ki(t,n,e,r){var i=n["spans_"+t.id],o=0;t.iter(Math.max(t.first,e),Math.min(t.first+t.size,r),function(e){e.markedSpans&&((i=i||(n["spans_"+t.id]={}))[o]=e.markedSpans),++o})}function Ti(e,t){var n=t["spans_"+e.id];if(!n)return null;for(var r=[],i=0;i<t.text.length;++i)r.push(function(e){if(!e)return null;for(var t,n=0;n<e.length;++n)e[n].marker.explicitlyCleared?t=t||e.slice(0,n):t&&t.push(e[n]);return t?t.length?t:null:e}(n[i]));return r}function Mi(e,t){var n=Ti(e,t),r=Nt(e,t);if(!n)return r;if(!r)return n;for(var i=0;i<n.length;++i){var o=n[i],l=r[i];if(o&&l)e:for(var s=0;s<l.length;++s){for(var a=l[s],u=0;u<o.length;++u)if(o[u].marker==a.marker)continue e;o.push(a)}else l&&(n[i]=l)}return n}function Ni(e,t,n){for(var r=[],i=0;i<e.length;++i){var o=e[i];if(o.ranges)r.push(n?ii.prototype.deepCopy.call(o):o);else{var l=o.changes,s=[];r.push({changes:s});for(var a=0;a<l.length;++a){var u,c=l[a];if(s.push({from:c.from,to:c.to,text:c.text}),t)for(var h in c)(u=h.match(/^spans_(\d+)$/))&&-1<R(t,Number(u[1]))&&(Y(s)[h]=c[h],delete c[h])}}}return r}function Ai(e,t,n,r){if(r){r=e.anchor;return n&&((e=it(t,r)<0)!=it(n,r)<0?(r=t,t=n):e!=it(t,n)<0&&(t=n)),new oi(r,t)}return new oi(n||t,t)}function Oi(e,t,n,r,i){null==i&&(i=e.cm&&(e.cm.display.shift||e.extend)),Ei(e,new ii([Ai(e.sel.primary(),t,n,i)],0),r)}function Di(e,t,n){for(var r=[],i=e.cm&&(e.cm.display.shift||e.extend),o=0;o<e.sel.ranges.length;o++)r[o]=Ai(e.sel.ranges[o],t[o],null,i);Ei(e,li(e.cm,r,e.sel.primIndex),n)}function Wi(e,t,n,r){var i=e.sel.ranges.slice(0);i[t]=n,Ei(e,li(e.cm,i,e.sel.primIndex),r)}function Hi(e,t,n,r){Ei(e,si(t,n),r)}function Fi(e,t,n){var r=e.history.done,i=Y(r);i&&i.ranges?Pi(e,r[r.length-1]=t,n):Ei(e,t,n)}function Ei(e,t,n){Pi(e,t,n),Si(e,e.sel,e.cm?e.cm.curOp.id:NaN,n)}function Pi(e,t,n){var r,i;(Le(e,"beforeSelectionChange")||e.cm&&Le(e.cm,"beforeSelectionChange"))&&(r=e,i=n,i={ranges:(o=t).ranges,update:function(e){this.ranges=[];for(var t=0;t<e.length;t++)this.ranges[t]=new oi(ct(r,e[t].anchor),ct(r,e[t].head))},origin:i&&i.origin},xe(r,"beforeSelectionChange",r,i),r.cm&&xe(r.cm,"beforeSelectionChange",r.cm,i),t=i.ranges!=o.ranges?li(r.cm,i.ranges,i.ranges.length-1):o);var o=n&&n.bias||(it(t.primary().head,e.sel.primary().head)<0?-1:1);Ii(e,zi(e,t,o,!0)),n&&!1===n.scroll||!e.cm||wr(e.cm)}function Ii(e,t){t.equals(e.sel)||(e.sel=t,e.cm&&(e.cm.curOp.updateInput=1,e.cm.curOp.selectionChanged=!0,Se(e.cm)),ln(e,"cursorActivity",e))}function Ri(e){Ii(e,zi(e,e.sel,null,!1))}function zi(e,t,n,r){for(var i,o=0;o<t.ranges.length;o++){var l=t.ranges[o],s=t.ranges.length==e.sel.ranges.length&&e.sel.ranges[o],a=Gi(e,l.anchor,s&&s.anchor,n,r),s=Gi(e,l.head,s&&s.head,n,r);!i&&a==l.anchor&&s==l.head||((i=i||t.ranges.slice(0,o))[o]=new oi(a,s))}return i?li(e.cm,i,t.primIndex):t}function Bi(e,t,n,r,i){var o=$e(e,t.line);if(o.markedSpans)for(var l=0;l<o.markedSpans.length;++l){var s=o.markedSpans[l],a=s.marker,u="selectLeft"in a?!a.selectLeft:a.inclusiveLeft,c="selectRight"in a?!a.selectRight:a.inclusiveRight;if((null==s.from||(u?s.from<=t.ch:s.from<t.ch))&&(null==s.to||(c?s.to>=t.ch:s.to>t.ch))){if(i&&(xe(a,"beforeCursorEnter"),a.explicitlyCleared)){if(o.markedSpans){--l;continue}break}if(a.atomic){if(n){var h=a.find(r<0?1:-1),s=void 0;if((r<0?c:u)&&(h=Ui(e,h,-r,h&&h.line==t.line?o:null)),h&&h.line==t.line&&(s=it(h,n))&&(r<0?s<0:0<s))return Bi(e,h,t,r,i)}a=a.find(r<0?-1:1);return(r<0?u:c)&&(a=Ui(e,a,r,a.line==t.line?o:null)),a?Bi(e,a,t,r,i):null}}}return t}function Gi(e,t,n,r,i){r=r||1,r=Bi(e,t,n,r,i)||!i&&Bi(e,t,n,r,!0)||Bi(e,t,n,-r,i)||!i&&Bi(e,t,n,-r,!0);return r||(e.cantEdit=!0,rt(e.first,0))}function Ui(e,t,n,r){return n<0&&0==t.ch?t.line>e.first?ct(e,rt(t.line-1)):null:0<n&&t.ch==(r||$e(e,t.line)).text.length?t.line<e.first+e.size-1?rt(t.line+1,0):null:new rt(t.line,t.ch+n)}function Vi(e){e.setSelection(rt(e.firstLine(),0),rt(e.lastLine()),G)}function Ki(i,e,t){var o={canceled:!1,from:e.from,to:e.to,text:e.text,origin:e.origin,cancel:function(){return o.canceled=!0}};return t&&(o.update=function(e,t,n,r){e&&(o.from=ct(i,e)),t&&(o.to=ct(i,t)),n&&(o.text=n),void 0!==r&&(o.origin=r)}),xe(i,"beforeChange",i,o),i.cm&&xe(i.cm,"beforeChange",i.cm,o),o.canceled?(i.cm&&(i.cm.curOp.updateInput=2),null):{from:o.from,to:o.to,text:o.text,origin:o.origin}}function ji(e,t,n){if(e.cm){if(!e.cm.curOp)return Pr(e.cm,ji)(e,t,n);if(e.cm.state.suppressEdits)return}if(!(Le(e,"beforeChange")||e.cm&&Le(e.cm,"beforeChange"))||(t=Ki(e,t,!0))){var r=Lt&&!n&&function(e,t,n){var r=null;if(e.iter(t.line,n.line+1,function(e){if(e.markedSpans)for(var t=0;t<e.markedSpans.length;++t){var n=e.markedSpans[t].marker;!n.readOnly||r&&-1!=R(r,n)||(r=r||[]).push(n)}}),!r)return null;for(var i=[{from:t,to:n}],o=0;o<r.length;++o)for(var l=r[o],s=l.find(0),a=0;a<i.length;++a){var u,c,h,d=i[a];it(d.to,s.from)<0||0<it(d.from,s.to)||(u=[a,1],c=it(d.from,s.from),h=it(d.to,s.to),(c<0||!l.inclusiveLeft&&!c)&&u.push({from:d.from,to:s.from}),(0<h||!l.inclusiveRight&&!h)&&u.push({from:s.to,to:d.to}),i.splice.apply(i,u),a+=u.length-3)}return i}(e,t.from,t.to);if(r)for(var i=r.length-1;0<=i;--i)Xi(e,{from:r[i].from,to:r[i].to,text:i?[""]:t.text,origin:t.origin});else Xi(e,t)}}function Xi(e,n){var t,r;1==n.text.length&&""==n.text[0]&&0==it(n.from,n.to)||(t=ci(e,n),Ci(e,n,t,e.cm?e.cm.curOp.id:NaN),$i(e,n,t,Nt(e,n)),r=[],mi(e,function(e,t){t||-1!=R(r,e.history)||(Ji(e.history,n),r.push(e.history)),$i(e,n,null,Nt(e,n))}))}function Yi(i,o,e){var t=i.cm&&i.cm.state.suppressEdits;if(!t||e){for(var l,n=i.history,r=i.sel,s="undo"==o?n.done:n.undone,a="undo"==o?n.undone:n.done,u=0;u<s.length&&(l=s[u],e?!l.ranges||l.equals(i.sel):l.ranges);u++);if(u!=s.length){for(n.lastOrigin=n.lastSelOrigin=null;;){if(!(l=s.pop()).ranges){if(t)return void s.push(l);break}if(Li(l,a),e&&!l.equals(i.sel))return void Ei(i,l,{clearRedo:!1});r=l}var c=[];Li(r,a),a.push({changes:c,generation:n.generation}),n.generation=l.generation||++n.maxGeneration;for(var h=Le(i,"beforeChange")||i.cm&&Le(i.cm,"beforeChange"),d=l.changes.length-1;0<=d;--d){var f=function(e){var n=l.changes[e];if(n.origin=o,h&&!Ki(i,n,!1))return s.length=0,{};c.push(wi(i,n));var t=e?ci(i,n):Y(s);$i(i,n,t,Mi(i,n)),!e&&i.cm&&i.cm.scrollIntoView({from:n.from,to:ai(n)});var r=[];mi(i,function(e,t){t||-1!=R(r,e.history)||(Ji(e.history,n),r.push(e.history)),$i(e,n,null,Mi(e,n))})}(d);if(f)return f.v}}}}function _i(e,t){if(0!=t&&(e.first+=t,e.sel=new ii(_(e.sel.ranges,function(e){return new oi(rt(e.anchor.line+t,e.anchor.ch),rt(e.head.line+t,e.head.ch))}),e.sel.primIndex),e.cm)){tr(e.cm,e.first,e.first-t,t);for(var n=e.cm.display,r=n.viewFrom;r<n.viewTo;r++)nr(e.cm,r,"gutter")}}function $i(e,t,n,r){if(e.cm&&!e.cm.curOp)return Pr(e.cm,$i)(e,t,n,r);var i;t.to.line<e.first?_i(e,t.text.length-1-(t.to.line-t.from.line)):t.from.line>e.lastLine()||(t.from.line<e.first&&(_i(e,i=t.text.length-1-(e.first-t.from.line)),t={from:rt(e.first,0),to:rt(t.to.line+i,t.to.ch),text:[Y(t.text)],origin:t.origin}),i=e.lastLine(),t.to.line>i&&(t={from:t.from,to:rt(i,$e(e,i).text.length),text:[t.text[0]],origin:t.origin}),t.removed=qe(e,t.from,t.to),n=n||ci(e,t),e.cm?function(e,t,n){var r=e.doc,i=e.display,o=t.from,l=t.to,s=!1,a=o.line;e.options.lineWrapping||(a=Je(zt($e(r,o.line))),r.iter(a,l.line+1,function(e){if(e==i.maxLine)return s=!0}));-1<r.sel.contains(t.from,t.to)&&Se(e);gi(r,t,n,Zn(e)),e.options.lineWrapping||(r.iter(a,o.line+t.text.length,function(e){var t=Kt(e);t>i.maxLineLength&&(i.maxLine=e,i.maxLineLength=t,i.maxLineChanged=!0,s=!1)}),s&&(e.curOp.updateMaxLine=!0));(function(e,t){if(e.modeFrontier=Math.min(e.modeFrontier,t),!(e.highlightFrontier<t-10)){for(var n=e.first,r=t-1;n<r;r--){var i=$e(e,r).stateAfter;if(i&&(!(i instanceof dt)||r+i.lookAhead<t)){n=r+1;break}}e.highlightFrontier=Math.min(e.highlightFrontier,n)}})(r,o.line),zr(e,400);a=t.text.length-(l.line-o.line)-1;t.full?tr(e):o.line!=l.line||1!=t.text.length||pi(e.doc,t)?tr(e,o.line,l.line+1,a):nr(e,o.line,"text");r=Le(e,"changes"),a=Le(e,"change");(a||r)&&(t={from:o,to:l,text:t.text,removed:t.removed,origin:t.origin},a&&ln(e,"change",e,t),r&&(e.curOp.changeObjs||(e.curOp.changeObjs=[])).push(t));e.display.selForContextMenu=null}(e.cm,t,r):gi(e,t,r),Pi(e,n,G),e.cantEdit&&Gi(e,rt(e.firstLine(),0))&&(e.cantEdit=!1))}function qi(e,t,n,r,i){var o;it(r=r||n,n)<0&&(n=(o=[r,n])[0],r=o[1]),"string"==typeof t&&(t=e.splitLines(t)),ji(e,{from:n,to:r,text:t,origin:i})}function Zi(e,t,n,r){n<e.line?e.line+=r:t<e.line&&(e.line=t,e.ch=0)}function Qi(e,t,n,r){for(var i=0;i<e.length;++i){var o=e[i],l=!0;if(o.ranges){o.copied||((o=e[i]=o.deepCopy()).copied=!0);for(var s=0;s<o.ranges.length;s++)Zi(o.ranges[s].anchor,t,n,r),Zi(o.ranges[s].head,t,n,r)}else{for(var a=0;a<o.changes.length;++a){var u=o.changes[a];if(n<u.from.line)u.from=rt(u.from.line+r,u.from.ch),u.to=rt(u.to.line+r,u.to.ch);else if(t<=u.to.line){l=!1;break}}l||(e.splice(0,i+1),i=0)}}}function Ji(e,t){var n=t.from.line,r=t.to.line,t=t.text.length-(r-n)-1;Qi(e.done,n,r,t),Qi(e.undone,n,r,t)}function eo(e,t,n,r){var i=t,o=t;return"number"==typeof t?o=$e(e,ut(e,t)):i=Je(t),null==i?null:(r(o,i)&&e.cm&&nr(e.cm,i,n),o)}function to(e){this.lines=e,this.parent=null;for(var t=0,n=0;n<e.length;++n)e[n].parent=this,t+=e[n].height;this.height=t}function no(e){this.children=e;for(var t=0,n=0,r=0;r<e.length;++r){var i=e[r];t+=i.chunkSize(),n+=i.height,i.parent=this}this.size=t,this.height=n,this.parent=null}oi.prototype.from=function(){return at(this.anchor,this.head)},oi.prototype.to=function(){return st(this.anchor,this.head)},oi.prototype.empty=function(){return this.head.line==this.anchor.line&&this.head.ch==this.anchor.ch},to.prototype={chunkSize:function(){return this.lines.length},removeInner:function(e,t){for(var n,r=e,i=e+t;r<i;++r){var o=this.lines[r];this.height-=o.height,(n=o).parent=null,Ot(n),ln(o,"delete")}this.lines.splice(e,t)},collapse:function(e){e.push.apply(e,this.lines)},insertInner:function(e,t,n){this.height+=n,this.lines=this.lines.slice(0,e).concat(t).concat(this.lines.slice(e));for(var r=0;r<t.length;++r)t[r].parent=this},iterN:function(e,t,n){for(var r=e+t;e<r;++e)if(n(this.lines[e]))return!0}},no.prototype={chunkSize:function(){return this.size},removeInner:function(e,t){this.size-=t;for(var n,r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e),s=i.height;if(i.removeInner(e,l),this.height-=s-i.height,o==l&&(this.children.splice(r--,1),i.parent=null),0==(t-=l))break;e=0}else e-=o}this.size-t<25&&(1<this.children.length||!(this.children[0]instanceof to))&&(n=[],this.collapse(n),this.children=[new to(n)],this.children[0].parent=this)},collapse:function(e){for(var t=0;t<this.children.length;++t)this.children[t].collapse(e)},insertInner:function(e,t,n){this.size+=t.length,this.height+=n;for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<=o){if(i.insertInner(e,t,n),i.lines&&50<i.lines.length){for(var l=i.lines.length%25+25,s=l;s<i.lines.length;){var a=new to(i.lines.slice(s,s+=25));i.height-=a.height,this.children.splice(++r,0,a),a.parent=this}i.lines=i.lines.slice(0,l),this.maybeSpill()}break}e-=o}},maybeSpill:function(){if(!(this.children.length<=10)){var e=this;do{var t,n=new no(e.children.splice(e.children.length-5,5))}while(e.parent?(e.size-=n.size,e.height-=n.height,t=R(e.parent.children,e),e.parent.children.splice(t+1,0,n)):(((t=new no(e.children)).parent=e).children=[t,n],e=t),n.parent=e.parent,10<e.children.length);e.parent.maybeSpill()}},iterN:function(e,t,n){for(var r=0;r<this.children.length;++r){var i=this.children[r],o=i.chunkSize();if(e<o){var l=Math.min(t,o-e);if(i.iterN(e,l,n))return!0;if(0==(t-=l))break;e=0}else e-=o}}};function ro(e,t,n){if(n)for(var r in n)n.hasOwnProperty(r)&&(this[r]=n[r]);this.doc=e,this.node=t}function io(e,t,n){Vt(t)<(e.curOp&&e.curOp.scrollTop||e.doc.scrollTop)&&br(e,n)}ro.prototype.clear=function(){var e=this.doc.cm,t=this.line.widgets,n=this.line,r=Je(n);if(null!=r&&t){for(var i=0;i<t.length;++i)t[i]==this&&t.splice(i--,1);t.length||(n.widgets=null);var o=gn(this);Qe(n,Math.max(0,n.height-o)),e&&(Er(e,function(){io(e,n,-o),nr(e,r,"widget")}),ln(e,"lineWidgetCleared",e,this,r))}},ro.prototype.changed=function(){var e=this,t=this.height,n=this.doc.cm,r=this.line;this.height=null;var i=gn(this)-t;i&&(Ut(this.doc,r)||Qe(r,r.height+i),n&&Er(n,function(){n.curOp.forceUpdate=!0,io(n,r,i),ln(n,"lineWidgetChanged",n,e,Je(r))}))},ke(ro);var oo=0,lo=function(e,t){this.lines=[],this.type=t,this.doc=e,this.id=++oo};function so(t,n,r,e,i){if(e&&e.shared)return function(e,n,r,i,o){(i=E(i)).shared=!1;var l=[so(e,n,r,i,o)],s=l[0],a=i.widgetNode;return mi(e,function(e){a&&(i.widgetNode=a.cloneNode(!0)),l.push(so(e,ct(e,n),ct(e,r),i,o));for(var t=0;t<e.linked.length;++t)if(e.linked[t].isParent)return;s=Y(l)}),new ao(l,s)}(t,n,r,e,i);if(t.cm&&!t.cm.curOp)return Pr(t.cm,so)(t,n,r,e,i);var o=new lo(t,i),i=it(n,r);if(e&&E(e,o,!1),0<i||0==i&&!1!==o.clearWhenEmpty)return o;if(o.replacedWith&&(o.collapsed=!0,o.widgetNode=N("span",[o.replacedWith],"CodeMirror-widget"),e.handleMouseEvents||o.widgetNode.setAttribute("cm-ignore-events","true"),e.insertLeft&&(o.widgetNode.insertLeft=!0)),o.collapsed){if(Rt(t,n.line,n,r,o)||n.line!=r.line&&Rt(t,r.line,n,r,o))throw new Error("Inserting collapsed marker partially overlapping an existing one");kt=!0}o.addToHistory&&Ci(t,{from:n,to:r,origin:"markText"},t.sel,NaN);var l,s=n.line,a=t.cm;if(t.iter(s,r.line+1,function(e){var t;a&&o.collapsed&&!a.options.lineWrapping&&zt(e)==a.display.maxLine&&(l=!0),o.collapsed&&s!=n.line&&Qe(e,0),t=e,e=new Tt(o,s==n.line?n.ch:null,s==r.line?r.ch:null),t.markedSpans=t.markedSpans?t.markedSpans.concat([e]):[e],e.marker.attachLine(t),++s}),o.collapsed&&t.iter(n.line,r.line+1,function(e){Ut(t,e)&&Qe(e,0)}),o.clearOnEnter&&ye(o,"beforeCursorEnter",function(){return o.clear()}),o.readOnly&&(Lt=!0,(t.history.done.length||t.history.undone.length)&&t.clearHistory()),o.collapsed&&(o.id=++oo,o.atomic=!0),a){if(l&&(a.curOp.updateMaxLine=!0),o.collapsed)tr(a,n.line,r.line+1);else if(o.className||o.startStyle||o.endStyle||o.css||o.attributes||o.title)for(var u=n.line;u<=r.line;u++)nr(a,u,"text");o.atomic&&Ri(a.doc),ln(a,"markerAdded",a,o)}return o}lo.prototype.clear=function(){if(!this.explicitlyCleared){var e,t=this.doc.cm,n=t&&!t.curOp;n&&Hr(t),!Le(this,"clear")||(e=this.find())&&ln(this,"clear",e.from,e.to);for(var r=null,i=null,o=0;o<this.lines.length;++o){var l=this.lines[o],s=Mt(l.markedSpans,this);t&&!this.collapsed?nr(t,Je(l),"text"):t&&(null!=s.to&&(i=Je(l)),null!=s.from&&(r=Je(l))),l.markedSpans=function(e,t){for(var n,r=0;r<e.length;++r)e[r]!=t&&(n=n||[]).push(e[r]);return n}(l.markedSpans,s),null==s.from&&this.collapsed&&!Ut(this.doc,l)&&t&&Qe(l,Yn(t.display))}if(t&&this.collapsed&&!t.options.lineWrapping)for(var a=0;a<this.lines.length;++a){var u=zt(this.lines[a]),c=Kt(u);c>t.display.maxLineLength&&(t.display.maxLine=u,t.display.maxLineLength=c,t.display.maxLineChanged=!0)}null!=r&&t&&this.collapsed&&tr(t,r,i+1),this.lines.length=0,this.explicitlyCleared=!0,this.atomic&&this.doc.cantEdit&&(this.doc.cantEdit=!1,t&&Ri(t.doc)),t&&ln(t,"markerCleared",t,this,r,i),n&&Fr(t),this.parent&&this.parent.clear()}},lo.prototype.find=function(e,t){var n,r;null==e&&"bookmark"==this.type&&(e=1);for(var i=0;i<this.lines.length;++i){var o=this.lines[i],l=Mt(o.markedSpans,this);if(null!=l.from&&(n=rt(t?o:Je(o),l.from),-1==e))return n;if(null!=l.to&&(r=rt(t?o:Je(o),l.to),1==e))return r}return n&&{from:n,to:r}},lo.prototype.changed=function(){var n=this,r=this.find(-1,!0),i=this,o=this.doc.cm;r&&o&&Er(o,function(){var e=r.line,t=Je(r.line),t=kn(o,t);t&&(Dn(t),o.curOp.selectionChanged=o.curOp.forceUpdate=!0),o.curOp.updateMaxLine=!0,Ut(i.doc,e)||null==i.height||(t=i.height,i.height=null,(t=gn(i)-t)&&Qe(e,e.height+t)),ln(o,"markerChanged",o,n)})},lo.prototype.attachLine=function(e){var t;!this.lines.length&&this.doc.cm&&((t=this.doc.cm.curOp).maybeHiddenMarkers&&-1!=R(t.maybeHiddenMarkers,this)||(t.maybeUnhiddenMarkers||(t.maybeUnhiddenMarkers=[])).push(this)),this.lines.push(e)},lo.prototype.detachLine=function(e){this.lines.splice(R(this.lines,e),1),!this.lines.length&&this.doc.cm&&((e=this.doc.cm.curOp).maybeHiddenMarkers||(e.maybeHiddenMarkers=[])).push(this)},ke(lo);var ao=function(e,t){this.markers=e,this.primary=t;for(var n=0;n<e.length;++n)e[n].parent=this};function uo(e){return e.findMarks(rt(e.first,0),e.clipPos(rt(e.lastLine())),function(e){return e.parent})}ao.prototype.clear=function(){if(!this.explicitlyCleared){this.explicitlyCleared=!0;for(var e=0;e<this.markers.length;++e)this.markers[e].clear();ln(this,"clear")}},ao.prototype.find=function(e,t){return this.primary.find(e,t)},ke(ao);var co=0,ho=function(e,t,n,r,i){if(!(this instanceof ho))return new ho(e,t,n,r,i);null==n&&(n=0),no.call(this,[new to([new Xt("",null)])]),this.first=n,this.scrollTop=this.scrollLeft=0,this.cantEdit=!1,this.cleanGeneration=1;n=rt(this.modeFrontier=this.highlightFrontier=n,0);this.sel=si(n),this.history=new bi(null),this.id=++co,this.modeOption=t,this.lineSep=r,this.direction="rtl"==i?"rtl":"ltr",this.extend=!1,"string"==typeof e&&(e=this.splitLines(e)),gi(this,{from:n,to:n,text:e}),Ei(this,si(n),G)};ho.prototype=q(no.prototype,{constructor:ho,iter:function(e,t,n){n?this.iterN(e-this.first,t-e,n):this.iterN(this.first,this.first+this.size,e)},insert:function(e,t){for(var n=0,r=0;r<t.length;++r)n+=t[r].height;this.insertInner(e-this.first,t,n)},remove:function(e,t){this.removeInner(e-this.first,t)},getValue:function(e){var t=Ze(this,this.first,this.first+this.size);return!1===e?t:t.join(e||this.lineSeparator())},setValue:Rr(function(e){var t=rt(this.first,0),n=this.first+this.size-1;ji(this,{from:t,to:rt(n,$e(this,n).text.length),text:this.splitLines(e),origin:"setValue",full:!0},!0),this.cm&&xr(this.cm,0,0),Ei(this,si(t),G)}),replaceRange:function(e,t,n,r){qi(this,e,t=ct(this,t),n=n?ct(this,n):t,r)},getRange:function(e,t,n){t=qe(this,ct(this,e),ct(this,t));return!1===n?t:t.join(n||this.lineSeparator())},getLine:function(e){e=this.getLineHandle(e);return e&&e.text},getLineHandle:function(e){if(tt(this,e))return $e(this,e)},getLineNumber:Je,getLineHandleVisualStart:function(e){return"number"==typeof e&&(e=$e(this,e)),zt(e)},lineCount:function(){return this.size},firstLine:function(){return this.first},lastLine:function(){return this.first+this.size-1},clipPos:function(e){return ct(this,e)},getCursor:function(e){var t=this.sel.primary(),t=null==e||"head"==e?t.head:"anchor"==e?t.anchor:"end"==e||"to"==e||!1===e?t.to():t.from();return t},listSelections:function(){return this.sel.ranges},somethingSelected:function(){return this.sel.somethingSelected()},setCursor:Rr(function(e,t,n){Hi(this,ct(this,"number"==typeof e?rt(e,t||0):e),null,n)}),setSelection:Rr(function(e,t,n){Hi(this,ct(this,e),ct(this,t||e),n)}),extendSelection:Rr(function(e,t,n){Oi(this,ct(this,e),t&&ct(this,t),n)}),extendSelections:Rr(function(e,t){Di(this,ht(this,e),t)}),extendSelectionsBy:Rr(function(e,t){Di(this,ht(this,_(this.sel.ranges,e)),t)}),setSelections:Rr(function(e,t,n){if(e.length){for(var r=[],i=0;i<e.length;i++)r[i]=new oi(ct(this,e[i].anchor),ct(this,e[i].head));null==t&&(t=Math.min(e.length-1,this.sel.primIndex)),Ei(this,li(this.cm,r,t),n)}}),addSelection:Rr(function(e,t,n){var r=this.sel.ranges.slice(0);r.push(new oi(ct(this,e),ct(this,t||e))),Ei(this,li(this.cm,r,r.length-1),n)}),getSelection:function(e){for(var t=this.sel.ranges,n=0;n<t.length;n++)var r=qe(this,t[n].from(),t[n].to()),i=i?i.concat(r):r;return!1===e?i:i.join(e||this.lineSeparator())},getSelections:function(e){for(var t=[],n=this.sel.ranges,r=0;r<n.length;r++){var i=qe(this,n[r].from(),n[r].to());!1!==e&&(i=i.join(e||this.lineSeparator())),t[r]=i}return t},replaceSelection:function(e,t,n){for(var r=[],i=0;i<this.sel.ranges.length;i++)r[i]=e;this.replaceSelections(r,t,n||"+input")},replaceSelections:Rr(function(e,t,n){for(var r=[],i=this.sel,o=0;o<i.ranges.length;o++){var l=i.ranges[o];r[o]={from:l.from(),to:l.to(),text:this.splitLines(e[o]),origin:n}}for(var t=t&&"end"!=t&&function(e,t,n){for(var r=[],i=u=rt(e.first,0),o=0;o<t.length;o++){var l=t[o],s=hi(l.from,u,i),a=hi(ai(l),u,i),u=l.to,i=a;"around"==n?(l=it((l=e.sel.ranges[o]).head,l.anchor)<0,r[o]=new oi(l?a:s,l?s:a)):r[o]=new oi(s,s)}return new ii(r,e.sel.primIndex)}(this,r,t),s=r.length-1;0<=s;s--)ji(this,r[s]);t?Fi(this,t):this.cm&&wr(this.cm)}),undo:Rr(function(){Yi(this,"undo")}),redo:Rr(function(){Yi(this,"redo")}),undoSelection:Rr(function(){Yi(this,"undo",!0)}),redoSelection:Rr(function(){Yi(this,"redo",!0)}),setExtending:function(e){this.extend=e},getExtending:function(){return this.extend},historySize:function(){for(var e=this.history,t=0,n=0,r=0;r<e.done.length;r++)e.done[r].ranges||++t;for(var i=0;i<e.undone.length;i++)e.undone[i].ranges||++n;return{undo:t,redo:n}},clearHistory:function(){var t=this;this.history=new bi(this.history.maxGeneration),mi(this,function(e){return e.history=t.history},!0)},markClean:function(){this.cleanGeneration=this.changeGeneration(!0)},changeGeneration:function(e){return e&&(this.history.lastOp=this.history.lastSelOp=this.history.lastOrigin=null),this.history.generation},isClean:function(e){return this.history.generation==(e||this.cleanGeneration)},getHistory:function(){return{done:Ni(this.history.done),undone:Ni(this.history.undone)}},setHistory:function(e){var t=this.history=new bi(this.history.maxGeneration);t.done=Ni(e.done.slice(0),null,!0),t.undone=Ni(e.undone.slice(0),null,!0)},setGutterMarker:Rr(function(e,n,r){return eo(this,e,"gutter",function(e){var t=e.gutterMarkers||(e.gutterMarkers={});return!(t[n]=r)&&ee(t)&&(e.gutterMarkers=null),1})}),clearGutter:Rr(function(t){var n=this;this.iter(function(e){e.gutterMarkers&&e.gutterMarkers[t]&&eo(n,e,"gutter",function(){return e.gutterMarkers[t]=null,ee(e.gutterMarkers)&&(e.gutterMarkers=null),1})})}),lineInfo:function(e){var t;if("number"==typeof e){if(!tt(this,e))return null;if(!(e=$e(this,t=e)))return null}else if(null==(t=Je(e)))return null;return{line:t,handle:e,text:e.text,gutterMarkers:e.gutterMarkers,textClass:e.textClass,bgClass:e.bgClass,wrapClass:e.wrapClass,widgets:e.widgets}},addLineClass:Rr(function(e,n,r){return eo(this,e,"gutter"==n?"gutter":"class",function(e){var t="text"==n?"textClass":"background"==n?"bgClass":"gutter"==n?"gutterClass":"wrapClass";if(e[t]){if(C(r).test(e[t]))return;e[t]+=" "+r}else e[t]=r;return 1})}),removeLineClass:Rr(function(e,o,l){return eo(this,e,"gutter"==o?"gutter":"class",function(e){var t="text"==o?"textClass":"background"==o?"bgClass":"gutter"==o?"gutterClass":"wrapClass",n=e[t];if(n){if(null==l)e[t]=null;else{var r=n.match(C(l));if(!r)return;var i=r.index+r[0].length;e[t]=n.slice(0,r.index)+(r.index&&i!=n.length?" ":"")+n.slice(i)||null}return 1}})}),addLineWidget:Rr(function(e,t,n){return e=e,i=new ro(r=this,t,n),(o=r.cm)&&i.noHScroll&&(o.display.alignWidgets=!0),eo(r,e,"widget",function(e){var t=e.widgets||(e.widgets=[]);return null==i.insertAt?t.push(i):t.splice(Math.min(t.length,Math.max(0,i.insertAt)),0,i),i.line=e,o&&!Ut(r,e)&&(t=Vt(e)<r.scrollTop,Qe(e,e.height+gn(i)),t&&br(o,i.height),o.curOp.forceUpdate=!0),1}),o&&ln(o,"lineWidgetAdded",o,i,"number"==typeof e?e:Je(e)),i;var r,i,o}),removeLineWidget:function(e){e.clear()},markText:function(e,t,n){return so(this,ct(this,e),ct(this,t),n,n&&n.type||"range")},setBookmark:function(e,t){t={replacedWith:t&&(null==t.nodeType?t.widget:t),insertLeft:t&&t.insertLeft,clearWhenEmpty:!1,shared:t&&t.shared,handleMouseEvents:t&&t.handleMouseEvents};return so(this,e=ct(this,e),e,t,"bookmark")},findMarksAt:function(e){var t=[],n=$e(this,(e=ct(this,e)).line).markedSpans;if(n)for(var r=0;r<n.length;++r){var i=n[r];(null==i.from||i.from<=e.ch)&&(null==i.to||i.to>=e.ch)&&t.push(i.marker.parent||i.marker)}return t},findMarks:function(i,o,l){i=ct(this,i),o=ct(this,o);var s=[],a=i.line;return this.iter(i.line,o.line+1,function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;n++){var r=t[n];null!=r.to&&a==i.line&&i.ch>=r.to||null==r.from&&a!=i.line||null!=r.from&&a==o.line&&r.from>=o.ch||l&&!l(r.marker)||s.push(r.marker.parent||r.marker)}++a}),s},getAllMarks:function(){var r=[];return this.iter(function(e){var t=e.markedSpans;if(t)for(var n=0;n<t.length;++n)null!=t[n].from&&r.push(t[n].marker)}),r},posFromIndex:function(t){var n,r=this.first,i=this.lineSeparator().length;return this.iter(function(e){e=e.text.length+i;if(t<e)return n=t,!0;t-=e,++r}),ct(this,rt(r,n))},indexFromPos:function(e){var t=(e=ct(this,e)).ch;if(e.line<this.first||e.ch<0)return 0;var n=this.lineSeparator().length;return this.iter(this.first,e.line,function(e){t+=e.text.length+n}),t},copy:function(e){var t=new ho(Ze(this,this.first,this.first+this.size),this.modeOption,this.first,this.lineSep,this.direction);return t.scrollTop=this.scrollTop,t.scrollLeft=this.scrollLeft,t.sel=this.sel,t.extend=!1,e&&(t.history.undoDepth=this.history.undoDepth,t.setHistory(this.getHistory())),t},linkedDoc:function(e){e=e||{};var t=this.first,n=this.first+this.size;null!=e.from&&e.from>t&&(t=e.from),null!=e.to&&e.to<n&&(n=e.to);t=new ho(Ze(this,t,n),e.mode||this.modeOption,t,this.lineSep,this.direction);return e.sharedHist&&(t.history=this.history),(this.linked||(this.linked=[])).push({doc:t,sharedHist:e.sharedHist}),t.linked=[{doc:this,isParent:!0,sharedHist:e.sharedHist}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n],i=r.find(),o=e.clipPos(i.from),i=e.clipPos(i.to);it(o,i)&&(i=so(e,o,i,r.primary,r.primary.type),r.markers.push(i),i.parent=r)}}(t,uo(this)),t},unlinkDoc:function(e){if(e instanceof ul&&(e=e.doc),this.linked)for(var t=0;t<this.linked.length;++t)if(this.linked[t].doc==e){this.linked.splice(t,1),e.unlinkDoc(this),function(o){for(var e=0;e<o.length;e++)!function(e){var t=o[e],n=[t.primary.doc];mi(t.primary.doc,function(e){return n.push(e)});for(var r=0;r<t.markers.length;r++){var i=t.markers[r];-1==R(n,i.doc)&&(i.parent=null,t.markers.splice(r--,1))}}(e)}(uo(this));break}var n;e.history==this.history&&(n=[e.id],mi(e,function(e){return n.push(e.id)},!0),e.history=new bi(null),e.history.done=Ni(this.history.done,n),e.history.undone=Ni(this.history.undone,n))},iterLinkedDocs:function(e){mi(this,e)},getMode:function(){return this.mode},getEditor:function(){return this.cm},splitLines:function(e){return this.lineSep?e.split(this.lineSep):Ee(e)},lineSeparator:function(){return this.lineSep||"\n"},setDirection:Rr(function(e){var t;"rtl"!=e&&(e="ltr"),e!=this.direction&&(this.direction=e,this.iter(function(e){return e.order=null}),this.cm&&Er(t=this.cm,function(){yi(t),tr(t)}))})}),ho.prototype.eachLine=ho.prototype.iter;var fo=0;function po(e){var r=this;if(go(r),!Ce(r,e)&&!mn(r.display,e)){Te(e),w&&(fo=+new Date);var t=Jn(r,e,!0),n=e.dataTransfer.files;if(t&&!r.isReadOnly())if(n&&n.length&&window.FileReader&&window.File)for(var i=n.length,o=Array(i),l=0,s=function(){++l==i&&Pr(r,function(){var e={from:t=ct(r.doc,t),to:t,text:r.doc.splitLines(o.filter(function(e){return null!=e}).join(r.doc.lineSeparator())),origin:"paste"};ji(r.doc,e),Fi(r.doc,si(ct(r.doc,t),ct(r.doc,ai(e))))})()},a=0;a<n.length;a++)!function(e,t){var n;r.options.allowDropFileTypes&&-1==R(r.options.allowDropFileTypes,e.type)?s():((n=new FileReader).onerror=s,n.onload=function(){var e=n.result;/[\x00-\x08\x0e-\x1f]{2}/.test(e)||(o[t]=e),s()},n.readAsText(e))}(n[a],a);else{if(r.state.draggingText&&-1<r.doc.sel.contains(t))return r.state.draggingText(e),void setTimeout(function(){return r.display.input.focus()},20);try{var u,c=e.dataTransfer.getData("Text");if(c){if(r.state.draggingText&&!r.state.draggingText.copy&&(u=r.listSelections()),Pi(r.doc,si(t,t)),u)for(var h=0;h<u.length;++h)qi(r.doc,"",u[h].anchor,u[h].head,"drag");r.replaceSelection(c,"around","paste"),r.display.input.focus()}}catch(e){}}}}function go(e){e.display.dragCursor&&(e.display.lineSpace.removeChild(e.display.dragCursor),e.display.dragCursor=null)}function mo(t){if(document.getElementsByClassName){for(var e=document.getElementsByClassName("CodeMirror"),n=[],r=0;r<e.length;r++){var i=e[r].CodeMirror;i&&n.push(i)}n.length&&n[0].operation(function(){for(var e=0;e<n.length;e++)t(n[e])})}}var vo=!1;function yo(){var e;vo||(ye(window,"resize",function(){null==e&&(e=setTimeout(function(){e=null,mo(bo)},100))}),ye(window,"blur",function(){return mo(pr)}),vo=!0)}function bo(e){var t=e.display;t.cachedCharWidth=t.cachedTextHeight=t.cachedPaddingH=null,t.scrollbarsClipped=!1,e.setSize()}for(var wo={3:"Pause",8:"Backspace",9:"Tab",13:"Enter",16:"Shift",17:"Ctrl",18:"Alt",19:"Pause",20:"CapsLock",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"PrintScrn",45:"Insert",46:"Delete",59:";",61:"=",91:"Mod",92:"Mod",93:"Mod",106:"*",107:"=",109:"-",110:".",111:"/",145:"ScrollLock",173:"-",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'",224:"Mod",63232:"Up",63233:"Down",63234:"Left",63235:"Right",63272:"Delete",63273:"Home",63275:"End",63276:"PageUp",63277:"PageDown",63302:"Insert"},xo=0;xo<10;xo++)wo[xo+48]=wo[xo+96]=String(xo);for(var Co=65;Co<=90;Co++)wo[Co]=String.fromCharCode(Co);for(var So=1;So<=12;So++)wo[So+111]=wo[So+63235]="F"+So;var Lo={};function ko(e){var t,n,r,i,o=e.split(/-(?!$)/);e=o[o.length-1];for(var l=0;l<o.length-1;l++){var s=o[l];if(/^(cmd|meta|m)$/i.test(s))i=!0;else if(/^a(lt)?$/i.test(s))t=!0;else if(/^(c|ctrl|control)$/i.test(s))n=!0;else{if(!/^s(hift)?$/i.test(s))throw new Error("Unrecognized modifier name: "+s);r=!0}}return t&&(e="Alt-"+e),n&&(e="Ctrl-"+e),i&&(e="Cmd-"+e),r&&(e="Shift-"+e),e}function To(e){var t,n,r={};for(t in e)if(e.hasOwnProperty(t)){var i=e[t];if(!/^(name|fallthrough|(de|at)tach)$/.test(t))if("..."!=i){for(var o=_(t.split(" "),ko),l=0;l<o.length;l++){var s=void 0,a=void 0,s=l==o.length-1?(a=o.join(" "),i):(a=o.slice(0,l+1).join(" "),"..."),u=r[a];if(u){if(u!=s)throw new Error("Inconsistent bindings for "+a)}else r[a]=s}delete e[t]}else delete e[t]}for(n in r)e[n]=r[n];return e}function Mo(e,t,n,r){var i=(t=Do(t)).call?t.call(e,r):t[e];if(!1===i)return"nothing";if("..."===i)return"multi";if(null!=i&&n(i))return"handled";if(t.fallthrough){if("[object Array]"!=Object.prototype.toString.call(t.fallthrough))return Mo(e,t.fallthrough,n,r);for(var o=0;o<t.fallthrough.length;o++){var l=Mo(e,t.fallthrough[o],n,r);if(l)return l}}}function No(e){e="string"==typeof e?e:wo[e.keyCode];return"Ctrl"==e||"Alt"==e||"Shift"==e||"Mod"==e}function Ao(e,t,n){var r=e;return t.altKey&&"Alt"!=r&&(e="Alt-"+e),(b?t.metaKey:t.ctrlKey)&&"Ctrl"!=r&&(e="Ctrl-"+e),(b?t.ctrlKey:t.metaKey)&&"Mod"!=r&&(e="Cmd-"+e),!n&&t.shiftKey&&"Shift"!=r&&(e="Shift-"+e),e}function Oo(e,t){if(p&&34==e.keyCode&&e.char)return!1;var n=wo[e.keyCode];return null!=n&&!e.altGraphKey&&(3==e.keyCode&&e.code&&(n=e.code),Ao(n,e,t))}function Do(e){return"string"==typeof e?Lo[e]:e}function Wo(t,e){for(var n=t.doc.sel.ranges,r=[],i=0;i<n.length;i++){for(var o=e(n[i]);r.length&&it(o.from,Y(r).to)<=0;){var l=r.pop();if(it(l.from,o.from)<0){o.from=l.from;break}}r.push(o)}Er(t,function(){for(var e=r.length-1;0<=e;e--)qi(t.doc,"",r[e].from,r[e].to,"+delete");wr(t)})}function Ho(e,t,n){n=re(e.text,t+n,n);return n<0||n>e.text.length?null:n}function Fo(e,t,n){e=Ho(e,t.ch,n);return null==e?null:new rt(t.line,e,n<0?"after":"before")}function Eo(e,t,n,r,i){if(e){"rtl"==t.doc.direction&&(i=-i);var o=me(n,t.doc.direction);if(o){var l,s,a,e=i<0?Y(o):o[0],o=i<0==(1==e.level)?"after":"before";return 0<e.level||"rtl"==t.doc.direction?(l=Tn(t,n),s=i<0?n.text.length-1:0,a=Mn(t,l,s).top,s=ie(function(e){return Mn(t,l,e).top==a},i<0==(1==e.level)?e.from:e.to-1,s),"before"==o&&(s=Ho(n,s,1))):s=i<0?e.to:e.from,new rt(r,s,o)}}return new rt(r,i<0?n.text.length:0,i<0?"before":"after")}function Po(t,n,s,e){var a=me(n,t.doc.direction);if(!a)return Fo(n,s,e);s.ch>=n.text.length?(s.ch=n.text.length,s.sticky="before"):s.ch<=0&&(s.ch=0,s.sticky="after");var r=le(a,s.ch,s.sticky),i=a[r];if("ltr"==t.doc.direction&&i.level%2==0&&(0<e?i.to>s.ch:i.from<s.ch))return Fo(n,s,e);function u(e,t){return Ho(n,e instanceof rt?e.ch:e,t)}function o(e){return t.options.lineWrapping?(l=l||Tn(t,n),jn(t,n,l,e)):{begin:0,end:n.text.length}}var l,c=o("before"==s.sticky?u(s,-1):s.ch);if("rtl"==t.doc.direction||1==i.level){var h=1==i.level==e<0,d=u(s,h?1:-1);if(null!=d&&(h?d<=i.to&&d<=c.end:d>=i.from&&d>=c.begin)){var f=h?"before":"after";return new rt(s.line,d,f)}}f=function(e,t,n){for(var r=function(e,t){return t?new rt(s.line,u(e,1),"before"):new rt(s.line,e,"after")};0<=e&&e<a.length;e+=t){var i=a[e],o=0<t==(1!=i.level),l=o?n.begin:u(n.end,-1);if(i.from<=l&&l<i.to)return r(l,o);if(l=o?i.from:u(i.to,-1),n.begin<=l&&l<n.end)return r(l,o)}},r=f(r+e,e,c);if(r)return r;c=0<e?c.end:u(c.begin,-1);return null==c||0<e&&c==n.text.length||!(r=f(0<e?0:a.length-1,e,o(c)))?null:r}Lo.basic={Left:"goCharLeft",Right:"goCharRight",Up:"goLineUp",Down:"goLineDown",End:"goLineEnd",Home:"goLineStartSmart",PageUp:"goPageUp",PageDown:"goPageDown",Delete:"delCharAfter",Backspace:"delCharBefore","Shift-Backspace":"delCharBefore",Tab:"defaultTab","Shift-Tab":"indentAuto",Enter:"newlineAndIndent",Insert:"toggleOverwrite",Esc:"singleSelection"},Lo.pcDefault={"Ctrl-A":"selectAll","Ctrl-D":"deleteLine","Ctrl-Z":"undo","Shift-Ctrl-Z":"redo","Ctrl-Y":"redo","Ctrl-Home":"goDocStart","Ctrl-End":"goDocEnd","Ctrl-Up":"goLineUp","Ctrl-Down":"goLineDown","Ctrl-Left":"goGroupLeft","Ctrl-Right":"goGroupRight","Alt-Left":"goLineStart","Alt-Right":"goLineEnd","Ctrl-Backspace":"delGroupBefore","Ctrl-Delete":"delGroupAfter","Ctrl-S":"save","Ctrl-F":"find","Ctrl-G":"findNext","Shift-Ctrl-G":"findPrev","Shift-Ctrl-F":"replace","Shift-Ctrl-R":"replaceAll","Ctrl-[":"indentLess","Ctrl-]":"indentMore","Ctrl-U":"undoSelection","Shift-Ctrl-U":"redoSelection","Alt-U":"redoSelection",fallthrough:"basic"},Lo.emacsy={"Ctrl-F":"goCharRight","Ctrl-B":"goCharLeft","Ctrl-P":"goLineUp","Ctrl-N":"goLineDown","Alt-F":"goWordRight","Alt-B":"goWordLeft","Ctrl-A":"goLineStart","Ctrl-E":"goLineEnd","Ctrl-V":"goPageDown","Shift-Ctrl-V":"goPageUp","Ctrl-D":"delCharAfter","Ctrl-H":"delCharBefore","Alt-D":"delWordAfter","Alt-Backspace":"delWordBefore","Ctrl-K":"killLine","Ctrl-T":"transposeChars","Ctrl-O":"openLine"},Lo.macDefault={"Cmd-A":"selectAll","Cmd-D":"deleteLine","Cmd-Z":"undo","Shift-Cmd-Z":"redo","Cmd-Y":"redo","Cmd-Home":"goDocStart","Cmd-Up":"goDocStart","Cmd-End":"goDocEnd","Cmd-Down":"goDocEnd","Alt-Left":"goGroupLeft","Alt-Right":"goGroupRight","Cmd-Left":"goLineLeft","Cmd-Right":"goLineRight","Alt-Backspace":"delGroupBefore","Ctrl-Alt-Backspace":"delGroupAfter","Alt-Delete":"delGroupAfter","Cmd-S":"save","Cmd-F":"find","Cmd-G":"findNext","Shift-Cmd-G":"findPrev","Cmd-Alt-F":"replace","Shift-Cmd-Alt-F":"replaceAll","Cmd-[":"indentLess","Cmd-]":"indentMore","Cmd-Backspace":"delWrappedLineLeft","Cmd-Delete":"delWrappedLineRight","Cmd-U":"undoSelection","Shift-Cmd-U":"redoSelection","Ctrl-Up":"goDocStart","Ctrl-Down":"goDocEnd",fallthrough:["basic","emacsy"]},Lo.default=g?Lo.macDefault:Lo.pcDefault;var Io={selectAll:Vi,singleSelection:function(e){return e.setSelection(e.getCursor("anchor"),e.getCursor("head"),G)},killLine:function(n){return Wo(n,function(e){if(e.empty()){var t=$e(n.doc,e.head.line).text.length;return e.head.ch==t&&e.head.line<n.lastLine()?{from:e.head,to:rt(e.head.line+1,0)}:{from:e.head,to:rt(e.head.line,t)}}return{from:e.from(),to:e.to()}})},deleteLine:function(t){return Wo(t,function(e){return{from:rt(e.from().line,0),to:ct(t.doc,rt(e.to().line+1,0))}})},delLineLeft:function(e){return Wo(e,function(e){return{from:rt(e.from().line,0),to:e.from()}})},delWrappedLineLeft:function(n){return Wo(n,function(e){var t=n.charCoords(e.head,"div").top+5;return{from:n.coordsChar({left:0,top:t},"div"),to:e.from()}})},delWrappedLineRight:function(n){return Wo(n,function(e){var t=n.charCoords(e.head,"div").top+5,t=n.coordsChar({left:n.display.lineDiv.offsetWidth+100,top:t},"div");return{from:e.from(),to:t}})},undo:function(e){return e.undo()},redo:function(e){return e.redo()},undoSelection:function(e){return e.undoSelection()},redoSelection:function(e){return e.redoSelection()},goDocStart:function(e){return e.extendSelection(rt(e.firstLine(),0))},goDocEnd:function(e){return e.extendSelection(rt(e.lastLine()))},goLineStart:function(t){return t.extendSelectionsBy(function(e){return Ro(t,e.head.line)},{origin:"+move",bias:1})},goLineStartSmart:function(t){return t.extendSelectionsBy(function(e){return zo(t,e.head)},{origin:"+move",bias:1})},goLineEnd:function(t){return t.extendSelectionsBy(function(e){return function(e,t){var n=$e(e.doc,t),r=function(e){for(var t;t=It(e);)e=t.find(1,!0).line;return e}(n);r!=n&&(t=Je(r));return Eo(!0,e,n,t,-1)}(t,e.head.line)},{origin:"+move",bias:-1})},goLineRight:function(t){return t.extendSelectionsBy(function(e){e=t.cursorCoords(e.head,"div").top+5;return t.coordsChar({left:t.display.lineDiv.offsetWidth+100,top:e},"div")},V)},goLineLeft:function(t){return t.extendSelectionsBy(function(e){e=t.cursorCoords(e.head,"div").top+5;return t.coordsChar({left:0,top:e},"div")},V)},goLineLeftSmart:function(n){return n.extendSelectionsBy(function(e){var t=n.cursorCoords(e.head,"div").top+5,t=n.coordsChar({left:0,top:t},"div");return t.ch<n.getLine(t.line).search(/\S/)?zo(n,e.head):t},V)},goLineUp:function(e){return e.moveV(-1,"line")},goLineDown:function(e){return e.moveV(1,"line")},goPageUp:function(e){return e.moveV(-1,"page")},goPageDown:function(e){return e.moveV(1,"page")},goCharLeft:function(e){return e.moveH(-1,"char")},goCharRight:function(e){return e.moveH(1,"char")},goColumnLeft:function(e){return e.moveH(-1,"column")},goColumnRight:function(e){return e.moveH(1,"column")},goWordLeft:function(e){return e.moveH(-1,"word")},goGroupRight:function(e){return e.moveH(1,"group")},goGroupLeft:function(e){return e.moveH(-1,"group")},goWordRight:function(e){return e.moveH(1,"word")},delCharBefore:function(e){return e.deleteH(-1,"codepoint")},delCharAfter:function(e){return e.deleteH(1,"char")},delWordBefore:function(e){return e.deleteH(-1,"word")},delWordAfter:function(e){return e.deleteH(1,"word")},delGroupBefore:function(e){return e.deleteH(-1,"group")},delGroupAfter:function(e){return e.deleteH(1,"group")},indentAuto:function(e){return e.indentSelection("smart")},indentMore:function(e){return e.indentSelection("add")},indentLess:function(e){return e.indentSelection("subtract")},insertTab:function(e){return e.replaceSelection("\t")},insertSoftTab:function(e){for(var t=[],n=e.listSelections(),r=e.options.tabSize,i=0;i<n.length;i++){var o=n[i].from(),o=P(e.getLine(o.line),o.ch,r);t.push(X(r-o%r))}e.replaceSelections(t)},defaultTab:function(e){e.somethingSelected()?e.indentSelection("add"):e.execCommand("insertTab")},transposeChars:function(l){return Er(l,function(){for(var e,t,n,r=l.listSelections(),i=[],o=0;o<r.length;o++)r[o].empty()&&(e=r[o].head,(t=$e(l.doc,e.line).text)&&(e.ch==t.length&&(e=new rt(e.line,e.ch-1)),0<e.ch?(e=new rt(e.line,e.ch+1),l.replaceRange(t.charAt(e.ch-1)+t.charAt(e.ch-2),rt(e.line,e.ch-2),e,"+transpose")):e.line>l.doc.first&&((n=$e(l.doc,e.line-1).text)&&(e=new rt(e.line,1),l.replaceRange(t.charAt(0)+l.doc.lineSeparator()+n.charAt(n.length-1),rt(e.line-1,n.length-1),e,"+transpose")))),i.push(new oi(e,e)));l.setSelections(i)})},newlineAndIndent:function(r){return Er(r,function(){for(var e=r.listSelections(),t=e.length-1;0<=t;t--)r.replaceRange(r.doc.lineSeparator(),e[t].anchor,e[t].head,"+input");e=r.listSelections();for(var n=0;n<e.length;n++)r.indentLine(e[n].from().line,null,!0);wr(r)})},openLine:function(e){return e.replaceSelection("\n","start")},toggleOverwrite:function(e){return e.toggleOverwrite()}};function Ro(e,t){var n=$e(e.doc,t),r=zt(n);return r!=n&&(t=Je(r)),Eo(!0,e,r,t,1)}function zo(e,t){var n=Ro(e,t.line),r=$e(e.doc,n.line),e=me(r,e.doc.direction);if(e&&0!=e[0].level)return n;r=Math.max(n.ch,r.text.search(/\S/)),t=t.line==n.line&&t.ch<=r&&t.ch;return rt(n.line,t?0:r,n.sticky)}function Bo(e,t,n){if("string"==typeof t&&!(t=Io[t]))return!1;e.display.input.ensurePolled();var r=e.display.shift,i=!1;try{e.isReadOnly()&&(e.state.suppressEdits=!0),n&&(e.display.shift=!1),i=t(e)!=B}finally{e.display.shift=r,e.state.suppressEdits=!1}return i}var Go=new I;function Uo(e,t,n,r){var i=e.state.keySeq;if(i){if(No(t))return"handled";if(/\'$/.test(t)?e.state.keySeq=null:Go.set(50,function(){e.state.keySeq==i&&(e.state.keySeq=null,e.display.input.reset())}),Vo(e,i+" "+t,n,r))return!0}return Vo(e,t,n,r)}function Vo(e,t,n,r){r=function(e,t,n){for(var r=0;r<e.state.keyMaps.length;r++){var i=Mo(t,e.state.keyMaps[r],n,e);if(i)return i}return e.options.extraKeys&&Mo(t,e.options.extraKeys,n,e)||Mo(t,e.options.keyMap,n,e)}(e,t,r);return"multi"==r&&(e.state.keySeq=t),"handled"==r&&ln(e,"keyHandled",e,t,n),"handled"!=r&&"multi"!=r||(Te(n),cr(e)),!!r}function Ko(t,e){var n=Oo(e,!0);return!!n&&(e.shiftKey&&!t.state.keySeq?Uo(t,"Shift-"+n,e,function(e){return Bo(t,e,!0)})||Uo(t,n,e,function(e){if("string"==typeof e?/^go[A-Z]/.test(e):e.motion)return Bo(t,e)}):Uo(t,n,e,function(e){return Bo(t,e)}))}var jo=null;function Xo(e){var t,n,r,i=this;function o(e){18!=e.keyCode&&e.altKey||(L(r,"CodeMirror-crosshair"),we(document,"keyup",o),we(document,"mouseover",o))}e.target&&e.target!=i.display.input.getField()||(i.curOp.focus=O(),Ce(i,e)||(w&&v<11&&27==e.keyCode&&(e.returnValue=!1),t=e.keyCode,i.display.shift=16==t||e.shiftKey,n=Ko(i,e),p&&(jo=n?t:null,!n&&88==t&&!Ie&&(g?e.metaKey:e.ctrlKey)&&i.replaceSelection("",null,"cut")),d&&!g&&!n&&46==t&&e.shiftKey&&!e.ctrlKey&&document.execCommand&&document.execCommand("cut"),18!=t||/\bCodeMirror-crosshair\b/.test(i.display.lineDiv.className)||(D(r=i.display.lineDiv,"CodeMirror-crosshair"),ye(document,"keyup",o),ye(document,"mouseover",o))))}function Yo(e){16==e.keyCode&&(this.doc.sel.shift=!1),Ce(this,e)}function _o(e){var t=this;if(!(e.target&&e.target!=t.display.input.getField()||mn(t.display,e)||Ce(t,e)||e.ctrlKey&&!e.altKey||g&&e.metaKey)){var n,r=e.keyCode,i=e.charCode;if(p&&r==jo)return jo=null,void Te(e);p&&(!e.which||e.which<10)&&Ko(t,e)||"\b"!=(i=String.fromCharCode(null==i?r:i))&&(Uo(n=t,"'"+i+"'",e,function(e){return Bo(n,e,!0)})||t.display.input.onKeyPress(e))}}var $o,qo,Zo=function(e,t,n){this.time=e,this.pos=t,this.button=n};function Qo(e){var t,n,r,i,o,l=this,s=l.display;Ce(l,e)||s.activeTouch&&s.input.supportsTouch()||(s.input.ensurePolled(),s.shift=e.shiftKey,mn(s,e)?f||(s.scroller.draggable=!1,setTimeout(function(){return s.scroller.draggable=!0},100)):tl(l,e)||(t=Jn(l,e),n=De(e),i=t?(r=t,i=n,o=+new Date,qo&&qo.compare(o,r,i)?($o=qo=null,"triple"):$o&&$o.compare(o,r,i)?(qo=new Zo(o,r,i),$o=null,"double"):($o=new Zo(o,r,i),qo=null,"single")):"single",window.focus(),1==n&&l.state.selectingText&&l.state.selectingText(e),t&&function(n,e,r,t,i){var o="Click";"double"==t?o="Double"+o:"triple"==t&&(o="Triple"+o);return Uo(n,Ao(o=(1==e?"Left":2==e?"Middle":"Right")+o,i),i,function(e){if("string"==typeof e&&(e=Io[e]),!e)return!1;var t=!1;try{n.isReadOnly()&&(n.state.suppressEdits=!0),t=e(n,r)!=B}finally{n.state.suppressEdits=!1}return t})}(l,n,t,i,e)||(1==n?t?function(e,t,n,r){w?setTimeout(F(hr,e),0):e.curOp.focus=O();var i,o=function(e,t,n){var r=e.getOption("configureMouse"),i=r?r(e,t,n):{};null==i.unit&&(r=m?n.shiftKey&&n.metaKey:n.altKey,i.unit=r?"rectangle":"single"==t?"char":"double"==t?"word":"line");null!=i.extend&&!e.doc.extend||(i.extend=e.doc.extend||n.shiftKey);null==i.addNew&&(i.addNew=g?n.metaKey:n.ctrlKey);null==i.moveOnDrag&&(i.moveOnDrag=!(g?n.altKey:n.ctrlKey));return i}(e,n,r),l=e.doc.sel;(e.options.dragDrop&&Fe&&!e.isReadOnly()&&"single"==n&&-1<(i=l.contains(t))&&(it((i=l.ranges[i]).from(),t)<0||0<t.xRel)&&(0<it(i.to(),t)||t.xRel<0)?function(t,n,r,i){var o=t.display,l=!1,s=Pr(t,function(e){f&&(o.scroller.draggable=!1),t.state.draggingText=!1,t.state.delayingBlurEvent&&(t.hasFocus()?t.state.delayingBlurEvent=!1:dr(t)),we(o.wrapper.ownerDocument,"mouseup",s),we(o.wrapper.ownerDocument,"mousemove",a),we(o.scroller,"dragstart",u),we(o.scroller,"drop",s),l||(Te(e),i.addNew||Oi(t.doc,r,null,null,i.extend),f&&!c||w&&9==v?setTimeout(function(){o.wrapper.ownerDocument.body.focus({preventScroll:!0}),o.input.focus()},20):o.input.focus())}),a=function(e){l=l||10<=Math.abs(n.clientX-e.clientX)+Math.abs(n.clientY-e.clientY)},u=function(){return l=!0};f&&(o.scroller.draggable=!0);(t.state.draggingText=s).copy=!i.moveOnDrag,ye(o.wrapper.ownerDocument,"mouseup",s),ye(o.wrapper.ownerDocument,"mousemove",a),ye(o.scroller,"dragstart",u),ye(o.scroller,"drop",s),t.state.delayingBlurEvent=!0,setTimeout(function(){return o.input.focus()},20),o.scroller.dragDrop&&o.scroller.dragDrop()}:function(d,e,f,p){w&&dr(d);var l=d.display,g=d.doc;Te(e);var m,v,y=g.sel,t=y.ranges;p.addNew&&!p.extend?(v=g.sel.contains(f),m=-1<v?t[v]:new oi(f,f)):(m=g.sel.primary(),v=g.sel.primIndex);"rectangle"==p.unit?(p.addNew||(m=new oi(f,f)),f=Jn(d,e,!0,!0),v=-1):(e=Jo(d,f,p.unit),m=p.extend?Ai(m,e.anchor,e.head,p.extend):e);p.addNew?-1==v?(v=t.length,Ei(g,li(d,t.concat([m]),v),{scroll:!1,origin:"*mouse"})):1<t.length&&t[v].empty()&&"char"==p.unit&&!p.extend?(Ei(g,li(d,t.slice(0,v).concat(t.slice(v+1)),0),{scroll:!1,origin:"*mouse"}),y=g.sel):Wi(g,v,m,U):(Ei(g,new ii([m],v=0),U),y=g.sel);var b=f;function s(e){if(0!=it(b,e))if(b=e,"rectangle"==p.unit){for(var t=[],n=d.options.tabSize,r=P($e(g,f.line).text,f.ch,n),i=P($e(g,e.line).text,e.ch,n),o=Math.min(r,i),l=Math.max(r,i),s=Math.min(f.line,e.line),a=Math.min(d.lastLine(),Math.max(f.line,e.line));s<=a;s++){var u=$e(g,s).text,c=K(u,o,n);o==l?t.push(new oi(rt(s,c),rt(s,c))):u.length>c&&t.push(new oi(rt(s,c),rt(s,K(u,l,n))))}t.length||t.push(new oi(f,f)),Ei(g,li(d,y.ranges.slice(0,v).concat(t),v),{origin:"*mouse",scroll:!1}),d.scrollIntoView(e)}else{var h,r=m,i=Jo(d,e,p.unit),e=r.anchor,e=0<it(i.anchor,e)?(h=i.head,at(r.from(),i.anchor)):(h=i.anchor,st(r.to(),i.head)),i=y.ranges.slice(0);i[v]=function(e,t){var n=t.anchor,r=t.head,i=$e(e.doc,n.line);if(0==it(n,r)&&n.sticky==r.sticky)return t;var o=me(i);if(!o)return t;var l=le(o,n.ch,n.sticky),s=o[l];if(s.from!=n.ch&&s.to!=n.ch)return t;i=l+(s.from==n.ch==(1!=s.level)?0:1);if(0==i||i==o.length)return t;a=r.line!=n.line?0<(r.line-n.line)*("ltr"==e.doc.direction?1:-1):(e=le(o,r.ch,r.sticky),a=e-l||(r.ch-n.ch)*(1==s.level?-1:1),e==i-1||e==i?a<0:0<a);var i=o[i+(a?-1:0)],a=a==(1==i.level),i=a?i.from:i.to,a=a?"after":"before";return n.ch==i&&n.sticky==a?t:new oi(new rt(n.line,i,a),r)}(d,new oi(ct(g,e),h)),Ei(g,li(d,i,v),U)}}var a=l.wrapper.getBoundingClientRect(),u=0;function n(e){d.state.selectingText=!1,u=1/0,e&&(Te(e),l.input.focus()),we(l.wrapper.ownerDocument,"mousemove",r),we(l.wrapper.ownerDocument,"mouseup",i),g.history.lastSelOrigin=null}var r=Pr(d,function(e){(0!==e.buttons&&De(e)?function e(t){var n,r,i=++u,o=Jn(d,t,!0,"rectangle"==p.unit);o&&(0!=it(o,b)?(d.curOp.focus=O(),s(o),n=vr(l,g),(o.line>=n.to||o.line<n.from)&&setTimeout(Pr(d,function(){u==i&&e(t)}),150)):(r=t.clientY<a.top?-20:t.clientY>a.bottom?20:0)&&setTimeout(Pr(d,function(){u==i&&(l.scroller.scrollTop+=r,e(t))}),50))}:n)(e)}),i=Pr(d,n);d.state.selectingText=i,ye(l.wrapper.ownerDocument,"mousemove",r),ye(l.wrapper.ownerDocument,"mouseup",i)})(e,r,t,o)}(l,t,i,e):Oe(e)==s.scroller&&Te(e):2==n?(t&&Oi(l.doc,t),setTimeout(function(){return s.input.focus()},20)):3==n&&(x?l.display.input.onContextMenu(e):dr(l)))))}function Jo(e,t,n){if("char"==n)return new oi(t,t);if("word"==n)return e.findWordAt(t);if("line"==n)return new oi(rt(t.line,0),ct(e.doc,rt(t.line+1,0)));t=n(e,t);return new oi(t.from,t.to)}function el(e,t,n,r){var i,o;if(t.touches)i=t.touches[0].clientX,o=t.touches[0].clientY;else try{i=t.clientX,o=t.clientY}catch(e){return!1}if(i>=Math.floor(e.display.gutters.getBoundingClientRect().right))return!1;r&&Te(t);var l=e.display,r=l.lineDiv.getBoundingClientRect();if(o>r.bottom||!Le(e,n))return Ne(t);o-=r.top-l.viewOffset;for(var s=0;s<e.display.gutterSpecs.length;++s){var a=l.gutters.childNodes[s];if(a&&a.getBoundingClientRect().right>=i)return xe(e,n,e,et(e.doc,o),e.display.gutterSpecs[s].className,t),Ne(t)}}function tl(e,t){return el(e,t,"gutterClick",!0)}function nl(e,t){var n,r;mn(e.display,t)||(r=t,Le(n=e,"gutterContextMenu")&&el(n,r,"gutterContextMenu",!1))||Ce(e,t,"contextmenu")||x||e.display.input.onContextMenu(t)}function rl(e){e.display.wrapper.className=e.display.wrapper.className.replace(/\s*cm-s-\S+/g,"")+e.options.theme.replace(/(^|\s)\s*/g," cm-s-"),Hn(e)}Zo.prototype.compare=function(e,t,n){return this.time+400>e&&0==it(t,this.pos)&&n==this.button};var il={toString:function(){return"CodeMirror.Init"}},ol={},ll={};function sl(e,t,n){!t!=!(n&&n!=il)&&(n=e.display.dragFunctions,(t=t?ye:we)(e.display.scroller,"dragstart",n.start),t(e.display.scroller,"dragenter",n.enter),t(e.display.scroller,"dragover",n.over),t(e.display.scroller,"dragleave",n.leave),t(e.display.scroller,"drop",n.drop))}function al(e){e.options.lineWrapping?(D(e.display.wrapper,"CodeMirror-wrap"),e.display.sizer.style.minWidth="",e.display.sizerWidth=null):(L(e.display.wrapper,"CodeMirror-wrap"),jt(e)),Qn(e),tr(e),Hn(e),setTimeout(function(){return Nr(e)},100)}function ul(e,t){var n=this;if(!(this instanceof ul))return new ul(e,t);this.options=t=t?E(t):{},E(ol,t,!1);var r=t.value;"string"==typeof r?r=new ho(r,t.mode,null,t.lineSeparator,t.direction):t.mode&&(r.modeOption=t.mode),this.doc=r;var i,o=new ul.inputStyles[t.inputStyle](this),o=this.display=new Qr(e,r,o,t);for(i in rl(o.wrapper.CodeMirror=this),t.lineWrapping&&(this.display.wrapper.className+=" CodeMirror-wrap"),Dr(this),this.state={keyMaps:[],overlays:[],modeGen:0,overwrite:!1,delayingBlurEvent:!1,focused:!1,suppressEdits:!1,pasteIncoming:-1,cutIncoming:-1,selectingText:!1,draggingText:!1,highlight:new I,keySeq:null,specialChars:null},t.autofocus&&!h&&o.input.focus(),w&&v<11&&setTimeout(function(){return n.display.input.reset(!0)},20),function(r){var i=r.display;ye(i.scroller,"mousedown",Pr(r,Qo)),ye(i.scroller,"dblclick",w&&v<11?Pr(r,function(e){var t;Ce(r,e)||(!(t=Jn(r,e))||tl(r,e)||mn(r.display,e)||(Te(e),t=r.findWordAt(t),Oi(r.doc,t.anchor,t.head)))}):function(e){return Ce(r,e)||Te(e)});ye(i.scroller,"contextmenu",function(e){return nl(r,e)}),ye(i.input.getField(),"contextmenu",function(e){i.scroller.contains(e.target)||nl(r,e)});var n,o={end:0};function l(){i.activeTouch&&(n=setTimeout(function(){return i.activeTouch=null},1e3),(o=i.activeTouch).end=+new Date)}function s(e,t){if(null==t.left)return 1;var n=t.left-e.left,e=t.top-e.top;return 400<n*n+e*e}ye(i.scroller,"touchstart",function(e){var t;Ce(r,e)||function(e){if(1==e.touches.length){e=e.touches[0];return e.radiusX<=1&&e.radiusY<=1}}(e)||tl(r,e)||(i.input.ensurePolled(),clearTimeout(n),t=+new Date,i.activeTouch={start:t,moved:!1,prev:t-o.end<=300?o:null},1==e.touches.length&&(i.activeTouch.left=e.touches[0].pageX,i.activeTouch.top=e.touches[0].pageY))}),ye(i.scroller,"touchmove",function(){i.activeTouch&&(i.activeTouch.moved=!0)}),ye(i.scroller,"touchend",function(e){var t,n=i.activeTouch;n&&!mn(i,e)&&null!=n.left&&!n.moved&&new Date-n.start<300&&(t=r.coordsChar(i.activeTouch,"page"),t=!n.prev||s(n,n.prev)?new oi(t,t):!n.prev.prev||s(n,n.prev.prev)?r.findWordAt(t):new oi(rt(t.line,0),ct(r.doc,rt(t.line+1,0))),r.setSelection(t.anchor,t.head),r.focus(),Te(e)),l()}),ye(i.scroller,"touchcancel",l),ye(i.scroller,"scroll",function(){i.scroller.clientHeight&&(Lr(r,i.scroller.scrollTop),Tr(r,i.scroller.scrollLeft,!0),xe(r,"scroll",r))}),ye(i.scroller,"mousewheel",function(e){return ri(r,e)}),ye(i.scroller,"DOMMouseScroll",function(e){return ri(r,e)}),ye(i.wrapper,"scroll",function(){return i.wrapper.scrollTop=i.wrapper.scrollLeft=0}),i.dragFunctions={enter:function(e){Ce(r,e)||Ae(e)},over:function(e){var t,n;Ce(r,e)||((n=Jn(t=r,n=e))&&(ar(t,n,n=document.createDocumentFragment()),t.display.dragCursor||(t.display.dragCursor=M("div",null,"CodeMirror-cursors CodeMirror-dragcursors"),t.display.lineSpace.insertBefore(t.display.dragCursor,t.display.cursorDiv)),T(t.display.dragCursor,n)),Ae(e))},start:function(e){return t=r,n=e,void(w&&(!t.state.draggingText||+new Date-fo<100)?Ae(n):Ce(t,n)||mn(t.display,n)||(n.dataTransfer.setData("Text",t.getSelection()),n.dataTransfer.effectAllowed="copyMove",n.dataTransfer.setDragImage&&!c&&((e=M("img",null,null,"position: fixed; left: 0; top: 0;")).src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",p&&(e.width=e.height=1,t.display.wrapper.appendChild(e),e._top=e.offsetTop),n.dataTransfer.setDragImage(e,0,0),p&&e.parentNode.removeChild(e))));var t,n},drop:Pr(r,po),leave:function(e){Ce(r,e)||go(r)}};var e=i.input.getField();ye(e,"keyup",function(e){return Yo.call(r,e)}),ye(e,"keydown",Pr(r,Xo)),ye(e,"keypress",Pr(r,_o)),ye(e,"focus",function(e){return fr(r,e)}),ye(e,"blur",function(e){return pr(r,e)})}(this),yo(),Hr(this),this.curOp.forceUpdate=!0,vi(this,r),t.autofocus&&!h||this.hasFocus()?setTimeout(function(){n.hasFocus()&&!n.state.focused&&fr(n)},20):pr(this),ll)ll.hasOwnProperty(i)&&ll[i](this,t[i],il);_r(this),t.finishInit&&t.finishInit(this);for(var l=0;l<cl.length;++l)cl[l](this);Fr(this),f&&t.lineWrapping&&"optimizelegibility"==getComputedStyle(o.lineDiv).textRendering&&(o.lineDiv.style.textRendering="auto")}ul.defaults=ol,ul.optionHandlers=ll;var cl=[];function hl(e,t,n,r){var i,o=e.doc;null==n&&(n="add"),"smart"==n&&(o.mode.indent?i=mt(e,t).state:n="prev");var l=e.options.tabSize,s=$e(o,t),a=P(s.text,null,l);s.stateAfter&&(s.stateAfter=null);var u,c=s.text.match(/^\s*/)[0];if(r||/\S/.test(s.text)){if("smart"==n&&((u=o.mode.indent(i,s.text.slice(c.length),s.text))==B||150<u)){if(!r)return;n="prev"}}else u=0,n="not";"prev"==n?u=t>o.first?P($e(o,t-1).text,null,l):0:"add"==n?u=a+e.options.indentUnit:"subtract"==n?u=a-e.options.indentUnit:"number"==typeof n&&(u=a+n),u=Math.max(0,u);var h="",d=0;if(e.options.indentWithTabs)for(var f=Math.floor(u/l);f;--f)d+=l,h+="\t";if(d<u&&(h+=X(u-d)),h!=c)return qi(o,h,rt(t,0),rt(t,c.length),"+input"),!(s.stateAfter=null);for(var p=0;p<o.sel.ranges.length;p++){var g=o.sel.ranges[p];if(g.head.line==t&&g.head.ch<c.length){g=rt(t,c.length);Wi(o,p,new oi(g,g));break}}}ul.defineInitHook=function(e){return cl.push(e)};var dl=null;function fl(e){dl=e}function pl(e,t,n,r,i){var o=e.doc;e.display.shift=!1,r=r||o.sel;var l=+new Date-200,s="paste"==i||e.state.pasteIncoming>l,a=Ee(t),u=null;if(s&&1<r.ranges.length)if(dl&&dl.text.join("\n")==t){if(r.ranges.length%dl.text.length==0){u=[];for(var c=0;c<dl.text.length;c++)u.push(o.splitLines(dl.text[c]))}}else a.length==r.ranges.length&&e.options.pasteLinesPerSelection&&(u=_(a,function(e){return[e]}));for(var h=e.curOp.updateInput,d=r.ranges.length-1;0<=d;d--){var f=r.ranges[d],p=f.from(),g=f.to();f.empty()&&(n&&0<n?p=rt(p.line,p.ch-n):e.state.overwrite&&!s?g=rt(g.line,Math.min($e(o,g.line).text.length,g.ch+Y(a).length)):s&&dl&&dl.lineWise&&dl.text.join("\n")==a.join("\n")&&(p=g=rt(p.line,0)));g={from:p,to:g,text:u?u[d%u.length]:a,origin:i||(s?"paste":e.state.cutIncoming>l?"cut":"+input")};ji(e.doc,g),ln(e,"inputRead",e,g)}t&&!s&&ml(e,t),wr(e),e.curOp.updateInput<2&&(e.curOp.updateInput=h),e.curOp.typing=!0,e.state.pasteIncoming=e.state.cutIncoming=-1}function gl(e,t){var n=e.clipboardData&&e.clipboardData.getData("Text");return n&&(e.preventDefault(),t.isReadOnly()||t.options.disableInput||Er(t,function(){return pl(t,n,0,null,"paste")}),1)}function ml(e,t){if(e.options.electricChars&&e.options.smartIndent)for(var n=e.doc.sel,r=n.ranges.length-1;0<=r;r--){var i=n.ranges[r];if(!(100<i.head.ch||r&&n.ranges[r-1].head.line==i.head.line)){var o=e.getModeAt(i.head),l=!1;if(o.electricChars){for(var s=0;s<o.electricChars.length;s++)if(-1<t.indexOf(o.electricChars.charAt(s))){l=hl(e,i.head.line,"smart");break}}else o.electricInput&&o.electricInput.test($e(e.doc,i.head.line).text.slice(0,i.head.ch))&&(l=hl(e,i.head.line,"smart"));l&&ln(e,"electricInput",e,i.head.line)}}}function vl(e){for(var t=[],n=[],r=0;r<e.doc.sel.ranges.length;r++){var i=e.doc.sel.ranges[r].head.line,i={anchor:rt(i,0),head:rt(i+1,0)};n.push(i),t.push(e.getRange(i.anchor,i.head))}return{text:t,ranges:n}}function yl(e,t,n,r){e.setAttribute("autocorrect",n?"":"off"),e.setAttribute("autocapitalize",r?"":"off"),e.setAttribute("spellcheck",!!t)}function bl(){var e=M("textarea",null,null,"position: absolute; bottom: -1em; padding: 0; width: 1px; height: 1em; outline: none"),t=M("div",[e],null,"overflow: hidden; position: relative; width: 3px; height: 0px;");return f?e.style.width="1000px":e.setAttribute("wrap","off"),s&&(e.style.border="1px solid black"),yl(e),t}function wl(r,i,o,l,s){var e=i,t=o,a=$e(r,i.line),u=s&&"rtl"==r.direction?-o:o;function n(e){var t,n;if(null==(t="codepoint"==l?(t=a.text.charCodeAt(i.ch+(0<l?0:-1)),isNaN(t)?null:new rt(i.line,Math.max(0,Math.min(a.text.length,i.ch+o*(55296<=t&&t<56320?2:1))),-o)):s?Po(r.cm,a,i,o):Fo(a,i,o))){if(e||(n=i.line+u)<r.first||n>=r.first+r.size||(i=new rt(n,i.ch,i.sticky),!(a=$e(r,n))))return;i=Eo(s,r.cm,a,i.line,u)}else i=t;return 1}if("char"==l||"codepoint"==l)n();else if("column"==l)n(!0);else if("word"==l||"group"==l)for(var c=null,h="group"==l,d=r.cm&&r.cm.getHelper(i,"wordChars"),f=!0;!(o<0)||n(!f);f=!1){var p=a.text.charAt(i.ch)||"\n",p=J(p,d)?"w":h&&"\n"==p?"n":!h||/\s/.test(p)?null:"p";if(!h||f||p||(p="s"),c&&c!=p){o<0&&(o=1,n(),i.sticky="after");break}if(p&&(c=p),0<o&&!n(!f))break}t=Gi(r,i,e,t,!0);return ot(e,t)&&(t.hitSide=!0),t}function xl(e,t,n,r){var i,o,l,s=e.doc,a=t.left;for("page"==r?(i=Math.min(e.display.wrapper.clientHeight,window.innerHeight||document.documentElement.clientHeight),i=Math.max(i-.5*Yn(e.display),3),o=(0<n?t.bottom:t.top)+n*i):"line"==r&&(o=0<n?t.bottom+3:t.top-3);(l=Vn(e,a,o)).outside;){if(n<0?o<=0:o>=s.height){l.hitSide=!0;break}o+=5*n}return l}e=function(e){this.cm=e,this.lastAnchorNode=this.lastAnchorOffset=this.lastFocusNode=this.lastFocusOffset=null,this.polling=new I,this.composing=null,this.gracePeriod=!1,this.readDOMTimeout=null};function Cl(e,t){var n=kn(e,t.line);if(!n||n.hidden)return null;var r=$e(e.doc,t.line),n=Sn(n,r,t.line),r=me(r,e.doc.direction),e="left";r&&(e=le(r,t.ch)%2?"right":"left");e=On(n.map,t.ch,e);return e.offset="right"==e.collapse?e.end:e.start,e}function Sl(e,t){return t&&(e.bad=!0),e}function Ll(e,t,n){var r;if(t==e.display.lineDiv){if(!(r=e.display.lineDiv.childNodes[n]))return Sl(e.clipPos(rt(e.display.viewTo-1)),!0);t=null,n=0}else for(r=t;;r=r.parentNode){if(!r||r==e.display.lineDiv)return null;if(r.parentNode&&r.parentNode==e.display.lineDiv)break}for(var i=0;i<e.display.view.length;i++){var o=e.display.view[i];if(o.node==r)return function(u,e,t){var n=u.text.firstChild,r=!1;if(!e||!A(n,e))return Sl(rt(Je(u.line),0),!0);if(e==n&&(r=!0,e=n.childNodes[t],t=0,!e)){var i=u.rest?Y(u.rest):u.line;return Sl(rt(Je(i),i.text.length),r)}var i=3==e.nodeType?e:null,o=e;i||1!=e.childNodes.length||3!=e.firstChild.nodeType||(i=e.firstChild,t=t&&i.nodeValue.length);for(;o.parentNode!=n;)o=o.parentNode;var c=u.measure,h=c.maps;function l(e,t,n){for(var r=-1;r<(h?h.length:0);r++)for(var i=r<0?c.map:h[r],o=0;o<i.length;o+=3){var l=i[o+2];if(l==e||l==t){var s=Je(r<0?u.line:u.rest[r]),a=i[o]+n;return(n<0||l!=e)&&(a=i[o+(n?1:0)]),rt(s,a)}}}var s=l(i,o,t);if(s)return Sl(s,r);for(var a=o.nextSibling,d=i?i.nodeValue.length-t:0;a;a=a.nextSibling){if(s=l(a,a.firstChild,0))return Sl(rt(s.line,s.ch-d),r);d+=a.textContent.length}for(var f=o.previousSibling,p=t;f;f=f.previousSibling){if(s=l(f,f.firstChild,-1))return Sl(rt(s.line,s.ch+p),r);p+=f.textContent.length}}(o,t,n)}}e.prototype.init=function(e){var t=this,o=this,l=o.cm,s=o.div=e.lineDiv;function a(e){for(var t=e.target;t;t=t.parentNode){if(t==s)return 1;if(/\bCodeMirror-(?:line)?widget\b/.test(t.className))break}}function n(e){if(a(e)&&!Ce(l,e)){if(l.somethingSelected())fl({lineWise:!1,text:l.getSelections()}),"cut"==e.type&&l.replaceSelection("",null,"cut");else{if(!l.options.lineWiseCopyCut)return;var t=vl(l);fl({lineWise:!0,text:t.text}),"cut"==e.type&&l.operation(function(){l.setSelections(t.ranges,0,G),l.replaceSelection("",null,"cut")})}if(e.clipboardData){e.clipboardData.clearData();var n=dl.text.join("\n");if(e.clipboardData.setData("Text",n),e.clipboardData.getData("Text")==n)return void e.preventDefault()}var r=bl(),e=r.firstChild;l.display.lineSpace.insertBefore(r,l.display.lineSpace.firstChild),e.value=dl.text.join("\n");var i=document.activeElement;H(e),setTimeout(function(){l.display.lineSpace.removeChild(r),i.focus(),i==s&&o.showPrimarySelection()},50)}}yl(s,l.options.spellcheck,l.options.autocorrect,l.options.autocapitalize),ye(s,"paste",function(e){!a(e)||Ce(l,e)||gl(e,l)||v<=11&&setTimeout(Pr(l,function(){return t.updateFromDOM()}),20)}),ye(s,"compositionstart",function(e){t.composing={data:e.data,done:!1}}),ye(s,"compositionupdate",function(e){t.composing||(t.composing={data:e.data,done:!1})}),ye(s,"compositionend",function(e){t.composing&&(e.data!=t.composing.data&&t.readFromDOMSoon(),t.composing.done=!0)}),ye(s,"touchstart",function(){return o.forceCompositionEnd()}),ye(s,"input",function(){t.composing||t.readFromDOMSoon()}),ye(s,"copy",n),ye(s,"cut",n)},e.prototype.screenReaderLabelChanged=function(e){e?this.div.setAttribute("aria-label",e):this.div.removeAttribute("aria-label")},e.prototype.prepareSelection=function(){var e=sr(this.cm,!1);return e.focus=document.activeElement==this.div,e},e.prototype.showSelection=function(e,t){e&&this.cm.display.view.length&&((e.focus||t)&&this.showPrimarySelection(),this.showMultipleSelections(e))},e.prototype.getSelection=function(){return this.cm.display.wrapper.ownerDocument.getSelection()},e.prototype.showPrimarySelection=function(){var e=this.getSelection(),t=this.cm,n=t.doc.sel.primary(),r=n.from(),i=n.to();if(t.display.viewTo==t.display.viewFrom||r.line>=t.display.viewTo||i.line<t.display.viewFrom)e.removeAllRanges();else{var o=Ll(t,e.anchorNode,e.anchorOffset),n=Ll(t,e.focusNode,e.focusOffset);if(!o||o.bad||!n||n.bad||0!=it(at(o,n),r)||0!=it(st(o,n),i)){var n=t.display.view,l=r.line>=t.display.viewFrom&&Cl(t,r)||{node:n[0].measure.map[2],offset:0},s=i.line<t.display.viewTo&&Cl(t,i);if(s||(s={node:(u=(u=n[n.length-1].measure).maps?u.maps[u.maps.length-1]:u.map)[u.length-1],offset:u[u.length-2]-u[u.length-3]}),l&&s){var a,u=e.rangeCount&&e.getRangeAt(0);try{a=S(l.node,l.offset,s.offset,s.node)}catch(e){}a&&(!d&&t.state.focused?(e.collapse(l.node,l.offset),a.collapsed||(e.removeAllRanges(),e.addRange(a))):(e.removeAllRanges(),e.addRange(a)),u&&null==e.anchorNode?e.addRange(u):d&&this.startGracePeriod()),this.rememberSelection()}else e.removeAllRanges()}}},e.prototype.startGracePeriod=function(){var e=this;clearTimeout(this.gracePeriod),this.gracePeriod=setTimeout(function(){e.gracePeriod=!1,e.selectionChanged()&&e.cm.operation(function(){return e.cm.curOp.selectionChanged=!0})},20)},e.prototype.showMultipleSelections=function(e){T(this.cm.display.cursorDiv,e.cursors),T(this.cm.display.selectionDiv,e.selection)},e.prototype.rememberSelection=function(){var e=this.getSelection();this.lastAnchorNode=e.anchorNode,this.lastAnchorOffset=e.anchorOffset,this.lastFocusNode=e.focusNode,this.lastFocusOffset=e.focusOffset},e.prototype.selectionInEditor=function(){var e=this.getSelection();if(!e.rangeCount)return!1;e=e.getRangeAt(0).commonAncestorContainer;return A(this.div,e)},e.prototype.focus=function(){"nocursor"!=this.cm.options.readOnly&&(this.selectionInEditor()&&document.activeElement==this.div||this.showSelection(this.prepareSelection(),!0),this.div.focus())},e.prototype.blur=function(){this.div.blur()},e.prototype.getField=function(){return this.div},e.prototype.supportsTouch=function(){return!0},e.prototype.receivedFocus=function(){var t=this;this.selectionInEditor()?this.pollSelection():Er(this.cm,function(){return t.cm.curOp.selectionChanged=!0}),this.polling.set(this.cm.options.pollInterval,function e(){t.cm.state.focused&&(t.pollSelection(),t.polling.set(t.cm.options.pollInterval,e))})},e.prototype.selectionChanged=function(){var e=this.getSelection();return e.anchorNode!=this.lastAnchorNode||e.anchorOffset!=this.lastAnchorOffset||e.focusNode!=this.lastFocusNode||e.focusOffset!=this.lastFocusOffset},e.prototype.pollSelection=function(){if(null==this.readDOMTimeout&&!this.gracePeriod&&this.selectionChanged()){var e,t,n=this.getSelection(),r=this.cm;if(a&&o&&this.cm.display.gutterSpecs.length&&function(e){for(var t=e;t;t=t.parentNode)if(/CodeMirror-gutter-wrapper/.test(t.className))return!0;return!1}(n.anchorNode))return this.cm.triggerOnKeyDown({type:"keydown",keyCode:8,preventDefault:Math.abs}),this.blur(),void this.focus();this.composing||(this.rememberSelection(),e=Ll(r,n.anchorNode,n.anchorOffset),t=Ll(r,n.focusNode,n.focusOffset),e&&t&&Er(r,function(){Ei(r.doc,si(e,t),G),(e.bad||t.bad)&&(r.curOp.selectionChanged=!0)}))}},e.prototype.pollContent=function(){null!=this.readDOMTimeout&&(clearTimeout(this.readDOMTimeout),this.readDOMTimeout=null);var e,t=this.cm,n=t.display,r=t.doc.sel.primary(),i=r.from(),r=r.to();if(0==i.ch&&i.line>t.firstLine()&&(i=rt(i.line-1,$e(t.doc,i.line-1).length)),r.ch==$e(t.doc,r.line).text.length&&r.line<t.lastLine()&&(r=rt(r.line+1,0)),i.line<n.viewFrom||r.line>n.viewTo-1)return!1;m=i.line==n.viewFrom||0==(m=er(t,i.line))?(e=Je(n.view[0].line),n.view[0].node):(e=Je(n.view[m].line),n.view[m-1].node.nextSibling);var o,r=er(t,r.line),r=r==n.view.length-1?(o=n.viewTo-1,n.lineDiv.lastChild):(o=Je(n.view[r+1].line)-1,n.view[r+1].node.previousSibling);if(!m)return!1;for(var l=t.doc.splitLines(function(l,e,t,s,a){var n="",u=!1,c=l.doc.lineSeparator(),h=!1;function d(){u&&(n+=c,h&&(n+=c),u=h=!1)}function f(e){e&&(d(),n+=e)}for(;!function e(t){if(1==t.nodeType){var n=t.getAttribute("cm-text");if(n)f(n);else if(n=t.getAttribute("cm-marker"))(n=l.findMarks(rt(s,0),rt(a+1,0),(o=+n,function(e){return e.id==o}))).length&&(r=n[0].find(0))&&f(qe(l.doc,r.from,r.to).join(c));else if("false"!=t.getAttribute("contenteditable")){var r=/^(pre|div|p|li|table|br)$/i.test(t.nodeName);if(/^br$/i.test(t.nodeName)||0!=t.textContent.length){r&&d();for(var i=0;i<t.childNodes.length;i++)e(t.childNodes[i]);/^(pre|p)$/i.test(t.nodeName)&&(h=!0),r&&(u=!0)}}}else 3==t.nodeType&&f(t.nodeValue.replace(/\u200b/g,"").replace(/\u00a0/g," "));var o}(e),e!=t;)e=e.nextSibling,h=!1;return n}(t,m,r,e,o)),s=qe(t.doc,rt(e,0),rt(o,$e(t.doc,o).text.length));1<l.length&&1<s.length;)if(Y(l)==Y(s))l.pop(),s.pop(),o--;else{if(l[0]!=s[0])break;l.shift(),s.shift(),e++}for(var a=0,u=0,c=l[0],h=s[0],d=Math.min(c.length,h.length);a<d&&c.charCodeAt(a)==h.charCodeAt(a);)++a;for(var f=Y(l),p=Y(s),g=Math.min(f.length-(1==l.length?a:0),p.length-(1==s.length?a:0));u<g&&f.charCodeAt(f.length-u-1)==p.charCodeAt(p.length-u-1);)++u;if(1==l.length&&1==s.length&&e==i.line)for(;a&&a>i.ch&&f.charCodeAt(f.length-u-1)==p.charCodeAt(p.length-u-1);)a--,u++;l[l.length-1]=f.slice(0,f.length-u).replace(/^\u200b+/,""),l[0]=l[0].slice(a).replace(/\u200b+$/,"");var m=rt(e,a),r=rt(o,s.length?Y(s).length-u:0);return 1<l.length||l[0]||it(m,r)?(qi(t.doc,l,m,r,"+input"),!0):void 0},e.prototype.ensurePolled=function(){this.forceCompositionEnd()},e.prototype.reset=function(){this.forceCompositionEnd()},e.prototype.forceCompositionEnd=function(){this.composing&&(clearTimeout(this.readDOMTimeout),this.composing=null,this.updateFromDOM(),this.div.blur(),this.div.focus())},e.prototype.readFromDOMSoon=function(){var e=this;null==this.readDOMTimeout&&(this.readDOMTimeout=setTimeout(function(){if(e.readDOMTimeout=null,e.composing){if(!e.composing.done)return;e.composing=null}e.updateFromDOM()},80))},e.prototype.updateFromDOM=function(){var e=this;!this.cm.isReadOnly()&&this.pollContent()||Er(this.cm,function(){return tr(e.cm)})},e.prototype.setUneditable=function(e){e.contentEditable="false"},e.prototype.onKeyPress=function(e){0==e.charCode||this.composing||(e.preventDefault(),this.cm.isReadOnly()||Pr(this.cm,pl)(this.cm,String.fromCharCode(null==e.charCode?e.keyCode:e.charCode),0))},e.prototype.readOnlyChanged=function(e){this.div.contentEditable=String("nocursor"!=e)},e.prototype.onContextMenu=function(){},e.prototype.resetPosition=function(){},e.prototype.needsContentAttribute=!0;var kl,Tl,Ml,Nl,Al,r=function(e){this.cm=e,this.prevInput="",this.pollingFast=!1,this.polling=new I,this.hasSelection=!1,this.composing=null};function Ol(e,t,r,n){kl.defaults[e]=t,r&&(Tl[e]=n?function(e,t,n){n!=il&&r(e,t,n)}:r)}r.prototype.init=function(n){var e=this,r=this,i=this.cm;this.createField(n);var o=this.textarea;function t(e){if(!Ce(i,e)){if(i.somethingSelected())fl({lineWise:!1,text:i.getSelections()});else{if(!i.options.lineWiseCopyCut)return;var t=vl(i);fl({lineWise:!0,text:t.text}),"cut"==e.type?i.setSelections(t.ranges,null,G):(r.prevInput="",o.value=t.text.join("\n"),H(o))}"cut"==e.type&&(i.state.cutIncoming=+new Date)}}n.wrapper.insertBefore(this.wrapper,n.wrapper.firstChild),s&&(o.style.width="0px"),ye(o,"input",function(){w&&9<=v&&e.hasSelection&&(e.hasSelection=null),r.poll()}),ye(o,"paste",function(e){Ce(i,e)||gl(e,i)||(i.state.pasteIncoming=+new Date,r.fastPoll())}),ye(o,"cut",t),ye(o,"copy",t),ye(n.scroller,"paste",function(e){if(!mn(n,e)&&!Ce(i,e)){if(!o.dispatchEvent)return i.state.pasteIncoming=+new Date,void r.focus();var t=new Event("paste");t.clipboardData=e.clipboardData,o.dispatchEvent(t)}}),ye(n.lineSpace,"selectstart",function(e){mn(n,e)||Te(e)}),ye(o,"compositionstart",function(){var e=i.getCursor("from");r.composing&&r.composing.range.clear(),r.composing={start:e,range:i.markText(e,i.getCursor("to"),{className:"CodeMirror-composing"})}}),ye(o,"compositionend",function(){r.composing&&(r.poll(),r.composing.range.clear(),r.composing=null)})},r.prototype.createField=function(e){this.wrapper=bl(),this.textarea=this.wrapper.firstChild},r.prototype.screenReaderLabelChanged=function(e){e?this.textarea.setAttribute("aria-label",e):this.textarea.removeAttribute("aria-label")},r.prototype.prepareSelection=function(){var e,t=this.cm,n=t.display,r=t.doc,i=sr(t);return t.options.moveInputWithCursor&&(e=Bn(t,r.sel.primary().head,"div"),t=n.wrapper.getBoundingClientRect(),r=n.lineDiv.getBoundingClientRect(),i.teTop=Math.max(0,Math.min(n.wrapper.clientHeight-10,e.top+r.top-t.top)),i.teLeft=Math.max(0,Math.min(n.wrapper.clientWidth-10,e.left+r.left-t.left))),i},r.prototype.showSelection=function(e){var t=this.cm.display;T(t.cursorDiv,e.cursors),T(t.selectionDiv,e.selection),null!=e.teTop&&(this.wrapper.style.top=e.teTop+"px",this.wrapper.style.left=e.teLeft+"px")},r.prototype.reset=function(e){var t,n;this.contextMenuPending||this.composing||((t=this.cm).somethingSelected()?(this.prevInput="",n=t.getSelection(),this.textarea.value=n,t.state.focused&&H(this.textarea),w&&9<=v&&(this.hasSelection=n)):e||(this.prevInput=this.textarea.value="",w&&9<=v&&(this.hasSelection=null)))},r.prototype.getField=function(){return this.textarea},r.prototype.supportsTouch=function(){return!1},r.prototype.focus=function(){if("nocursor"!=this.cm.options.readOnly&&(!h||O()!=this.textarea))try{this.textarea.focus()}catch(e){}},r.prototype.blur=function(){this.textarea.blur()},r.prototype.resetPosition=function(){this.wrapper.style.top=this.wrapper.style.left=0},r.prototype.receivedFocus=function(){this.slowPoll()},r.prototype.slowPoll=function(){var e=this;this.pollingFast||this.polling.set(this.cm.options.pollInterval,function(){e.poll(),e.cm.state.focused&&e.slowPoll()})},r.prototype.fastPoll=function(){var t=!1,n=this;n.pollingFast=!0,n.polling.set(20,function e(){n.poll()||t?(n.pollingFast=!1,n.slowPoll()):(t=!0,n.polling.set(60,e))})},r.prototype.poll=function(){var e=this,t=this.cm,n=this.textarea,r=this.prevInput;if(this.contextMenuPending||!t.state.focused||Pe(n)&&!r&&!this.composing||t.isReadOnly()||t.options.disableInput||t.state.keySeq)return!1;var i=n.value;if(i==r&&!t.somethingSelected())return!1;if(w&&9<=v&&this.hasSelection===i||g&&/[\uf700-\uf7ff]/.test(i))return t.display.input.reset(),!1;if(t.doc.sel==t.display.selForContextMenu){var o=i.charCodeAt(0);if(8203!=o||r||(r="​"),8666==o)return this.reset(),this.cm.execCommand("undo")}for(var l=0,s=Math.min(r.length,i.length);l<s&&r.charCodeAt(l)==i.charCodeAt(l);)++l;return Er(t,function(){pl(t,i.slice(l),r.length-l,null,e.composing?"*compose":null),1e3<i.length||-1<i.indexOf("\n")?n.value=e.prevInput="":e.prevInput=i,e.composing&&(e.composing.range.clear(),e.composing.range=t.markText(e.composing.start,t.getCursor("to"),{className:"CodeMirror-composing"}))}),!0},r.prototype.ensurePolled=function(){this.pollingFast&&this.poll()&&(this.pollingFast=!1)},r.prototype.onKeyPress=function(){w&&9<=v&&(this.hasSelection=null),this.fastPoll()},r.prototype.onContextMenu=function(e){var n=this,r=n.cm,i=r.display,o=n.textarea;n.contextMenuPending&&n.contextMenuPending();var l,s,t,a,u=Jn(r,e),c=i.scroller.scrollTop;function h(){var e,t;null!=o.selectionStart&&(t="​"+((e=r.somethingSelected())?o.value:""),o.value="⇚",o.value=t,n.prevInput=e?"":"​",o.selectionStart=1,o.selectionEnd=t.length,i.selForContextMenu=r.doc.sel)}function d(){var e,t;n.contextMenuPending==d&&(n.contextMenuPending=!1,n.wrapper.style.cssText=s,o.style.cssText=l,w&&v<9&&i.scrollbars.setScrollTop(i.scroller.scrollTop=c),null!=o.selectionStart&&((!w||w&&v<9)&&h(),e=0,t=function(){i.selForContextMenu==r.doc.sel&&0==o.selectionStart&&0<o.selectionEnd&&"​"==n.prevInput?Pr(r,Vi)(r):e++<10?i.detectingSelectAll=setTimeout(t,500):(i.selForContextMenu=null,i.input.reset())},i.detectingSelectAll=setTimeout(t,200)))}u&&!p&&(r.options.resetSelectionOnContextMenu&&-1==r.doc.sel.contains(u)&&Pr(r,Ei)(r.doc,si(u),G),l=o.style.cssText,s=n.wrapper.style.cssText,u=n.wrapper.offsetParent.getBoundingClientRect(),n.wrapper.style.cssText="position: static",o.style.cssText="position: absolute; width: 30px; height: 30px;\n top: "+(e.clientY-u.top-5)+"px; left: "+(e.clientX-u.left-5)+"px;\n z-index: 1000; background: "+(w?"rgba(255, 255, 255, .05)":"transparent")+";\n outline: none; border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);",f&&(t=window.scrollY),i.input.focus(),f&&window.scrollTo(null,t),i.input.reset(),r.somethingSelected()||(o.value=n.prevInput=" "),n.contextMenuPending=d,i.selForContextMenu=r.doc.sel,clearTimeout(i.detectingSelectAll),w&&9<=v&&h(),x?(Ae(e),a=function(){we(window,"mouseup",a),setTimeout(d,20)},ye(window,"mouseup",a)):setTimeout(d,50))},r.prototype.readOnlyChanged=function(e){e||this.reset(),this.textarea.disabled="nocursor"==e,this.textarea.readOnly=!!e},r.prototype.setUneditable=function(){},r.prototype.needsContentAttribute=!1,Tl=(kl=ul).optionHandlers,kl.defineOption=Ol,kl.Init=il,Ol("value","",function(e,t){return e.setValue(t)},!0),Ol("mode",null,function(e,t){e.doc.modeOption=t,di(e)},!0),Ol("indentUnit",2,di,!0),Ol("indentWithTabs",!1),Ol("smartIndent",!0),Ol("tabSize",4,function(e){fi(e),Hn(e),tr(e)},!0),Ol("lineSeparator",null,function(e,r){if(e.doc.lineSep=r){var i=[],o=e.doc.first;e.doc.iter(function(e){for(var t=0;;){var n=e.text.indexOf(r,t);if(-1==n)break;t=n+r.length,i.push(rt(o,n))}o++});for(var t=i.length-1;0<=t;t--)qi(e.doc,r,i[t],rt(i[t].line,i[t].ch+r.length))}}),Ol("specialChars",/[\u0000-\u001f\u007f-\u009f\u00ad\u061c\u200b-\u200c\u200e\u200f\u2028\u2029\ufeff\ufff9-\ufffc]/g,function(e,t,n){e.state.specialChars=new RegExp(t.source+(t.test("\t")?"":"|\t"),"g"),n!=il&&e.refresh()}),Ol("specialCharPlaceholder",Zt,function(e){return e.refresh()},!0),Ol("electricChars",!0),Ol("inputStyle",h?"contenteditable":"textarea",function(){throw new Error("inputStyle can not (yet) be changed in a running editor")},!0),Ol("spellcheck",!1,function(e,t){return e.getInputField().spellcheck=t},!0),Ol("autocorrect",!1,function(e,t){return e.getInputField().autocorrect=t},!0),Ol("autocapitalize",!1,function(e,t){return e.getInputField().autocapitalize=t},!0),Ol("rtlMoveVisually",!y),Ol("wholeLineUpdateBefore",!0),Ol("theme","default",function(e){rl(e),Zr(e)},!0),Ol("keyMap","default",function(e,t,n){t=Do(t),n=n!=il&&Do(n);n&&n.detach&&n.detach(e,t),t.attach&&t.attach(e,n||null)}),Ol("extraKeys",null),Ol("configureMouse",null),Ol("lineWrapping",!1,al,!0),Ol("gutters",[],function(e,t){e.display.gutterSpecs=$r(t,e.options.lineNumbers),Zr(e)},!0),Ol("fixedGutter",!0,function(e,t){e.display.gutters.style.left=t?qn(e.display)+"px":"0",e.refresh()},!0),Ol("coverGutterNextToScrollbar",!1,function(e){return Nr(e)},!0),Ol("scrollbarStyle","native",function(e){Dr(e),Nr(e),e.display.scrollbars.setScrollTop(e.doc.scrollTop),e.display.scrollbars.setScrollLeft(e.doc.scrollLeft)},!0),Ol("lineNumbers",!1,function(e,t){e.display.gutterSpecs=$r(e.options.gutters,t),Zr(e)},!0),Ol("firstLineNumber",1,Zr,!0),Ol("lineNumberFormatter",function(e){return e},Zr,!0),Ol("showCursorWhenSelecting",!1,lr,!0),Ol("resetSelectionOnContextMenu",!0),Ol("lineWiseCopyCut",!0),Ol("pasteLinesPerSelection",!0),Ol("selectionsMayTouch",!1),Ol("readOnly",!1,function(e,t){"nocursor"==t&&(pr(e),e.display.input.blur()),e.display.input.readOnlyChanged(t)}),Ol("screenReaderLabel",null,function(e,t){t=""===t?null:t,e.display.input.screenReaderLabelChanged(t)}),Ol("disableInput",!1,function(e,t){t||e.display.input.reset()},!0),Ol("dragDrop",!0,sl),Ol("allowDropFileTypes",null),Ol("cursorBlinkRate",530),Ol("cursorScrollMargin",0),Ol("cursorHeight",1,lr,!0),Ol("singleCursorHeightPerLine",!0,lr,!0),Ol("workTime",100),Ol("workDelay",100),Ol("flattenSpans",!0,fi,!0),Ol("addModeClass",!1,fi,!0),Ol("pollInterval",100),Ol("undoDepth",200,function(e,t){return e.doc.history.undoDepth=t}),Ol("historyEventDelay",1250),Ol("viewportMargin",10,function(e){return e.refresh()},!0),Ol("maxHighlightLength",1e4,fi,!0),Ol("moveInputWithCursor",!0,function(e,t){t||e.display.input.resetPosition()}),Ol("tabindex",null,function(e,t){return e.display.input.getField().tabIndex=t||""}),Ol("autofocus",null),Ol("direction","ltr",function(e,t){return e.doc.setDirection(t)},!0),Ol("phrases",null),Nl=(Ml=ul).optionHandlers,Al=Ml.helpers={},Ml.prototype={constructor:Ml,focus:function(){window.focus(),this.display.input.focus()},setOption:function(e,t){var n=this.options,r=n[e];n[e]==t&&"mode"!=e||(n[e]=t,Nl.hasOwnProperty(e)&&Pr(this,Nl[e])(this,t,r),xe(this,"optionChange",this,e))},getOption:function(e){return this.options[e]},getDoc:function(){return this.doc},addKeyMap:function(e,t){this.state.keyMaps[t?"push":"unshift"](Do(e))},removeKeyMap:function(e){for(var t=this.state.keyMaps,n=0;n<t.length;++n)if(t[n]==e||t[n].name==e)return t.splice(n,1),!0},addOverlay:Ir(function(e,t){var n=e.token?e:Ml.getMode(this.options,e);if(n.startState)throw new Error("Overlays may not be stateful.");!function(e,t,n){for(var r=0,i=n(t);r<e.length&&n(e[r])<=i;)r++;e.splice(r,0,t)}(this.state.overlays,{mode:n,modeSpec:e,opaque:t&&t.opaque,priority:t&&t.priority||0},function(e){return e.priority}),this.state.modeGen++,tr(this)}),removeOverlay:Ir(function(e){for(var t=this.state.overlays,n=0;n<t.length;++n){var r=t[n].modeSpec;if(r==e||"string"==typeof e&&r.name==e)return t.splice(n,1),this.state.modeGen++,void tr(this)}}),indentLine:Ir(function(e,t,n){"string"!=typeof t&&"number"!=typeof t&&(t=null==t?this.options.smartIndent?"smart":"prev":t?"add":"subtract"),tt(this.doc,e)&&hl(this,e,t,n)}),indentSelection:Ir(function(e){for(var t=this.doc.sel.ranges,n=-1,r=0;r<t.length;r++){var i=t[r];if(i.empty())i.head.line>n&&(hl(this,i.head.line,e,!0),n=i.head.line,r==this.doc.sel.primIndex&&wr(this));else{for(var o=i.from(),l=i.to(),i=Math.max(n,o.line),n=Math.min(this.lastLine(),l.line-(l.ch?0:1))+1,s=i;s<n;++s)hl(this,s,e);i=this.doc.sel.ranges;0==o.ch&&t.length==i.length&&0<i[r].from().ch&&Wi(this.doc,r,new oi(o,i[r].to()),G)}}}),getTokenAt:function(e,t){return xt(this,e,t)},getLineTokens:function(e,t){return xt(this,rt(e),t,!0)},getTokenTypeAt:function(e){e=ct(this.doc,e);var t,n=gt(this,$e(this.doc,e.line)),r=0,i=(n.length-1)/2,o=e.ch;if(0==o)t=n[2];else for(;;){var l=r+i>>1;if((l?n[2*l-1]:0)>=o)i=l;else{if(!(n[2*l+1]<o)){t=n[2*l+2];break}r=1+l}}e=t?t.indexOf("overlay "):-1;return e<0?t:0==e?null:t.slice(0,e-1)},getModeAt:function(e){var t=this.doc.mode;return t.innerMode?Ml.innerMode(t,this.getTokenAt(e).state).mode:t},getHelper:function(e,t){return this.getHelpers(e,t)[0]},getHelpers:function(e,t){var n=[];if(!Al.hasOwnProperty(t))return n;var r=Al[t],i=this.getModeAt(e);if("string"==typeof i[t])r[i[t]]&&n.push(r[i[t]]);else if(i[t])for(var o=0;o<i[t].length;o++){var l=r[i[t][o]];l&&n.push(l)}else i.helperType&&r[i.helperType]?n.push(r[i.helperType]):r[i.name]&&n.push(r[i.name]);for(var s=0;s<r._global.length;s++){var a=r._global[s];a.pred(i,this)&&-1==R(n,a.val)&&n.push(a.val)}return n},getStateAfter:function(e,t){var n=this.doc;return mt(this,(e=ut(n,null==e?n.first+n.size-1:e))+1,t).state},cursorCoords:function(e,t){var n=this.doc.sel.primary(),n=null==e?n.head:"object"==typeof e?ct(this.doc,e):e?n.from():n.to();return Bn(this,n,t||"page")},charCoords:function(e,t){return zn(this,ct(this.doc,e),t||"page")},coordsChar:function(e,t){return Vn(this,(e=Rn(this,e,t||"page")).left,e.top)},lineAtHeight:function(e,t){return e=Rn(this,{top:e,left:0},t||"page").top,et(this.doc,e+this.display.viewOffset)},heightAtLine:function(e,t,n){var r,i=!1,e="number"==typeof e?(r=this.doc.first+this.doc.size-1,e<this.doc.first?e=this.doc.first:r<e&&(e=r,i=!0),$e(this.doc,e)):e;return In(this,e,{top:0,left:0},t||"page",n||i).top+(i?this.doc.height-Vt(e):0)},defaultTextHeight:function(){return Yn(this.display)},defaultCharWidth:function(){return _n(this.display)},getViewport:function(){return{from:this.display.viewFrom,to:this.display.viewTo}},addWidget:function(e,t,n,r,i){var o,l,s=this.display,a=(e=Bn(this,ct(this.doc,e))).bottom,u=e.left;t.style.position="absolute",t.setAttribute("cm-ignore-events","true"),this.display.input.setUneditable(t),s.sizer.appendChild(t),"over"==r?a=e.top:"above"!=r&&"near"!=r||(o=Math.max(s.wrapper.clientHeight,this.doc.height),l=Math.max(s.sizer.clientWidth,s.lineSpace.clientWidth),("above"==r||e.bottom+t.offsetHeight>o)&&e.top>t.offsetHeight?a=e.top-t.offsetHeight:e.bottom+t.offsetHeight<=o&&(a=e.bottom),u+t.offsetWidth>l&&(u=l-t.offsetWidth)),t.style.top=a+"px",t.style.left=t.style.right="","right"==i?(u=s.sizer.clientWidth-t.offsetWidth,t.style.right="0px"):("left"==i?u=0:"middle"==i&&(u=(s.sizer.clientWidth-t.offsetWidth)/2),t.style.left=u+"px"),n&&(n=this,t={left:u,top:a,right:u+t.offsetWidth,bottom:a+t.offsetHeight},null!=(t=yr(n,t)).scrollTop&&Lr(n,t.scrollTop),null!=t.scrollLeft&&Tr(n,t.scrollLeft))},triggerOnKeyDown:Ir(Xo),triggerOnKeyPress:Ir(_o),triggerOnKeyUp:Yo,triggerOnMouseDown:Ir(Qo),execCommand:function(e){if(Io.hasOwnProperty(e))return Io[e].call(null,this)},triggerElectric:Ir(function(e){ml(this,e)}),findPosH:function(e,t,n,r){var i=1;t<0&&(i=-1,t=-t);for(var o=ct(this.doc,e),l=0;l<t&&!(o=wl(this.doc,o,i,n,r)).hitSide;++l);return o},moveH:Ir(function(t,n){var r=this;this.extendSelectionsBy(function(e){return r.display.shift||r.doc.extend||e.empty()?wl(r.doc,e.head,t,n,r.options.rtlMoveVisually):t<0?e.from():e.to()},V)}),deleteH:Ir(function(n,r){var e=this.doc.sel,i=this.doc;e.somethingSelected()?i.replaceSelection("",null,"+delete"):Wo(this,function(e){var t=wl(i,e.head,n,r,!1);return n<0?{from:t,to:e.head}:{from:e.head,to:t}})}),findPosV:function(e,t,n,r){var i=1,o=r;t<0&&(i=-1,t=-t);for(var l=ct(this.doc,e),s=0;s<t;++s){var a=Bn(this,l,"div");if(null==o?o=a.left:a.left=o,(l=xl(this,a,i,n)).hitSide)break}return l},moveV:Ir(function(r,i){var o=this,l=this.doc,s=[],a=!this.display.shift&&!l.extend&&l.sel.somethingSelected();if(l.extendSelectionsBy(function(e){if(a)return r<0?e.from():e.to();var t=Bn(o,e.head,"div");null!=e.goalColumn&&(t.left=e.goalColumn),s.push(t.left);var n=xl(o,t,r,i);return"page"==i&&e==l.sel.primary()&&br(o,zn(o,n,"div").top-t.top),n},V),s.length)for(var e=0;e<l.sel.ranges.length;e++)l.sel.ranges[e].goalColumn=s[e]}),findWordAt:function(e){var t=$e(this.doc,e.line).text,n=e.ch,r=e.ch;if(t){var i=this.getHelper(e,"wordChars");"before"!=e.sticky&&r!=t.length||!n?++r:--n;for(var o=t.charAt(n),l=J(o,i)?function(e){return J(e,i)}:/\s/.test(o)?function(e){return/\s/.test(e)}:function(e){return!/\s/.test(e)&&!J(e)};0<n&&l(t.charAt(n-1));)--n;for(;r<t.length&&l(t.charAt(r));)++r}return new oi(rt(e.line,n),rt(e.line,r))},toggleOverwrite:function(e){null!=e&&e==this.state.overwrite||(((this.state.overwrite=!this.state.overwrite)?D:L)(this.display.cursorDiv,"CodeMirror-overwrite"),xe(this,"overwriteToggle",this,this.state.overwrite))},hasFocus:function(){return this.display.input.getField()==O()},isReadOnly:function(){return!(!this.options.readOnly&&!this.doc.cantEdit)},scrollTo:Ir(function(e,t){xr(this,e,t)}),getScrollInfo:function(){var e=this.display.scroller;return{left:e.scrollLeft,top:e.scrollTop,height:e.scrollHeight-wn(this)-this.display.barHeight,width:e.scrollWidth-wn(this)-this.display.barWidth,clientHeight:Cn(this),clientWidth:xn(this)}},scrollIntoView:Ir(function(e,t){var n;null==e?(e={from:this.doc.sel.primary().head,to:null},null==t&&(t=this.options.cursorScrollMargin)):"number"==typeof e?e={from:rt(e,0),to:null}:null==e.from&&(e={from:e,to:null}),e.to||(e.to=e.from),e.margin=t||0,null!=e.from.line?(n=e,Cr(t=this),t.curOp.scrollToPos=n):Sr(this,e.from,e.to,e.margin)}),setSize:Ir(function(e,t){function n(e){return"number"==typeof e||/^\d+$/.test(String(e))?e+"px":e}var r=this;null!=e&&(this.display.wrapper.style.width=n(e)),null!=t&&(this.display.wrapper.style.height=n(t)),this.options.lineWrapping&&Wn(this);var i=this.display.viewFrom;this.doc.iter(i,this.display.viewTo,function(e){if(e.widgets)for(var t=0;t<e.widgets.length;t++)if(e.widgets[t].noHScroll){nr(r,i,"widget");break}++i}),this.curOp.forceUpdate=!0,xe(this,"refresh",this)}),operation:function(e){return Er(this,e)},startOperation:function(){return Hr(this)},endOperation:function(){return Fr(this)},refresh:Ir(function(){var e=this.display.cachedTextHeight;tr(this),this.curOp.forceUpdate=!0,Hn(this),xr(this,this.doc.scrollLeft,this.doc.scrollTop),jr(this.display),(null==e||.5<Math.abs(e-Yn(this.display))||this.options.lineWrapping)&&Qn(this),xe(this,"refresh",this)}),swapDoc:Ir(function(e){var t=this.doc;return t.cm=null,this.state.selectingText&&this.state.selectingText(),vi(this,e),Hn(this),this.display.input.reset(),xr(this,e.scrollLeft,e.scrollTop),this.curOp.forceScroll=!0,ln(this,"swapDoc",this,t),t}),phrase:function(e){var t=this.options.phrases;return t&&Object.prototype.hasOwnProperty.call(t,e)?t[e]:e},getInputField:function(){return this.display.input.getField()},getWrapperElement:function(){return this.display.wrapper},getScrollerElement:function(){return this.display.scroller},getGutterElement:function(){return this.display.gutters}},ke(Ml),Ml.registerHelper=function(e,t,n){Al.hasOwnProperty(e)||(Al[e]=Ml[e]={_global:[]}),Al[e][t]=n},Ml.registerGlobalHelper=function(e,t,n,r){Ml.registerHelper(e,t,r),Al[e]._global.push({pred:n,val:r})};var Dl,Wl,Hl="iter insert remove copy getEditor constructor".split(" ");for(Dl in ho.prototype)ho.prototype.hasOwnProperty(Dl)&&R(Hl,Dl)<0&&(ul.prototype[Dl]=function(e){return function(){return e.apply(this.doc,arguments)}}(ho.prototype[Dl]));return ke(ho),ul.inputStyles={textarea:r,contenteditable:e},ul.defineMode=function(e){ul.defaults.mode||"null"==e||(ul.defaults.mode=e),function(e,t){2<arguments.length&&(t.dependencies=Array.prototype.slice.call(arguments,2)),ze[e]=t}.apply(this,arguments)},ul.defineMIME=function(e,t){Be[e]=t},ul.defineMode("null",function(){return{token:function(e){return e.skipToEnd()}}}),ul.defineMIME("text/plain","null"),ul.defineExtension=function(e,t){ul.prototype[e]=t},ul.defineDocExtension=function(e,t){ho.prototype[e]=t},ul.fromTextArea=function(t,n){var e;function r(){t.value=s.getValue()}if(n=n?E(n):{},n.value=t.value,!n.tabindex&&t.tabIndex&&(n.tabindex=t.tabIndex),!n.placeholder&&t.placeholder&&(n.placeholder=t.placeholder),null==n.autofocus&&(e=O(),n.autofocus=e==t||null!=t.getAttribute("autofocus")&&e==document.body),t.form&&(ye(t.form,"submit",r),!n.leaveSubmitMethodAlone)){var i=t.form,o=i.submit;try{var l=i.submit=function(){r(),i.submit=o,i.submit(),i.submit=l}}catch(e){}}n.finishInit=function(e){e.save=r,e.getTextArea=function(){return t},e.toTextArea=function(){e.toTextArea=isNaN,r(),t.parentNode.removeChild(e.getWrapperElement()),t.style.display="",t.form&&(we(t.form,"submit",r),n.leaveSubmitMethodAlone||"function"!=typeof t.form.submit||(t.form.submit=o))}},t.style.display="none";var s=ul(function(e){return t.parentNode.insertBefore(e,t.nextSibling)},n);return s},(Wl=ul).off=we,Wl.on=ye,Wl.wheelEventPixels=ni,Wl.Doc=ho,Wl.splitLines=Ee,Wl.countColumn=P,Wl.findColumn=K,Wl.isWordChar=Q,Wl.Pass=B,Wl.signal=xe,Wl.Line=Xt,Wl.changeEnd=ai,Wl.scrollbarModel=Or,Wl.Pos=rt,Wl.cmpPos=it,Wl.modes=ze,Wl.mimeModes=Be,Wl.resolveMode=Ge,Wl.getMode=Ue,Wl.modeExtensions=Ve,Wl.extendMode=Ke,Wl.copyState=je,Wl.startState=Ye,Wl.innerMode=Xe,Wl.commands=Io,Wl.keyMap=Lo,Wl.keyName=Oo,Wl.isModifierKey=No,Wl.lookupKey=Mo,Wl.normalizeKeyMap=To,Wl.StringStream=_e,Wl.SharedTextMarker=ao,Wl.TextMarker=lo,Wl.LineWidget=ro,Wl.e_preventDefault=Te,Wl.e_stopPropagation=Me,Wl.e_stop=Ae,Wl.addClass=D,Wl.contains=A,Wl.rmClass=L,Wl.keyNames=wo,ul.version="5.58.3",ul}); From 552843369c34bfea11cf6a2586842879f5103ada Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 2 Dec 2020 17:55:55 +0100 Subject: [PATCH 109/124] Update shortcuts-mac.multids (#5179) --- core/wiki/config/shortcuts/shortcuts-mac.multids | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/wiki/config/shortcuts/shortcuts-mac.multids b/core/wiki/config/shortcuts/shortcuts-mac.multids index fc3fc060f..7b41dce17 100644 --- a/core/wiki/config/shortcuts/shortcuts-mac.multids +++ b/core/wiki/config/shortcuts/shortcuts-mac.multids @@ -1,6 +1,8 @@ title: $:/config/shortcuts-mac/ bold: meta-B +input-tab-left: ctrl-Left +input-tab-right: ctrl-Right italic: meta-I underline: meta-U new-image: ctrl-I From 9d5babc248d2fbd25922ee1690ada31c0c282e2f Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 2 Dec 2020 22:12:56 +0100 Subject: [PATCH 110/124] Bump CodeMirror plugin version (#5184) --- plugins/tiddlywiki/codemirror/readme.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/tiddlywiki/codemirror/readme.tid b/plugins/tiddlywiki/codemirror/readme.tid index bc899c1dc..c36e2eac0 100755 --- a/plugins/tiddlywiki/codemirror/readme.tid +++ b/plugins/tiddlywiki/codemirror/readme.tid @@ -4,4 +4,4 @@ This plugin provides an enhanced text editor component based on [[CodeMirror|htt [[Source code|https://github.com/Jermolene/TiddlyWiki5/blob/master/plugins/tiddlywiki/codemirror]] -Based on ~CodeMirror version 5.58.2 +Based on ~CodeMirror version 5.58.3 From 6b03105bed733dbf0436191b14227f89e72e28e3 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Wed, 2 Dec 2020 22:13:42 +0100 Subject: [PATCH 111/124] Update CupertinoDark.tid (#5183) --- core/palettes/CupertinoDark.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/palettes/CupertinoDark.tid b/core/palettes/CupertinoDark.tid index f97cab56d..8097322cc 100644 --- a/core/palettes/CupertinoDark.tid +++ b/core/palettes/CupertinoDark.tid @@ -113,7 +113,7 @@ selection-background: #3F638B selection-foreground: #ffffff wikilist-background: <<colour page-background>> wikilist-button-background: <<colour button-background>> -wikilist-button-foreground: <<colour foreground>> +wikilist-button-foreground: <<colour background>> wikilist-button-open: #32D74B wikilist-button-open-hover: #32D74B wikilist-button-reveal: #0A84FF From 1f5e1205ec633e55ea8377cef15f357e935e880a Mon Sep 17 00:00:00 2001 From: Saq Imtiaz <saq.imtiaz@gmail.com> Date: Wed, 2 Dec 2020 22:15:35 +0100 Subject: [PATCH 112/124] Extend Eventcatcher to handle multiple events (#5185) * support multiple events * Add variables for event type and detail. Rename types attribute to events * Correct typo in refresh handling --- core/modules/widgets/eventcatcher.js | 126 ++++++++++-------- .../tiddlers/widgets/EventCatcherWidget.tid | 24 ++-- 2 files changed, 83 insertions(+), 67 deletions(-) diff --git a/core/modules/widgets/eventcatcher.js b/core/modules/widgets/eventcatcher.js index 1f3d96688..09f2e3ad7 100644 --- a/core/modules/widgets/eventcatcher.js +++ b/core/modules/widgets/eventcatcher.js @@ -43,66 +43,76 @@ EventWidget.prototype.render = function(parent,nextSibling) { // Assign classes this.assignDomNodeClasses(); // Add our event handler - domNode.addEventListener(this.type,function(event) { - var selector = self.getAttribute("selector"), - actions = self.getAttribute("actions"), - selectedNode = event.target, - selectedNodeRect, - catcherNodeRect, - variables = {}; - if(selector) { - // Search ancestors for a node that matches the selector - while(!selectedNode.matches(selector) && selectedNode !== domNode) { - selectedNode = selectedNode.parentNode; - } - // If we found one, copy the attributes as variables, otherwise exit - if(selectedNode.matches(selector)) { - $tw.utils.each(selectedNode.attributes,function(attribute) { - variables["dom-" + attribute.name] = attribute.value.toString(); - }); - //Add a variable with a popup coordinate string for the selected node - variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")"; - - //Add variables for offset of selected node - variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString(); - variables["tv-selectednode-posy"] = selectedNode.offsetTop.toString(); - variables["tv-selectednode-width"] = selectedNode.offsetWidth.toString(); - variables["tv-selectednode-height"] = selectedNode.offsetHeight.toString(); + $tw.utils.each(this.types,function(type) { + domNode.addEventListener(type,function(event) { + var selector = self.getAttribute("selector"), + actions = self.getAttribute("actions-"+type), + selectedNode = event.target, + selectedNodeRect, + catcherNodeRect, + variables = {}; + if(selector) { + // Search ancestors for a node that matches the selector + while(!selectedNode.matches(selector) && selectedNode !== domNode) { + selectedNode = selectedNode.parentNode; + } + // If we found one, copy the attributes as variables, otherwise exit + if(selectedNode.matches(selector)) { + $tw.utils.each(selectedNode.attributes,function(attribute) { + variables["dom-" + attribute.name] = attribute.value.toString(); + }); + //Add a variable with a popup coordinate string for the selected node + variables["tv-popup-coords"] = "(" + selectedNode.offsetLeft + "," + selectedNode.offsetTop +"," + selectedNode.offsetWidth + "," + selectedNode.offsetHeight + ")"; + + //Add variables for offset of selected node + variables["tv-selectednode-posx"] = selectedNode.offsetLeft.toString(); + variables["tv-selectednode-posy"] = selectedNode.offsetTop.toString(); + variables["tv-selectednode-width"] = selectedNode.offsetWidth.toString(); + variables["tv-selectednode-height"] = selectedNode.offsetHeight.toString(); - //Add variables for event X and Y position relative to selected node - selectedNodeRect = selectedNode.getBoundingClientRect(); - variables["event-fromselected-posx"] = (event.clientX - selectedNodeRect.left).toString(); - variables["event-fromselected-posy"] = (event.clientY - selectedNodeRect.top).toString(); + //Add variables for event X and Y position relative to selected node + selectedNodeRect = selectedNode.getBoundingClientRect(); + variables["event-fromselected-posx"] = (event.clientX - selectedNodeRect.left).toString(); + variables["event-fromselected-posy"] = (event.clientY - selectedNodeRect.top).toString(); - //Add variables for event X and Y position relative to event catcher node - catcherNodeRect = self.domNode.getBoundingClientRect(); - variables["event-fromcatcher-posx"] = (event.clientX - catcherNodeRect.left).toString(); - variables["event-fromcatcher-posy"] = (event.clientY - catcherNodeRect.top).toString(); - } else { - return false; - } - } - // Execute our actions with the variables - if(actions) { - // Add a variable for the modifier key - variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event); - // Add a variable for the mouse button - if("button" in event) { - if(event.button === 0) { - variables["event-mousebutton"] = "left"; - } else if(event.button === 1) { - variables["event-mousebutton"] = "middle"; - } else if(event.button === 2) { - variables["event-mousebutton"] = "right"; + //Add variables for event X and Y position relative to event catcher node + catcherNodeRect = self.domNode.getBoundingClientRect(); + variables["event-fromcatcher-posx"] = (event.clientX - catcherNodeRect.left).toString(); + variables["event-fromcatcher-posy"] = (event.clientY - catcherNodeRect.top).toString(); + } else { + return false; } } - self.invokeActionString(actions,self,event,variables); - event.preventDefault(); - event.stopPropagation(); - return true; - } - return false; - },false); + // Execute our actions with the variables + if(actions) { + // Add a variable for the modifier key + variables.modifier = $tw.keyboardManager.getEventModifierKeyDescriptor(event); + // Add a variable for the mouse button + if("button" in event) { + if(event.button === 0) { + variables["event-mousebutton"] = "left"; + } else if(event.button === 1) { + variables["event-mousebutton"] = "middle"; + } else if(event.button === 2) { + variables["event-mousebutton"] = "right"; + } + } + variables["event-type"] = event.type; + if(typeof event.detail === "object" && !!event.detail) { + $tw.utils.each(event.detail,function(detailValue,detail) { + variables["event-detail-" + detail] = detailValue; + }); + } else if(!!event.detail) { + variables["event-detail"] = event.detail; + } + self.invokeActionString(actions,self,event,variables); + event.preventDefault(); + event.stopPropagation(); + return true; + } + return false; + },false); + }); // Insert element parent.insertBefore(domNode,nextSibling); this.renderChildren(domNode,null); @@ -115,7 +125,7 @@ Compute the internal state of the widget EventWidget.prototype.execute = function() { var self = this; // Get attributes that require a refresh on change - this.type = this.getAttribute("type"); + this.types = this.getAttribute("events","").split(" "); this.elementTag = this.getAttribute("tag"); // Make child widgets this.makeChildWidgets(); @@ -132,7 +142,7 @@ Selectively refreshes the widget if needed. Returns true if the widget or any of */ EventWidget.prototype.refresh = function(changedTiddlers) { var changedAttributes = this.computeAttributes(); - if(changedAttributes.type || changedAttributes["tag"]) { + if(changedAttributes["events"] || changedAttributes["tag"]) { this.refreshSelf(); return true; } else if(changedAttributes["class"]) { diff --git a/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid b/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid index 28d2c9e9a..9a4b498c5 100644 --- a/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid +++ b/editions/tw5.com/tiddlers/widgets/EventCatcherWidget.tid @@ -1,5 +1,5 @@ created: 20201123113532200 -modified: 20201123172753436 +modified: 20201202200719126 tags: Widgets title: EventCatcherWidget type: text/vnd.tiddlywiki @@ -11,10 +11,10 @@ The event catcher widget traps JavaScript events dispatched within its child con In order for the events to be trapped they must: -* be of the type specified as a parameter to the event catcher widget. +* be of one of the types specified as a parameter to the event catcher widget. * arise within a DOM node matching the selector specified as a parameter to the widget. -Use of the event catcher widget is useful when using large numbers of other trigger widgets such as the ButtonWidget is causing performance problems. The workflow it enables is akin to what is referred to as "event delegation" in JavaScript parlance. +Use of the event catcher widget is beneficial when using large numbers of other trigger widgets such as the ButtonWidget is causing performance problems. The workflow it enables is akin to what is referred to as "event delegation" in JavaScript parlance. //This is an advanced widget intended to be used by those familiar with HTML, CSS and JavaScript.// @@ -23,9 +23,9 @@ Use of the event catcher widget is useful when using large numbers of other trig The content of the `<$eventcatcher>` widget is displayed normally. |!Attribute |!Description | -|type |The JavaScript event type to be trapped, for example "click", or "dblclick" | +|events |Space separated list of JavaScript events to be trapped, for example "click" or "click dblclick" | |selector |A CSS selector. Only events originating inside a DOM node with this selector will be trapped. | -|actions |Action strings to be invoked when a matching event is trapped | +|actions-* |Action strings to be invoked when a matching event is trapped. Each event is mapped to an action attribute name of the form `actions-"event"` where `event` represents the type of the event. For example: `actions-click` or `actions-dblclick` | |class |An optional CSS class name to be assigned to the HTML element | |tag |Optional. The html element the widget creates to capture the events, defaults to:<br>» `span` when parsed in inline-mode<br>» `div` when parsed in block-mode | @@ -37,6 +37,8 @@ The following variables are made available to the actions: |`dom-*` |All DOM attributes of the node matching the given selector are made available as variables, with the prefix `dom-` | |`modifier` |The [[modifier Variable]] contains the Modifier Key held during the event (can be "normal", "ctrl", "shift", "alt" or combinations thereof) | |`event-mousebutton`|The mouse button (if any) used to trigger the event (can be "left", "right" or "middle"). Note that not all event types support the mousebutton property | +|`event-type`|The type property of the JavaScript event | +|`event-detail-*`|Any properties in the detail attribute of the event are made available with the prefix `event-detail-` | |`tv-popup-coords`|A co-ordinate string that can be used with the ActionPopupWidget to trigger a popup at the DOM node matching the selector where the event originated | |`tv-selectednode-posx`|`x` offset position of the selected DOM node | |`tv-selectednode-posy`|`y` offset position of the selected DOM node | @@ -52,11 +54,15 @@ The following variables are made available to the actions: This example uses the ActionLogWidget and will log the `data-item-id` attribute of the clicked DOM node to the browser's JavaScript [[console|Web Developer Tools]] ``` -\define myactions() -<$action-log item=<<dom-data-item-id>>/> +\define clickactions() +<$action-log item=<<dom-data-item-id>> event=<<event-type>>/> \end -<$eventcatcher type="click" selector=".item" actions=<<myactions>> tag="div"> +\define contextmenu-actions() +<$action-log item=<<dom-data-item-id>> event=<<event-type>>/> +\end + +<$eventcatcher events="click contextmenu" selector=".item" actions-click=<<clickactions>> actions-contextmenu=<<contextmenu-actions>> tag="div"> <div class="item" data-item-id="item1"> Click events here will be trapped @@ -74,6 +80,6 @@ Not here And here </div> -</$eventcatcher>""" +</$eventcatcher> ``` From c92f9dd404a2a1194bc7ebfa91ef6f3928311472 Mon Sep 17 00:00:00 2001 From: Robin Munn <rmunn@pobox.com> Date: Fri, 4 Dec 2020 04:20:23 +0700 Subject: [PATCH 113/124] Docs for trim operator suffix use from-version (#5161) Trim suffix was introduced in version 5.1.23; docs should mention that. --- editions/tw5.com/tiddlers/filters/trim Operator.tid | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editions/tw5.com/tiddlers/filters/trim Operator.tid b/editions/tw5.com/tiddlers/filters/trim Operator.tid index 918b4f4c4..a24790eb0 100644 --- a/editions/tw5.com/tiddlers/filters/trim Operator.tid +++ b/editions/tw5.com/tiddlers/filters/trim Operator.tid @@ -6,7 +6,7 @@ op-input: a [[selection of titles|Title Selection]] op-parameter: <<.from-version "5.1.23">> a string of characters op-parameter-name: S op-output: the input titles with <<.place S>>, or whitespace if <<.place S>> is not specified, trimmed from the start and/or end -op-suffix: `prefix` to trim from the start only, `suffix` to trim from the end only. If omitted (default), trim from both start and end +op-suffix: <<.from-version "5.1.23">> `prefix` to trim from the start only, `suffix` to trim from the end only. If omitted (default), trim from both start and end op-suffix-name: T tags: [[Filter Operators]] [[String Operators]] title: trim Operator From 8ffe1389423440a67aa64aba9c6421fdcf951d33 Mon Sep 17 00:00:00 2001 From: Robin Munn <rmunn@pobox.com> Date: Fri, 4 Dec 2020 20:19:59 +0700 Subject: [PATCH 114/124] Add rawunicode suffix to (json)stringify operators (#5191) Default with no suffix is pre-5.1.23 behavior, escaping all Unicode characters for maximum compatibility (avoids encoding issues). New "rawunicode" suffix allows passing through Unicode characters U+0080 and up unchanged, for cases where you know your tools are handling encoding correctly and you want less verbose escaping. --- core/modules/filters/encodings.js | 4 +-- core/modules/utils/utils.js | 10 ++++--- .../jsonstringify Operator (Examples).tid | 2 ++ .../stringify_Operator_(Examples).tid | 2 ++ .../filters/jsonstringify Operator.tid | 27 ++++++++++++------- .../tiddlers/filters/stringify_Operator.tid | 26 +++++++++++------- 6 files changed, 46 insertions(+), 25 deletions(-) diff --git a/core/modules/filters/encodings.js b/core/modules/filters/encodings.js index f41350791..557599c1a 100644 --- a/core/modules/filters/encodings.js +++ b/core/modules/filters/encodings.js @@ -77,7 +77,7 @@ exports.encodehtml = function(source,operator,options) { exports.stringify = function(source,operator,options) { var results = []; source(function(tiddler,title) { - results.push($tw.utils.stringify(title)); + results.push($tw.utils.stringify(title,(operator.suffix === "rawunicode"))); }); return results; }; @@ -85,7 +85,7 @@ exports.stringify = function(source,operator,options) { exports.jsonstringify = function(source,operator,options) { var results = []; source(function(tiddler,title) { - results.push($tw.utils.jsonStringify(title)); + results.push($tw.utils.jsonStringify(title,(operator.suffix === "rawunicode"))); }); return results; }; diff --git a/core/modules/utils/utils.js b/core/modules/utils/utils.js index b3c56fb8c..14d251f01 100644 --- a/core/modules/utils/utils.js +++ b/core/modules/utils/utils.js @@ -564,7 +564,7 @@ exports.escape = function(ch) { // Turns a string into a legal JavaScript string // Copied from peg.js, thanks to David Majda -exports.stringify = function(s) { +exports.stringify = function(s, rawUnicode) { /* * ECMA-262, 5th ed., 7.8.4: All characters may appear literally in a string * literal except for the closing quote character, backslash, carriage return, @@ -573,19 +573,21 @@ exports.stringify = function(s) { * * For portability, we also escape all non-ASCII characters. */ + var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g; return (s || "") .replace(/\\/g, '\\\\') // backslash .replace(/"/g, '\\"') // double quote character .replace(/'/g, "\\'") // single quote character .replace(/\r/g, '\\r') // carriage return .replace(/\n/g, '\\n') // line feed - .replace(/[\x00-\x1f\x80-\uFFFF]/g, exports.escape); // non-ASCII characters + .replace(regex, exports.escape); // non-ASCII characters }; // Turns a string into a legal JSON string // Derived from peg.js, thanks to David Majda -exports.jsonStringify = function(s) { +exports.jsonStringify = function(s, rawUnicode) { // See http://www.json.org/ + var regex = rawUnicode ? /[\x00-\x1f]/g : /[\x00-\x1f\x80-\uFFFF]/g; return (s || "") .replace(/\\/g, '\\\\') // backslash .replace(/"/g, '\\"') // double quote character @@ -594,7 +596,7 @@ exports.jsonStringify = function(s) { .replace(/\x08/g, '\\b') // backspace .replace(/\x0c/g, '\\f') // formfeed .replace(/\t/g, '\\t') // tab - .replace(/[\x00-\x1f\x80-\uFFFF]/g,function(s) { + .replace(regex,function(s) { return '\\u' + $tw.utils.pad(s.charCodeAt(0).toString(16).toUpperCase(),4); }); // non-ASCII characters }; diff --git a/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid index 20f7bff75..ead9ffb38 100644 --- a/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/jsonstringify Operator (Examples).tid @@ -5,3 +5,5 @@ title: jsonstringify Operator (Examples) type: text/vnd.tiddlywiki <<.operator-example 1 """[[Title with "double quotes" and single ' and \backslash]] +[jsonstringify[]]""">> +<<.operator-example 2 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 without suffix]] +[jsonstringify[]]""">> +<<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[jsonstringify:rawunicode[]]""">> diff --git a/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid b/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid index 1378287f5..a664cf7d2 100644 --- a/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/stringify_Operator_(Examples).tid @@ -5,3 +5,5 @@ title: stringify Operator (Examples) type: text/vnd.tiddlywiki <<.operator-example 1 """[[Title with "double quotes" and single ' and \backslash]] +[stringify[]]""">> +<<.operator-example 2 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 without suffix]] +[stringify[]]""">> +<<.operator-example 3 """[[Accents and emojis -> äñøßπ ⌛🎄🍪🍓 with rawunicode suffix]] +[stringify:rawunicode[]]""">> diff --git a/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid b/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid index ff361450e..a7e4d565c 100644 --- a/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid +++ b/editions/tw5.com/tiddlers/filters/jsonstringify Operator.tid @@ -7,22 +7,29 @@ op-output: the input with JSON string encodings applied op-parameter: op-parameter-name: op-purpose: apply JSON string encoding to a string +op-suffix: <<.from-version "5.1.23">> optionally, the keyword `rawunicode` +op-suffix-name: R tags: [[Filter Operators]] [[String Operators]] title: jsonstringify Operator type: text/vnd.tiddlywiki The following substitutions are made: -|!Character |!Replacement | -|`\` |`\\` | -|`"` |`\"` | -|`\r` (carriage return) |`\\r` | -|`\n` (line feed) |`\\n` | -|`\x08` (backspace) |`\\b` | -|`\x0c` (form field) |`\\f` | -|`\t` (tab) |`\\t` | -|Characters from 0x00 to 0x1f |`\\x##` where ## is two hex digits | -|Characters from 0x80 to 0xffff |`\\u####` where #### is four hex digits | +|!Character |!Replacement |!Condition | +|`\` |`\\` |Always | +|`"` |`\"` |Always | +|Carriage return (0x0d) |`\\r` |Always | +|Line feed (0x0a) |`\\n` |Always | +|Backspace (0x08) |`\\b` |Always | +|Form field (0x0c) |`\\f` |Always | +|Tab (0x09) |`\\t` |Always | +|Characters from 0x00 to 0x1f |`\\u####` where #### is four hex digits |Always | +|Characters from 0x80 to 0xffff|`\\u####` where #### is four hex digits |If `rawunicode` suffix is not present (default) | +|Characters from 0x80 to 0xffff|Unchanged |If `rawunicode` suffix is present <<.from-version "5.1.23">> | + +<<.from-version "5.1.23">> If the suffix `rawunicode` is present, Unicode characters above 0x80 (such as ß, ä, ñ or 🎄) will be passed through unchanged. Without the suffix, they will be substituted with `\\u` codes, which was the default behavior before 5.1.23. + +<<.note """Technical note: Characters outside the Basic Multilingual Plane, such as 🎄 and other emojis, will be encoded as a UTF-16 surrogate pair, i.e. with two `\u` sequences.""">> Also see the [[stringify Operator]]. diff --git a/editions/tw5.com/tiddlers/filters/stringify_Operator.tid b/editions/tw5.com/tiddlers/filters/stringify_Operator.tid index 7bd0847d9..e06be4387 100644 --- a/editions/tw5.com/tiddlers/filters/stringify_Operator.tid +++ b/editions/tw5.com/tiddlers/filters/stringify_Operator.tid @@ -6,6 +6,8 @@ op-output: the input with ~JavaScript string encodings applied op-parameter: op-parameter-name: op-purpose: apply ~JavaScript string encoding to a string +op-suffix: <<.from-version "5.1.23">> optionally, the keyword `rawunicode` +op-suffix-name: R tags: [[Filter Operators]] [[String Operators]] title: stringify Operator type: text/vnd.tiddlywiki @@ -13,15 +15,21 @@ from-version: 5.1.14 The following substitutions are made: -|!Character |!Replacement | -|`\` |`\\` | -|`"` |`\"` | -|`\r` (carriage return) |`\\r` | -|`\n` (line feed) |`\\n` | -|`\x08` (backspace) |`\\b` | -|`\x0c` (form feed) |`\\f` | -|`\t` (tab) |`\\t` | -|Characters from 0x00 to 0x1f and characters from 0x80 to 0xffff |`\\u####` where #### is four hex digits | +|!Character |!Replacement |!Condition | +|`\` |`\\` |Always | +|`"` |`\"` |Always | +|Carriage return (0x0d) |`\\r` |Always | +|Line feed (0x0a) |`\\n` |Always | +|Backspace (0x08) |`\\b` |Always | +|Form field (0x0c) |`\\f` |Always | +|Tab (0x09) |`\\t` |Always | +|Characters from 0x00 to 0x1f |`\\x##` where ## is two hex digits |Always | +|Characters from 0x80 to 0xffff|`\\u####` where #### is four hex digits |If `rawunicode` suffix is not present (default) | +|Characters from 0x80 to 0xffff|<<.from-version "5.1.23">> Unchanged |If `rawunicode` suffix is present | + +<<.from-version "5.1.23">> If the suffix `rawunicode` is present, Unicode characters above 0x80 (such as ß, ä, ñ or 🎄) will be passed through unchanged. Without the suffix, they will be substituted with `\\u` codes, which was the default behavior before 5.1.23. + +<<.note """Technical note: Characters outside the Basic Multilingual Plane, such as 🎄 and other emojis, will be encoded as a UTF-16 surrogate pair, i.e. with two `\u` sequences.""">> Also see the [[jsonstringify Operator]]. From 046746ba20d129e5f3f936627e8d7754c385d264 Mon Sep 17 00:00:00 2001 From: Saq Imtiaz <saq.imtiaz@gmail.com> Date: Fri, 4 Dec 2020 19:23:50 +0100 Subject: [PATCH 115/124] Add :reduce filter run prefix (#5196) --- core/modules/filterrunprefixes/reduce.js | 49 ++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 core/modules/filterrunprefixes/reduce.js diff --git a/core/modules/filterrunprefixes/reduce.js b/core/modules/filterrunprefixes/reduce.js new file mode 100644 index 000000000..3ca305720 --- /dev/null +++ b/core/modules/filterrunprefixes/reduce.js @@ -0,0 +1,49 @@ +/*\ +title: $:/core/modules/filterrunprefixes/reduce.js +type: application/javascript +module-type: filterrunprefix +\*/ +(function(){ + +/*jslint node: true, browser: true */ +/*global $tw: false */ +"use strict"; + +/* +Export our filter prefix function +*/ +exports.reduce = function(operationSubFunction) { + return function(results,source,widget) { + if(results.length > 0) { + var accumulator = ""; + for(var index=0; index<results.length; index++) { + var title = results[index], + list = operationSubFunction($tw.wiki.makeTiddlerIterator([title]),{ + getVariable: function(name) { + switch(name) { + case "currentTiddler": + return "" + title; + case "accumulator": + return "" + accumulator; + case "index": + return "" + index; + case "revIndex": + return "" + (results.length - 1 - index); + case "length": + return "" + results.length; + default: + return widget.getVariable(name); + } + } + }); + if(list.length > 0) { + accumulator = "" + list[0]; + } + } + results.splice(0,results.length); + results.push(accumulator); + } + } +}; + +})(); \ No newline at end of file From 911e23ee6d1b54618eb98adf93b421e3b7e90e1f Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Fri, 4 Dec 2020 19:27:40 +0100 Subject: [PATCH 116/124] Make sidebarsegments/search button display the count of ALL search results (de-duplicated) (#5194) --- core/ui/SideBarSegments/search.tid | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/ui/SideBarSegments/search.tid b/core/ui/SideBarSegments/search.tid index 4e7e6eb72..a5b6f1b97 100644 --- a/core/ui/SideBarSegments/search.tid +++ b/core/ui/SideBarSegments/search.tid @@ -8,9 +8,9 @@ tags: $:/tags/SideBarSegment <$button popup=<<qualify "$:/state/popup/search-dropdown">> class="tc-btn-invisible"> {{$:/core/images/down-arrow}} <$list filter="[{$(searchTiddler)$}minlength{$:/config/Search/MinLength}limit[1]]" variable="listItem"> -<$vars userInput={{{ [<searchTiddler>get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}}> -<$vars primaryListFilter={{{ [<configTiddler>get[first-search-filter]] }}} secondaryListFilter={{{ [<configTiddler>get[second-search-filter]] }}}> -<$set name="resultCount" value="""<$count filter="[subfilter<primaryListFilter>] =[subfilter<secondaryListFilter>]"/>"""> +<$vars userInput={{{ [<searchTiddler>get[text]] }}} configTiddler={{{ [[$:/state/search/currentTab]!is[missing]get[text]] ~[{$:/config/SearchResults/Default}] }}} replaceRegexp="limit\[\d+\]"> +<$vars primaryListFilter={{{ [<configTiddler>get[first-search-filter]search-replace:g:regexp<replaceRegexp>,[]] }}} secondaryListFilter={{{ [<configTiddler>get[second-search-filter]search-replace:g:regexp<replaceRegexp>,[]] }}}> +<$set name="resultCount" value="""<$count filter="[subfilter<primaryListFilter>] [subfilter<secondaryListFilter>]"/>"""> {{$:/language/Search/Matches}} </$set> </$vars> From 813e28e1eafe954eb3d9352addf4d41bd9564576 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Fri, 4 Dec 2020 19:28:36 +0100 Subject: [PATCH 117/124] Make the tag-picker tags-dropdown more performant (#5195) * Replace macrocall for tag-button with transclusion of a TagPickerTagTemplate * Create TagPickerTagTemplate.tid --- core/ui/TagPickerTagTemplate.tid | 17 +++++++++++++++++ core/wiki/macros/tag-picker.tid | 27 +++++++-------------------- 2 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 core/ui/TagPickerTagTemplate.tid diff --git a/core/ui/TagPickerTagTemplate.tid b/core/ui/TagPickerTagTemplate.tid new file mode 100644 index 000000000..43406a565 --- /dev/null +++ b/core/ui/TagPickerTagTemplate.tid @@ -0,0 +1,17 @@ +title: $:/core/ui/TagPickerTagTemplate + +\whitespace trim +<$button class=<<button-classes>> tag="a" tooltip={{$:/language/EditTemplate/Tags/Add/Button/Hint}}> +<$list filter="[<saveTiddler>minlength[1]]"> +<$action-listops $tiddler=<<saveTiddler>> $field=<<tagField>> $subfilter="[<tag>]"/> +</$list> +<$set name="currentTiddlerCSSEscaped" value={{{ [<saveTiddler>escapecss[]] }}}> +<$action-sendmessage $message="tm-focus-selector" $param=<<get-tagpicker-focus-selector>> preventScroll="true"/> +</$set> +<<delete-tag-state-tiddlers>> +<$list filter="[<refreshTitle>minlength[1]]"> +<$action-setfield $tiddler=<<refreshTitle>> text="yes"/> +</$list> +<<actions>> +<$macrocall $name="tag-pill-inner" tag=<<currentTiddler>> icon={{{ [<tag>get[icon]] }}} colour={{{ [<tag>get[color]] }}} fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>> element-tag="span" element-attributes="" actions=<<actions>>/> +</$button> diff --git a/core/wiki/macros/tag-picker.tid b/core/wiki/macros/tag-picker.tid index 31d6c786d..8a48532b1 100644 --- a/core/wiki/macros/tag-picker.tid +++ b/core/wiki/macros/tag-picker.tid @@ -20,19 +20,6 @@ $actions$ <$action-setfield $tiddler=<<refreshTitle>> text="yes"/> \end -\define tag-button(actions,selectedClass,tagField:"tags") -<$button class="tc-btn-invisible $selectedClass$" tag="a" tooltip={{$:/language/EditTemplate/Tags/Add/Button/Hint}}> -<$action-listops $tiddler=<<saveTiddler>> $field=<<__tagField__>> $subfilter="[<tag>]"/> -<$set name="currentTiddlerCSSEscaped" value={{{ [<saveTiddler>escapecss[]] }}}> -<$action-sendmessage $message="tm-focus-selector" $param=<<get-tagpicker-focus-selector>> preventScroll="true"/> -</$set> -<<delete-tag-state-tiddlers>> -<$action-setfield $tiddler=<<refreshTitle>> text="yes"/> -$actions$ -<$macrocall $name="tag-pill" tag=<<tag>>/> -</$button> -\end - \define clear-tags-actions-inner() <$list filter="[<storeTitle>has[text]] [<newTagNameTiddler>has[text]]" variable="ignore" emptyMessage="""<<cancel-delete-tiddler-actions "cancel">>"""> <<delete-tag-state-tiddlers>> @@ -49,7 +36,7 @@ $actions$ \define tag-picker-inner(actions,tagField:"tags") \whitespace trim -<$vars newTagNameInputTiddlerQualified=<<qualify "$:/temp/NewTagName/input">> newTagNameSelectionTiddlerQualified=<<qualify "$:/temp/NewTagName/selected-item">>> +<$vars newTagNameInputTiddlerQualified=<<qualify "$:/temp/NewTagName/input">> newTagNameSelectionTiddlerQualified=<<qualify "$:/temp/NewTagName/selected-item">> fallbackTarget={{$(palette)$##tag-background}} colourA={{$(palette)$##foreground}} colourB={{$(palette)$##background}}> <$vars storeTitle={{{ [<newTagNameInputTiddler>!match[]] ~[<newTagNameInputTiddlerQualified>] }}} tagSelectionState={{{ [<newTagNameSelectionTiddler>!match[]] ~[<newTagNameSelectionTiddlerQualified>] }}}> <$vars refreshTitle=<<qualify "$:/temp/NewTagName/refresh">> nonSystemTagsFilter="[tags[]!is[system]search:title<userInput>sort[]]" systemTagsFilter="[tags[]is[system]search:title<userInput>sort[]]"> <div class="tc-edit-add-tag"> @@ -80,15 +67,15 @@ $actions$ <$set name="userInput" value={{{ [<storeTitle>get[text]] }}}> <$list filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]" emptyMessage="""<div class="tc-search-results">{{$:/language/Search/Search/TooShort}}</div>""" variable="listItem"> <$list filter=<<nonSystemTagsFilter>> variable="tag"> -<$list filter="[<tag>addsuffix[-primaryList]] -[<tagSelectionState>get[text]]" emptyMessage="""<$macrocall $name="tag-button" actions=<<__actions__>> selectedClass="tc-tag-button-selected"/>"""> -<$macrocall $name="tag-button" actions=<<__actions__>> tagField=<<__tagField__>>/> +<$list filter="[<tag>addsuffix[-primaryList]] -[<tagSelectionState>get[text]]" emptyMessage="""<$vars button-classes="tc-btn-invisible tc-tag-button-selected" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>"""> +<$vars button-classes="tc-btn-invisible" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars> </$list> </$list></$list> <hr> <$list filter="[<userInput>minlength{$:/config/Tags/MinLength}limit[1]]" emptyMessage="""<div class="tc-search-results">{{$:/language/Search/Search/TooShort}}</div>""" variable="listItem"> <$list filter=<<systemTagsFilter>> variable="tag"> -<$list filter="[<tag>addsuffix[-secondaryList]] -[<tagSelectionState>get[text]]" emptyMessage="""<$macrocall $name="tag-button" actions=<<__actions__>> selectedClass="tc-tag-button-selected"/>"""> -<$macrocall $name="tag-button" actions=<<__actions__>> tagField=<<__tagField__>>/> +<$list filter="[<tag>addsuffix[-secondaryList]] -[<tagSelectionState>get[text]]" emptyMessage="""<$vars button-classes="tc-btn-invisible tc-tag-button-selected" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars>"""> +<$vars button-classes="tc-btn-invisible" actions=<<__actions__>> tagField=<<__tagField__>> currentTiddler=<<tag>>>{{||$:/core/ui/TagPickerTagTemplate}}</$vars> </$list> </$list></$list> </$set> @@ -102,11 +89,11 @@ $actions$ \end \define tag-picker(actions,tagField:"tags") \whitespace trim -<$set name="saveTiddler" value=<<currentTiddler>>> +<$vars saveTiddler=<<currentTiddler>> palette={{$:/palette}}> <$list filter="[<newTagNameTiddler>match[]]" emptyMessage="""<$macrocall $name="tag-picker-inner" actions=<<__actions__>> tagField=<<__tagField__>>/>"""> <$set name="newTagNameTiddler" value=<<qualify "$:/temp/NewTagName">>> <$macrocall $name="tag-picker-inner" actions=<<__actions__>> tagField=<<__tagField__>>/> </$set> </$list> -</$set> +</$vars> \end From 8799911162de6e5f5b656edb93a55a7a679cae13 Mon Sep 17 00:00:00 2001 From: Saq Imtiaz <saq.imtiaz@gmail.com> Date: Fri, 4 Dec 2020 19:31:23 +0100 Subject: [PATCH 118/124] Reduce operator: second optional parameter instead of suffix (#5193) * Tweak reduce operator to use an optional second parameter instead of a suffix * Updated docs --- core/modules/filters/reduce.js | 2 +- .../filters/examples/reduce Operator (Examples).tid | 12 ++++++------ editions/tw5.com/tiddlers/filters/reduce.tid | 8 +++----- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/core/modules/filters/reduce.js b/core/modules/filters/reduce.js index 74d1131eb..fd5ccf568 100644 --- a/core/modules/filters/reduce.js +++ b/core/modules/filters/reduce.js @@ -23,7 +23,7 @@ exports.reduce = function(source,operator,options) { }); // Run the filter over each item var filterFn = options.wiki.compileFilter(operator.operand), - accumulator = operator.suffix || ""; + accumulator = operator.operands[1] || ""; for(var index=0; index<results.length; index++) { var title = results[index], list = filterFn.call(options.wiki,options.wiki.makeTiddlerIterator([title]),{ diff --git a/editions/tw5.com/tiddlers/filters/examples/reduce Operator (Examples).tid b/editions/tw5.com/tiddlers/filters/examples/reduce Operator (Examples).tid index 9d92ea0c8..1c619c506 100644 --- a/editions/tw5.com/tiddlers/filters/examples/reduce Operator (Examples).tid +++ b/editions/tw5.com/tiddlers/filters/examples/reduce Operator (Examples).tid @@ -1,5 +1,5 @@ created: 20201004154413968 -modified: 20201006181831622 +modified: 20201204131137081 tags: [[Operator Examples]] [[reduce Operator]] title: reduce Operator (Examples) type: text/vnd.tiddlywiki @@ -42,7 +42,7 @@ Using `<index>` to act differently on the first item than the rest: <<.operator-example 3 "[tag[shopping]reduce<join-with-commas>]">> -Empty input, no suffix: +Empty input, no second parameter: <<.operator-example 4 "[tag[non-existent]reduce<add-price>]">> @@ -50,12 +50,12 @@ Note how the output contains a single item with no text. This is not "empty outp <$macrocall $name=".tip" _=<<reduce-tip>> /> -Empty input, no suffix, followed by <<.op else>>: +Empty input, no second parameter, followed by <<.op else>>: <<.operator-example 5 "[tag[non-existent]reduce<add-price>else[0]]">> -Note how the output still contains a single item with no text: <<.op else>> did not trigger. If you want the value to be 0 when <<.op reduce>> has no items to process, you need to specify 0 as the initial value by passing it as a suffix to <<.op reduce>>. +Note how the output still contains a single item with no text: <<.op else>> did not trigger. If you want the value to be 0 when <<.op reduce>> has no items to process, you need to specify 0 as the initial value by passing it as a second parameter to <<.op reduce>>. -Empty input, suffix provided: +Empty input, second parameter provided: -<<.operator-example 6 "[tag[non-existent]reduce:0<add-price>]">> +<<.operator-example 6 "[tag[non-existent]reduce<add-price>,[0]]">> diff --git a/editions/tw5.com/tiddlers/filters/reduce.tid b/editions/tw5.com/tiddlers/filters/reduce.tid index d47955da3..debd28c9f 100644 --- a/editions/tw5.com/tiddlers/filters/reduce.tid +++ b/editions/tw5.com/tiddlers/filters/reduce.tid @@ -1,19 +1,17 @@ caption: reduce created: 20201004154131193 -modified: 20201006174749170 +modified: 20201204130601564 op-input: a [[selection of titles|Title Selection]] passed as input to the filter op-output: the final result of running the subfilter <<.place S>> -op-parameter: a [[filter expression|Filter Expression]] +op-parameter: a [[filter expression|Filter Expression]]. Optional second parameter for initial value for accumulator op-parameter-name: S op-purpose: apply a subfilter to each input title in turn, accumulating a single value -op-suffix: Initial value for accumulator -op-suffix-name: V tags: [[Filter Operators]] title: reduce Operator type: text/vnd.tiddlywiki \define reduce-tip() -The <<.op reduce>> operator will always produce output, even if its input was empty. If its input is empty, the output of <<.op reduce>> will be the initial value of the accumulator, i.e. the value of the suffix. One result of this fact is that the <<.op else>> operator will never be triggered if it follows a <<.op reduce>>. The "Empty input" examples show what happens when <<.op reduce>> receives no input. +The <<.op reduce>> operator will always produce output, even if its input was empty. If its input is empty, the output of <<.op reduce>> will be the initial value of the accumulator, i.e. the value of the second parameter. One result of this fact is that the <<.op else>> operator will never be triggered if it follows a <<.op reduce>>. The "Empty input" examples show what happens when <<.op reduce>> receives no input. \end <<.from-version "5.1.23">> The <<.op reduce>> operator runs a subfilter for each input title, passing the result of the previous subfilter run as a variable. The initial value of the accumulator can optionally be specified. It returns the result of the final subfilter run. From 9825b5b4a0ccab82d38c8daac8b5e85ab82ee84d Mon Sep 17 00:00:00 2001 From: Saq Imtiaz <saq.imtiaz@gmail.com> Date: Fri, 4 Dec 2020 20:02:05 +0100 Subject: [PATCH 119/124] Ensure new variables are strings (#5197) --- core/modules/widgets/eventcatcher.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/modules/widgets/eventcatcher.js b/core/modules/widgets/eventcatcher.js index 09f2e3ad7..c014f8997 100644 --- a/core/modules/widgets/eventcatcher.js +++ b/core/modules/widgets/eventcatcher.js @@ -97,13 +97,13 @@ EventWidget.prototype.render = function(parent,nextSibling) { variables["event-mousebutton"] = "right"; } } - variables["event-type"] = event.type; + variables["event-type"] = event.type.toString(); if(typeof event.detail === "object" && !!event.detail) { $tw.utils.each(event.detail,function(detailValue,detail) { - variables["event-detail-" + detail] = detailValue; + variables["event-detail-" + detail] = detailValue.toString(); }); } else if(!!event.detail) { - variables["event-detail"] = event.detail; + variables["event-detail"] = event.detail.toString(); } self.invokeActionString(actions,self,event,variables); event.preventDefault(); @@ -153,4 +153,4 @@ EventWidget.prototype.refresh = function(changedTiddlers) { exports.eventcatcher = EventWidget; -})(); \ No newline at end of file +})(); From ae5d78b4dd8024190dcd9334dcbd69f636884b20 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Fri, 4 Dec 2020 20:14:59 +0100 Subject: [PATCH 120/124] Update codemirror styles (#5198) --- plugins/tiddlywiki/codemirror/styles.tid | 35 ++++++++++++++---------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/plugins/tiddlywiki/codemirror/styles.tid b/plugins/tiddlywiki/codemirror/styles.tid index 2c44f8d1a..3d097c234 100755 --- a/plugins/tiddlywiki/codemirror/styles.tid +++ b/plugins/tiddlywiki/codemirror/styles.tid @@ -3,6 +3,21 @@ tags: [[$:/tags/Stylesheet]] module-type: codemirror-theme name: tiddlywiki +\define set-fat-cursor-background-css(colour,colourA,colourB) +<$set name="backgroundColour" value=<<contrastcolour target:"""$colour$""" fallbackTarget:"""""" colourA:"""$colourA$""" colourB:"""$colourB$""">>> +.cm-s-tiddlywiki.cm-fat-cursor .CodeMirror-cursor { background: <<backgroundColour>>; } +.cm-s-tiddlywiki .cm-animate-fat-cursor { background-color: <<backgroundColour>>; } +</$set> +\end +\define set-fat-cursor-background-colours(palette) +<$macrocall $name="set-fat-cursor-background-css" colour={{$palette$##foreground}} colourA="#77ee77" colourB="#586e75"/> +\end +\define set-fat-cursor-background() +<$macrocall $name="set-fat-cursor-background-colours" palette={{$:/palette}}/> +\end + +\rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock + /* Make the editor resize to fit its content */ .CodeMirror { @@ -37,37 +52,25 @@ name: tiddlywiki .cm-s-tiddlywiki .CodeMirror-line > span::-moz-selection, .cm-s-tiddlywiki .CodeMirror-line > span > span::-moz-selection { background: <<colour selection-background>>; } .cm-s-tiddlywiki span.cm-comment { color: <<colour muted-foreground>>; font-style:italic; font-weight:normal; } -.cm-s-tiddlywiki .CodeMirror-activeline-background, .cm-s-tiddlywiki .CodeMirror-activeline-gutter .CodeMirror-linenumber { background: <<colour background>>; } -.cm-s-tiddlywiki .CodeMirror-activeline .CodeMirror-linenumber.CodeMirror-gutter-elt { background: <<colour primary>>; color: <<colour background>>; } -.cm-s-tiddlywiki .CodeMirror-matchingbracket { background: <<colour primary>>; color:<<colour foreground>> !important; } -.cm-s-tiddlywiki span.cm-matchhighlight { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} -.cm-s-tiddlywiki span.cm-searching { color: <<colour foreground>>; background-color: <<colour primary>>; font-weight: normal;} - - +.cm-s-tiddlywiki .CodeMirror-activeline-background, .cm-s-tiddlywiki .CodeMirror-activeline-gutter .CodeMirror-linenumber { background: rgba(127,127,127,0.2); } +.cm-s-tiddlywiki span.cm-matchhighlight { color: <<colour background>>; background-color: <<colour primary>>; font-weight: normal;} .cm-s-tiddlywiki .CodeMirror-widget { text-shadow: none; } - .cm-s-tiddlywiki .cm-header { color: #586e75; } .cm-s-tiddlywiki .cm-quote { color: #93a1a1; } - .cm-s-tiddlywiki .cm-keyword { color: #cb4b16; } .cm-s-tiddlywiki .cm-atom { color: #d33682; } .cm-s-tiddlywiki .cm-number { color: #d33682; } .cm-s-tiddlywiki .cm-def { color: #2aa198; } - .cm-s-tiddlywiki .cm-variable { color: #839496; } .cm-s-tiddlywiki .cm-variable-2 { color: #b58900; } .cm-s-tiddlywiki .cm-variable-3, .cm-s-tiddlywiki .cm-type { color: #6c71c4; } - .cm-s-tiddlywiki .cm-property { color: #2aa198; } .cm-s-tiddlywiki .cm-operator { color: #6c71c4; } - .cm-s-tiddlywiki .cm-comment { color: #586e75; font-style:italic; } - .cm-s-tiddlywiki .cm-string { color: #859900; } .cm-s-tiddlywiki .cm-string-2 { color: #b58900; } - .cm-s-tiddlywiki .cm-meta { color: #859900; } .cm-s-tiddlywiki .cm-qualifier { color: #b58900; } .cm-s-tiddlywiki .cm-builtin { color: #d33682; } @@ -93,3 +96,7 @@ name: tiddlywiki color: #586e75; border-bottom: 1px dotted #dc322f; } +.cm-s-tiddlywiki .CodeMirror-matchingbracket { color: #859900; } +.cm-s-tiddlywiki .CodeMirror-nonmatchingbracket { color: #dc322f; } +.cm-s-tiddlywiki .cm-searching { background: rgba(243, 155, 53, .3); outline: 1px solid #F39B35; } +<<set-fat-cursor-background>> From fbe5bb229a937108220a16e13509739a68c3da66 Mon Sep 17 00:00:00 2001 From: Cameron Fischer <fischer.cameron@gmail.com> Date: Sat, 5 Dec 2020 11:12:40 -0500 Subject: [PATCH 121/124] Fix for filterrunprefixes using $tw.wiki (#5202) * Fixed runprefix 'and' to use widget wiki * Made widget arg of filterTiddlers optional again * Switched to passing {wiki: wiki} to prefixes --- core/modules/filterrunprefixes/and.js | 4 ++-- core/modules/filterrunprefixes/reduce.js | 6 +++--- core/modules/filters.js | 13 +++++++------ editions/test/tiddlers/tests/test-filters.js | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/modules/filterrunprefixes/and.js b/core/modules/filterrunprefixes/and.js index 29ccf1619..ad41c049c 100644 --- a/core/modules/filterrunprefixes/and.js +++ b/core/modules/filterrunprefixes/and.js @@ -16,10 +16,10 @@ Equivalent to + filter run prefix. /* Export our filter prefix function */ -exports.and = function(operationSubFunction) { +exports.and = function(operationSubFunction,options) { return function(results,source,widget) { // This replaces all the elements of the array, but keeps the actual array so that references to it are preserved - source = $tw.wiki.makeTiddlerIterator(results); + source = options.wiki.makeTiddlerIterator(results); results.splice(0,results.length); $tw.utils.pushTop(results,operationSubFunction(source,widget)); }; diff --git a/core/modules/filterrunprefixes/reduce.js b/core/modules/filterrunprefixes/reduce.js index 3ca305720..4dcef4bc7 100644 --- a/core/modules/filterrunprefixes/reduce.js +++ b/core/modules/filterrunprefixes/reduce.js @@ -12,13 +12,13 @@ module-type: filterrunprefix /* Export our filter prefix function */ -exports.reduce = function(operationSubFunction) { +exports.reduce = function(operationSubFunction,options) { return function(results,source,widget) { if(results.length > 0) { var accumulator = ""; for(var index=0; index<results.length; index++) { var title = results[index], - list = operationSubFunction($tw.wiki.makeTiddlerIterator([title]),{ + list = operationSubFunction(options.wiki.makeTiddlerIterator([title]),{ getVariable: function(name) { switch(name) { case "currentTiddler": @@ -46,4 +46,4 @@ exports.reduce = function(operationSubFunction) { } }; -})(); \ No newline at end of file +})(); diff --git a/core/modules/filters.js b/core/modules/filters.js index 0beb86208..0fc0a3dc9 100644 --- a/core/modules/filters.js +++ b/core/modules/filters.js @@ -280,20 +280,21 @@ exports.compileFilter = function(filterString) { var filterRunPrefixes = self.getFilterRunPrefixes(); // Wrap the operator functions in a wrapper function that depends on the prefix operationFunctions.push((function() { + var options = {wiki: self}; switch(operation.prefix || "") { case "": // No prefix means that the operation is unioned into the result - return filterRunPrefixes["or"](operationSubFunction); + return filterRunPrefixes["or"](operationSubFunction, options); case "=": // The results of the operation are pushed into the result without deduplication - return filterRunPrefixes["all"](operationSubFunction); + return filterRunPrefixes["all"](operationSubFunction, options); case "-": // The results of this operation are removed from the main result - return filterRunPrefixes["except"](operationSubFunction); + return filterRunPrefixes["except"](operationSubFunction, options); case "+": // This operation is applied to the main results so far - return filterRunPrefixes["and"](operationSubFunction); + return filterRunPrefixes["and"](operationSubFunction, options); case "~": // This operation is unioned into the result only if the main result so far is empty - return filterRunPrefixes["else"](operationSubFunction); + return filterRunPrefixes["else"](operationSubFunction, options); default: if(operation.namedPrefix && filterRunPrefixes[operation.namedPrefix]) { - return filterRunPrefixes[operation.namedPrefix](operationSubFunction); + return filterRunPrefixes[operation.namedPrefix](operationSubFunction, options); } else { return function(results,source,widget) { results.splice(0,results.length); diff --git a/editions/test/tiddlers/tests/test-filters.js b/editions/test/tiddlers/tests/test-filters.js index 895c83ca3..4a9e9f950 100644 --- a/editions/test/tiddlers/tests/test-filters.js +++ b/editions/test/tiddlers/tests/test-filters.js @@ -459,7 +459,7 @@ function runTests(wiki) { it("should handle indirect operands", function() { expect(wiki.filterTiddlers("[prefix{Tiddler8}] +[sort[title]]").join(",")).toBe("Tiddler Three,TiddlerOne"); expect(wiki.filterTiddlers("[modifier{Tiddler8!!test-field}] +[sort[title]]").join(",")).toBe("TiddlerOne"); - var fakeWidget = {getVariable: function() {return "Tiddler Three";}}; + var fakeWidget = {wiki: wiki, getVariable: function() {return "Tiddler Three";}}; expect(wiki.filterTiddlers("[modifier{!!modifier}] +[sort[title]]",fakeWidget).join(",")).toBe("$:/TiddlerTwo,a fourth tiddler,one,Tiddler Three"); }); From d957b3e4e68fb76ba60e7c92b293fbc1b98f245b Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 5 Dec 2020 17:37:50 +0100 Subject: [PATCH 122/124] Update CodeMirror styles to set selection colors based on foreground contrastcolour (#5200) * Update styles.tid * Update styles.tid * Update styles.tid --- plugins/tiddlywiki/codemirror/styles.tid | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/plugins/tiddlywiki/codemirror/styles.tid b/plugins/tiddlywiki/codemirror/styles.tid index 3d097c234..d2b1e3916 100755 --- a/plugins/tiddlywiki/codemirror/styles.tid +++ b/plugins/tiddlywiki/codemirror/styles.tid @@ -15,6 +15,17 @@ name: tiddlywiki \define set-fat-cursor-background() <$macrocall $name="set-fat-cursor-background-colours" palette={{$:/palette}}/> \end +\define set-selection-background-css(colour,colourA,colourB) +<$set name="backgroundColour" value=<<contrastcolour target:"""$colour$""" fallbackTarget:"""""" colourA:"""$colourA$""" colourB:"""$colourB$""">>> +.cm-s-tiddlywiki div.CodeMirror-selected, .cm-s-tiddlywiki .CodeMirror-selectedtext, .cm-s-tiddlywiki .CodeMirror-selected, .cm-s-tiddlywiki .CodeMirror-line::selection, .cm-s-tiddlywiki .CodeMirror-line > span::selection, .cm-s-tiddlywiki .CodeMirror-line > span > span::selection, .cm-s-tiddlywiki .CodeMirror-line::-moz-selection, .cm-s-tiddlywiki .CodeMirror-line > span::-moz-selection, .cm-s-tiddlywiki .CodeMirror-line > span > span::-moz-selection { background: <<backgroundColour>> ; } +</$set> +\end +\define set-selection-background-colours(palette) +<$macrocall $name="set-selection-background-css" colour={{$palette$##foreground}} colourA={{{ [{$palette$##selection-background}!match[]!prefix[<<]!suffix[>>]] ~#073642 }}} colourB={{{ [{$palette$##selection-background}!match[]!prefix[<<]!suffix[>>]] ~#eee8d5 }}}/> +\end +\define set-selection-background() +<$macrocall $name="set-selection-background-colours" palette={{$:/palette}}/> +\end \rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock @@ -42,16 +53,7 @@ name: tiddlywiki .cm-s-tiddlywiki .CodeMirror-gutters {background: <<colour tiddler-editor-background>>; border-right: 0px;} .cm-s-tiddlywiki .CodeMirror-linenumber {color: <<colour foreground>>;} .cm-s-tiddlywiki .CodeMirror-cursor { border-left: 2px solid <<colour foreground>>; } -.cm-s-tiddlywiki div.CodeMirror-selected { background: <<colour selection-background>>; } -.cm-s-tiddlywiki .CodeMirror-selectedtext, -.cm-s-tiddlywiki .CodeMirror-selected, -.cm-s-tiddlywiki .CodeMirror-line::selection, -.cm-s-tiddlywiki .CodeMirror-line > span::selection, -.cm-s-tiddlywiki .CodeMirror-line > span > span::selection, -.cm-s-tiddlywiki .CodeMirror-line::-moz-selection, -.cm-s-tiddlywiki .CodeMirror-line > span::-moz-selection, -.cm-s-tiddlywiki .CodeMirror-line > span > span::-moz-selection { background: <<colour selection-background>>; } -.cm-s-tiddlywiki span.cm-comment { color: <<colour muted-foreground>>; font-style:italic; font-weight:normal; } +.cm-s-tiddlywiki span.cm-comment { color: #586e75; font-style:italic; font-weight:normal; } .cm-s-tiddlywiki .CodeMirror-activeline-background, .cm-s-tiddlywiki .CodeMirror-activeline-gutter .CodeMirror-linenumber { background: rgba(127,127,127,0.2); } .cm-s-tiddlywiki span.cm-matchhighlight { color: <<colour background>>; background-color: <<colour primary>>; font-weight: normal;} .cm-s-tiddlywiki .CodeMirror-widget { @@ -100,3 +102,4 @@ name: tiddlywiki .cm-s-tiddlywiki .CodeMirror-nonmatchingbracket { color: #dc322f; } .cm-s-tiddlywiki .cm-searching { background: rgba(243, 155, 53, .3); outline: 1px solid #F39B35; } <<set-fat-cursor-background>> +<<set-selection-background>> From bfc4b447dab6dfdb68c3f0d31ed1f630e68ebe39 Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 5 Dec 2020 17:38:08 +0100 Subject: [PATCH 123/124] Add selection-background/foreground to GruvboxDark and Nord palettes (#5204) * Update GruvBoxDark.tid * Update Nord.tid * Update Nord.tid * Update Nord.tid * Update Nord.tid --- core/palettes/GruvBoxDark.tid | 2 ++ core/palettes/Nord.tid | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/core/palettes/GruvBoxDark.tid b/core/palettes/GruvBoxDark.tid index a8db56807..d53ec61e0 100644 --- a/core/palettes/GruvBoxDark.tid +++ b/core/palettes/GruvBoxDark.tid @@ -60,6 +60,8 @@ pre-border: #504945 primary: #d79921 select-tag-background: #665c54 select-tag-foreground: <<colour foreground>> +selection-background: #458588 +selection-foreground: <<colour foreground>> sidebar-button-foreground: <<colour page-background>> sidebar-controls-foreground-hover: #7c6f64 sidebar-controls-foreground: #504945 diff --git a/core/palettes/Nord.tid b/core/palettes/Nord.tid index 73174a4d6..21d93a759 100644 --- a/core/palettes/Nord.tid +++ b/core/palettes/Nord.tid @@ -11,9 +11,7 @@ alert-highlight: #B48EAD alert-muted-foreground: #4C566A background: #3b4252 blockquote-bar: <<colour muted-foreground>> -button-background: #4C566A -button-foreground: #D8DEE9 -button-border: transparent +button-foreground: <<colour page-background>> code-background: #2E3440 code-border: #2E3440 code-foreground: #BF616A @@ -62,7 +60,9 @@ pre-border: #2E3440 primary: #5E81AC select-tag-background: #3b4252 select-tag-foreground: <<colour foreground>> -sidebar-button-foreground: <<colour foreground>> +selection-background: #5E81AC +selection-foreground: <<colour foreground>> +sidebar-button-foreground: <<colour page-background>> sidebar-controls-foreground-hover: #D8DEE9 sidebar-controls-foreground: #4C566A sidebar-foreground-shadow: transparent From 396703c4784e0993e1b85ae7cdb39d4aa4c80d4a Mon Sep 17 00:00:00 2001 From: Simon Huber <huber.simon@protonmail.com> Date: Sat, 5 Dec 2020 18:38:39 +0100 Subject: [PATCH 124/124] An even faster version of the TagPickerTagTemplate (#5207) --- core/ui/TagPickerTagTemplate.tid | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/ui/TagPickerTagTemplate.tid b/core/ui/TagPickerTagTemplate.tid index 43406a565..0588a0698 100644 --- a/core/ui/TagPickerTagTemplate.tid +++ b/core/ui/TagPickerTagTemplate.tid @@ -13,5 +13,11 @@ title: $:/core/ui/TagPickerTagTemplate <$action-setfield $tiddler=<<refreshTitle>> text="yes"/> </$list> <<actions>> -<$macrocall $name="tag-pill-inner" tag=<<currentTiddler>> icon={{{ [<tag>get[icon]] }}} colour={{{ [<tag>get[color]] }}} fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>> element-tag="span" element-attributes="" actions=<<actions>>/> +<$set name="backgroundColor" value={{!!color}}> +<$wikify name="foregroundColor" text="""<$macrocall $name="contrastcolour" target={{!!color}} fallbackTarget=<<fallbackTarget>> colourA=<<colourA>> colourB=<<colourB>>/>"""> +<span class="tc-tag-label tc-btn-invisible" style=<<tag-pill-styles>>> +<$transclude tiddler={{!!icon}}/><$view field="title" format="text"/> +</span> +</$wikify> +</$set> </$button>