Updating composer to fix line breaks and other rich text issues
• Updating: - composer to fix line breaks and other rich text issues
This commit is contained in:
parent
a9a566e211
commit
fc80955306
@ -264,30 +264,22 @@ export function submitCompose(group, replyToId = null, router, isStandalone) {
|
|||||||
|
|
||||||
let status = getState().getIn(['compose', 'text'], '');
|
let status = getState().getIn(['compose', 'text'], '');
|
||||||
let markdown = getState().getIn(['compose', 'markdown'], '');
|
let markdown = getState().getIn(['compose', 'markdown'], '');
|
||||||
const media = getState().getIn(['compose', 'media_attachments']);
|
const media = getState().getIn(['compose', 'media_attachments']);
|
||||||
|
|
||||||
// : hack :
|
const replacer = (match) => {
|
||||||
//Prepend http:// to urls in status that don't have protocol
|
|
||||||
status = `${status}`.replace(urlRegex, (match, a, b, c) =>{
|
|
||||||
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
||||||
//Make sure not a remote mention like @someone@somewhere.com
|
//Make sure not a remote mention like @someone@somewhere.com
|
||||||
if (!hasProtocol) {
|
if (!hasProtocol) {
|
||||||
if (status.indexOf(`@${match}`) > -1) return match
|
if (status.indexOf(`@${match}`) > -1) return match
|
||||||
}
|
}
|
||||||
return hasProtocol ? match : `http://${match}`
|
return hasProtocol ? match : `http://${match}`
|
||||||
})
|
|
||||||
markdown = !!markdown ? markdown.replace(urlRegex, (match) =>{
|
|
||||||
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
|
||||||
if (!hasProtocol) {
|
|
||||||
if (status.indexOf(`@${match}`) > -1) return match
|
|
||||||
}
|
|
||||||
return hasProtocol ? match : `http://${match}`
|
|
||||||
}) : undefined
|
|
||||||
|
|
||||||
if (status === markdown) {
|
|
||||||
markdown = undefined
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// : hack :
|
||||||
|
//Prepend http:// to urls in status that don't have protocol
|
||||||
|
status = `${status}`.replace(urlRegex, replacer)
|
||||||
|
markdown = !!markdown ? `${markdown}`.replace(urlRegex, replacer) : undefined
|
||||||
|
|
||||||
const inReplyToId = getState().getIn(['compose', 'in_reply_to'], null) || replyToId
|
const inReplyToId = getState().getIn(['compose', 'in_reply_to'], null) || replyToId
|
||||||
|
|
||||||
dispatch(submitComposeRequest());
|
dispatch(submitComposeRequest());
|
||||||
|
@ -36,6 +36,8 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
|||||||
onBlur: PropTypes.func,
|
onBlur: PropTypes.func,
|
||||||
textarea: PropTypes.bool,
|
textarea: PropTypes.bool,
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
|
isPro: PropTypes.bool,
|
||||||
|
isEdit: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -211,6 +213,8 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
|||||||
children,
|
children,
|
||||||
valueMarkdown,
|
valueMarkdown,
|
||||||
id,
|
id,
|
||||||
|
isPro,
|
||||||
|
isEdit,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const { suggestionsHidden } = this.state
|
const { suggestionsHidden } = this.state
|
||||||
@ -284,6 +288,8 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
|||||||
onBlur={this.onBlur}
|
onBlur={this.onBlur}
|
||||||
onPaste={this.onPaste}
|
onPaste={this.onPaste}
|
||||||
small={small}
|
small={small}
|
||||||
|
isEdit={isEdit}
|
||||||
|
isPro={isPro}
|
||||||
/>
|
/>
|
||||||
</Responsive>
|
</Responsive>
|
||||||
|
|
||||||
|
@ -18,6 +18,21 @@ import '!style-loader!css-loader!draft-js/dist/Draft.css'
|
|||||||
|
|
||||||
const cx = classNames.bind(_s)
|
const cx = classNames.bind(_s)
|
||||||
|
|
||||||
|
const markdownOptions = {
|
||||||
|
escapeMarkdownCharacters: false,
|
||||||
|
preserveNewlines: true,
|
||||||
|
remarkablePreset: 'commonmark',
|
||||||
|
remarkableOptions: {
|
||||||
|
disable: {
|
||||||
|
inline: ['links'],
|
||||||
|
block: ['table', 'heading'],
|
||||||
|
},
|
||||||
|
enable: {
|
||||||
|
inline: ['del', 'ins'],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const getBlockStyle = (block) => {
|
const getBlockStyle = (block) => {
|
||||||
switch (block.getType()) {
|
switch (block.getType()) {
|
||||||
case 'blockquote':
|
case 'blockquote':
|
||||||
@ -100,6 +115,8 @@ export default class Composer extends PureComponent {
|
|||||||
onBlur: PropTypes.func,
|
onBlur: PropTypes.func,
|
||||||
onPaste: PropTypes.func,
|
onPaste: PropTypes.func,
|
||||||
small: PropTypes.bool,
|
small: PropTypes.bool,
|
||||||
|
isPro: PropTypes.bool,
|
||||||
|
isEdit: PropTypes.bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -109,8 +126,8 @@ export default class Composer extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (this.props.valueMarkdown) {
|
if (this.props.valueMarkdown && this.props.isPro && this.props.isEdit) {
|
||||||
const rawData = markdownToDraft(this.props.valueMarkdown)
|
const rawData = markdownToDraft(this.props.valueMarkdown, markdownOptions)
|
||||||
const contentState = convertFromRaw(rawData)
|
const contentState = convertFromRaw(rawData)
|
||||||
const editorState = EditorState.createWithContent(contentState)
|
const editorState = EditorState.createWithContent(contentState)
|
||||||
|
|
||||||
@ -146,29 +163,23 @@ export default class Composer extends PureComponent {
|
|||||||
|
|
||||||
onChange = (editorState) => {
|
onChange = (editorState) => {
|
||||||
const content = editorState.getCurrentContent()
|
const content = editorState.getCurrentContent()
|
||||||
const plainText = content.getPlainText('\u0001')
|
// const plainText = content.getPlainText('\u0001')
|
||||||
|
|
||||||
this.setState({ editorState, plainText })
|
const blocks = convertToRaw(editorState.getCurrentContent()).blocks
|
||||||
|
const value = blocks.map(block => (!block.text.trim() && '') || block.text).join('\n')
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
editorState,
|
||||||
|
plainText: value,
|
||||||
|
})
|
||||||
|
|
||||||
const selectionState = editorState.getSelection()
|
const selectionState = editorState.getSelection()
|
||||||
const selectionStart = selectionState.getStartOffset()
|
const selectionStart = selectionState.getStartOffset()
|
||||||
|
|
||||||
const rawObject = convertToRaw(content)
|
const rawObject = convertToRaw(content)
|
||||||
const markdownString = draftToMarkdown(rawObject, {
|
const markdownString = this.props.isPro ? draftToMarkdown(rawObject,markdownOptions) : null
|
||||||
escapeMarkdownCharacters: false,
|
|
||||||
preserveNewlines: false,
|
|
||||||
remarkablePreset: 'commonmark',
|
|
||||||
remarkableOptions: {
|
|
||||||
disable: {
|
|
||||||
block: ['table']
|
|
||||||
},
|
|
||||||
enable: {
|
|
||||||
inline: ['del', 'ins'],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.props.onChange(null, plainText, markdownString, selectionStart)
|
this.props.onChange(null, value, markdownString, selectionStart)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleOnFocus = () => {
|
handleOnFocus = () => {
|
||||||
@ -227,6 +238,7 @@ export default class Composer extends PureComponent {
|
|||||||
disabled,
|
disabled,
|
||||||
placeholder,
|
placeholder,
|
||||||
small,
|
small,
|
||||||
|
isPro,
|
||||||
} = this.props
|
} = this.props
|
||||||
const { editorState } = this.state
|
const { editorState } = this.state
|
||||||
|
|
||||||
@ -247,7 +259,7 @@ export default class Composer extends PureComponent {
|
|||||||
<div className={_s.default}>
|
<div className={_s.default}>
|
||||||
|
|
||||||
{
|
{
|
||||||
!small &&
|
!small && isPro &&
|
||||||
<RichTextEditorBar
|
<RichTextEditorBar
|
||||||
editorState={editorState}
|
editorState={editorState}
|
||||||
onChange={this.onChange}
|
onChange={this.onChange}
|
||||||
|
@ -88,6 +88,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
reduxReplyToId: PropTypes.string,
|
reduxReplyToId: PropTypes.string,
|
||||||
hasPoll: PropTypes.bool,
|
hasPoll: PropTypes.bool,
|
||||||
selectedGifSrc: PropTypes.string,
|
selectedGifSrc: PropTypes.string,
|
||||||
|
isPro: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -244,6 +245,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
isChangingUpload,
|
isChangingUpload,
|
||||||
isSubmitting,
|
isSubmitting,
|
||||||
selectedGifSrc,
|
selectedGifSrc,
|
||||||
|
isPro,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
const disabled = isSubmitting
|
const disabled = isSubmitting
|
||||||
@ -322,6 +324,8 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
onPaste={onPaste}
|
onPaste={onPaste}
|
||||||
autoFocus={shouldAutoFocus}
|
autoFocus={shouldAutoFocus}
|
||||||
small={shouldCondense}
|
small={shouldCondense}
|
||||||
|
isPro={isPro}
|
||||||
|
isEdit={!!edit}
|
||||||
id='comment-composer'
|
id='comment-composer'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -414,6 +418,8 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
onPaste={onPaste}
|
onPaste={onPaste}
|
||||||
autoFocus={shouldAutoFocus}
|
autoFocus={shouldAutoFocus}
|
||||||
small={shouldCondense}
|
small={shouldCondense}
|
||||||
|
isPro={isPro}
|
||||||
|
isEdit={!!edit}
|
||||||
id='main-composer'
|
id='main-composer'
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -90,12 +90,13 @@ const mapStateToProps = (state, props) => {
|
|||||||
quoteOfId: state.getIn(['compose', 'quote_of_id']),
|
quoteOfId: state.getIn(['compose', 'quote_of_id']),
|
||||||
scheduledAt: state.getIn(['compose', 'scheduled_at']),
|
scheduledAt: state.getIn(['compose', 'scheduled_at']),
|
||||||
account: state.getIn(['accounts', me]),
|
account: state.getIn(['accounts', me]),
|
||||||
|
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||||
hasPoll: state.getIn(['compose', 'poll']),
|
hasPoll: state.getIn(['compose', 'poll']),
|
||||||
selectedGifSrc: state.getIn(['tenor', 'selectedGif', 'src']),
|
selectedGifSrc: state.getIn(['tenor', 'selectedGif', 'src']),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch, { reduxReplyToId, replyToId, isStandalone }) => ({
|
const mapDispatchToProps = (dispatch, { isStandalone }) => ({
|
||||||
|
|
||||||
onChange(text, markdown, newReplyToId, position) {
|
onChange(text, markdown, newReplyToId, position) {
|
||||||
dispatch(changeCompose(text, markdown, newReplyToId, isStandalone, position))
|
dispatch(changeCompose(text, markdown, newReplyToId, isStandalone, position))
|
||||||
|
@ -123,7 +123,8 @@ class Formatter
|
|||||||
|
|
||||||
def format_markdown(html)
|
def format_markdown(html)
|
||||||
html = markdown_formatter.render(html)
|
html = markdown_formatter.render(html)
|
||||||
html.delete("\r").delete("\n")
|
# html.delete("\r").delete("\n")
|
||||||
|
html = html.gsub(/(?:\n\r?|\r\n?)/, '<br />')
|
||||||
end
|
end
|
||||||
|
|
||||||
def reformat(html, outgoing = false)
|
def reformat(html, outgoing = false)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user