Skip to content
This repository has been archived by the owner on Aug 7, 2023. It is now read-only.

Commit

Permalink
Add support for ignore files, local remark-lint (#85)
Browse files Browse the repository at this point in the history
*   Update `remark` to 5.1.0;
*   Update `remark-lint` to 4.1.0;
*   Update `eslint`, `eslint-config-airbnb-base`
*   Use `unified-engine-atom` to deal with processing,
    this adds support for `.remarkignore` files, local remark-lint
    configuration files.

Closes GH-71 -  `remark-lint` specified in `.remarkrc` or
`package.json` files now precedes over the packaged `remark-lint`.

Closes GH-93 - Update `remark`;

Closes GH-92 - Update `remark-lint`;

Closes GH-76, closes GH-83 - Using `unified-engine`, which comes with
pretty JSON errors.
  • Loading branch information
wooorm committed Aug 10, 2016
1 parent 8c6fe5a commit 0152d8c
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 165 deletions.
22 changes: 17 additions & 5 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
git:
depth: 10
language: node_js
node_js:
- '4.0'
- '6.0'
os:
- linux
- osx
script: curl -s https://raw.githubusercontent.com/Arcanemagus/ci/atomlinter/build-package.sh
| sh
&& npm run lint
addons:
apt:
packages:
- build-essential
- git
- libgnome-keyring-dev
- fakeroot
branches:
only:
- master
notifications:
email:
on_success: never
on_failure: change
os: osx

script: 'curl -s https://raw.githubusercontent.com/atom/ci/master/build-package.sh | sh && npm run lint'
24 changes: 8 additions & 16 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,11 @@
version: "{build}"
os: Windows Server 2012 R2
branches:
only:
- master
platform: x64
environment:
APM_TEST_PACKAGES:
matrix:
- ATOM_CHANNEL: stable
- ATOM_CHANNEL: beta
build_script:
- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/Arcanemagus/ci/atomlinter/build-package.ps1'))
test: off
deploy: off

install:
- appveyor DownloadFile https://atom.io/download/windows -FileName AtomSetup.exe
- AtomSetup.exe /silent

build_script:
- cd %APPVEYOR_BUILD_FOLDER%
- SET PATH=%LOCALAPPDATA%\atom\bin;%PATH%
- apm clean
- apm install
- npm run lint
- apm test
15 changes: 6 additions & 9 deletions circle.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
machine:
node:
version: 4.4.7
dependencies:
pre:
# Force updating wget due to the current containers being too out of date
- sudo apt-get update
- sudo apt-get install wget
override:
- wget -O atom-amd64.deb https://atom.io/download/deb
# - sudo apt-get update # Cut out until wget is fixed on the containers
- curl -L https://atom.io/download/deb -o atom-amd64.deb
- sudo dpkg --install atom-amd64.deb || true
- sudo apt-get -f install -y
- atom -v
- apm -v
- sudo apt-get update
- sudo apt-get -f install
- apm install
test:
pre:
Expand Down
38 changes: 38 additions & 0 deletions lib/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use babel';
/**
* @author Titus Wormer
* @copyright 2016 Titus Wormer
* @license MIT
* @module atom:linter-markdown:config
* @fileoverview Configuration loaded into the engine.
*/

const path = require('path');

const local = require.resolve('remark-lint');

function configure(config) {
const current = config.plugins;
const next = {};
let found = false;

Object.keys(current).forEach(key => {
/* Turn off plug-ins. */
next[key] = false;

/* Keep remark-lint */
if (path.basename(key) === 'remark-lint') {
next[key] = current[key];
found = true;
}
});

/* Set local `remark-lint`. */
if (!found) {
next[local] = null;
}

return { plugins: next };
}

module.exports = configure;
142 changes: 15 additions & 127 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,144 +7,32 @@
* @fileoverview Linter.
*/

const Configuration = require('remark/lib/cli/configuration.js');
const loadPlugin = require('load-plugin');

/* Lazy loading these */
let remark = null;
let lint = null;
const path = require('path');
const engine = require('unified-engine-atom');

/**
* Linter-markdown.
*
* @return {LinterConfiguration}
*/
function linter() {
const CODE_EXPRESSION = /`([^`]+)`/g;

/**
* Transform a (stringified) vfile range to a linter
* nested-tuple.
*
* @param {Object} location - Positional information.
* @return {Array.<Array.<number>>} - Linter range.
*/
function toRange(location) {
const result = [[
Number(location.start.line) - 1,
Number(location.start.column) - 1
]];

result[1] = [
location.end.line ? Number(location.end.line) - 1 : result[0][0],
location.end.column ? Number(location.end.column) - 1 : result[0][1]
];

return result;
}

/**
* Transform a reason for warning from remark into
* pretty HTML.
*
* @param {string} reason - Messsage in plain-text.
* @return {string} - Messsage in HTML.
*/
function toHTML(reason) {
return reason.replace(CODE_EXPRESSION, '<code>$1</code>');
}

/**
* Transform VFile messages
* nested-tuple.
*
* @see https://github.com/wooorm/vfile#vfilemessage
*
* @param {VFileMessage} message - Virtual file error.
* @return {Object} - Linter error.
*/
function transform(message) {
const reason = toHTML(message.reason);

return {
type: 'Error',
html: `<span class="badge badge-flexible">${message.ruleId}</span> ${reason}`,
filePath: this.getPath(),
range: toRange(message.location)
};
}

/**
* Handle on-the-fly or on-save (depending on the
* global atom-linter settings) events. Yeah!
*
* Loads `remark` on first invocation.
*
* @see https://github.com/atom-community/linter/wiki/Linter-API#messages
*
* @param {AtomTextEditor} editor - Access to editor.
* @return {Promise.<Message, Error>} - Promise
* resolved with a list of linter-errors or an error.
*/
function onchange(editor) {
const filePath = editor.getPath();

if (!filePath) {
return Promise.resolve([]);
}

return new Promise((resolve, reject) => {
if (!remark) {
remark = require('remark');
lint = require('remark-lint');
}

const config = new Configuration({ detectRC: true });

config.getConfiguration(filePath, (err, conf) => {
let plugins;

if (err) {
return resolve([{
type: 'Error',
text: err.message,
filePath,
range: [[0, 0], [0, 0]]
}]);
}

plugins = conf.plugins || {};
plugins = plugins['remark-lint'] || plugins.lint || {};

plugins.external = (plugins.external || []).map(name =>
loadPlugin(name, {
prefix: 'remark-lint',
cwd: filePath,
global: true
})
);

/* Load processor for current path */

return remark()
.use(lint, plugins)
.process(editor.getText(), conf.settings, (err2, file) => {
if (err2) {
reject(err2);
}

resolve(file.messages.map(transform, editor));
});
});
});
}

return {
grammarScopes: ['source.gfm', 'source.pfm', 'text.md'],
grammarScopes: [
'source.gfm',
'source.pfm',
'text.md'
],
name: 'remark-lint',
scope: 'file',
lintOnFly: true,
lint: onchange
lint: engine({
processor: require('remark'),
rcName: '.remarkrc',
rcPath: path.resolve(__dirname, 'config.js'),
packageField: 'remarkConfig',
ignoreName: '.remarkignore',
pluginPrefix: 'remark'
})
};
}

Expand Down
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@
},
"dependencies": {
"atom-package-deps": "^4.0.1",
"load-plugin": "^1.0.0",
"remark": "4.2.2",
"remark-lint": "4.0.2"
"remark": "5.1.0",
"remark-lint": "4.1.0",
"unified-engine-atom": "^1.0.0"
},
"devDependencies": {
"eslint": "^2.9.0",
"eslint-config-airbnb-base": "^3.0.1",
"eslint-plugin-import": "^1.7.0"
"eslint": "^3.1.1",
"eslint-config-airbnb-base": "^5.0.0",
"eslint-plugin-import": "^1.10.2",
"remark-cli": "^1.0.0"
},
"eslintConfig": {
"rules": {
Expand Down
5 changes: 3 additions & 2 deletions spec/linter-markdown-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ describe('The remark-lint provider for Linter', () => {
expect(messages[0].type).toEqual('Error');
expect(messages[0].html).toBeDefined();
expect(messages[0].html).toEqual(
'<span class="badge badge-flexible">definition-case</span> ' +
'Do not use upper-case characters in definition labels'
'<span class="badge badge-flexible">remark-lint:' +
'definition-case</span> Do not use upper-case ' +
'characters in definition labels'
);
expect(messages[0].filePath).toBeDefined();
expect(messages[0].filePath).toMatch(/.+definition-case-invalid\.md$/);
Expand Down

0 comments on commit 0152d8c

Please sign in to comment.