Utilities to write codemods for config files (JSON, YAML, INI, Markdown, etc.). Can be used to make tasks for Mrm .
Example# Add ESLint to your project:
Copy const { json , lines , packageJson , install } = require ( 'mrm-core' ) ;
module . exports = function ( config ) {
const preset = config ( 'preset' , 'tamia' ) ;
const packages = [ 'eslint' , ` eslint-config- ${ preset } ` ] ;
const eslintrc = json ( '.eslintrc' ) ;
if ( ! eslintrc . get ( 'extends' ) . startsWith ( preset ) ) {
eslintrc . set ( 'extends' , preset ) . save ( ) ;
}
lines ( '.eslintignore' )
. add ( 'node_modules' )
. save ( ) ;
const pkg = packageJson ( )
. setScript ( 'lint' , 'eslint . --fix' )
. setScript ( 'pretest' , 'npm run line' )
. save ( ) ;
install ( packages ) ;
} ;
module . exports . description = 'Adds ESLint with a custom preset' ;
Read more in the docs , and this task is already included by default.
You can find more examples in my dotfiles repository .
You don’t have to use mrm-core with mrm, you can run this tasks from your own code:
Copy const get = require ( 'lodash/get' ) ;
const addEslint = require ( './tasks/eslint' ) ;
const config = {
preset : 'airbnb'
} ;
const getConfig = ( prop , defaultValue ) =>
get ( config , prop , defaultValue ) ;
addEslint ( getConfig ) ;
Installation# API# Work with files# Do not overwrite original files, unless you want to. All functions (except getters) can be chained. save()
will create file if it doesn’t exist or update it with new data.save()
will write file to disk only if the new content is different from the original file.save()
will try to keep formatting (indentation, end of file new line) of the original file or use style from EditorConfig. JSON# API:
Copy const { json } = require ( 'mrm-core' ) ;
const file = json ( 'file name' , { default : 'values' } ) ;
file . exists ( ) ;
file . get ( ) ;
file . get ( 'key.subkey' , 'default value' ) ;
file . set ( 'key.subkey' , 'value' ) ;
file . set ( { key : value } ) ;
file . unset ( 'key.subkey' ) ;
file . merge ( { key : value } ) ;
file . save ( ) ;
file . delete ( ) ;
Example:
Copy json ( '.eslintrc' )
. merge ( {
extends : 'eslint-config-recommended'
} )
. save ( ) ;
YAML# API:
Copy const { yaml } = require ( 'mrm-core' ) ;
const file = yaml (
'file name' ,
{ default : 'values' } ,
{ version : '1.2' }
) ;
file . exists ( ) ;
file . get ( ) ;
file . get ( 'key.subkey' , 'default value' ) ;
file . set ( 'key.subkey' , 'value' ) ;
file . set ( { key : value } ) ;
file . unset ( 'key.subkey' ) ;
file . merge ( { key : value } ) ;
file . save ( ) ;
file . delete ( ) ;
Example:
Copy yaml ( '.travis.yml' )
. set ( 'language' , 'node_js' )
. set ( 'node_js' , [ 4 , 6 ] )
. save ( ) ;
INI# API:
Copy const { ini } = require ( 'mrm-core' ) ;
const file = ini ( 'file name' , 'comment' ) ;
file . exists ( ) ;
file . get ( ) ;
file . get ( 'section name' ) ;
file . set ( 'section name' , { key : value } ) ;
file . unset ( 'section name' ) ;
file . save ( ) ;
file . save ( { withSpaces : false } ) ;
file . delete ( ) ;
Example:
Copy const { ini } = require ( 'mrm-core' ) ;
ini ( '.editorconfig' , 'editorconfig.org' )
. set ( '_global' , { root : true } )
. set ( '*' , {
indent_style : 'tab' ,
end_of_line : 'lf'
} )
. save ( ) ;
Result:
Copy # editorconfig.org
root = true
[*]
indent_style = tab
end_of_line = lf
New line separated text files# API:
Copy const { lines } = require ( 'mrm-core' ) ;
const file = lines ( 'file name' , [ 'default' , 'values' ] ) ;
file . exists ( ) ;
file . get ( ) ;
file . set ( [ 'line 1' , 'line 2' , 'line 3' ] ) ;
file . add ( 'new' ) ;
file . add ( [ 'new' , 'lines' ] ) ;
file . remove ( 'new' ) ;
file . remove ( [ 'new' , 'lines' ] ) ;
file . save ( ) ;
file . delete ( ) ;
Example:
Copy lines ( '.eslintignore' )
. add ( 'node_modules' )
. save ( ) ;
Markdown# Note: use template
function to create Markdown files.
API:
Copy const { markdown } = require ( 'mrm-core' ) ;
const file = markdown ( 'file name' ) ;
file . exists ( ) ;
file . get ( ) ;
file . addBadge ( 'image URL' , 'link URL' , 'alt text' ) ;
file . removeBadge ( ( { imageUrl , linkUrl , altText } ) =>
imageUrl . startsWith ( 'https://travis-ci.org' )
) ;
file . save ( ) ;
file . delete ( ) ;
Example:
Copy const name = 'pizza' ;
markdown ( 'Readme.md' )
. addBadge (
` https://travis-ci.org/ ${ config ( 'github' ) } / ${ name } .svg ` ,
` https://travis-ci.org/ ${ config ( 'github' ) } / ${ name } ` ,
'Build Status'
)
. save ( ) ;
Plain text templates# Templates use ECMAScript template literals syntax.
API:
Copy const { template } = require ( 'mrm-core' ) ;
const file = template ( 'file name' , 'template file name' ) ;
file . exists ( ) ;
file . get ( ) ;
file . apply ( { key : 'value' } ) ;
file . save ( ) ;
file . delete ( ) ;
Example:
Copy template ( 'License.md' , path . join ( __dirname , 'License.md' ) )
. apply ( config ( ) , {
year : new Date ( ) . getFullYear ( )
} )
. save ( ) ;
Template:
Copy The MIT License
===============
Copyright ${year} ${name} (${url}), contributors
Permission is hereby granted, free of charge, to any person obtaining...
Special files# package.json# API:
Copy const { packageJson } = require ( 'mrm-core' ) ;
const file = packageJson ( { default : 'values' } ) ;
file . exists ( ) ;
file . get ( ) ;
file . getScript ( 'test' ) ;
file . getScript ( 'test' , 'eslint' ) ;
file . setScript ( 'test' , 'eslint --fix' ) ;
file . appendScript ( 'test' , 'eslint --fix' ) ;
file . prependScript ( 'test' , 'eslint --fix' ) ;
file . removeScript ( 'test' ) ;
file . removeScript ( /^mocha|ava$/ ) ;
file . removeScript ( 'test' , /b/ ) ;
file . save ( ) ;
file . delete ( ) ;
Note: subcommand is a command between &&
in an npm script. For example, prettier --write '**/*.js' && eslint . --fix
has two subcommands: prettier…
and eslint…
.
Example:
Copy packageJson ( )
. appendScript ( 'lint' , 'eslint . --ext .js --fix' )
. save ( ) ;
File system helpers# Copy const { copyFiles , deleteFiles , makeDirs } = require ( 'mrm-core' ) ;
copyFiles ( 'source dir' , 'file name' ) ;
copyFiles ( 'source dir' , [ 'file name 1' , 'file name 2' ] ) ;
copyFiles ( 'source dir' , 'file name' , { overwrite : false } ) ;
deleteFiles ( 'file name 1' ) ;
deleteFiles ( [ 'file name 1' , 'folder name 1' ] ) ;
makeDirs ( 'dir name' ) ;
makeDirs ( [ 'dir name 1' , 'dir name 2' ] ) ;
Install and uninstall npm, Yarn, or pnpm packages# Installs npm package(s) and saves them to package.json
if they aren’t installed yet or not satisfying range.
Copy const { install } = require ( 'mrm-core' ) ;
install ( 'eslint' ) ;
install ( [ 'tamia' , 'lodash' ] , { dev : false } ) ;
install ( { lodash : '^4.17.3' } ) ;
install ( [ 'lodash' ] , {
versions : { lodash : '^4.17.3' , other : '1.0.0' }
} ) ;
install ( [ 'github/repo' ] ) ;
Note: Works with all semver ranges, like 1.2.3
, ^1.2.0
or >=2
.
Uninstalls npm package(s) and removes them from package.json
:
Copy const { uninstall } = require ( 'mrm-core' ) ;
uninstall ( 'eslint' ) ;
uninstall ( [ 'tamia' , 'lodash' ] , { dev : false } ) ;
To use Yarn pass yarn: true
:
Copy const { install , uninstall } = require ( 'mrm-core' ) ;
uninstall ( [ 'eslint' ] , { yarn : true } ) ;
install ( [ 'standard' ] , { yarn : true } ) ;
With Yarn Berry, pass yarnBerry: true
and for pnpm, pass pnpm: true
.
Utilities# Infers style (indentation, new line at the end of file) from a source code or reads from the .editorconfig
file.
Copy const {
inferStyle ,
getStyleForFile ,
getIndent ,
format
} = require ( 'mrm-core' ) ;
inferStyle ( 'for (;;) {\n alert(1);\n}\n' ) ;
getStyleForFile ( 'test.js' ) ;
getIndent ( { indent_style : 'space' , indent_size : 2 } ) ;
format ( 'alert(1)\n' , { insert_final_newline : false } ) ;
Get file extensions list from a command like eslint . --fix --ext .js,.jsx
:
Copy const { getExtsFromCommand } = require ( 'mrm-core' ) ;
getExtsFromCommand ( ` eslint . --fix --ext .js,.jsx ` , 'ext' ) ;
getExtsFromCommand ( ` prettier --write '**/*.js' ` ) ;
Custom error class: MrmError
# Use this class to notify user about expected errors in your tasks. It will be printed without a stack trace and will abort task.
Copy const { MrmError } = require ( 'mrm-core' ) ;
if ( ! fs . existsSync ( '.travis.yml' ) ) {
throw new MrmError ( 'Run travis task first' ) ;
}