Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,3 @@ build/Release
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
lib
8 changes: 4 additions & 4 deletions dist/markdown-react.min.js

Large diffs are not rendered by default.

242 changes: 242 additions & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
'use strict';

var _extends = require('babel-runtime/helpers/extends')['default'];

var _objectWithoutProperties = require('babel-runtime/helpers/object-without-properties')['default'];

var _toConsumableArray = require('babel-runtime/helpers/to-consumable-array')['default'];

var _interopRequireDefault = require('babel-runtime/helpers/interop-require-default')['default'];

Object.defineProperty(exports, '__esModule', {
value: true
});

var _markdownIt = require('markdown-it');

var _markdownIt2 = _interopRequireDefault(_markdownIt);

var _react = require('react');

var _react2 = _interopRequireDefault(_react);

var _lodashLangIsPlainObject = require('lodash/lang/isPlainObject');

var _lodashLangIsPlainObject2 = _interopRequireDefault(_lodashLangIsPlainObject);

var _lodashObjectAssign = require('lodash/object/assign');

var _lodashObjectAssign2 = _interopRequireDefault(_lodashObjectAssign);

var _lodashCollectionReduce = require('lodash/collection/reduce');

var _lodashCollectionReduce2 = _interopRequireDefault(_lodashCollectionReduce);

var _lodashArrayZipObject = require('lodash/array/zipObject');

var _lodashArrayZipObject2 = _interopRequireDefault(_lodashArrayZipObject);

var _lodashCollectionSortBy = require('lodash/collection/sortBy');

var _lodashCollectionSortBy2 = _interopRequireDefault(_lodashCollectionSortBy);

var _lodashArrayCompact = require('lodash/array/compact');

var _lodashArrayCompact2 = _interopRequireDefault(_lodashArrayCompact);

var _lodashStringCamelCase = require('lodash/string/camelCase');

var _lodashStringCamelCase2 = _interopRequireDefault(_lodashStringCamelCase);

var _lodashLangIsString = require('lodash/lang/isString');

var _lodashLangIsString2 = _interopRequireDefault(_lodashLangIsString);

var DEFAULT_TAGS = {
'html': 'span'
};

var DEFAULT_RULES = {
image: function image(token, attrs, children) {
if (children.length) {
attrs = (0, _lodashObjectAssign2['default'])({}, attrs, { alt: children[0] });
}
return [[token.tag, attrs]];
},

codeInline: function codeInline(token, attrs) {
return [(0, _lodashArrayCompact2['default'])([token.tag, attrs, token.content])];
},

codeBlock: function codeBlock(token, attrs) {
return [['pre', (0, _lodashArrayCompact2['default'])([token.tag, attrs, token.content])]];
},

fence: function fence(token, attrs) {
if (token.info) {
var langName = token.info.trim().split(/\s+/g)[0];
attrs = (0, _lodashObjectAssign2['default'])({}, attrs, { 'data-language': langName });
}

return [['pre', (0, _lodashArrayCompact2['default'])([token.tag, attrs, token.content])]];
},

hardbreak: function hardbreak() {
return [['br']];
},

softbreak: function softbreak(token, attrs, children, options) {
return options.breaks ? [['br']] : '\n';
},

text: function text(token) {
return token.content;
},

htmlBlock: function htmlBlock(token) {
return token.content;
},

htmlInline: function htmlInline(token) {
return token.content;
},

inline: function inline(token, attrs, children) {
return children;
},

'default': function _default(token, attrs, children, options, getNext) {
if (token.nesting === 1 && token.hidden) {
return getNext();
}
/* plugin-related */
if (!token.tag) {
return token.content;
}
if (token.info) {
attrs = (0, _lodashObjectAssign2['default'])({}, attrs, { 'data-info': token.info.trim() });
}
/* plugin-related */
return [(0, _lodashArrayCompact2['default'])([token.tag, attrs].concat(token.nesting === 1 && getNext()))];
}
};

function convertTree(tokens, convertRules, options) {
function convertBranch(tkns, nested) {
var branch = [];

if (!nested) {
branch.push('html');
}

function getNext() {
return convertBranch(tkns, true);
}

var token = tkns.shift();
while (token && token.nesting !== -1) {
var attrs = token.attrs && (0, _lodashArrayZipObject2['default'])((0, _lodashCollectionSortBy2['default'])(token.attrs, 0));
var children = token.children && convertBranch(token.children.slice(), true);
var rule = convertRules[(0, _lodashStringCamelCase2['default'])(token.type)] || convertRules['default'];

branch = branch.concat(rule(token, attrs, children, options, getNext));
token = tkns.shift();
}
return branch;
}

return convertBranch(tokens, false);
}

function mdReactFactory() {
var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
var onIterate = options.onIterate;
var _options$tags = options.tags;
var tags = _options$tags === undefined ? DEFAULT_TAGS : _options$tags;
var presetName = options.presetName;
var markdownOptions = options.markdownOptions;
var _options$enableRules = options.enableRules;
var enableRules = _options$enableRules === undefined ? [] : _options$enableRules;
var _options$disableRules = options.disableRules;
var disableRules = _options$disableRules === undefined ? [] : _options$disableRules;
var _options$plugins = options.plugins;
var plugins = _options$plugins === undefined ? [] : _options$plugins;
var _options$onGenerateKey = options.onGenerateKey;
var onGenerateKey = _options$onGenerateKey === undefined ? function (tag, index) {
return 'mdrct-' + tag + '-' + index;
} : _options$onGenerateKey;

var rootElementProps = _objectWithoutProperties(options, ['onIterate', 'tags', 'presetName', 'markdownOptions', 'enableRules', 'disableRules', 'plugins', 'onGenerateKey']);

var md = (0, _markdownIt2['default'])(markdownOptions || presetName).enable(enableRules).disable(disableRules);

var convertRules = (0, _lodashObjectAssign2['default'])({}, DEFAULT_RULES, options.convertRules);

md = (0, _lodashCollectionReduce2['default'])(plugins, function (m, plugin) {
return plugin.plugin ? m.use.apply(m, [plugin.plugin].concat(_toConsumableArray(plugin.args))) : m.use(plugin);
}, md);

function renderChildren(tag) {
return tag !== 'img';
}

function iterateTree(tree) {
var level = arguments.length <= 1 || arguments[1] === undefined ? 0 : arguments[1];
var index = arguments.length <= 2 || arguments[2] === undefined ? 0 : arguments[2];

var tag = tree.shift();
var key = onGenerateKey(tag, index);

var props = tree.length && (0, _lodashLangIsPlainObject2['default'])(tree[0]) ? (0, _lodashObjectAssign2['default'])(tree.shift(), { key: key }) : { key: key };

if (level === 0) {
props = _extends({}, props, rootElementProps);
}

var children = tree.map(function (branch, idx) {
return Array.isArray(branch) ? iterateTree(branch, level + 1, idx) : branch;
});

tag = tags[tag] || tag;

if ((0, _lodashLangIsString2['default'])(props.style)) {
props.style = (0, _lodashArrayZipObject2['default'])(props.style.split(';').map(function (prop) {
return prop.split(':');
}).map(function (keyVal) {
return [(0, _lodashStringCamelCase2['default'])(keyVal[0].trim()), keyVal[1].trim()];
}));
}

return typeof onIterate === 'function' ? onIterate(tag, props, children, level) : _react2['default'].createElement(tag, props, renderChildren(tag) ? children : undefined);
}

return function (text) {
var tree = convertTree(md.parse(text, {}), convertRules, md.options);
return iterateTree(tree);
};
}

var MDReactComponent = function MDReactComponent(props) {
var text = props.text;

var propsWithoutText = _objectWithoutProperties(props, ['text']);

return mdReactFactory(propsWithoutText)(text);
};

MDReactComponent.propTypes = {
text: _react.PropTypes.string.isRequired,
onIterate: _react.PropTypes.func,
onGenerateKey: _react.PropTypes.func,
tags: _react.PropTypes.object,
presetName: _react.PropTypes.string,
markdownOptions: _react.PropTypes.object,
enableRules: _react.PropTypes.array,
disableRules: _react.PropTypes.array,
convertRules: _react.PropTypes.object,
plugins: _react.PropTypes.array,
className: _react.PropTypes.string
};

exports['default'] = MDReactComponent;
exports.mdReact = mdReactFactory;
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"webpack": "^1.8.11"
},
"peerDependencies": {
"react": ">=0.13.2"
"react": "0.14.x",
"react-dom" : "0.14.x"
},
"scripts": {
"test": "NODE_ENV=test ./node_modules/.bin/mocha --compilers js:babelhook --recursive --reporter spec --timeout 3000",
Expand Down
68 changes: 38 additions & 30 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,17 @@ function convertTree(tokens, convertRules, options) {
}

function mdReactFactory(options={}) {
const { onIterate, tags=DEFAULT_TAGS,
presetName, markdownOptions,
enableRules=[], disableRules=[], plugins=[],
onGenerateKey=(tag, index) => `mdrct-${tag}-${index}`,
className } = options;
const {
onIterate,
tags = DEFAULT_TAGS,
presetName,
markdownOptions,
enableRules = [],
disableRules = [],
plugins = [],
onGenerateKey = (tag, index) => `mdrct-${tag}-${index}`,
...rootElementProps
} = options;

let md = markdown(markdownOptions || presetName)
.enable(enableRules)
Expand All @@ -130,16 +136,20 @@ function mdReactFactory(options={}) {
md
);

function renderChildren(tag) {
return tag !== 'img';
}

function iterateTree(tree, level=0, index=0) {
let tag = tree.shift();
const key = onGenerateKey(tag, index);

const props = (tree.length && isPlainObject(tree[0])) ?
assign(tree.shift(), { key }) :
{ key };
let props = (tree.length && isPlainObject(tree[0])) ?
assign(tree.shift(), { key }) :
{ key };

if (level === 0 && className) {
props.className = className;
if (level === 0) {
props = { ...props, ...rootElementProps };
}

const children = tree.map(
Expand All @@ -160,7 +170,7 @@ function mdReactFactory(options={}) {

return (typeof onIterate === 'function') ?
onIterate(tag, props, children, level) :
React.createElement(tag, props, children);
React.createElement(tag, props, renderChildren(tag) ? children : undefined);
}

return function(text) {
Expand All @@ -169,26 +179,24 @@ function mdReactFactory(options={}) {
};
}

class MDReactComponent extends Component {
static propTypes = {
text: PropTypes.string.isRequired,
onIterate: PropTypes.func,
onGenerateKey: PropTypes.func,
tags: PropTypes.object,
presetName: PropTypes.string,
markdownOptions: PropTypes.object,
enableRules: PropTypes.array,
disableRules: PropTypes.array,
convertRules: PropTypes.object,
plugins: PropTypes.array,
className: PropTypes.string
}
const MDReactComponent = props => {
const { text, ...propsWithoutText } = props;
return mdReactFactory(propsWithoutText)(text);
};

render() {
const { text, ...props } = this.props;
return mdReactFactory(props)(text);
}
}
MDReactComponent.propTypes = {
text: PropTypes.string.isRequired,
onIterate: PropTypes.func,
onGenerateKey: PropTypes.func,
tags: PropTypes.object,
presetName: PropTypes.string,
markdownOptions: PropTypes.object,
enableRules: PropTypes.array,
disableRules: PropTypes.array,
convertRules: PropTypes.object,
plugins: PropTypes.array,
className: PropTypes.string
};

export default MDReactComponent;
export { mdReactFactory as mdReact };
Loading