Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 2x 2x 2x 1x | /**
* Format Provider Resolver
*
* Resolves the appropriate format provider (YAML, TOML, JSON) based on
* file extension, file content, or first line of frontmatter.
*/
import fs from 'fs-extra';
import path from 'path';
import { JsonFormatProvider } from './format-providers/json-format-provider.js';
import { TomlFormatProvider } from './format-providers/toml-format-provider.js';
import { YamlFormatProvider } from './format-providers/yaml-format-provider.js';
/**
* FormatProviderResolver manages format providers and resolves the correct one
* based on various inputs (file path, content, first line, etc.)
*/
export class FormatProviderResolver {
_formats;
_exts;
constructor() {
const yaml = new YamlFormatProvider();
this._formats = {
json: new JsonFormatProvider(),
toml: new TomlFormatProvider(),
yaml: yaml,
yml: yaml, // yml is an alias for yaml
};
this._exts = Object.keys(this._formats);
}
/**
* Get the default format provider (YAML)
*/
getDefaultFormat() {
return this._formats[this.getDefaultFormatExt()];
}
/**
* Get the default format extension
*/
getDefaultFormatExt() {
return 'yaml';
}
/**
* Read a specific line from a file (async)
* @private
*/
_getFileLinePromise(filename, line_no) {
return new Promise((resolve, reject) => {
const stream = fs.createReadStream(filename, {
flags: 'r',
encoding: 'utf8',
mode: 0o666,
});
let fileData = '';
stream.on('data', (data) => {
fileData += data.toString();
// The next lines should be improved
const lines = fileData.split('\n');
if (lines.length >= line_no + 1) {
stream.destroy();
resolve(lines[line_no]);
}
});
stream.on('error', (e) => {
reject(e);
});
stream.on('end', () => {
resolve(undefined);
});
});
}
/**
* Resolve format provider by matching the first line of frontmatter
*/
resolveForMdFirstLine(line) {
if (line === undefined)
return undefined;
for (let i = 0; i < this._exts.length; i++) {
const f = this._formats[this._exts[i]];
if (f.matchContentFirstLine(line)) {
return f;
}
}
return undefined;
}
/**
* Resolve format provider based on file path extension
*/
resolveForFilePath(filePath) {
if (filePath === undefined)
return undefined;
const ext = path.extname(filePath).replace('.', '');
return this.resolveForExtension(ext);
}
/**
* Resolve format provider by analyzing file content string
*/
resolveForMdFileString(fileContent) {
if (fileContent === undefined)
return null;
const firstLine = fileContent.split('\n', 1)[0];
return this.resolveForMdFirstLine(firstLine) ?? null;
}
/**
* Resolve format provider by reading file and checking first line
*/
async resolveForMdFilePromise(filePath) {
const line = await this._getFileLinePromise(filePath, 0);
if (line != null) {
return this.resolveForMdFirstLine(line);
}
return null;
}
/**
* Resolve format provider by file extension
*/
resolveForExtension(ext) {
if (ext === undefined)
return undefined;
ext = ext.toLowerCase();
return this._formats[ext];
}
/**
* Get all supported format extensions
*/
allFormatsExt() {
return this._exts;
}
}
/**
* Default singleton instance
*/
export default new FormatProviderResolver();
|