From 5c80e3cdd716b4ad26ee6958c9137278530b7816 Mon Sep 17 00:00:00 2001
From: Alice Koreman <a.koreman@outlook.com>
Date: Wed, 25 Oct 2023 17:16:42 +0200
Subject: [PATCH] fix: improve yaml folding

---
 src/mode/folding/yaml.js | 90 ++++++++++++++++++++++++++++++++++++++++
 src/mode/yaml.js         |  2 +-
 2 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 src/mode/folding/yaml.js

diff --git a/src/mode/folding/yaml.js b/src/mode/folding/yaml.js
new file mode 100644
index 00000000000..a05d80773d4
--- /dev/null
+++ b/src/mode/folding/yaml.js
@@ -0,0 +1,90 @@
+"use strict";
+
+var oop = require("../../lib/oop");
+var BaseFoldMode = require("./fold_mode").FoldMode;
+var Range = require("../../range").Range;
+
+var FoldMode = exports.FoldMode = function() {};
+oop.inherits(FoldMode, BaseFoldMode);
+
+(function() {
+    this.getFoldWidgetRange = function(session, foldStyle, row) {
+        var re = /\S/;
+        var line = session.getLine(row);
+        var startLevel = line.search(re);
+        if (startLevel == -1)
+            return;
+
+        var startColumn = line.length;
+        var maxRow = session.getLength();
+        var startRow = row;
+        var endRow = row;
+
+        while (++row < maxRow) {
+            line = session.getLine(row);
+            var level = line.search(re);
+
+            if (level == -1 && row !== maxRow - 1) {
+                endRow = row;
+                break;
+            }
+
+            if ((level == -1 && row !== maxRow - 1) || line[level] == "-" || level > startLevel)
+                continue;
+
+            if (level <= startLevel) {
+                var token = session.getTokenAt(row, 0);
+                if (!token || token.type !== "string")
+                    break;
+            }
+        }
+
+        if (endRow > startRow) {
+            var endColumn = session.getLine(endRow).length;
+            return new Range(startRow, startColumn, endRow, endColumn);
+        }
+    };
+
+    // must return "" if there's no fold, to enable caching
+    this.getFoldWidget = function(session, foldStyle, row) {
+        var line = session.getLine(row);
+        var indent = line.search(/[^\s]/);
+        var next = session.getLine(row + 1);
+        var prev = session.getLine(row - 1);
+        var prevIndent = prev.search(/[^\s]/);
+        var nextIndent = next.search(/[^\s]/);
+
+        var lineStartsWithDash = line.search(/^\-/) !== -1;
+
+        if (indent == -1) {
+            session.foldWidgets[row - 1] = prevIndent!= -1 && prevIndent < nextIndent ? "start" : "";
+            return "";
+        }
+
+        // documentation comments
+        if (prevIndent == -1) {
+            if (indent == nextIndent && line[indent] == "#" && next[indent] == "#") {
+                session.foldWidgets[row - 1] = "";
+                session.foldWidgets[row + 1] = "";
+                return "start";
+            }
+        } else if (prevIndent == indent && line[indent] == "#" && prev[indent] == "#") {
+            if (session.getLine(row - 2).search(/[^\s]/) == -1) {
+                session.foldWidgets[row - 1] = "start";
+                session.foldWidgets[row + 1] = "";
+                return "";
+            }
+        }
+
+        if (prevIndent!= -1 && (prevIndent < indent || lineStartsWithDash))
+            session.foldWidgets[row - 1] = "start";
+        else
+            session.foldWidgets[row - 1] = "";
+
+        if (indent < nextIndent)
+            return "start";
+        else
+            return "";
+    };
+
+}).call(FoldMode.prototype);
diff --git a/src/mode/yaml.js b/src/mode/yaml.js
index 78293f0e055..cf4fd985d69 100644
--- a/src/mode/yaml.js
+++ b/src/mode/yaml.js
@@ -4,7 +4,7 @@ var oop = require("../lib/oop");
 var TextMode = require("./text").Mode;
 var YamlHighlightRules = require("./yaml_highlight_rules").YamlHighlightRules;
 var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent;
-var FoldMode = require("./folding/coffee").FoldMode;
+var FoldMode = require("./folding/yaml").FoldMode;
 var WorkerClient = require("../worker/worker_client").WorkerClient;
 
 var Mode = function() {