[help]Nodejs中如何令长字符串的yaml输出可读性更好

[help]Nodejs中如何令长字符串的yaml输出可读性更好

var book={
‘title’:‘THE PROBLEMS OF PHILOSOPHY’,
‘author’:‘Bertrand Russell’,
‘preface’:‘In the following pages I have confined myself in the main to those problems of philosophy in regard to which I thought it possible to say something positive and constructive, since merely negative criticism seemed out of place…’
}

一般的yaml库格式化输出的结果大致都类似于

title: THE PROBLEMS OF PHILOSOPHY
author: Bertrand Russell
preface: "In the following pages I have confined myself in the main to those problems of philosophy in regard to which I thought it possible to say something positive and constructive, since merely negative criticism seemed out of place..."

这种双引号前后一闭合,管你多长的字符通通放一行,中间还可能插入各种恶心转义字符例如\"\n,可读性真的很差。python/node.js/ruby/java的yaml库都翻了遍,python比较接近*1。各种库对输入的parse/load都很强大,但是反过来输出yaml时,就开始变成各种反人类亲机器的文件格式,完全抛弃yaml的可读性。

求推荐yaml库,可通过简单的设置或者扩展,自定义长字符串以区块的形式的输出,多于80列则自动换行,如下

title: THE PROBLEMS OF PHILOSOPHY
author: Bertrand Russell
preface: >
    In the following pages I have confined myself in the main to those problems of 
    philosophy in regard to which I thought it possible to say something positive 
    and constructive, since merely negative criticism seemed out of place...

或者是扩展性比较高的格式化输出工具。


2 回复

在 Node.js 中处理 YAML 文件时,确实会遇到长字符串输出不友好、难以阅读的问题。为了解决这个问题,可以使用 js-yaml 库,并结合一些额外的配置来改善输出的可读性。

推荐的 YAML 库

首先,我们需要安装 js-yaml 库,这是一个流行的 YAML 解析和序列化库。

npm install js-yaml

示例代码

接下来,我们可以通过以下代码来实现长字符串以区块形式输出,并且当长度超过指定列数时自动换行。

const yaml = require('js-yaml');
const fs = require('fs');

// 定义书的信息
const book = {
    title: 'THE PROBLEMS OF PHILOSOPHY',
    author: 'Bertrand Russell',
    preface: `In the following pages I have confined myself in the main to those problems of philosophy in regard to which I thought it possible to say something positive and constructive, since merely negative criticism seemed out of place...`
};

// 自定义流式序列化器
function serializeWithBlockStyle(doc) {
    const output = [];
    doc.stringify = function (object, ctx, onComment, onChompKeep) {
        ctx.flowLevel = -1; // 禁用流式输出
        return this.DEFAULT_STRINGIFY(object, ctx, onComment, onChompKeep);
    };
    const originalStringify = doc.stringify;
    doc.stringify = function (object, ctx, onComment, onChompKeep) {
        if (typeof object === 'string' && object.length > 80) { // 如果字符串长度超过80列
            ctx.style = '|'; // 使用块风格
        }
        return originalStringify.apply(this, arguments);
    };
    output.push(doc.dump());
    return output.join('\n');
}

// 将对象转换为 YAML 字符串
const yamlContent = serializeWithBlockStyle(yaml.Dumper(book));

// 输出到文件
fs.writeFileSync('book.yaml', yamlContent);

console.log(yamlContent);

代码解释

  1. 引入依赖:我们首先引入 js-yamlfs 模块。
  2. 定义数据:定义一个包含书信息的对象 book
  3. 自定义序列化器:创建一个 serializeWithBlockStyle 函数,该函数通过修改 Dumperstringify 方法来控制输出格式。
    • ctx.flowLevel = -1:禁用流式输出。
    • if (typeof object === 'string' && object.length > 80):如果字符串长度超过80列,则使用块风格(style: '|')。
  4. 生成 YAML 字符串:使用 yaml.Dumper 和自定义的序列化器将对象转换为 YAML 字符串。
  5. 写入文件:将生成的 YAML 字符串写入文件 book.yaml

通过这种方式,我们可以确保长字符串以区块形式输出,并且在超过指定列数时自动换行,从而提高可读性。


要解决这个问题,可以使用 js-yaml 库,并通过配置使其支持长字符串的区块(block)形式输出。以下是如何实现这一点的步骤:

  1. 安装 js-yaml 库:

    npm install js-yaml
    
  2. 使用 js-yaml 进行配置并输出 YAML 文件:

const yaml = require('js-yaml');
const fs = require('fs');

// 自定义字符串样式
function longStringReplacer(tag, ctx) {
    if (ctx.tag === '!str' && ctx.value.length > 80) {
        return { value: ctx.value.replace(/\n/g, '\n '), type: 'block', style: '>' };
    }
    return null;
}

// 注册自定义样式
yaml.DEFAULT_SAFE_SCHEMA.addTag({
    tag: 'tag:yaml.org,2002:str',
    format: 'long-string',
    resolve: function (arg) {
        return arg;
    },
    represent: longStringReplacer
});

// 原始数据
var book = {
    'title': 'THE PROBLEMS OF PHILOSOPHY',
    'author': 'Bertrand Russell',
    'preface': 'In the following pages I have confined myself in the main to those problems of philosophy in regard to which I thought it possible to say something positive and constructive, since merely negative criticism seemed out of place...'
};

// 输出 YAML 文件
const output = yaml.dump(book, { lineWidth: 80 });
fs.writeFileSync('book.yaml', output);

这段代码首先安装了 js-yaml 库,然后定义了一个自定义的字符串样式替换器 longStringReplacer,用于处理长度超过80个字符的字符串。接下来,我们注册了这个自定义的字符串样式到 js-yaml 的默认安全模式中。

最后,我们使用 yaml.dump 方法将对象转换为 YAML 字符串,并将其写入文件。通过设置 lineWidth: 80,我们确保长字符串会在超过80列时自动换行。

这样,生成的 YAML 文件将具有更好的可读性。

回到顶部