Support markdown makeup in claim description #242
10 changed files with 77 additions and 8 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -17,3 +17,5 @@ dist
|
|||
|
||||
build/daemon.zip
|
||||
.vimrc
|
||||
|
||||
ui/yarn.lock
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue