yaml-language-server
Version:
225 lines • 9.4 kB
JavaScript
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define(["require", "exports", "yaml"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BlockStringRewriter = void 0;
const yaml_1 = require("yaml");
class BlockStringRewriter {
constructor(indentation, maxLineLength) {
this.indentation = indentation;
this.maxLineLength = maxLineLength;
}
writeFoldedBlockScalar(node) {
if (node.type !== 'QUOTE_DOUBLE' && node.type !== 'QUOTE_SINGLE') {
return null;
}
const stringContent = node.value;
const currentIndentNum = node.srcToken.indent;
let indentText = this.indentation;
for (let i = 0; i < currentIndentNum / this.indentation.length; i++) {
indentText += this.indentation;
}
const lines = [];
const splitLines = stringContent.split('\n');
for (const line of splitLines) {
let remainder = line;
slicing: while (remainder.length > this.maxLineLength) {
let location = this.maxLineLength;
// for folded strings, space characters are placed in place of each line break
// so we need to split the line on a space and remove the space
while (!/ /.test(remainder.charAt(location))) {
location++;
if (location >= remainder.length) {
break slicing;
}
}
// however any leading space characters will be taken literally and also a newline gets inserted
// so instead we need them to be trailing
// which could be problematic as "trim trailing whitespace" is a common setting to have enabled but oh well
while (/ /.test(remainder.charAt(location))) {
location++;
if (location >= remainder.length) {
break slicing;
}
}
const head = remainder.substring(0, location - 1 /* -1 to remove one space character, which is automatically added between lines */);
lines.push(head);
remainder = remainder.substring(location);
}
lines.push(remainder);
lines.push('\n');
}
// no trailng newline
lines.pop();
for (let i = 1; i < lines.length;) {
if (/^[ \t]+$/.test(lines[i])) {
if (lines[i - 1] === '\n' || lines[i - 1] === '') {
lines.splice(i - 1, 1);
// i now points to the next entry,
// i - 1 points to the current entry
// so do not increment i
continue;
}
else {
// It's unconvertable, give up
// Explanation:
// If the line of text is only whitespace and it's more whitespace than the expected indentation,
// then it's joined with the previous line with a real newline instead of a space.
// This means an extra newline gets inserted if we change nothing.
// We can avoid this if the preceeding text is a newline,
// because we can just remove the preceeding newline to compensate,
// but if it's not we are SOL
return null;
}
}
i++;
}
let blockScalarHeaderSource = '>';
if (lines[lines.length - 1] !== '\n' && lines[lines.length - 1] !== '') {
blockScalarHeaderSource += '-';
}
else if ((lines[lines.length - 2] === '\n' || lines[lines.length - 2] === '') &&
lines[lines.length - 3] !== '\n' &&
lines[lines.length - 3] !== '') {
lines.splice(lines.length - 2, 2);
}
else {
blockScalarHeaderSource += '+';
}
if (/ /.test(stringContent.charAt(0))) {
blockScalarHeaderSource += `${indentText.length}`;
}
const newProps = lines.flatMap((line) => {
if (line === '\n' || line === '') {
// newlines can be represented as two newlines in folded blocks
return [
{
type: 'newline',
indent: 0,
offset: node.srcToken.offset,
source: '\n',
},
];
}
return [
{
type: 'newline',
indent: 0,
offset: node.srcToken.offset,
source: '\n',
},
{
type: 'space',
indent: 0,
offset: node.srcToken.offset,
source: indentText,
},
{
type: 'scalar',
indent: 0,
offset: node.srcToken.offset,
source: line,
},
];
});
newProps.unshift({
type: 'block-scalar-header',
source: blockScalarHeaderSource,
offset: node.srcToken.offset,
indent: 0,
});
const blockString = {
type: 'block-scalar',
offset: node.srcToken.offset,
indent: 0,
source: '',
props: newProps,
};
return yaml_1.CST.stringify(blockString);
}
writeLiteralBlockScalar(node) {
if (node.type !== 'QUOTE_DOUBLE' && node.type !== 'QUOTE_SINGLE') {
return null;
}
const stringContent = node.value;
// I don't think it's worth it
if (stringContent.indexOf('\n') < 0) {
return null;
}
const currentIndentNum = node.srcToken.indent;
let indentText = this.indentation;
for (let i = 0; i < currentIndentNum / this.indentation.length; i++) {
indentText += this.indentation;
}
const lines = stringContent.split('\n');
let blockScalarHeaderSource = '|';
if (lines[lines.length - 1] !== '\n' && lines[lines.length - 1] !== '') {
blockScalarHeaderSource += '-';
}
else if (lines[lines.length - 2] !== '\n' && lines[lines.length - 2] !== '') {
lines.splice(lines.length - 1, 1);
}
else {
blockScalarHeaderSource += '+';
}
if (/ /.test(stringContent.charAt(0))) {
blockScalarHeaderSource += `${indentText.length}`;
}
const newProps = lines.flatMap((line) => {
if (line === '') {
return [
{
type: 'newline',
indent: 0,
offset: node.srcToken.offset,
source: '\n',
},
];
}
return [
{
type: 'newline',
indent: 0,
offset: node.srcToken.offset,
source: '\n',
},
{
type: 'space',
indent: 0,
offset: node.srcToken.offset,
source: indentText,
},
{
type: 'scalar',
indent: 0,
offset: node.srcToken.offset,
source: line,
},
];
});
newProps.unshift({
type: 'block-scalar-header',
source: blockScalarHeaderSource,
offset: node.srcToken.offset,
indent: 0,
});
const blockString = {
type: 'block-scalar',
offset: node.srcToken.offset,
indent: 0,
source: '',
props: newProps,
};
return yaml_1.CST.stringify(blockString);
}
}
exports.BlockStringRewriter = BlockStringRewriter;
});
//# sourceMappingURL=block-string-rewriter.js.map