@codemirror/language 6.8.0 → 6.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/dist/index.cjs +39 -24
- package/dist/index.d.cts +15 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +39 -24
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
## 6.9.0 (2023-08-16)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Make `getIndentation` return null, rather than 0, when there is no syntax tree available.
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
The new `preparePlaceholder` option to `codeFolding` makes it possible to display contextual information in a folded range placeholder widget.
|
|
10
|
+
|
|
1
11
|
## 6.8.0 (2023-06-12)
|
|
2
12
|
|
|
3
13
|
### New features
|
package/dist/index.cjs
CHANGED
|
@@ -865,7 +865,7 @@ function getIndentation(context, pos) {
|
|
|
865
865
|
return result;
|
|
866
866
|
}
|
|
867
867
|
let tree = syntaxTree(context.state);
|
|
868
|
-
return tree ? syntaxIndentation(context, tree, pos) : null;
|
|
868
|
+
return tree.length >= pos ? syntaxIndentation(context, tree, pos) : null;
|
|
869
869
|
}
|
|
870
870
|
/**
|
|
871
871
|
Create a change set that auto-indents all lines touched by the
|
|
@@ -1304,11 +1304,16 @@ const foldState = state.StateField.define({
|
|
|
1304
1304
|
update(folded, tr) {
|
|
1305
1305
|
folded = folded.map(tr.changes);
|
|
1306
1306
|
for (let e of tr.effects) {
|
|
1307
|
-
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to))
|
|
1308
|
-
|
|
1309
|
-
|
|
1307
|
+
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to)) {
|
|
1308
|
+
let { preparePlaceholder } = tr.state.facet(foldConfig);
|
|
1309
|
+
let widget = !preparePlaceholder ? foldWidget :
|
|
1310
|
+
view.Decoration.replace({ widget: new PreparedFoldWidget(preparePlaceholder(tr.state, e.value)) });
|
|
1311
|
+
folded = folded.update({ add: [widget.range(e.value.from, e.value.to)] });
|
|
1312
|
+
}
|
|
1313
|
+
else if (e.is(unfoldEffect)) {
|
|
1310
1314
|
folded = folded.update({ filter: (from, to) => e.value.from != from || e.value.to != to,
|
|
1311
1315
|
filterFrom: e.value.from, filterTo: e.value.to });
|
|
1316
|
+
}
|
|
1312
1317
|
}
|
|
1313
1318
|
// Clear folded ranges that cover the selection head
|
|
1314
1319
|
if (tr.selection) {
|
|
@@ -1485,6 +1490,7 @@ const foldKeymap = [
|
|
|
1485
1490
|
];
|
|
1486
1491
|
const defaultConfig = {
|
|
1487
1492
|
placeholderDOM: null,
|
|
1493
|
+
preparePlaceholder: null,
|
|
1488
1494
|
placeholderText: "…"
|
|
1489
1495
|
};
|
|
1490
1496
|
const foldConfig = state.Facet.define({
|
|
@@ -1499,27 +1505,36 @@ function codeFolding(config) {
|
|
|
1499
1505
|
result.push(foldConfig.of(config));
|
|
1500
1506
|
return result;
|
|
1501
1507
|
}
|
|
1508
|
+
function widgetToDOM(view, prepared) {
|
|
1509
|
+
let { state } = view, conf = state.facet(foldConfig);
|
|
1510
|
+
let onclick = (event) => {
|
|
1511
|
+
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1512
|
+
let folded = findFold(view.state, line.from, line.to);
|
|
1513
|
+
if (folded)
|
|
1514
|
+
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1515
|
+
event.preventDefault();
|
|
1516
|
+
};
|
|
1517
|
+
if (conf.placeholderDOM)
|
|
1518
|
+
return conf.placeholderDOM(view, onclick, prepared);
|
|
1519
|
+
let element = document.createElement("span");
|
|
1520
|
+
element.textContent = conf.placeholderText;
|
|
1521
|
+
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1522
|
+
element.title = state.phrase("unfold");
|
|
1523
|
+
element.className = "cm-foldPlaceholder";
|
|
1524
|
+
element.onclick = onclick;
|
|
1525
|
+
return element;
|
|
1526
|
+
}
|
|
1502
1527
|
const foldWidget = view.Decoration.replace({ widget: new class extends view.WidgetType {
|
|
1503
|
-
toDOM(view) {
|
|
1504
|
-
let { state } = view, conf = state.facet(foldConfig);
|
|
1505
|
-
let onclick = (event) => {
|
|
1506
|
-
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1507
|
-
let folded = findFold(view.state, line.from, line.to);
|
|
1508
|
-
if (folded)
|
|
1509
|
-
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1510
|
-
event.preventDefault();
|
|
1511
|
-
};
|
|
1512
|
-
if (conf.placeholderDOM)
|
|
1513
|
-
return conf.placeholderDOM(view, onclick);
|
|
1514
|
-
let element = document.createElement("span");
|
|
1515
|
-
element.textContent = conf.placeholderText;
|
|
1516
|
-
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1517
|
-
element.title = state.phrase("unfold");
|
|
1518
|
-
element.className = "cm-foldPlaceholder";
|
|
1519
|
-
element.onclick = onclick;
|
|
1520
|
-
return element;
|
|
1521
|
-
}
|
|
1528
|
+
toDOM(view) { return widgetToDOM(view, null); }
|
|
1522
1529
|
} });
|
|
1530
|
+
class PreparedFoldWidget extends view.WidgetType {
|
|
1531
|
+
constructor(value) {
|
|
1532
|
+
super();
|
|
1533
|
+
this.value = value;
|
|
1534
|
+
}
|
|
1535
|
+
eq(other) { return this.value == other.value; }
|
|
1536
|
+
toDOM(view) { return widgetToDOM(view, this.value); }
|
|
1537
|
+
}
|
|
1523
1538
|
const foldGutterDefaults = {
|
|
1524
1539
|
openText: "⌄",
|
|
1525
1540
|
closedText: "›",
|
|
@@ -2489,7 +2504,7 @@ function createTokenType(extra, tagStr) {
|
|
|
2489
2504
|
return type.id;
|
|
2490
2505
|
}
|
|
2491
2506
|
function docID(data) {
|
|
2492
|
-
let type = common.NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)] });
|
|
2507
|
+
let type = common.NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true });
|
|
2493
2508
|
typeArray.push(type);
|
|
2494
2509
|
return type;
|
|
2495
2510
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -761,17 +761,30 @@ interface FoldConfig {
|
|
|
761
761
|
position of folded code. The `onclick` argument is the default
|
|
762
762
|
click event handler, which toggles folding on the line that
|
|
763
763
|
holds the element, and should probably be added as an event
|
|
764
|
-
handler to the returned element.
|
|
764
|
+
handler to the returned element. If
|
|
765
|
+
[`preparePlaceholder`](https://codemirror.net/6/docs/ref/#language.FoldConfig.preparePlaceholder)
|
|
766
|
+
is given, its result will be passed as 3rd argument. Otherwise,
|
|
767
|
+
this will be null.
|
|
765
768
|
|
|
766
769
|
When this option isn't given, the `placeholderText` option will
|
|
767
770
|
be used to create the placeholder element.
|
|
768
771
|
*/
|
|
769
|
-
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void) => HTMLElement) | null;
|
|
772
|
+
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void, prepared: any) => HTMLElement) | null;
|
|
770
773
|
/**
|
|
771
774
|
Text to use as placeholder for folded text. Defaults to `"…"`.
|
|
772
775
|
Will be styled with the `"cm-foldPlaceholder"` class.
|
|
773
776
|
*/
|
|
774
777
|
placeholderText?: string;
|
|
778
|
+
/**
|
|
779
|
+
Given a range that is being folded, create a value that
|
|
780
|
+
describes it, to be used by `placeholderDOM` to render a custom
|
|
781
|
+
widget that, for example, indicates something about the folded
|
|
782
|
+
range's size or type.
|
|
783
|
+
*/
|
|
784
|
+
preparePlaceholder?: (state: EditorState, range: {
|
|
785
|
+
from: number;
|
|
786
|
+
to: number;
|
|
787
|
+
}) => any;
|
|
775
788
|
}
|
|
776
789
|
/**
|
|
777
790
|
Create an extension that configures code folding.
|
package/dist/index.d.ts
CHANGED
|
@@ -761,17 +761,30 @@ interface FoldConfig {
|
|
|
761
761
|
position of folded code. The `onclick` argument is the default
|
|
762
762
|
click event handler, which toggles folding on the line that
|
|
763
763
|
holds the element, and should probably be added as an event
|
|
764
|
-
handler to the returned element.
|
|
764
|
+
handler to the returned element. If
|
|
765
|
+
[`preparePlaceholder`](https://codemirror.net/6/docs/ref/#language.FoldConfig.preparePlaceholder)
|
|
766
|
+
is given, its result will be passed as 3rd argument. Otherwise,
|
|
767
|
+
this will be null.
|
|
765
768
|
|
|
766
769
|
When this option isn't given, the `placeholderText` option will
|
|
767
770
|
be used to create the placeholder element.
|
|
768
771
|
*/
|
|
769
|
-
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void) => HTMLElement) | null;
|
|
772
|
+
placeholderDOM?: ((view: EditorView, onclick: (event: Event) => void, prepared: any) => HTMLElement) | null;
|
|
770
773
|
/**
|
|
771
774
|
Text to use as placeholder for folded text. Defaults to `"…"`.
|
|
772
775
|
Will be styled with the `"cm-foldPlaceholder"` class.
|
|
773
776
|
*/
|
|
774
777
|
placeholderText?: string;
|
|
778
|
+
/**
|
|
779
|
+
Given a range that is being folded, create a value that
|
|
780
|
+
describes it, to be used by `placeholderDOM` to render a custom
|
|
781
|
+
widget that, for example, indicates something about the folded
|
|
782
|
+
range's size or type.
|
|
783
|
+
*/
|
|
784
|
+
preparePlaceholder?: (state: EditorState, range: {
|
|
785
|
+
from: number;
|
|
786
|
+
to: number;
|
|
787
|
+
}) => any;
|
|
775
788
|
}
|
|
776
789
|
/**
|
|
777
790
|
Create an extension that configures code folding.
|
package/dist/index.js
CHANGED
|
@@ -861,7 +861,7 @@ function getIndentation(context, pos) {
|
|
|
861
861
|
return result;
|
|
862
862
|
}
|
|
863
863
|
let tree = syntaxTree(context.state);
|
|
864
|
-
return tree ? syntaxIndentation(context, tree, pos) : null;
|
|
864
|
+
return tree.length >= pos ? syntaxIndentation(context, tree, pos) : null;
|
|
865
865
|
}
|
|
866
866
|
/**
|
|
867
867
|
Create a change set that auto-indents all lines touched by the
|
|
@@ -1300,11 +1300,16 @@ const foldState = /*@__PURE__*/StateField.define({
|
|
|
1300
1300
|
update(folded, tr) {
|
|
1301
1301
|
folded = folded.map(tr.changes);
|
|
1302
1302
|
for (let e of tr.effects) {
|
|
1303
|
-
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to))
|
|
1304
|
-
|
|
1305
|
-
|
|
1303
|
+
if (e.is(foldEffect) && !foldExists(folded, e.value.from, e.value.to)) {
|
|
1304
|
+
let { preparePlaceholder } = tr.state.facet(foldConfig);
|
|
1305
|
+
let widget = !preparePlaceholder ? foldWidget :
|
|
1306
|
+
Decoration.replace({ widget: new PreparedFoldWidget(preparePlaceholder(tr.state, e.value)) });
|
|
1307
|
+
folded = folded.update({ add: [widget.range(e.value.from, e.value.to)] });
|
|
1308
|
+
}
|
|
1309
|
+
else if (e.is(unfoldEffect)) {
|
|
1306
1310
|
folded = folded.update({ filter: (from, to) => e.value.from != from || e.value.to != to,
|
|
1307
1311
|
filterFrom: e.value.from, filterTo: e.value.to });
|
|
1312
|
+
}
|
|
1308
1313
|
}
|
|
1309
1314
|
// Clear folded ranges that cover the selection head
|
|
1310
1315
|
if (tr.selection) {
|
|
@@ -1481,6 +1486,7 @@ const foldKeymap = [
|
|
|
1481
1486
|
];
|
|
1482
1487
|
const defaultConfig = {
|
|
1483
1488
|
placeholderDOM: null,
|
|
1489
|
+
preparePlaceholder: null,
|
|
1484
1490
|
placeholderText: "…"
|
|
1485
1491
|
};
|
|
1486
1492
|
const foldConfig = /*@__PURE__*/Facet.define({
|
|
@@ -1495,27 +1501,36 @@ function codeFolding(config) {
|
|
|
1495
1501
|
result.push(foldConfig.of(config));
|
|
1496
1502
|
return result;
|
|
1497
1503
|
}
|
|
1504
|
+
function widgetToDOM(view, prepared) {
|
|
1505
|
+
let { state } = view, conf = state.facet(foldConfig);
|
|
1506
|
+
let onclick = (event) => {
|
|
1507
|
+
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1508
|
+
let folded = findFold(view.state, line.from, line.to);
|
|
1509
|
+
if (folded)
|
|
1510
|
+
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1511
|
+
event.preventDefault();
|
|
1512
|
+
};
|
|
1513
|
+
if (conf.placeholderDOM)
|
|
1514
|
+
return conf.placeholderDOM(view, onclick, prepared);
|
|
1515
|
+
let element = document.createElement("span");
|
|
1516
|
+
element.textContent = conf.placeholderText;
|
|
1517
|
+
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1518
|
+
element.title = state.phrase("unfold");
|
|
1519
|
+
element.className = "cm-foldPlaceholder";
|
|
1520
|
+
element.onclick = onclick;
|
|
1521
|
+
return element;
|
|
1522
|
+
}
|
|
1498
1523
|
const foldWidget = /*@__PURE__*/Decoration.replace({ widget: /*@__PURE__*/new class extends WidgetType {
|
|
1499
|
-
toDOM(view) {
|
|
1500
|
-
let { state } = view, conf = state.facet(foldConfig);
|
|
1501
|
-
let onclick = (event) => {
|
|
1502
|
-
let line = view.lineBlockAt(view.posAtDOM(event.target));
|
|
1503
|
-
let folded = findFold(view.state, line.from, line.to);
|
|
1504
|
-
if (folded)
|
|
1505
|
-
view.dispatch({ effects: unfoldEffect.of(folded) });
|
|
1506
|
-
event.preventDefault();
|
|
1507
|
-
};
|
|
1508
|
-
if (conf.placeholderDOM)
|
|
1509
|
-
return conf.placeholderDOM(view, onclick);
|
|
1510
|
-
let element = document.createElement("span");
|
|
1511
|
-
element.textContent = conf.placeholderText;
|
|
1512
|
-
element.setAttribute("aria-label", state.phrase("folded code"));
|
|
1513
|
-
element.title = state.phrase("unfold");
|
|
1514
|
-
element.className = "cm-foldPlaceholder";
|
|
1515
|
-
element.onclick = onclick;
|
|
1516
|
-
return element;
|
|
1517
|
-
}
|
|
1524
|
+
toDOM(view) { return widgetToDOM(view, null); }
|
|
1518
1525
|
} });
|
|
1526
|
+
class PreparedFoldWidget extends WidgetType {
|
|
1527
|
+
constructor(value) {
|
|
1528
|
+
super();
|
|
1529
|
+
this.value = value;
|
|
1530
|
+
}
|
|
1531
|
+
eq(other) { return this.value == other.value; }
|
|
1532
|
+
toDOM(view) { return widgetToDOM(view, this.value); }
|
|
1533
|
+
}
|
|
1519
1534
|
const foldGutterDefaults = {
|
|
1520
1535
|
openText: "⌄",
|
|
1521
1536
|
closedText: "›",
|
|
@@ -2485,7 +2500,7 @@ function createTokenType(extra, tagStr) {
|
|
|
2485
2500
|
return type.id;
|
|
2486
2501
|
}
|
|
2487
2502
|
function docID(data) {
|
|
2488
|
-
let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)] });
|
|
2503
|
+
let type = NodeType.define({ id: typeArray.length, name: "Document", props: [languageDataProp.add(() => data)], top: true });
|
|
2489
2504
|
typeArray.push(type);
|
|
2490
2505
|
return type;
|
|
2491
2506
|
}
|