mirror of
https://framagit.org/tykayn/mastodon.git
synced 2023-08-25 08:33:12 +02:00
add preview and style
This commit is contained in:
parent
e4df081141
commit
016b39ae75
@ -21,12 +21,11 @@ import { length } from 'stringz';
|
|||||||
import { countableText } from '../util/counter';
|
import { countableText } from '../util/counter';
|
||||||
import Icon from 'mastodon/components/icon';
|
import Icon from 'mastodon/components/icon';
|
||||||
import snarkdown from 'snarkdown';
|
import snarkdown from 'snarkdown';
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
// import elephantUIPlane from '../../../images/elephant_ui_plane.svg';
|
// import elephantUIPlane from '../../../images/elephant_ui_plane.svg';
|
||||||
// import { mascot } from '../../initial_state';
|
// import { mascot } from '../../initial_state';
|
||||||
|
|
||||||
|
|
||||||
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\u2028\u2029\u0009\u000a\u000b\u000c\u000d';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@ -39,6 +38,8 @@ const messages = defineMessages({
|
|||||||
export default @injectIntl
|
export default @injectIntl
|
||||||
class ComposeForm extends ImmutablePureComponent {
|
class ComposeForm extends ImmutablePureComponent {
|
||||||
|
|
||||||
|
textMarkdownConverted = '';
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
router: PropTypes.object,
|
router: PropTypes.object,
|
||||||
};
|
};
|
||||||
@ -46,6 +47,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
static propTypes = {
|
static propTypes = {
|
||||||
intl : PropTypes.object.isRequired,
|
intl : PropTypes.object.isRequired,
|
||||||
text : PropTypes.string.isRequired,
|
text : PropTypes.string.isRequired,
|
||||||
|
textMarkdownConverted: PropTypes.string,
|
||||||
suggestions : ImmutablePropTypes.list,
|
suggestions : ImmutablePropTypes.list,
|
||||||
spoiler : PropTypes.bool,
|
spoiler : PropTypes.bool,
|
||||||
privacy : PropTypes.string,
|
privacy : PropTypes.string,
|
||||||
@ -80,14 +82,18 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleKeyDown = (e) => {
|
handleKeyDown = (e) => {
|
||||||
|
let markdownConverted = this.convertMarkdown(this.props.text);
|
||||||
|
console.log('markdownConverted', markdownConverted);
|
||||||
|
this.render();
|
||||||
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
|
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
|
||||||
this.handleSubmit();
|
this.handleSubmit();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
getFulltextForCharacterCounting = () => {
|
getFulltextForCharacterCounting = () => {
|
||||||
return [this.props.spoiler ? this.props.spoilerText : '', countableText(this.props.text)].join('');
|
return [this.props.spoiler ? this.props.spoilerText : '', countableText(this.props.text)].join('');
|
||||||
}
|
};
|
||||||
|
|
||||||
canSubmit = () => {
|
canSubmit = () => {
|
||||||
const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props;
|
const { isSubmitting, isChangingUpload, isUploading, anyMedia } = this.props;
|
||||||
@ -95,7 +101,7 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0;
|
const isOnlyWhitespace = fulltext.length !== 0 && fulltext.trim().length === 0;
|
||||||
|
|
||||||
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 500 || (isOnlyWhitespace && !anyMedia));
|
return !(isSubmitting || isUploading || isChangingUpload || length(fulltext) > 500 || (isOnlyWhitespace && !anyMedia));
|
||||||
}
|
};
|
||||||
|
|
||||||
handleSubmit = () => {
|
handleSubmit = () => {
|
||||||
if (this.props.text !== this.autosuggestTextarea.textarea.value) {
|
if (this.props.text !== this.autosuggestTextarea.textarea.value) {
|
||||||
@ -193,10 +199,36 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
this.props.onPickEmoji(position, data, needsSpace);
|
this.props.onPickEmoji(position, data, needsSpace);
|
||||||
};
|
};
|
||||||
|
|
||||||
convertMarkdown(){
|
convertMarkdown(markdownInput) {
|
||||||
let md = '_this_ is **easy** to `use`.';
|
let md = `# title ouane
|
||||||
let html = snarkdown(md);
|
* aaaaaa
|
||||||
console.log(html);
|
* bbbbbb
|
||||||
|
* cccccc
|
||||||
|
aaaaa
|
||||||
|
|
||||||
|
## title deux
|
||||||
|
deuuuux
|
||||||
|
|
||||||
|
### title trois
|
||||||
|
|
||||||
|
_this_ is **easy** to \` use\`.
|
||||||
|
|
||||||
|
* aaaaaa
|
||||||
|
* bbbbbb
|
||||||
|
* cccccc
|
||||||
|
|
||||||
|
un lien vers [[www.wikipedia.org]]
|
||||||
|
[un lien vers cipherbliss.com](https://cipherbliss.com)
|
||||||
|
`;
|
||||||
|
let html = '';
|
||||||
|
if (!markdownInput) {
|
||||||
|
html = snarkdown(md);
|
||||||
|
} else {
|
||||||
|
html = snarkdown(markdownInput);
|
||||||
|
html = DOMPurify.sanitize(markdownInput);
|
||||||
|
}
|
||||||
|
this.textMarkdownConverted = html;
|
||||||
|
return html;
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -210,7 +242,6 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
} else {
|
} else {
|
||||||
publishText = this.props.privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish);
|
publishText = this.props.privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish);
|
||||||
}
|
}
|
||||||
this.convertMarkdown();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='compose-form'>
|
<div className='compose-form'>
|
||||||
@ -268,14 +299,37 @@ class ComposeForm extends ImmutablePureComponent {
|
|||||||
<PrivacyDropdownContainer />
|
<PrivacyDropdownContainer />
|
||||||
<SpoilerButtonContainer />
|
<SpoilerButtonContainer />
|
||||||
</div >
|
</div >
|
||||||
<div className='character-counter__wrapper'><CharacterCounter max={7777} text={this.getFulltextForCharacterCounting()} /></div>
|
<div className='character-counter__wrapper'><CharacterCounter
|
||||||
|
max={this.props.maxTootCharsLimit}
|
||||||
|
text={this.getFulltextForCharacterCounting()}
|
||||||
|
/></div >
|
||||||
</div >
|
</div >
|
||||||
|
|
||||||
<div className='compose-form__publish'>
|
<div className='compose-form__publish'>
|
||||||
<div className='compose-form__publish-button-wrapper'><Button text={publishText} onClick={this.handleSubmit} disabled={!this.canSubmit()} block /></div>
|
<div className='compose-form__publish-button-wrapper'><Button
|
||||||
|
text={publishText}
|
||||||
|
onClick={this.handleSubmit}
|
||||||
|
disabled={!this.canSubmit()}
|
||||||
|
block
|
||||||
|
/></div >
|
||||||
|
</div >
|
||||||
|
|
||||||
|
{this.textMarkdownConverted &&
|
||||||
|
|
||||||
|
<div className='preview formatted-markdown'>
|
||||||
|
<h1>Markdown:</h1>
|
||||||
|
<div
|
||||||
|
dangerouslySetInnerHTML={{
|
||||||
|
__html: this.textMarkdownConverted,
|
||||||
|
}}
|
||||||
|
>
|
||||||
</div >
|
</div >
|
||||||
</div >
|
</div >
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
</div >
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
|
|
||||||
const mapStateToProps = state => ({
|
const mapStateToProps = state => ({
|
||||||
text: state.getIn(['compose', 'text']),
|
text: state.getIn(['compose', 'text']),
|
||||||
|
textMarkdownConverted: state.getIn(['compose', 'textMarkdownConverted']),
|
||||||
suggestions: state.getIn(['compose', 'suggestions']),
|
suggestions: state.getIn(['compose', 'suggestions']),
|
||||||
spoiler: state.getIn(['compose', 'spoiler']),
|
spoiler: state.getIn(['compose', 'spoiler']),
|
||||||
spoilerText: state.getIn(['compose', 'spoiler_text']),
|
spoilerText: state.getIn(['compose', 'spoiler_text']),
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
@import 'bliss/compact_header';
|
@import 'bliss/compact_header';
|
||||||
@import 'bliss/widgets';
|
@import 'bliss/widgets';
|
||||||
@import 'bliss/forms';
|
@import 'bliss/forms';
|
||||||
|
@import 'bliss/markdown';
|
||||||
@import 'bliss/accounts';
|
@import 'bliss/accounts';
|
||||||
@import 'bliss/statuses';
|
@import 'bliss/statuses';
|
||||||
@import 'bliss/boost';
|
@import 'bliss/boost';
|
||||||
|
56
app/javascript/styles/bliss/_markdown.scss
Normal file
56
app/javascript/styles/bliss/_markdown.scss
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
.formatted-markdown{
|
||||||
|
padding: 1em;
|
||||||
|
&.preview{
|
||||||
|
|
||||||
|
background: $dark-text-color;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6{
|
||||||
|
&:first-letter{
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h1{
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-top: 1.5em;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
h2{
|
||||||
|
font-size: 1.25rem;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-top: 1.25em;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
h3{
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
font-weight: 300;
|
||||||
|
}
|
||||||
|
h4{
|
||||||
|
font-size: 0.85rem;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
h5{
|
||||||
|
font-size: 0.75rem;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
h6{
|
||||||
|
font-size: 0.70rem;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
strong{
|
||||||
|
font-weight:700;
|
||||||
|
}
|
||||||
|
i{
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
color: $primary-text-color;
|
||||||
|
}
|
||||||
|
em{
|
||||||
|
background: $darker-text-color;
|
||||||
|
padding: 0.25em;
|
||||||
|
}
|
||||||
|
}
|
@ -89,6 +89,7 @@
|
|||||||
"css-loader": "^5.0.1",
|
"css-loader": "^5.0.1",
|
||||||
"cssnano": "^4.1.10",
|
"cssnano": "^4.1.10",
|
||||||
"detect-passive-events": "^2.0.2",
|
"detect-passive-events": "^2.0.2",
|
||||||
|
"dompurify": "^2.2.6",
|
||||||
"dotenv": "^8.2.0",
|
"dotenv": "^8.2.0",
|
||||||
"emoji-mart": "Gargron/emoji-mart#build",
|
"emoji-mart": "Gargron/emoji-mart#build",
|
||||||
"es6-symbol": "^3.1.3",
|
"es6-symbol": "^3.1.3",
|
||||||
|
@ -3956,6 +3956,11 @@ domexception@^2.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
webidl-conversions "^5.0.0"
|
webidl-conversions "^5.0.0"
|
||||||
|
|
||||||
|
dompurify@^2.2.6:
|
||||||
|
version "2.2.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.2.6.tgz#54945dc5c0b45ce5ae228705777e8e59d7b2edc4"
|
||||||
|
integrity sha512-7b7ZArhhH0SP6W2R9cqK6RjaU82FZ2UPM7RO8qN1b1wyvC/NY1FNWcX1Pu00fFOAnzEORtwXe4bPaClg6pUybQ==
|
||||||
|
|
||||||
domutils@^1.7.0:
|
domutils@^1.7.0:
|
||||||
version "1.7.0"
|
version "1.7.0"
|
||||||
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
|
resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a"
|
||||||
|
Loading…
Reference in New Issue
Block a user