Progress
This commit is contained in:
parent
bfda5978d1
commit
1a33759e19
@ -3,6 +3,7 @@ import { CancelToken, isCancel } from 'axios';
|
||||
import { throttle } from 'lodash';
|
||||
import moment from 'moment';
|
||||
import { search as emojiSearch } from '../components/emoji/emoji_mart_search_light';
|
||||
import { urlRegex } from '../features/compose/util/url_regex'
|
||||
import { tagHistory } from '../settings';
|
||||
import { useEmoji } from './emojis';
|
||||
import resizeImage from '../utils/resize_image';
|
||||
@ -62,6 +63,8 @@ export const COMPOSE_POLL_SETTINGS_CHANGE = 'COMPOSE_POLL_SETTINGS_CHANGE';
|
||||
|
||||
export const COMPOSE_SCHEDULED_AT_CHANGE = 'COMPOSE_SCHEDULED_AT_CHANGE';
|
||||
|
||||
export const COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY = 'COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY'
|
||||
|
||||
const messages = defineMessages({
|
||||
uploadErrorLimit: { id: 'upload_error.limit', defaultMessage: 'File upload limit exceeded.' },
|
||||
uploadErrorPoll: { id: 'upload_error.poll', defaultMessage: 'File upload not allowed with polls.' },
|
||||
@ -170,12 +173,20 @@ export function submitCompose(routerHistory, group) {
|
||||
return function (dispatch, getState) {
|
||||
if (!me) return;
|
||||
|
||||
const status = getState().getIn(['compose', 'text'], '');
|
||||
let status = getState().getIn(['compose', 'text'], '');
|
||||
let statusMarkdown = getState().getIn(['compose', 'text_markdown'], '');
|
||||
const media = getState().getIn(['compose', 'media_attachments']);
|
||||
|
||||
if ((!status || !status.length) && media.size === 0) {
|
||||
return;
|
||||
}
|
||||
// : hack :
|
||||
//Prepend http:// to urls in status that don't have protocol
|
||||
status = status.replace(urlRegex, (match) =>{
|
||||
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
||||
return hasProtocol ? match : `http://${match}`
|
||||
})
|
||||
statusMarkdown = statusMarkdown.replace(urlRegex, (match) =>{
|
||||
const hasProtocol = match.startsWith('https://') || match.startsWith('http://')
|
||||
return hasProtocol ? match : `http://${match}`
|
||||
})
|
||||
|
||||
dispatch(submitComposeRequest());
|
||||
dispatch(closeModal());
|
||||
@ -191,6 +202,7 @@ export function submitCompose(routerHistory, group) {
|
||||
|
||||
api(getState)[method](endpoint, {
|
||||
status,
|
||||
statusMarkdown,
|
||||
scheduled_at,
|
||||
in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
|
||||
quote_of_id: getState().getIn(['compose', 'quote_of_id'], null),
|
||||
@ -594,3 +606,9 @@ export function changeScheduledAt(date) {
|
||||
date,
|
||||
};
|
||||
};
|
||||
|
||||
export function changeRichTextEditorControlsVisibility() {
|
||||
return {
|
||||
type: COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY,
|
||||
}
|
||||
}
|
26
app/javascript/gabsocial/assets/donor_icon.js
Normal file
26
app/javascript/gabsocial/assets/donor_icon.js
Normal file
@ -0,0 +1,26 @@
|
||||
const DonorIcon = ({
|
||||
className = '',
|
||||
width = '24px',
|
||||
height = '24px',
|
||||
viewBox = '0 0 24 24',
|
||||
title = 'Gab.com Donor',
|
||||
}) => (
|
||||
<svg
|
||||
className={className}
|
||||
version='1.1'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
x='0px'
|
||||
y='0px'
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox={viewBox}
|
||||
xmlSpace='preserve'
|
||||
aria-label={title}
|
||||
>
|
||||
<g>
|
||||
<path fill='purple' d='M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default DonorIcon
|
@ -1,9 +1,11 @@
|
||||
const GabLogo = ({
|
||||
className = _s.fillColorBrand,
|
||||
width = '50px',
|
||||
height = '30px',
|
||||
viewBox = '0 0 50 30'
|
||||
}) => (
|
||||
<svg
|
||||
className={className}
|
||||
version='1.1'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
x='0px'
|
||||
@ -14,14 +16,14 @@ const GabLogo = ({
|
||||
xmlSpace='preserve'
|
||||
>
|
||||
<g>
|
||||
<path className={_s.fillColorBrand} d='M13.8,7.6h-2.4v0.7V9l-0.4-0.3C10.2,7.8,9,7.2,7.7,7.2c-0.2,0-0.4,0-0.4,0c-0.1,0-0.3,0-0.5,0
|
||||
<path className={_s.inheritFill} d='M13.8,7.6h-2.4v0.7V9l-0.4-0.3C10.2,7.8,9,7.2,7.7,7.2c-0.2,0-0.4,0-0.4,0c-0.1,0-0.3,0-0.5,0
|
||||
c-5.6,0.3-8.7,7.2-5.4,12.1c2.3,3.4,7.1,4.1,9.7,1.5l0.3-0.3l0,0.7c0,1-0.1,1.5-0.4,2.2c-1,2.4-4.1,3-6.8,1.3
|
||||
c-0.2-0.1-0.4-0.2-0.4-0.2c-0.1,0.1-1.9,3.5-1.9,3.6c0,0.1,0.5,0.4,0.8,0.6c2.2,1.4,5.6,1.7,8.3,0.8c2.7-0.9,4.5-3.2,5-6.4
|
||||
c0.2-1.1,0.2-0.8,0.2-8.4l0-7.1H13.8z M9.7,17.6c-2.2,1.2-4.9-0.4-4.9-2.9C4.8,12.6,7,11,9,11.6C11.8,12.4,12.3,16.1,9.7,17.6z'/>
|
||||
<path className={_s.fillColorBrand} d='M45.6,7.7c-2.4-1-5-0.6-6.7,1L38.6,9V4.5V0h-2.4h-2.4v11v11h2.4h2.4v-0.7v-0.7l0.3,0.3
|
||||
<path className={_s.inheritFill} d='M45.6,7.7c-2.4-1-5-0.6-6.7,1L38.6,9V4.5V0h-2.4h-2.4v11v11h2.4h2.4v-0.7v-0.7l0.3,0.3
|
||||
c2.4,2.4,6.9,1.9,9.3-0.9C51.5,15.9,50.1,9.6,45.6,7.7z M43.7,17.5c-2.1,1.4-5.1-0.2-5.1-2.8c0-2.1,1.9-3.7,3.9-3.3
|
||||
C45.4,12.1,46.2,15.8,43.7,17.5z'/>
|
||||
<path className={_s.fillColorBrand} d='M31.5,12.5c-0.7-3.7-3.1-5.5-7.1-5.3c-1.7,0.1-4,0.7-4.8,1.4l-0.1,0.1l0.7,1.7c0.4,0.9,0.7,1.7,0.7,1.7
|
||||
<path className={_s.inheritFill} d='M31.5,12.5c-0.7-3.7-3.1-5.5-7.1-5.3c-1.7,0.1-4,0.7-4.8,1.4l-0.1,0.1l0.7,1.7c0.4,0.9,0.7,1.7,0.7,1.7
|
||||
c0,0,0.1,0,0.2-0.1c2.7-1.4,5.4-0.9,5.6,1.1l0,0.2l-0.4-0.1c-3-0.8-6.3-0.1-7.7,1.6c-1.8,2.2-0.9,5.8,1.7,7.1
|
||||
c2.1,1,4.6,0.6,6.1-0.8l0.2-0.2v0.6v0.6h2.4h2.4v-4C31.7,13.7,31.7,13.3,31.5,12.5z M26.9,16.4c-0.1,0.7-0.5,1.5-1,2
|
||||
c-1.2,1.1-3,0.7-3.2-0.7c-0.2-1,0.6-1.7,2-1.8c0.1,0,0.2,0,0.2,0c0,0,0.2,0,0.4,0c0.5,0,1,0.1,1.4,0.2l0.3,0.1L26.9,16.4z'/>
|
||||
|
26
app/javascript/gabsocial/assets/investor_icon.js
Normal file
26
app/javascript/gabsocial/assets/investor_icon.js
Normal file
@ -0,0 +1,26 @@
|
||||
const InvestorIcon = ({
|
||||
className = '',
|
||||
width = '24px',
|
||||
height = '24px',
|
||||
viewBox = '0 0 24 24',
|
||||
title = 'Gab.com Investor',
|
||||
}) => (
|
||||
<svg
|
||||
className={className}
|
||||
version='1.1'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
x='0px'
|
||||
y='0px'
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox={viewBox}
|
||||
xmlSpace='preserve'
|
||||
aria-label={title}
|
||||
>
|
||||
<g>
|
||||
<path fill='red' d='M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default InvestorIcon
|
26
app/javascript/gabsocial/assets/pro_icon.js
Normal file
26
app/javascript/gabsocial/assets/pro_icon.js
Normal file
@ -0,0 +1,26 @@
|
||||
const ProIcon = ({
|
||||
className = '',
|
||||
width = '24px',
|
||||
height = '24px',
|
||||
viewBox = '0 0 24 24',
|
||||
title = 'GabPRO Account',
|
||||
}) => (
|
||||
<svg
|
||||
className={className}
|
||||
version='1.1'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
x='0px'
|
||||
y='0px'
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox={viewBox}
|
||||
xmlSpace='preserve'
|
||||
aria-label={title}
|
||||
>
|
||||
<g>
|
||||
<path fill='green' d='M22.5 12.5c0-1.58-.875-2.95-2.148-3.6.154-.435.238-.905.238-1.4 0-2.21-1.71-3.998-3.818-3.998-.47 0-.92.084-1.336.25C14.818 2.415 13.51 1.5 12 1.5s-2.816.917-3.437 2.25c-.415-.165-.866-.25-1.336-.25-2.11 0-3.818 1.79-3.818 4 0 .494.083.964.237 1.4-1.272.65-2.147 2.018-2.147 3.6 0 1.495.782 2.798 1.942 3.486-.02.17-.032.34-.032.514 0 2.21 1.708 4 3.818 4 .47 0 .92-.086 1.335-.25.62 1.334 1.926 2.25 3.437 2.25 1.512 0 2.818-.916 3.437-2.25.415.163.865.248 1.336.248 2.11 0 3.818-1.79 3.818-4 0-.174-.012-.344-.033-.513 1.158-.687 1.943-1.99 1.943-3.484zm-6.616-3.334l-4.334 6.5c-.145.217-.382.334-.625.334-.143 0-.288-.04-.416-.126l-.115-.094-2.415-2.415c-.293-.293-.293-.768 0-1.06s.768-.294 1.06 0l1.77 1.767 3.825-5.74c.23-.345.696-.436 1.04-.207.346.23.44.696.21 1.04z' />
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default ProIcon
|
@ -253,10 +253,21 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
<div className={[_s.default, _s.flexGrow1].join(' ')}>
|
||||
<div className={[_s.default, _s.ml5].join(' ')}>
|
||||
|
||||
{/*<Composer
|
||||
/>*/}
|
||||
<Composer
|
||||
inputRef={this.setTextbox}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
autoFocus={autoFocus}
|
||||
value={value}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
/>
|
||||
|
||||
<Textarea
|
||||
{ /* <Textarea
|
||||
className={_s.default}
|
||||
inputRef={this.setTextbox}
|
||||
disabled={disabled}
|
||||
@ -270,8 +281,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
aria-autocomplete='list'
|
||||
/>
|
||||
|
||||
/> */ }
|
||||
|
||||
{ /*
|
||||
<Textarea
|
||||
|
@ -1,36 +1,315 @@
|
||||
import {
|
||||
Editor,
|
||||
EditorState,
|
||||
CompositeDecorator,
|
||||
RichUtils
|
||||
} from 'draft-js'
|
||||
import { urlRegex } from '../features/compose/util/url_regex'
|
||||
import classNames from 'classnames/bind'
|
||||
import Button from './button'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
const getBlockStyle = (block) => {
|
||||
switch (block.getType()) {
|
||||
case 'blockquote':
|
||||
return 'RichEditor-blockquote'
|
||||
default:
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function handleStrategy(contentBlock, callback, contentState) {
|
||||
findWithRegex(HANDLE_REGEX, contentBlock, callback)
|
||||
}
|
||||
|
||||
function hashtagStrategy (contentBlock, callback, contentState) {
|
||||
findWithRegex(HASHTAG_REGEX, contentBlock, callback)
|
||||
}
|
||||
|
||||
function urlStrategy (contentBlock, callback, contentState) {
|
||||
findWithRegex(urlRegex, contentBlock, callback)
|
||||
}
|
||||
|
||||
const findWithRegex = (regex, contentBlock, callback) => {
|
||||
const text = contentBlock.getText()
|
||||
let matchArr, start
|
||||
while ((matchArr = regex.exec(text)) !== null) {
|
||||
start = matchArr.index
|
||||
callback(start, start + matchArr[0].length)
|
||||
}
|
||||
}
|
||||
|
||||
const HighlightedSpan = (props) => {
|
||||
console.log("HighlightedSpan:", props)
|
||||
return (
|
||||
<span
|
||||
className={_s.colorBrand}
|
||||
data-offset-key={props.offsetKey}
|
||||
>
|
||||
{props.children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
const RTE_ITEMS = [
|
||||
{
|
||||
label: 'Bold',
|
||||
style: 'BOLD',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Italic',
|
||||
style: 'ITALIC',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Underline',
|
||||
style: 'UNDERLINE',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Monospace',
|
||||
style: 'CODE',
|
||||
type: 'style',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'H1',
|
||||
style: 'header-one',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Blockquote',
|
||||
style: 'blockquote',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'UL',
|
||||
style: 'unordered-list-item',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'OL',
|
||||
style: 'ordered-list-item',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
{
|
||||
label: 'Code Block',
|
||||
style: 'code-block',
|
||||
type: 'block',
|
||||
icon: 'circle',
|
||||
},
|
||||
]
|
||||
|
||||
const compositeDecorator = new CompositeDecorator([
|
||||
{
|
||||
strategy: handleStrategy,
|
||||
component: HighlightedSpan,
|
||||
},
|
||||
{
|
||||
strategy: hashtagStrategy,
|
||||
component: HighlightedSpan,
|
||||
},
|
||||
{
|
||||
strategy: urlStrategy,
|
||||
component: HighlightedSpan,
|
||||
}
|
||||
])
|
||||
|
||||
const HANDLE_REGEX = /\@[\w]+/g;
|
||||
const HASHTAG_REGEX = /\#[\w\u0590-\u05ff]+/g;
|
||||
|
||||
export default class Composer extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
inputRef: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
autoFocus: PropTypes.bool,
|
||||
value: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onKeyDown: PropTypes.func,
|
||||
onKeyUp: PropTypes.func,
|
||||
onFocus: PropTypes.func,
|
||||
onBlur: PropTypes.func,
|
||||
onPaste: PropTypes.func,
|
||||
}
|
||||
|
||||
state = {
|
||||
editorState: EditorState.createEmpty(),
|
||||
editorState: EditorState.createEmpty(compositeDecorator),
|
||||
}
|
||||
|
||||
onChange = (editorState) => {
|
||||
this.setState({ editorState })
|
||||
}
|
||||
|
||||
onBoldClick() {
|
||||
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, 'BOLD'));
|
||||
onToggleInlineStyle = (style) => {
|
||||
this.onChange(RichUtils.toggleInlineStyle(this.state.editorState, style))
|
||||
}
|
||||
|
||||
focus = () => {
|
||||
this.textbox.editor.focus()
|
||||
}
|
||||
|
||||
handleKeyCommand = (command) => {
|
||||
const { editorState } = this.state
|
||||
const newState = RichUtils.handleKeyCommand(editorState, command)
|
||||
|
||||
if (newState) {
|
||||
this.onChange(newState)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
onTab = (e) => {
|
||||
const maxDepth = 4
|
||||
this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth))
|
||||
}
|
||||
|
||||
toggleBlockType = (blockType) => {
|
||||
this.onChange(
|
||||
RichUtils.toggleBlockType(
|
||||
this.state.editorState,
|
||||
blockType
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
toggleInlineStyle = (inlineStyle) => {
|
||||
this.onChange(
|
||||
RichUtils.toggleInlineStyle(
|
||||
this.state.editorState,
|
||||
inlineStyle
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
setRef = (n) => {
|
||||
this.textbox = n
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
inputRef,
|
||||
disabled,
|
||||
placeholder,
|
||||
autoFocus,
|
||||
// value,
|
||||
onChange,
|
||||
onKeyDown,
|
||||
onKeyUp,
|
||||
onFocus,
|
||||
onBlur,
|
||||
onPaste
|
||||
} = this.props
|
||||
const { editorState } = this.state
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className={[_s.default].join(' ')}>
|
||||
|
||||
{/*<button onClick={this.onBoldClick.bind(this)}>Bold</button>*/}
|
||||
|
||||
<Editor
|
||||
editorState={this.state.editorState}
|
||||
onChange={this.onChange}
|
||||
/>
|
||||
<div className={[_s.default, _s.backgroundColorPrimary, _s.borderBottom1PX, _s.borderColorSecondary, _s.py5, _s.px15, _s.alignItemsCenter, _s.flexRow].join(' ')}>
|
||||
{
|
||||
RTE_ITEMS.map((item, i) => (
|
||||
<StyleButton
|
||||
key={`rte-button-${i}`}
|
||||
editorState={editorState}
|
||||
{...item}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<div
|
||||
onClick={this.focus}
|
||||
className={[_s.text, _s.fontSize16PX].join(' ')}
|
||||
>
|
||||
<Editor
|
||||
blockStyleFn={getBlockStyle}
|
||||
// customStyleMap={styleMap}
|
||||
editorState={editorState}
|
||||
handleKeyCommand={this.handleKeyCommand}
|
||||
onChange={this.onChange}
|
||||
onTab={this.onTab}
|
||||
placeholder={placeholder}
|
||||
ref={this.setRef}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class StyleButton extends PureComponent {
|
||||
static propTypes = {
|
||||
onToggle: PropTypes.func,
|
||||
label: PropTypes.string,
|
||||
style: PropTypes.string,
|
||||
icon: PropTypes.string,
|
||||
type: PropTypes.string,
|
||||
}
|
||||
|
||||
handleOnToggle = (e) => {
|
||||
const { onToggle, style } = this.props
|
||||
e.preventDefault()
|
||||
onToggle(style)
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
label,
|
||||
style,
|
||||
type,
|
||||
icon,
|
||||
editorState
|
||||
} = this.props
|
||||
|
||||
const selection = editorState.getSelection()
|
||||
|
||||
const currentStyle = editorState.getCurrentInlineStyle()
|
||||
const blockType = editorState.getCurrentContent().getBlockForKey(selection.getStartKey()).getType()
|
||||
|
||||
let active
|
||||
// active={type.style === blockType}
|
||||
// active={currentStyle.has(type.style)}
|
||||
|
||||
const btnClasses = cx({
|
||||
px10: 1,
|
||||
mr5: 1,
|
||||
backgroundSubtle2Dark_onHover: 1,
|
||||
backgroundColorBrandLight: active,
|
||||
// py10: !small,
|
||||
// py5: small,
|
||||
// px5: small,
|
||||
})
|
||||
|
||||
const iconClasses = cx({
|
||||
fillColorSecondary: !active,
|
||||
fillColorWhite: active,
|
||||
})
|
||||
|
||||
return (
|
||||
<Button
|
||||
className={btnClasses}
|
||||
backgroundColor='none'
|
||||
onClick={this.handleOnToggle}
|
||||
title={label}
|
||||
icon={'rich-text'}
|
||||
iconClassName={iconClasses}
|
||||
iconWidth='10px'
|
||||
iconHeight='10px'
|
||||
radiusSmall
|
||||
/>
|
||||
)
|
||||
}
|
||||
}
|
@ -105,6 +105,11 @@ class DisplayName extends ImmutablePureComponent {
|
||||
!!large ? '19px' :
|
||||
!!small ? '14px' : '16px'
|
||||
|
||||
const domain = account.get('acct').split('@')[1];
|
||||
const isRemoteUser = !!domain
|
||||
|
||||
console.log("domain, isRemoteUser:", domain, isRemoteUser)
|
||||
|
||||
// : todo :
|
||||
return (
|
||||
<span {...containerOptions} ref={this.setRef}>
|
||||
@ -117,20 +122,20 @@ class DisplayName extends ImmutablePureComponent {
|
||||
</bdi>
|
||||
{
|
||||
account.get('is_verified') &&
|
||||
<Icon id='verified' width={iconSize} height={iconSize} className={_s.default} title='Verified Account' />
|
||||
<Icon id='verified' width={iconSize} height={iconSize} className={_s.default} />
|
||||
}
|
||||
{ /*
|
||||
{
|
||||
account.get('is_pro') &&
|
||||
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab PRO' />
|
||||
*/ }
|
||||
{ /*
|
||||
<Icon id='pro' width='16px' height='16px' className={_s.default} />
|
||||
}
|
||||
{
|
||||
account.get('is_donor') &&
|
||||
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab Donor' />
|
||||
*/ }
|
||||
{ /*
|
||||
<Icon id='donor' width='16px' height='16px' className={_s.default} />
|
||||
}
|
||||
{
|
||||
account.get('is_investor') &&
|
||||
<Icon id='verified' width='16px' height='16px' className={_s.default} title='Gab Investor' />
|
||||
*/ }
|
||||
<Icon id='investor' width='16px' height='16px' className={_s.default} />
|
||||
}
|
||||
</div>
|
||||
{
|
||||
!noUsername &&
|
||||
|
@ -10,15 +10,18 @@ import CircleIcon from '../assets/circle_icon'
|
||||
import CloseIcon from '../assets/close_icon'
|
||||
import CommentIcon from '../assets/comment_icon'
|
||||
import DissenterIcon from '../assets/dissenter_icon'
|
||||
import DonorIcon from '../assets/donor_icon'
|
||||
import EllipsisIcon from '../assets/ellipsis_icon'
|
||||
import ErrorIcon from '../assets/error_icon'
|
||||
import FullscreenIcon from '../assets/fullscreen_icon'
|
||||
import GabLogoIcon from '../assets/gab_logo'
|
||||
import GifIcon from '../assets/gif_icon'
|
||||
import GlobeIcon from '../assets/globe_icon'
|
||||
import GroupIcon from '../assets/group_icon'
|
||||
import GroupAddIcon from '../assets/group_add_icon'
|
||||
import HappyIcon from '../assets/happy_icon'
|
||||
import HomeIcon from '../assets/home_icon'
|
||||
import InvestorIcon from '../assets/investor_icon'
|
||||
import LikeIcon from '../assets/like_icon'
|
||||
import LinkIcon from '../assets/link_icon'
|
||||
import ListIcon from '../assets/list_icon'
|
||||
@ -33,6 +36,7 @@ import PauseIcon from '../assets/pause_icon'
|
||||
import PinIcon from '../assets/pin_icon'
|
||||
import PlayIcon from '../assets/play_icon'
|
||||
import PollIcon from '../assets/poll_icon'
|
||||
import ProIcon from '../assets/pro_icon'
|
||||
import RepostIcon from '../assets/repost_icon'
|
||||
import RichTextIcon from '../assets/rich_text_icon'
|
||||
import SearchIcon from '../assets/search_icon'
|
||||
@ -56,15 +60,18 @@ const ICONS = {
|
||||
'close': CloseIcon,
|
||||
'comment': CommentIcon,
|
||||
'dissenter': DissenterIcon,
|
||||
'donor': DonorIcon,
|
||||
'ellipsis': EllipsisIcon,
|
||||
'error': ErrorIcon,
|
||||
'fullscreen': FullscreenIcon,
|
||||
'gab-logo': GabLogoIcon,
|
||||
'gif': GifIcon,
|
||||
'globe': GlobeIcon,
|
||||
'group': GroupIcon,
|
||||
'group-add': GroupAddIcon,
|
||||
'happy': HappyIcon,
|
||||
'home': HomeIcon,
|
||||
'investor': InvestorIcon,
|
||||
'like': LikeIcon,
|
||||
'link': LinkIcon,
|
||||
'list': ListIcon,
|
||||
@ -79,6 +86,7 @@ const ICONS = {
|
||||
'pin': PinIcon,
|
||||
'play': PlayIcon,
|
||||
'poll': PollIcon,
|
||||
'pro': ProIcon,
|
||||
'repost': RepostIcon,
|
||||
'rich-text': RichTextIcon,
|
||||
'search': SearchIcon,
|
||||
|
@ -134,7 +134,7 @@ class LinkFooter extends PureComponent {
|
||||
defaultMessage='Gab Social is open source software. You can contribute or report issues on our self-hosted GitLab at {gitlab}.'
|
||||
values={{
|
||||
gitlab: (
|
||||
<a href={source_url} className={_s.inherit} rel='noopener' target='_blank'>
|
||||
<a href={source_url} className={_s.inherit} rel='noopener noreferrer' target='_blank'>
|
||||
{repository}
|
||||
</a>
|
||||
)
|
||||
|
@ -0,0 +1,27 @@
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import Button from '../button'
|
||||
import Text from '../text'
|
||||
import ModalLayout from './modal_layout'
|
||||
|
||||
const messages = defineMessages({
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class LeavingGabModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props
|
||||
|
||||
return (
|
||||
<ModalLayout>
|
||||
</ModalLayout>
|
||||
)
|
||||
}
|
||||
}
|
@ -96,12 +96,12 @@ class ProfileInfoPanel extends ImmutablePureComponent {
|
||||
|
||||
{ /* : todo : */}
|
||||
<dd className='verified'>
|
||||
<a href={proof.get('proof_url')} target='_blank' rel='noopener'>
|
||||
<a href={proof.get('proof_url')} target='_blank' rel='noopener noreferrer'>
|
||||
<span title={intl.formatMessage(messages.linkVerifiedOn, { date: intl.formatDate(proof.get('updated_at'), dateFormatOptions) })}>
|
||||
<Icon id='check' className='verified__mark' />
|
||||
</span>
|
||||
</a>
|
||||
<a href={proof.get('profile_url')} target='_blank' rel='noopener'>
|
||||
<a href={proof.get('profile_url')} target='_blank' rel='noopener noreferrer'>
|
||||
<span
|
||||
className={_s.dangerousContent}
|
||||
dangerouslySetInnerHTML={{ __html: ' ' + proof.get('provider_username') }}
|
||||
|
@ -0,0 +1,63 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { shortNumberFormat } from '../../utils/numbers'
|
||||
import PopoverLayout from './popover_layout'
|
||||
import Avatar from '../avatar'
|
||||
import Button from '../button'
|
||||
import DisplayName from '../display_name'
|
||||
import Text from '../text'
|
||||
|
||||
export default class RemoteUserInfoPopover extends ImmutablePureComponent {
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account } = this.props
|
||||
|
||||
const content = !account ? null : { __html: account.get('note_emojified') }
|
||||
|
||||
return (
|
||||
<PopoverLayout>
|
||||
<div className={[_s.default, _s.px15, _s.py15].join(' ')} style={{width: '260px'}}>
|
||||
|
||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||
<div className={[_s.default, _s.flexGrow1].join(' ')}>
|
||||
<Avatar account={account} size={42} />
|
||||
<DisplayName account={account} multiline noHover />
|
||||
</div>
|
||||
<div className={[_s.default, _s.marginLeftAuto].join(' ')}>
|
||||
<Button
|
||||
color='white'
|
||||
>
|
||||
<Text size='medium' weight='bold' color='inherit'>
|
||||
Following
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.my10].join(' ')}>
|
||||
<div className={_s.dangerousContent} dangerouslySetInnerHTML={content} />
|
||||
</div>
|
||||
|
||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||
<div>
|
||||
<Text size='small'>
|
||||
{shortNumberFormat(account.get('following_count'))}
|
||||
Following
|
||||
</Text>
|
||||
</div>
|
||||
<div>
|
||||
<Text size='small'>
|
||||
{shortNumberFormat(account.get('followers_count'))}
|
||||
Followers
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</PopoverLayout>
|
||||
)
|
||||
}
|
||||
}
|
@ -68,7 +68,7 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(messages.open),
|
||||
title: intl.formatMessage(messages.open),
|
||||
onClick: this.handleOpen
|
||||
});
|
||||
|
||||
@ -76,13 +76,13 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(messages.copy),
|
||||
title: intl.formatMessage(messages.copy),
|
||||
onClick: this.handleCopy,
|
||||
})
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(messages.embed),
|
||||
title: intl.formatMessage(messages.embed),
|
||||
onClick: this.handleEmbed,
|
||||
})
|
||||
}
|
||||
@ -93,7 +93,7 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation),
|
||||
title: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation),
|
||||
onClick: this.handleConversationMuteClick,
|
||||
})
|
||||
}
|
||||
@ -103,33 +103,33 @@ class StatusOptionsPopover extends ImmutablePureComponent {
|
||||
menu.push({
|
||||
icon: 'circle',
|
||||
hideArrow: true,
|
||||
title: formatMessage(status.get('pinned') ? messages.unpin : messages.pin),
|
||||
title: intl.formatMessage(status.get('pinned') ? messages.unpin : messages.pin),
|
||||
onClick: this.handlePinClick,
|
||||
})
|
||||
} else {
|
||||
if (status.get('visibility') === 'private') {
|
||||
menu.push({
|
||||
title: formatMessage(status.get('reblogged') ? messages.cancel_repost_private : messages.repost_private),
|
||||
title: intl.formatMessage(status.get('reblogged') ? messages.cancel_repost_private : messages.repost_private),
|
||||
onClick: this.handleRepostClick
|
||||
})
|
||||
}
|
||||
}
|
||||
menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||
menu.push({ text: formatMessage(messages.edit), action: this.handleEditClick });
|
||||
menu.push({ text: intl.formatMessage(messages.delete), action: this.handleDeleteClick });
|
||||
menu.push({ text: intl.formatMessage(messages.edit), action: this.handleEditClick });
|
||||
} else {
|
||||
menu.push({ text: formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
|
||||
menu.push({ text: formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
|
||||
menu.push({ text: formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
|
||||
menu.push({ text: formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
|
||||
menu.push({ text: intl.formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick });
|
||||
menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick });
|
||||
menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick });
|
||||
menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport });
|
||||
|
||||
if (isStaff) {
|
||||
menu.push({ text: formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
||||
menu.push({ text: formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
|
||||
menu.push({ text: intl.formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` });
|
||||
menu.push({ text: intl.formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` });
|
||||
}
|
||||
|
||||
if (withGroupAdmin) {
|
||||
menu.push({ text: formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount });
|
||||
menu.push({ text: formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost });
|
||||
menu.push({ text: intl.formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount });
|
||||
menu.push({ text: intl.formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +142,7 @@ class Sidebar extends ImmutablePureComponent {
|
||||
{
|
||||
title: 'Home',
|
||||
icon: 'home',
|
||||
to: '/',
|
||||
to: '/home',
|
||||
count: homeItemsQueueCount,
|
||||
},
|
||||
{
|
||||
|
@ -4,7 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { me } from '../initial_state'
|
||||
import { makeGetAccount } from '../selectors'
|
||||
import GabLogo from '../assets/gab_logo'
|
||||
import Icon from './icon'
|
||||
import SidebarSectionItem from './sidebar_section_item'
|
||||
import Text from './text'
|
||||
|
||||
@ -27,14 +27,20 @@ class SidebarHeader extends ImmutablePureComponent {
|
||||
render() {
|
||||
const { account } = this.props
|
||||
|
||||
const isPro = account.get('is_pro')
|
||||
const gabLogoClasses = isPro ? _s.fillColorGabPro : _s.fillColorBrand
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<h1 className={[_s.default].join(' ')}>
|
||||
<NavLink to='/' aria-label='Gab' className={[_s.default, _s.flexRow, _s.noSelect, _s.noUnderline, _s.height50PX, _s.cursorPointer, _s.px10].join(' ')}>
|
||||
<GabLogo />
|
||||
<Text weight='bold' color='brand' size='extraSmall' className={[_s.pb5].join(' ')}>
|
||||
BETA
|
||||
</Text>
|
||||
<Icon id='gab-logo' className={gabLogoClasses} />
|
||||
{
|
||||
isPro &&
|
||||
<Text weight='bold' color='pro' size='extraSmall' className={[_s.pb5].join(' ')}>
|
||||
PRO
|
||||
</Text>
|
||||
}
|
||||
</NavLink>
|
||||
</h1>
|
||||
|
||||
|
@ -5,6 +5,10 @@ import Icon from './icon'
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
export default class SidebarSectionItem extends PureComponent {
|
||||
static contextTypes = {
|
||||
router: PropTypes.object,
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
to: PropTypes.string,
|
||||
href: PropTypes.string,
|
||||
@ -46,7 +50,8 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
const { hovering } = this.state
|
||||
|
||||
const iconSize = '16px'
|
||||
const shouldShowActive = hovering || active
|
||||
const currentPathname = this.context.router.route.location.pathname
|
||||
const shouldShowActive = hovering || active || currentPathname === to || currentPathname === href
|
||||
const isNotifications = to === '/notifications'
|
||||
|
||||
const containerClasses = cx({
|
||||
@ -58,10 +63,12 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
px10: 1,
|
||||
alignItemsCenter: 1,
|
||||
radiusSmall: 1,
|
||||
// border1PX: shouldShowActive,
|
||||
// borderColorSecondary: shouldShowActive,
|
||||
backgroundSubtle2: shouldShowActive,
|
||||
backgroundTransparent: 1,
|
||||
mt2: 1,
|
||||
border1PX: 1,
|
||||
borderColorTransparent: !shouldShowActive,
|
||||
borderColorSecondary: shouldShowActive,
|
||||
backgroundTransparent: !shouldShowActive,
|
||||
backgroundColorPrimary: shouldShowActive,
|
||||
})
|
||||
|
||||
const textClasses = cx({
|
||||
@ -70,13 +77,13 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
fontSize15PX: 1,
|
||||
text: 1,
|
||||
textOverflowEllipsis: 1,
|
||||
colorSecondary: !hovering && !active && !me && !shouldShowActive,
|
||||
colorPrimary: shouldShowActive || me,
|
||||
colorSecondary: !hovering && !active && !me,
|
||||
})
|
||||
|
||||
const iconClasses = cx({
|
||||
fillColorSecondary: !hovering && !active && !shouldShowActive,
|
||||
fillColorBlack: shouldShowActive,
|
||||
fillColorSecondary: !hovering && !active,
|
||||
})
|
||||
|
||||
const countClasses = cx({
|
||||
|
@ -44,7 +44,7 @@ export default class StatusActionBarItem extends PureComponent {
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.flexGrow1, _s.px10].join(' ')}>
|
||||
<div className={[_s.default, _s.flexGrow1, _s.px5].join(' ')}>
|
||||
<button
|
||||
ref={buttonRef}
|
||||
className={btnClasses}
|
||||
|
@ -144,7 +144,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
className={[_s.default, _s.displayFlex, _s.text, _s.noUnderline, _s.overflowWrapBreakWord, _s.colorPrimary, _s.fontSize15PX, _s.fontWeightMedium].join(' ')}
|
||||
href={card.get('url')}
|
||||
title={card.get('title')}
|
||||
rel='noopener'
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
{card.get('title')}
|
||||
@ -228,7 +228,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
<a
|
||||
href={card.get('url')}
|
||||
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.backgroundSubtle_onHover, _s.borderColorSecondary2, _s.border1PX, _s.radiusSmall].join(' ')}
|
||||
rel='noopener'
|
||||
rel='noopener noreferrer'
|
||||
ref={this.setRef}
|
||||
>
|
||||
{embed}
|
||||
|
@ -49,14 +49,15 @@ class StatusContent extends ImmutablePureComponent {
|
||||
|
||||
const links = node.querySelectorAll('a')
|
||||
|
||||
for (var i = 0; i < links.length; ++i) {
|
||||
let link = links[i]
|
||||
if (link.classList.contains('status-link')) {
|
||||
for (let i = 0; i < links.length; ++i) {
|
||||
const link = links[i]
|
||||
if (link.classList.contains('linked')) {
|
||||
continue
|
||||
}
|
||||
link.classList.add('status-link')
|
||||
link.classList.add('linked')
|
||||
link.classList.add(_s.text, _s.colorBrand, _s.cursorPointer, _s.inherit)
|
||||
|
||||
let mention = this.props.status.get('mentions').find(item => link.href === `${item.get('url')}`)
|
||||
const mention = this.props.status.get('mentions').find(item => link.href === `${item.get('url')}`)
|
||||
|
||||
if (mention) {
|
||||
link.addEventListener('click', this.onMentionClick.bind(this, mention), false)
|
||||
@ -66,6 +67,20 @@ class StatusContent extends ImmutablePureComponent {
|
||||
} else {
|
||||
link.setAttribute('title', link.href)
|
||||
}
|
||||
|
||||
const descendents = link.getElementsByTagName('*')
|
||||
for (let j = 0; j < descendents.length; j++) {
|
||||
const descendent = descendents[j];
|
||||
|
||||
if (descendent.classList.contains('invisible')) {
|
||||
descendent.classList.remove('invisible')
|
||||
descendent.classList.add(_s.fontSize0, _s.text, _s.inherit)
|
||||
}
|
||||
if (descendent.classList.contains('ellipsis')) {
|
||||
descendent.classList.remove('ellipsis')
|
||||
descendent.classList.add(_s.noSelect, _s.text, _s.inherit)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
@ -89,8 +104,8 @@ class StatusContent extends ImmutablePureComponent {
|
||||
|
||||
onMentionClick = (mention, e) => {
|
||||
if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault()
|
||||
this.context.router.history.push(`/${mention.get('acct')}`)
|
||||
// e.preventDefault()
|
||||
// this.context.router.history.push(`/${mention.get('acct')}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ const COLORS = {
|
||||
error: 'error',
|
||||
white: 'white',
|
||||
inherit: 'inherit',
|
||||
pro: 'pro',
|
||||
}
|
||||
|
||||
const SIZES = {
|
||||
@ -73,6 +74,7 @@ export default class Text extends PureComponent {
|
||||
colorSecondary: color === COLORS.secondary,
|
||||
colorBrand: color === COLORS.brand,
|
||||
colorWhite: color === COLORS.white,
|
||||
colorGabPro: color === COLORS.pro,
|
||||
inherit: color === COLORS.inherit,
|
||||
|
||||
fontSize19PX: size === SIZES.large,
|
||||
|
@ -1,14 +1,12 @@
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import classNames from 'classnames/bind'
|
||||
import { me } from '../initial_state'
|
||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||
import Avatar from './avatar'
|
||||
import Block from './block'
|
||||
import Heading from './heading'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
|
||||
const messages = defineMessages({
|
||||
createPost: { id: 'column_header.create_post', defaultMessage: 'Create Post' },
|
||||
})
|
||||
@ -57,12 +55,15 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
||||
return (
|
||||
<section className={[_s.default, _s.mb15].join(' ')}>
|
||||
<Block>
|
||||
<div className={[_s.default, _s.backgroundSubtle, _s.borderBottom1PX, _s.borderColorSecondary, _s.px15, _s.py2].join(' ')}>
|
||||
<div className={[_s.default, _s.backgroundSubtle, _s.borderBottom1PX, _s.borderColorSecondary, _s.px15, _s.py2, _s.alignItemsCenter, _s.flexRow].join(' ')}>
|
||||
<div className={_s.mr10}>
|
||||
<Avatar account={account} size='20' />
|
||||
</div>
|
||||
<Heading size='h5'>
|
||||
{intl.formatMessage(messages.createPost)}
|
||||
</Heading>
|
||||
</div>
|
||||
<div className={[_s.default, _s.flexRow, _s.px15, _s.py15].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.px15, _s.pt15, _s.pb10].join(' ')}>
|
||||
<ComposeFormContainer {...rest} />
|
||||
</div>
|
||||
</Block>
|
||||
|
@ -210,7 +210,7 @@ class Video extends PureComponent {
|
||||
const y = 1 - ((e.clientY - rect.top) / this.volHeight)
|
||||
|
||||
if (!isNaN(y)) {
|
||||
var slideamt = y
|
||||
const slideamt = y
|
||||
if (y > 1) {
|
||||
slideamt = 1
|
||||
} else if (y < 0) {
|
||||
|
@ -5,7 +5,6 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import classNames from 'classnames/bind'
|
||||
import CharacterCounter from '../../../../components/character_counter'
|
||||
import UploadForm from '../upload_form'
|
||||
import ReplyIndicatorContainer from '../../containers/reply_indicator_container'
|
||||
import AutosuggestTextbox from '../../../../components/autosuggest_textbox'
|
||||
import PollButton from '../../components/poll_button'
|
||||
import UploadButton from '../media_upload_button'
|
||||
@ -255,12 +254,6 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
mt10: !shouldCondense,
|
||||
})
|
||||
|
||||
const avatarContainerClasses = cx({
|
||||
default: 1,
|
||||
mr10: 1,
|
||||
mt5: shouldCondense,
|
||||
})
|
||||
|
||||
const contentWarningClasses = cx({
|
||||
default: 1,
|
||||
pt5: 1,
|
||||
@ -271,13 +264,14 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
displayNone: !spoiler
|
||||
})
|
||||
|
||||
const avatarSize = shouldCondense ? 28 : 46
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.flexRow, _s.width100PC].join(' ')}>
|
||||
<div className={avatarContainerClasses}>
|
||||
<Avatar account={account} size={avatarSize} />
|
||||
</div>
|
||||
{
|
||||
shouldCondense &&
|
||||
<div className={[_s.default, _s.mr10, _s.mt5]}>
|
||||
<Avatar account={account} size='28' />
|
||||
</div>
|
||||
}
|
||||
|
||||
<div
|
||||
className={containerClasses}
|
||||
@ -285,8 +279,6 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
|
||||
{ /* !shouldCondense && <ReplyIndicatorContainer /> */}
|
||||
|
||||
<div className={contentWarningClasses}>
|
||||
<AutosuggestTextbox
|
||||
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
|
||||
@ -301,7 +293,6 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
onSuggestionSelected={this.onSpoilerSuggestionSelected}
|
||||
searchTokens={[':']}
|
||||
id='cw-spoiler-input'
|
||||
className='spoiler-input__input'
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
export { default } from './reply_indicator'
|
@ -1,64 +0,0 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import Avatar from '../../../../components/avatar';
|
||||
import Button from '../../../../components/button';
|
||||
import DisplayName from '../../../../components/display_name';
|
||||
import { isRtl } from '../../../../utils/rtl';
|
||||
|
||||
const messages = defineMessages({
|
||||
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
|
||||
});
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
class ReplyIndicator extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
router: PropTypes.object,
|
||||
};
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
handleClick = () => {
|
||||
this.props.onCancel();
|
||||
}
|
||||
|
||||
render () {
|
||||
const { status, intl } = this.props;
|
||||
|
||||
if (!status) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const content = { __html: status.get('contentHtml') };
|
||||
const style = {
|
||||
direction: isRtl(status.get('search_index')) ? 'rtl' : 'ltr',
|
||||
};
|
||||
|
||||
return (
|
||||
<div className='reply-indicator'>
|
||||
<div className='reply-indicator__header'>
|
||||
<div className='reply-indicator__cancel'>
|
||||
<Button title={intl.formatMessage(messages.cancel)} icon='times' onClick={this.handleClick} inverted />
|
||||
</div>
|
||||
|
||||
<NavLink to={`/${status.getIn(['account', 'acct'])}`} className='reply-indicator__display-name'>
|
||||
<div className='reply-indicator__display-avatar'>
|
||||
<Avatar account={status.get('account')} size={24} />
|
||||
</div>
|
||||
<DisplayName account={status.get('account')} />
|
||||
</NavLink>
|
||||
</div>
|
||||
|
||||
<div className='reply-indicator-content' style={style} dangerouslySetInnerHTML={content} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
.reply-indicator {
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
background: $gab-background-base-light;
|
||||
padding: 10px;
|
||||
min-height: 23px;
|
||||
overflow-y: auto;
|
||||
flex: 0 2 auto;
|
||||
max-height: 500px;
|
||||
|
||||
@media screen and (min-width: 320px) and (max-width: 375px) {
|
||||
max-height: 220px;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 320px) {
|
||||
max-height: 130px;
|
||||
}
|
||||
|
||||
&__header {
|
||||
margin-bottom: 5px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&__cancel {
|
||||
float: right;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
&__display-name {
|
||||
color: $inverted-text-color;
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
line-height: 24px;
|
||||
overflow: hidden;
|
||||
padding-right: 25px;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover strong {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
&__display-avatar {
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.reply-indicator-content {
|
||||
position: relative;
|
||||
padding-top: 2px;
|
||||
color: $primary-text-color;
|
||||
|
||||
@include text-sizing(15px, 400, 20px);
|
||||
@include text-overflow(normal, break-word);
|
||||
|
||||
&:focus {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&.status__content--with-spoiler {
|
||||
white-space: normal;
|
||||
|
||||
.status__content__text {
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.emojione {
|
||||
margin: -3px 0 0;
|
||||
|
||||
@include size(20px);
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 20px;
|
||||
white-space: pre-wrap;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $gab-brand-default;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
|
||||
.fa {
|
||||
color: lighten($dark-text-color, 7%);
|
||||
}
|
||||
}
|
||||
|
||||
&.mention {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
|
||||
span {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.fa {
|
||||
color: $dark-text-color;
|
||||
}
|
||||
}
|
||||
|
||||
.status__content__spoiler-link {
|
||||
background: $action-button-color;
|
||||
|
||||
&:hover {
|
||||
background: lighten($action-button-color, 7%);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
&::-moz-focus-inner,
|
||||
&:focus,
|
||||
&:active {
|
||||
outline: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.status__content__text {
|
||||
display: none;
|
||||
|
||||
&.status__content__text--visible {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
import { cancelReplyCompose } from '../../../actions/compose';
|
||||
import { makeGetStatus } from '../../../selectors';
|
||||
import ReplyIndicator from '../components/reply_indicator';
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
const getStatus = makeGetStatus();
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
status: getStatus(state, { id: state.getIn(['compose', 'in_reply_to']) }),
|
||||
});
|
||||
|
||||
return mapStateToProps;
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
|
||||
onCancel () {
|
||||
dispatch(cancelReplyCompose());
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default connect(makeMapStateToProps, mapDispatchToProps)(ReplyIndicator);
|
@ -16,7 +16,7 @@ const regexSupplant = function(regex, flags) {
|
||||
regex = regex.source;
|
||||
}
|
||||
return new RegExp(regex.replace(/#\{(\w+)\}/g, function(match, name) {
|
||||
var newRegex = regexen[name] || '';
|
||||
let newRegex = regexen[name] || '';
|
||||
if (typeof newRegex !== 'string') {
|
||||
newRegex = newRegex.source;
|
||||
}
|
||||
@ -185,7 +185,7 @@ export const urlRegex = (function() {
|
||||
regexen.validUrlQueryEndingChars = /[a-z0-9_&=#\/]/i;
|
||||
regexen.validUrl = regexSupplant(
|
||||
'(' + // $1 URL
|
||||
'(https?:\\/\\/)' + // $2 Protocol
|
||||
'(https?:\\/\\/)?' + // $2 Protocol
|
||||
'(#{validDomain})' + // $3 Domain(s)
|
||||
'(?::(#{validPortNumber}))?' + // $4 Port number (optional)
|
||||
'(\\/#{validUrlPath}*)?' + // $5 URL Path
|
||||
|
@ -36,6 +36,7 @@ import {
|
||||
COMPOSE_POLL_OPTION_REMOVE,
|
||||
COMPOSE_POLL_SETTINGS_CHANGE,
|
||||
COMPOSE_SCHEDULED_AT_CHANGE,
|
||||
COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY
|
||||
} from '../actions/compose';
|
||||
import { TIMELINE_DELETE } from '../actions/timelines';
|
||||
import { STORE_HYDRATE } from '../actions/store';
|
||||
@ -73,6 +74,7 @@ const initialState = ImmutableMap({
|
||||
idempotencyKey: null,
|
||||
tagHistory: ImmutableList(),
|
||||
scheduled_at: null,
|
||||
rte_controls_visible: false,
|
||||
});
|
||||
|
||||
const initialPoll = ImmutableMap({
|
||||
@ -386,6 +388,8 @@ export default function compose(state = initialState, action) {
|
||||
return state.update('poll', poll => poll.set('expires_in', action.expiresIn).set('multiple', action.isMultiple));
|
||||
case COMPOSE_SCHEDULED_AT_CHANGE:
|
||||
return state.set('scheduled_at', action.date);
|
||||
case COMPOSE_RICH_TEXT_EDITOR_CONTROLS_VISIBILITY:
|
||||
return ''
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
|
@ -368,6 +368,10 @@ body {
|
||||
color: #21cf7a
|
||||
}
|
||||
|
||||
.colorGabPro {
|
||||
color: #ffd700;
|
||||
}
|
||||
|
||||
.fillColorBlack {
|
||||
fill: #000;
|
||||
}
|
||||
@ -388,6 +392,10 @@ body {
|
||||
fill: #666;
|
||||
}
|
||||
|
||||
.fillColorGabPro {
|
||||
fill: #ffd700;
|
||||
}
|
||||
|
||||
.bottom0 {
|
||||
bottom: 0;
|
||||
}
|
||||
@ -716,6 +724,10 @@ body {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.fontSize0 {
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.fontWeightNormal {
|
||||
font-weight: 400;
|
||||
}
|
||||
@ -858,6 +870,10 @@ body {
|
||||
padding-top: 25%;
|
||||
}
|
||||
|
||||
.pt15 {
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.pt10 {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
@ -43,6 +43,8 @@ class Formatter
|
||||
|
||||
def reformat(html)
|
||||
sanitize(html, Sanitize::Config::GABSOCIAL_STRICT)
|
||||
rescue ArgumentError
|
||||
''
|
||||
end
|
||||
|
||||
def plaintext(status)
|
||||
@ -246,7 +248,7 @@ class Formatter
|
||||
|
||||
def link_to_url(entity, options = {})
|
||||
url = Addressable::URI.parse(entity[:url])
|
||||
html_attrs = { target: '_blank', rel: 'nofollow noopener' }
|
||||
html_attrs = { target: '_blank', rel: 'nofollow noopener noreferrer' }
|
||||
|
||||
html_attrs[:rel] = "me #{html_attrs[:rel]}" if options[:me]
|
||||
|
||||
@ -284,14 +286,14 @@ class Formatter
|
||||
suffix = url[prefix.length + 30..-1]
|
||||
cutoff = url[prefix.length..-1].length > 30
|
||||
|
||||
"<span class=\"invisible\">#{encode(prefix)}</span><span class=\"#{cutoff ? 'ellipsis' : ''}\">#{encode(text)}</span><span class=\"invisible\">#{encode(suffix)}</span>"
|
||||
"<span aria-hidden=\"true\" class=\"invisible\">#{encode(prefix)}</span>#{encode(text)}<span aria-hidden=\"true\" class=\"invisible\">#{encode(suffix)}</span>" + (cutoff ? "<span aria-hidden=\"true\" class=\"ellipsis\">…</span>" : "")
|
||||
end
|
||||
|
||||
def hashtag_html(tag)
|
||||
"<a href=\"#{encode(tag_url(tag.downcase))}\" class=\"mention hashtag\" rel=\"tag\">#<span>#{encode(tag)}</span></a>"
|
||||
"<a data-focusable=\"true\" role=\"link\" href=\"#{encode(tag_url(tag.downcase))}\" class=\"mention hashtag\" rel=\"tag\">##{encode(tag)}</a>"
|
||||
end
|
||||
|
||||
def mention_html(account)
|
||||
"<span class=\"h-card\"><a href=\"#{encode(TagManager.instance.url_for(account))}\" class=\"u-url mention\">@<span>#{encode(account.username)}</span></a></span>"
|
||||
"<a data-focusable=\"true\" role=\"link\" href=\"#{encode(TagManager.instance.url_for(account))}\" class=\"u-url mention\">@#{encode(account.acct)}</a>"
|
||||
end
|
||||
end
|
||||
|
@ -29,7 +29,7 @@ class Sanitize
|
||||
|
||||
add_attributes: {
|
||||
'a' => {
|
||||
'rel' => 'nofollow noopener',
|
||||
'rel' => 'nofollow noopener noreferrer',
|
||||
'target' => '_blank',
|
||||
},
|
||||
},
|
||||
|
4
spec/fixtures/xml/gabsocial.atom
vendored
4
spec/fixtures/xml/gabsocial.atom
vendored
@ -123,7 +123,7 @@
|
||||
<published>2016-10-10T00:41:31Z</published>
|
||||
<updated>2016-10-10T00:41:31Z</updated>
|
||||
<title>Social media needs MOAR cats! http://kickass.zone/media/3</title>
|
||||
<content type="html"><p>Social media needs MOAR cats! <a rel="nofollow noopener" href="http://kickass.zone/media/3">http://kickass.zone/media/3</a></p></content>
|
||||
<content type="html"><p>Social media needs MOAR cats! <a rel="nofollow noopener noreferrer" href="http://kickass.zone/media/3">http://kickass.zone/media/3</a></p></content>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="self" type="application/atom+xml" href="http://kickass.zone/users/localhost/updates/9.atom"/>
|
||||
<link rel="alternate" type="text/html" href="http://kickass.zone/users/localhost/updates/9"/>
|
||||
@ -135,7 +135,7 @@
|
||||
<published>2016-10-10T00:38:39Z</published>
|
||||
<updated>2016-10-10T00:38:39Z</updated>
|
||||
<title>http://kickass.zone/media/2</title>
|
||||
<content type="html"><p><a rel="nofollow noopener" href="http://kickass.zone/media/2">http://kickass.zone/media/2</a></p></content>
|
||||
<content type="html"><p><a rel="nofollow noopener noreferrer" href="http://kickass.zone/media/2">http://kickass.zone/media/2</a></p></content>
|
||||
<activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb>
|
||||
<link rel="self" type="application/atom+xml" href="http://kickass.zone/users/localhost/updates/8.atom"/>
|
||||
<link rel="alternate" type="text/html" href="http://kickass.zone/users/localhost/updates/8"/>
|
||||
|
@ -87,7 +87,7 @@ RSpec.describe FetchLinkCardService, type: :service do
|
||||
end
|
||||
|
||||
context 'in a remote status' do
|
||||
let(:status) { Fabricate(:status, account: Fabricate(:account, domain: 'example.com'), text: 'Habt ihr ein paar gute Links zu #<span class="tag"><a href="https://quitter.se/tag/wannacry" target="_blank" rel="tag noopener" title="https://quitter.se/tag/wannacry">Wannacry</a></span> herumfliegen? Ich will mal unter <br> <a href="https://github.com/qbi/WannaCry" target="_blank" rel="noopener" title="https://github.com/qbi/WannaCry">https://github.com/qbi/WannaCry</a> was sammeln. !<a href="http://sn.jonkman.ca/group/416/id" target="_blank" rel="noopener" title="http://sn.jonkman.ca/group/416/id">security</a> ') }
|
||||
let(:status) { Fabricate(:status, account: Fabricate(:account, domain: 'example.com'), text: 'Habt ihr ein paar gute Links zu #<span class="tag"><a href="https://quitter.se/tag/wannacry" target="_blank" rel="tag noopener noreferrer" title="https://quitter.se/tag/wannacry">Wannacry</a></span> herumfliegen? Ich will mal unter <br> <a href="https://github.com/qbi/WannaCry" target="_blank" rel="noopener noreferrer" title="https://github.com/qbi/WannaCry">https://github.com/qbi/WannaCry</a> was sammeln. !<a href="http://sn.jonkman.ca/group/416/id" target="_blank" rel="noopener noreferrer" title="http://sn.jonkman.ca/group/416/id">security</a> ') }
|
||||
|
||||
it 'parses out URLs' do
|
||||
expect(a_request(:head, 'https://github.com/qbi/WannaCry')).to have_been_made.at_least_once
|
||||
|
@ -28,12 +28,12 @@ RSpec.describe VerifyLinkService, type: :service do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a link contains an <a rel="noopener"> back' do
|
||||
context 'when a link contains an <a rel="noopener noreferrer"> back' do
|
||||
let(:html) do
|
||||
<<-HTML
|
||||
<!doctype html>
|
||||
<body>
|
||||
<a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="noopener me" target="_blank">Follow me on Gab Social</a>
|
||||
<a href="#{ActivityPub::TagManager.instance.url_for(account)}" rel="noopener noreferrer me" target="_blank">Follow me on Gab Social</a>
|
||||
</body>
|
||||
HTML
|
||||
end
|
||||
|
134
yarn.lock
134
yarn.lock
@ -3020,7 +3020,7 @@ debug@=3.1.0:
|
||||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6:
|
||||
debug@^3.0.0, debug@^3.1.1, debug@^3.2.5:
|
||||
version "3.2.6"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b"
|
||||
integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==
|
||||
@ -3061,11 +3061,6 @@ deep-extend@^0.5.1:
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f"
|
||||
integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==
|
||||
|
||||
deep-extend@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
|
||||
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
|
||||
|
||||
deep-is@~0.1.3:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
|
||||
@ -3154,11 +3149,6 @@ detect-file@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7"
|
||||
integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=
|
||||
|
||||
detect-libc@^1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||
|
||||
detect-newline@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2"
|
||||
@ -4231,13 +4221,6 @@ fs-extra@^8.0.1:
|
||||
jsonfile "^4.0.0"
|
||||
universalify "^0.1.0"
|
||||
|
||||
fs-minipass@^1.2.5:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7"
|
||||
integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==
|
||||
dependencies:
|
||||
minipass "^2.6.0"
|
||||
|
||||
fs-write-stream-atomic@^1.0.8:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9"
|
||||
@ -4781,7 +4764,7 @@ https-browserify@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73"
|
||||
integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=
|
||||
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
|
||||
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
|
||||
version "0.4.24"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
|
||||
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
|
||||
@ -4810,13 +4793,6 @@ iferr@^0.1.5:
|
||||
resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501"
|
||||
integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE=
|
||||
|
||||
ignore-walk@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37"
|
||||
integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==
|
||||
dependencies:
|
||||
minimatch "^3.0.4"
|
||||
|
||||
ignore@^4.0.6:
|
||||
version "4.0.6"
|
||||
resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc"
|
||||
@ -4928,7 +4904,7 @@ inherits@2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
|
||||
ini@^1.3.4, ini@^1.3.5:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
|
||||
integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==
|
||||
@ -6447,21 +6423,6 @@ minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5:
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||
|
||||
minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0:
|
||||
version "2.9.0"
|
||||
resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6"
|
||||
integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==
|
||||
dependencies:
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.0"
|
||||
|
||||
minizlib@^1.2.1:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d"
|
||||
integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==
|
||||
dependencies:
|
||||
minipass "^2.9.0"
|
||||
|
||||
mississippi@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022"
|
||||
@ -6598,15 +6559,6 @@ nearley@^2.7.10:
|
||||
randexp "0.4.6"
|
||||
semver "^5.4.1"
|
||||
|
||||
needle@^2.2.1:
|
||||
version "2.3.3"
|
||||
resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.3.tgz#a041ad1d04a871b0ebb666f40baaf1fb47867117"
|
||||
integrity sha512-EkY0GeSq87rWp1hoq/sH/wnTWgFVhYlnIkbJ0YJFfRgEFlz2RraCjBpFQ+vrEgEdp0ThfyHADmkChEhcb7PKyw==
|
||||
dependencies:
|
||||
debug "^3.2.6"
|
||||
iconv-lite "^0.4.4"
|
||||
sax "^1.2.4"
|
||||
|
||||
negotiator@0.6.2:
|
||||
version "0.6.2"
|
||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||
@ -6708,22 +6660,6 @@ node-notifier@^5.4.2:
|
||||
shellwords "^0.1.1"
|
||||
which "^1.3.0"
|
||||
|
||||
node-pre-gyp@*:
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83"
|
||||
integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==
|
||||
dependencies:
|
||||
detect-libc "^1.0.2"
|
||||
mkdirp "^0.5.1"
|
||||
needle "^2.2.1"
|
||||
nopt "^4.0.1"
|
||||
npm-packlist "^1.1.6"
|
||||
npmlog "^4.0.2"
|
||||
rc "^1.2.7"
|
||||
rimraf "^2.6.1"
|
||||
semver "^5.3.0"
|
||||
tar "^4.4.2"
|
||||
|
||||
node-releases@^1.1.52:
|
||||
version "1.1.52"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.52.tgz#bcffee3e0a758e92e44ecfaecd0a47554b0bcba9"
|
||||
@ -6761,14 +6697,6 @@ node-sass@^4.13.1:
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
|
||||
nopt@^4.0.1:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48"
|
||||
integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==
|
||||
dependencies:
|
||||
abbrev "1"
|
||||
osenv "^0.1.4"
|
||||
|
||||
normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
|
||||
version "2.5.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
|
||||
@ -6811,27 +6739,6 @@ normalize-url@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559"
|
||||
integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==
|
||||
|
||||
npm-bundled@^1.0.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b"
|
||||
integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==
|
||||
dependencies:
|
||||
npm-normalize-package-bin "^1.0.1"
|
||||
|
||||
npm-normalize-package-bin@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2"
|
||||
integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==
|
||||
|
||||
npm-packlist@^1.1.6:
|
||||
version "1.4.8"
|
||||
resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e"
|
||||
integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==
|
||||
dependencies:
|
||||
ignore-walk "^3.0.1"
|
||||
npm-bundled "^1.0.1"
|
||||
npm-normalize-package-bin "^1.0.1"
|
||||
|
||||
npm-run-path@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
|
||||
@ -6839,7 +6746,7 @@ npm-run-path@^2.0.0:
|
||||
dependencies:
|
||||
path-key "^2.0.0"
|
||||
|
||||
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2:
|
||||
"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||
@ -7081,7 +6988,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"
|
||||
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
|
||||
|
||||
osenv@0, osenv@^0.1.4:
|
||||
osenv@0:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410"
|
||||
integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==
|
||||
@ -8152,16 +8059,6 @@ raw-body@2.4.0:
|
||||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
rc@^1.2.7:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
|
||||
dependencies:
|
||||
deep-extend "^0.6.0"
|
||||
ini "~1.3.0"
|
||||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-contenteditable@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.yarnpkg.com/react-contenteditable/-/react-contenteditable-3.3.3.tgz#73ea271a0e84d54516e6075c318d4372e5b95c70"
|
||||
@ -8866,7 +8763,7 @@ rgba-regex@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3"
|
||||
integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=
|
||||
|
||||
rimraf@2, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3:
|
||||
rimraf@2, rimraf@^2.5.4, rimraf@^2.6.3:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec"
|
||||
integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==
|
||||
@ -9071,7 +8968,7 @@ selfsigned@^1.10.7:
|
||||
dependencies:
|
||||
node-forge "0.9.0"
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
@ -9651,7 +9548,7 @@ strip-indent@^1.0.1:
|
||||
dependencies:
|
||||
get-stdin "^4.0.1"
|
||||
|
||||
strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
|
||||
strip-json-comments@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||
@ -9766,19 +9663,6 @@ tar@^2.0.0:
|
||||
fstream "^1.0.12"
|
||||
inherits "2"
|
||||
|
||||
tar@^4.4.2:
|
||||
version "4.4.13"
|
||||
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525"
|
||||
integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==
|
||||
dependencies:
|
||||
chownr "^1.1.1"
|
||||
fs-minipass "^1.2.5"
|
||||
minipass "^2.8.6"
|
||||
minizlib "^1.2.1"
|
||||
mkdirp "^0.5.0"
|
||||
safe-buffer "^5.1.2"
|
||||
yallist "^3.0.3"
|
||||
|
||||
tcomb@^2.5.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/tcomb/-/tcomb-2.7.0.tgz#10d62958041669a5d53567b9a4ee8cde22b1c2b0"
|
||||
@ -10629,7 +10513,7 @@ yallist@^2.1.2:
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
|
||||
integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=
|
||||
|
||||
yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3:
|
||||
yallist@^3.0.2:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd"
|
||||
integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
|
||||
|
Loading…
Reference in New Issue
Block a user