sharec-utils
Version:
Common utilities
130 lines (109 loc) • 3.07 kB
JavaScript
// @ts-check
const { EOL } = require('os')
const get = require('lodash.get')
const detectIndent = require('detect-indent')
const minimatch = require('minimatch')
const { basename } = require('./path')
const eolRe = new RegExp(`${EOL}$`)
/**
* @typedef {import('./index').FormattingRules} FormattingRules
* @typedef {import('./index').MappedFormattingRules} MappedFormattingRules
*/
/**
* Returns true if given string contains tab indent
* @param {string} str
* @returns {boolean}
*/
const hasTabsIndent = (str) => detectIndent(str).type === 'tab'
/**
* Returns true if given string containse space indent
* @param {string} str
* @returns {boolean}
*/
const hasSpacesIndent = (str) => detectIndent(str).type === 'space'
/**
* Returns true if given string contains empty line at the end
* @param {string} str
* @returns {boolean}
*/
const hasEOF = (str) => eolRe.test(str)
/**
* Cuts off EOL in the end of the file
* @param {string} str
* @returns {string}
*/
const cutEOF = (str) => str.replace(eolRe, '')
/**
* Replaces all indents in string by tabs
* @param {string} [str = '']
* @returns {string}
*/
const indentWithTab = (str = '') => {
const { type, indent } = detectIndent(str)
if (type !== 'space') return str
return str.replace(new RegExp(indent, 'gm'), '\t')
}
/**
* Replaces all indents in string by spaces with given size
* @param {string} [str = '']
* @param {number} [size = 2]
* @returns {string}
*/
const indentWithSpace = (str = '', size = 2) => {
const { indent } = detectIndent(str)
const newIndent = Array(size).fill(' ').join('')
return str.replace(new RegExp(indent, 'gm'), newIndent)
}
/**
* Formats string (probably file's content) with given formatting options
* @param {Object} params
* @param {string} params.filename
* @param {string} params.content
* @param {FormattingRules} [params.rules]
* @returns {string}
*/
const applyFormat = ({ filename, content, rules }) => {
const indentType = get(rules, 'indentType', 'space')
const indentSize = get(rules, 'indentSize', 2)
const eof = get(rules, 'eof', true)
const isYaml = filename && /\.ya?ml/.test(filename)
let result = content
switch (true) {
case indentType === 'tab' && !isYaml:
result = indentWithTab(result)
break
case indentType === 'space' || isYaml:
result = indentWithSpace(result, indentSize)
break
case eof && !hasEOF(content):
result += EOL
break
default:
break
}
return result
}
/**
* @param {MappedFormattingRules} formats
* @param {string} filename
* @returns {FormattingRules|null}
*/
const getFormatByFilename = (formats, filename) => {
if (formats['*']) return formats['*']
const formatKey = Object.keys(formats).find((key) => {
const fileBasename = basename(filename)
return minimatch(fileBasename, key)
})
if (!formatKey) return null
return formats[formatKey]
}
module.exports = {
hasSpacesIndent,
hasTabsIndent,
hasEOF,
cutEOF,
indentWithSpace,
indentWithTab,
applyFormat,
getFormatByFilename,
}