Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
3 changes: 1 addition & 2 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
[ignore]
.*node_modules/babel.*
.*node_modules/fbjs.*

[include]

[libs]

[options]
esproposal.class_static_fields=enable
module.system=haste
suppress_type=$FlowIssue
suppress_comment=\\(.\\|\n\\)*\\$FlowIssue
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
test/*.txt text eol=lf
2 changes: 2 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
ISC License

Copyright (c) 2016, Simon Sturmer <sstur@me.com>

Permission to use, copy, modify, and/or distribute this software for any
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ This project is still under development. If you want to help out, please open an

## License

This software is [BSD Licensed](/LICENSE).
This software is [ISC Licensed](/LICENSE).
3 changes: 3 additions & 0 deletions flow-typed/globals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @flow
/* eslint-disable no-unused-vars */
declare var __DEV__: bool;
51 changes: 33 additions & 18 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
{
"name": "draft-js-export-markdown",
"version": "0.1.2",
"version": "0.2.1",
"description": "DraftJS: Export ContentState to Markdown",
"main": "lib/main.js",
"scripts": {
"build": "babel src --ignore '_*' --out-dir lib",
"lint": "eslint --max-warnings 0 .",
"typecheck": "flow",
"prepublish": "npm run build",
"test": "npm run lint && npm run test-src",
"test-src": "mocha"
"test": "npm run lint && npm run typecheck && npm run test-src",
"test-src": "mocha src/__tests__/*.js src/**/__tests__/*.js"
},
"dependencies": {
"draft-js-tools": "^0.1.2"
"draft-js-utils": "^0.1.5"
},
"peerDependencies": {
"draft-js": ">=0.5.0",
"immutable": "3.x.x"
},
"devDependencies": {
"babel-core": "^6.7.2",
"babel-eslint": "^5.0.0",
"babel-plugin-transform-class-properties": "^6.6.0",
"babel-preset-es2015": "^6.6.0",
"babel-cli": "^6.9.0",
"babel-core": "^6.9.0",
"babel-eslint": "^7.0.0",
"babel-plugin-transform-class-properties": "^6.9.0",
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-2": "^6.5.0",
"draft-js": "^0.2.2",
"eslint": "2.2.0",
"eslint-plugin-babel": "^3.1.0",
"eslint-plugin-flow-vars": "^0.2.1",
"eslint-plugin-react": "^4.2.1",
"expect": "^1.15.2",
"immutable": "^3.7.6",
"mocha": "^2.4.5",
"react": "^0.14.7",
"react-dom": "^0.14.7"
"eslint": "^3.7.1",
"eslint-plugin-babel": "^3.2.0",
"eslint-plugin-flow-vars": "^0.5.0",
"eslint-plugin-react": "^6.3.0",
"expect": "^1.20.1",
"flow-bin": "^0.32.0",
"mocha": "^3.1.0",
"react": "^15.0.2",
"react-dom": "^15.0.2"
},
"repository": {
"type": "git",
Expand All @@ -40,6 +45,16 @@
"export-markdown"
],
"author": "sstur@me.com",
"contributors": [
{
"name": "Freddy Harris",
"url": "https://github.com/Freddy03h"
},
{
"name": "Simon Sturmer",
"url": "https://github.com/sstur"
}
],
"license": "ISC",
"bugs": {
"url": "https://github.com/sstur/draft-js-export-markdown/issues"
Expand Down
6 changes: 2 additions & 4 deletions src/__tests__/stateToMarkdown-test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* @flow */
const {describe, it} = global;
import expect from 'expect';
import {ContentState, convertFromRaw} from 'draft-js';
import {convertFromRaw} from 'draft-js';
import stateToMarkdown from '../stateToMarkdown';
import fs from 'fs';
import {join} from 'path';
Expand All @@ -26,9 +26,7 @@ describe('stateToMarkdown', () => {
testCases.forEach((testCase) => {
let {description, state, markdown} = testCase;
it(`should render ${description}`, () => {
let contentState = ContentState.createFromBlockArray(
convertFromRaw(state)
);
let contentState = convertFromRaw(state);
expect(stateToMarkdown(contentState)).toBe(markdown + '\n');
});
});
Expand Down
28 changes: 24 additions & 4 deletions src/stateToMarkdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
BLOCK_TYPE,
ENTITY_TYPE,
INLINE_STYLE,
} from 'draft-js-tools';
} from 'draft-js-utils';
import {Entity} from 'draft-js';

import type {ContentState, ContentBlock} from 'draft-js';
Expand Down Expand Up @@ -63,6 +63,21 @@ class MarkupGenerator {
this.output.push('### ' + this.renderBlockContent(block) + '\n');
break;
}
case BLOCK_TYPE.HEADER_FOUR: {
this.insertLineBreaks(1);
this.output.push('#### ' + this.renderBlockContent(block) + '\n');
break;
}
case BLOCK_TYPE.HEADER_FIVE: {
this.insertLineBreaks(1);
this.output.push('##### ' + this.renderBlockContent(block) + '\n');
break;
}
case BLOCK_TYPE.HEADER_SIX: {
this.insertLineBreaks(1);
this.output.push('###### ' + this.renderBlockContent(block) + '\n');
break;
}
case BLOCK_TYPE.UNORDERED_LIST_ITEM: {
let blockDepth = block.getDepth();
let lastBlock = this.getLastBlock();
Expand All @@ -80,7 +95,7 @@ class MarkupGenerator {
this.insertLineBreaks(1);
}
}
let indent = ' '.repeat(block.depth * 2);
let indent = ' '.repeat(block.depth * 4);
this.output.push(
indent + '- ' + this.renderBlockContent(block) + '\n'
);
Expand All @@ -100,7 +115,7 @@ class MarkupGenerator {
this.insertLineBreaks(1);
}
}
let indent = ' '.repeat(blockDepth * 2);
let indent = ' '.repeat(blockDepth * 4);
// TODO: figure out what to do with two-digit numbers
let count = this.getListItemCount(block) % 10;
this.output.push(
Expand Down Expand Up @@ -193,7 +208,7 @@ class MarkupGenerator {
content = `++${content}++`;
}
if (style.has(ITALIC)) {
content = `_${content}_`;
content = `*${content}*`;
}
if (style.has(STRIKETHROUGH)) {
// TODO: encode `~`?
Expand All @@ -210,6 +225,11 @@ class MarkupGenerator {
let url = data.url || '';
let title = data.title ? ` "${escapeTitle(data.title)}"` : '';
return `[${content}](${encodeURL(url)}${title})`;
} else if (entity != null && entity.getType() === ENTITY_TYPE.IMAGE) {
let data = entity.getData();
let src = data.src || '';
let alt = data.alt ? ` "${escapeTitle(data.alt)}"` : '';
return `![${alt}](${encodeURL(src)})`;
} else {
return content;
}
Expand Down
1 change: 0 additions & 1 deletion test/mocha.opts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
--compilers js:babel-core/register
src/__tests__/*.js src/**/__tests__/*.js
8 changes: 8 additions & 0 deletions test/test-cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ _**BoldItalic**_
{"entityMap":{},"blocks":[{"key":"9nc73","text":"BoldItalic","type":"unstyled","depth":0,"inlineStyleRanges":[{"offset":4,"length":6,"style":"BOLD"},{"offset":0,"length":4,"style":"ITALIC"}],"entityRanges":[]}]}
_Bold_**Italic**

>> Image with alt
{"entityMap":{"0":{"type":"IMAGE","mutability":"MUTABLE","data":{"src":"/a.jpg","alt":"x"}}},"blocks":[{"key":"f131g","text":"Hello World.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":5,"length":1,"key":0}]}]}
Hello![ "x"](/a.jpg)World.

>> Image with empty alt
{"entityMap":{"0":{"type":"IMAGE","mutability":"MUTABLE","data":{"src":"/a.jpg","alt":""}}},"blocks":[{"key":"f131g","text":"Hello World.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":5,"length":1,"key":0}]}]}
Hello![](/a.jpg)World.

>> Link without title
{"entityMap":{"0":{"type":"LINK","mutability":"MUTABLE","data":{"url":"/a","foo":"x"}}},"blocks":[{"key":"f131g","text":"Hello World.","type":"unstyled","depth":0,"inlineStyleRanges":[],"entityRanges":[{"offset":6,"length":5,"key":0}]}]}
Hello [World](/a).
Expand Down