Support markdown makeup in claim description #242

Closed
longle255 wants to merge 11 commits from claim-desc-markdown-support into master
10 changed files with 77 additions and 8 deletions

2
.gitignore vendored
View file

@ -17,3 +17,5 @@ dist
build/daemon.zip
.vimrc
ui/yarn.lock

View file

@ -8,7 +8,10 @@ Web UI version numbers should always match the corresponding version of LBRY App
## [Unreleased]
### Added
* Support markdown makeup in claim description
* State is persisted through app close and re-open, resulting in faster opens
*
### Changed
* Upgraded to lbry daemon 0.13, including updating API signatures

View file

@ -1,5 +1,7 @@
import React from "react";
import ReactDOMServer from "react-dom/server";
import lbry from "../lbry.js";
import ReactMarkdown from "react-markdown";
//component/icon.js
export class Icon extends React.PureComponent {
@ -42,6 +44,40 @@ export class TruncatedText extends React.PureComponent {
}
}
export class TruncatedMarkdown extends React.PureComponent {
static propTypes = {
lines: React.PropTypes.number,
};
static defaultProps = {
lines: null,
};
transformMarkdown(text) {
// render markdown to html string then trim html tag
let htmlString = ReactDOMServer.renderToStaticMarkup(
<ReactMarkdown source={this.props.children} />
);
var txt = document.createElement("textarea");
txt.innerHTML = htmlString;
return txt.value.replace(/<(?:.|\n)*?>/gm, "");
}
render() {
let content = this.props.children && typeof this.props.children === "string"
? this.transformMarkdown(this.props.children)
: this.props.children;
return (
<span
className="truncated-text"
style={{ WebkitLineClamp: this.props.lines }}
>
{content}
</span>
);
}
}
export class BusyMessage extends React.PureComponent {
static propTypes = {
message: React.PropTypes.string,

View file

@ -2,7 +2,12 @@ import React from "react";
import lbry from "lbry.js";
import lbryuri from "lbryuri.js";
import Link from "component/link";
import { Thumbnail, TruncatedText, Icon } from "component/common";
import {
Thumbnail,
TruncatedText,
Icon,
TruncatedMarkdown,
} from "component/common";
import FilePrice from "component/filePrice";
import UriIndicator from "component/uriIndicator";
@ -86,7 +91,7 @@ class FileCard extends React.PureComponent {
style={{ backgroundImage: "url('" + metadata.thumbnail + "')" }}
/>}
<div className="card__content card__subtext card__subtext--two-lines">
<TruncatedText lines={2}>{description}</TruncatedText>
<TruncatedMarkdown lines={2}>{description}</TruncatedMarkdown>
</div>
</Link>
{obscureNsfw && this.state.hovered

View file

@ -3,7 +3,11 @@ import lbry from "lbry.js";
import lbryuri from "lbryuri.js";
import Link from "component/link";
import FileActions from "component/fileActions";
import { Thumbnail, TruncatedText } from "component/common.js";
import {
Thumbnail,
TruncatedText,
TruncatedMarkdown,
} from "component/common.js";
import FilePrice from "component/filePrice";
import UriIndicator from "component/uriIndicator";
@ -117,9 +121,9 @@ class FileTile extends React.PureComponent {
<h3><TruncatedText lines={1}>{title}</TruncatedText></h3>
</div>
<div className="card__content card__subtext">
<TruncatedText lines={3}>
<TruncatedMarkdown lines={3}>
{description}
</TruncatedText>
</TruncatedMarkdown>
</div>
</div>
</div>

View file

@ -1,6 +1,8 @@
import React from "react";
import FileSelector from "./file-selector.js";
import { Icon } from "./common.js";
import SimpleMDE from "react-simplemde-editor";
import style from "react-simplemde-editor/dist/simplemde.min.css";
var formFieldCounter = 0,
formFieldFileSelectorTypes = ["file", "directory"],
@ -38,6 +40,9 @@ export class FormField extends React.PureComponent {
} else if (this.props.type == "text-number") {
this._element = "input";
this._type = "text";
} else if (this.props.type == "SimpleMDE") {
this._element = SimpleMDE;
this._type = "textarea";
} else if (formFieldFileSelectorTypes.includes(this.props.type)) {
this._element = "input";
this._type = "hidden";
@ -81,6 +86,8 @@ export class FormField extends React.PureComponent {
getValue() {
if (this.props.type == "checkbox") {
return this.refs.field.checked;
} else if (this.props.type == "SimpleMDE") {
return this.refs.field.simplemde.value();
} else {
return this.refs.field.value;
}
@ -106,7 +113,6 @@ export class FormField extends React.PureComponent {
delete otherProps.className;
delete otherProps.postfix;
delete otherProps.prefix;
const element = (
<this._element
id={elementId}

View file

@ -1,4 +1,5 @@
import React from "react";
import ReactMarkdown from "react-markdown";
import lbry from "lbry.js";
import lbryuri from "lbryuri.js";
import Video from "component/video";
@ -118,7 +119,11 @@ class FilePage extends React.PureComponent {
</div>
</div>
<div className="card__content card__subtext card__subtext card__subtext--allow-newlines">
{metadata && metadata.description}
<ReactMarkdown
source={(metadata && metadata.description) || ""}
escapeHtml={true}
disallowedTypes={["Heading", "HtmlInline", "HtmlBlock"]}
/>
</div>
</div>
{metadata

View file

@ -520,7 +520,7 @@ class PublishPage extends React.PureComponent {
<div className="card__content">
<FormRow
label={__("Description")}
type="textarea"
type="SimpleMDE"
ref="meta_description"
name="description"
placeholder={__("Description of your content")}

View file

@ -31,8 +31,10 @@
"rc-progress": "^2.0.6",
"react": "^15.4.0",
"react-dom": "^15.4.0",
"react-markdown": "^2.5.0",
"react-modal": "^1.5.2",
"react-redux": "^5.0.3",
"react-simplemde-editor": "^3.6.11",
"redux": "^3.6.0",
"redux-action-buffer": "^1.1.0",
"redux-logger": "^3.0.1",
@ -53,6 +55,7 @@
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babel-preset-stage-2": "^6.18.0",
"css-loader": "^0.28.4",
"eslint": "^3.10.2",
"eslint-config-airbnb": "^13.0.0",
"eslint-loader": "^1.6.1",
@ -64,6 +67,7 @@
"lint-staged": "^3.6.0",
"node-sass": "^3.13.0",
"prettier": "^1.4.2",
"style-loader": "^0.18.2",
"webpack": "^2.6.1",
"webpack-dev-server": "^2.4.4",
"webpack-notifier": "^1.5.0",

View file

@ -163,4 +163,8 @@ input[type="text"].input-copyable {
}
.form-field__helper {
color: $color-help;
}
.form-field__input.form-field__input-SimpleMDE .CodeMirror-scroll {
height: auto;
}