Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature mathtex #28

Closed
wants to merge 77 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
004c55b
apply autolatex and mathjax
christianp Oct 9, 2019
2ceebc0
use custom css
christianp May 23, 2018
bedc4e2
add MathJax v3 rendering
christianp Oct 13, 2019
693cddc
don't include MathJax config
christianp Oct 13, 2019
2ce8978
try/catch around MathJax call
christianp Oct 13, 2019
017877b
fix MathJax on embedded page
christianp Oct 13, 2019
7b0659c
MathJax v3 support
christianp Oct 13, 2019
e7080b1
Merge branch 'mathjax-v3' into mathstodon-3.0.0
christianp Jan 23, 2020
e705549
log mathjax errors
christianp Mar 3, 2020
a8d5c0b
Merge tag 'v3.1.2' into mathstodon-3.0.0
christianp Mar 3, 2020
b69f73f
Merge tag 'v3.1.4' into mathstodon-3.0.0
christianp Jun 14, 2020
771cf5f
mathjax: add unsafe-inline style content security policy
christianp Jun 29, 2020
fa3f78e
Fix other sessions not being logged out on password change
Gargron Jun 23, 2020
951e997
Change rate limits for various paths
Gargron Jun 23, 2020
2d2e365
Fix media attachment enumeration
ClearlyClaire Jun 22, 2020
661f3f2
Bump version to 3.1.5
Gargron Jul 7, 2020
9507510
Merge tag 'v3.1.5' into mathstodon-3.1.4
christianp Jul 7, 2020
471c3ed
latex preview and completion
christianp Aug 25, 2020
aecdaf5
Do not serve account actors at all in limited federation mode (#14800)
ClearlyClaire Sep 14, 2020
0abfa06
Fix inefficiencies in fan-out-on-write service (#14682)
Gargron Aug 30, 2020
c98b775
Fix limited follower id in fan-out-on-write service (#14709)
noellabo Aug 31, 2020
4acfc3c
Fix handling of Reject Follow when a matching follow relationship exi…
ClearlyClaire Aug 1, 2020
8f79ed0
Fix reported statuses not being included in warning e-mail (#14778)
Gargron Sep 13, 2020
ce6aaed
Remove dependency on goldfinger gem (#14919)
Gargron Oct 7, 2020
3f4ccee
Fix videos with near-60 fps being rejected (#14684)
Gargron Aug 29, 2020
58c59af
Fix an error when file_file_size is nil in tootctl media remove (#14657)
noellabo Aug 24, 2020
856cb96
Fix new audio player features not working on Safari (#14465)
ClearlyClaire Aug 2, 2020
399c5f0
Change content-type to be always computed from file data (#14452)
ClearlyClaire Aug 2, 2020
469c4c7
Fix audio player on Safari (#14485)
ClearlyClaire Aug 2, 2020
1995a5c
Fix audio/video player not using CDN_HOST in media paths on public pa…
ClearlyClaire Aug 2, 2020
3b699f1
Fix thumbnail color extraction (#14464)
ClearlyClaire Aug 2, 2020
6db143e
Fix crash when failing to load emoji picker (#14525)
ClearlyClaire Aug 8, 2020
8b448ae
Fix `tootctl media` commands not handling snowflake ids for media_att…
ClearlyClaire Aug 9, 2020
aea0161
Add support for inlined objects in activity audience (#14514)
ClearlyClaire Aug 24, 2020
dd3a86e
Fix: also use custom private boost icon for detailed status (#14471)
OmmyZhang Aug 24, 2020
aa98655
Fix dereferencing remote statuses not using the correct account (#14656)
ClearlyClaire Aug 24, 2020
4ea7193
Add support for latest HTTP Signatures spec draft (#14556)
ClearlyClaire Aug 24, 2020
a583e54
Bump version to 3.2.1
Gargron Oct 19, 2020
ccc1eb0
Merge tag 'v3.2.1' into mathstodon-3.1.5
christianp Oct 19, 2020
536c046
Merge tag 'v3.3.0' into mathstodon-3.3.0
christianp Dec 29, 2020
5b19673
load MathJax config
christianp Mar 30, 2021
b0b9a26
TeX to unicode now happens in autocomplete
christianp Jul 12, 2021
9f25a7a
Merge tag 'v3.5.1' into mathstodon-3.5.1
christianp Apr 26, 2022
d125605
Merge tag 'v3.5.3' into mathstodon-3.5.3
christianp May 27, 2022
6cb33de
reserve some mathematical usernames
christianp Nov 3, 2022
7b91ff0
adding a "start LaTeX" button
christianp Nov 11, 2022
11ea5a9
"Start LaTeX" icon is sort of working?
christianp Nov 11, 2022
bf3b0a0
tidying up the latex button
christianp Nov 11, 2022
9423a9a
remove reference to a thing I ended up not including
christianp Nov 11, 2022
8c784c0
strip closing display-mode delimiter from the preview
christianp Nov 11, 2022
1d85983
Merge branch 'mathstodon-3.5.3' into mathstodon-4.0.2
christianp Nov 15, 2022
6b53f7d
mathstodon on 4.0.2
christianp Nov 15, 2022
418140c
fix latex autosuggestions with extra closing braces
christianp Nov 22, 2022
e7115cc
Merge branch 'glitch-soc:main' into feature-mathtex
sneakers-the-rat Dec 2, 2022
852cc75
Remove custom font
sneakers-the-rat Dec 11, 2022
9956861
remove whitespace
sneakers-the-rat Dec 11, 2022
e0199b4
Merge branch 'feature-mathtex' into mathstodon-4.0.2
sneakers-the-rat Dec 11, 2022
8d3ed4e
adding CDN for testing until we figure out webpack
sneakers-the-rat Dec 12, 2022
e088e8e
Working version, had to move all the mathstodon stuff into the glitch…
sneakers-the-rat Dec 13, 2022
149d374
[style] expand number of lines in collapsed posts, add button to expand
sneakers-the-rat Dec 18, 2022
7e77459
Merge pull request #5 from NeuromatchAcademy/feature-autofollow
sneakers-the-rat Dec 22, 2022
5594b42
Merge pull request #3 from NeuromatchAcademy/mathstodon-4.0.2
sneakers-the-rat Dec 25, 2022
7b709b2
Merge branch 'glitch-soc:main' into dev
sneakers-the-rat Dec 25, 2022
dd2d580
Merge branch 'dev' of https://github.com/NeuromatchAcademy/mastodon i…
sneakers-the-rat Dec 25, 2022
d49752c
Merge remote-tracking branch 'origin/dev' into feature-mathtex
sneakers-the-rat Dec 25, 2022
7a27227
Merge pull request #6 from NeuromatchAcademy/feature-mathtex
sneakers-the-rat Dec 25, 2022
607eb3a
Merge pull request #4 from NeuromatchAcademy/style-bigger-collapse
sneakers-the-rat Dec 25, 2022
c66d56f
[config] no notifiaction emails on follow
sneakers-the-rat Dec 25, 2022
51e90be
[bugfix] content security settings don't let you load from cdn actual…
sneakers-the-rat Dec 25, 2022
b7b0ad1
Merge remote-tracking branch 'origin/dev' into feature-mathtex
sneakers-the-rat Dec 25, 2022
b8fac47
Merge upstream
sneakers-the-rat Oct 7, 2023
b3b9b18
replay https://github.com/NeuromatchAcademy/mastodon/commit/41437dda7…
sneakers-the-rat Oct 7, 2023
e18f0d2
Use non-decorator injectintl
sneakers-the-rat Oct 7, 2023
49754b7
Icon destructuring, replays https://github.com/NeuromatchAcademy/mast…
sneakers-the-rat Oct 7, 2023
8143935
Destructure both icons
sneakers-the-rat Oct 7, 2023
bd45f8c
fix linting errors
sneakers-the-rat Oct 7, 2023
4e14300
Merge branch 'dev-stable' into feature-mathtex
sneakers-the-rat Oct 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,5 @@ yarn-debug.log

# Ignore Docker option files
docker-compose.override.yml

public/MathJax
57 changes: 57 additions & 0 deletions app/javascript/flavours/glitch/actions/compose.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@ import { tagHistory } from 'flavours/glitch/settings';
import { recoverHashtags } from 'flavours/glitch/utils/hashtag';
import resizeImage from 'flavours/glitch/utils/resize_image';

import { tex_to_unicode } from '../features/compose/util/autolatex/autolatex';

import { showAlert, showAlertForError } from './alerts';
import { useEmoji } from './emojis';
import { importFetchedAccounts, importFetchedStatus } from './importer';
import { openModal } from './modal';
import { updateTimeline } from './timelines';


/** @type {AbortController | undefined} */
let fetchComposeSuggestionsAccountsController;
/** @type {AbortController | undefined} */
Expand Down Expand Up @@ -64,6 +67,7 @@ export const COMPOSE_CONTENT_TYPE_CHANGE = 'COMPOSE_CONTENT_TYPE_CHANGE';
export const COMPOSE_LANGUAGE_CHANGE = 'COMPOSE_LANGUAGE_CHANGE';

export const COMPOSE_EMOJI_INSERT = 'COMPOSE_EMOJI_INSERT';
export const COMPOSE_START_LATEX = 'COMPOSE_START_LATEX';

export const COMPOSE_UPLOAD_CHANGE_REQUEST = 'COMPOSE_UPLOAD_UPDATE_REQUEST';
export const COMPOSE_UPLOAD_CHANGE_SUCCESS = 'COMPOSE_UPLOAD_UPDATE_SUCCESS';
Expand Down Expand Up @@ -565,6 +569,36 @@ const fetchComposeSuggestionsAccounts = throttle((dispatch, getState, token) =>
});
}, 200, { leading: true, trailing: true });

const fetchComposeSuggestionsLatex = (dispatch, getState, token) => {
const start_delimiter = token.slice(0,2);
const end_delimiter = {'\\(': '\\)', '\\[': '\\]'}[start_delimiter];
let expression = token.slice(2).replace(/\\[)\]]?$/,'');
let brace = 0;
for(let i=0;i<expression.length;i++) {
switch(expression[i]) {
case '\\':
i += 1;
break;
case '{':
brace += 1;
break;
case '}':
brace -= 1;
break;
}
}
for(;brace<0;brace++) {
expression = '{'+expression;
}
for(;brace>0;brace--) {
expression += '}';
}
const results = [
{ start_delimiter, end_delimiter, expression }
];
dispatch(readyComposeSuggestionsLatex(token, results));
};

const fetchComposeSuggestionsEmojis = (dispatch, getState, token) => {
const results = emojiSearch(token.replace(':', ''), { maxResults: 5 });
dispatch(readyComposeSuggestionsEmojis(token, results));
Expand Down Expand Up @@ -608,13 +642,24 @@ export function fetchComposeSuggestions(token) {
case '#':
fetchComposeSuggestionsTags(dispatch, getState, token);
break;
case '\\':
fetchComposeSuggestionsLatex(dispatch, getState, token);
break;
default:
fetchComposeSuggestionsAccounts(dispatch, getState, token);
break;
}
};
}

export function readyComposeSuggestionsLatex(token, latex) {
return {
type: COMPOSE_SUGGESTIONS_READY,
token,
latex,
};
};

export function readyComposeSuggestionsEmojis(token, emojis) {
return {
type: COMPOSE_SUGGESTIONS_READY,
Expand Down Expand Up @@ -647,6 +692,10 @@ export function selectComposeSuggestion(position, token, suggestion, path) {
completion = `#${suggestion.name}`;
} else if (suggestion.type === 'account') {
completion = '@' + getState().getIn(['accounts', suggestion.id, 'acct']);
} else if (suggestion.type === 'latex') {
const unicode = tex_to_unicode(suggestion.expression);
completion = unicode || `${suggestion.start_delimiter}${suggestion.expression}${suggestion.end_delimiter}`;
position -= 1;
}

// We don't want to replace hashtags that vary only in case due to accessibility, but we need to fire off an event so that
Expand Down Expand Up @@ -779,6 +828,14 @@ export function insertEmojiCompose(position, emoji) {
};
}

export function startLaTeXCompose(position, latex_style) {
return {
type: COMPOSE_START_LATEX,
position,
latex_style,
};
};

export function addPoll() {
return {
type: COMPOSE_POLL_ADD,
Expand Down
26 changes: 24 additions & 2 deletions app/javascript/flavours/glitch/components/autosuggest_input.jsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PropTypes from 'prop-types';
import React from 'react';

import classNames from 'classnames';

Expand All @@ -9,12 +10,30 @@ import AutosuggestAccountContainer from 'flavours/glitch/features/compose/contai

import AutosuggestEmoji from './autosuggest_emoji';
import { AutosuggestHashtag } from './autosuggest_hashtag';
import AutosuggestLatex from './autosuggest_latex';


const textAtCursorMatchesToken = (str, caretPosition, searchTokens) => {
let word;
let left;
let right;

left = str.slice(0, caretPosition).search(/\\\((?:(?!\\\)).)*$/);
if (left >= 0) {
right = str.slice(caretPosition).search(/\\\)/);
if (right < 0) {
word = str.slice(left);
} else {
word = str.slice(left, right + caretPosition);
}
if (word.trim().length >= 3) {
return [left + 1, word];
}
}

left = str.slice(0, caretPosition).search(/[^\s\u200B]+$/);
right = str.slice(caretPosition).search(/[\s\u200B]/);

let left = str.slice(0, caretPosition).search(/[^\s\u200B]+$/);
let right = str.slice(caretPosition).search(/[\s\u200B]/);

if (right < 0) {
word = str.slice(left);
Expand Down Expand Up @@ -180,6 +199,9 @@ export default class AutosuggestInput extends ImmutablePureComponent {
} else if (suggestion.type === 'account') {
inner = <AutosuggestAccountContainer id={suggestion.id} />;
key = suggestion.id;
} else if (suggestion.type === 'latex') {
inner = <AutosuggestLatex latex={suggestion} />;
key = 'latex' + suggestion.expression;
}

return (
Expand Down
38 changes: 38 additions & 0 deletions app/javascript/flavours/glitch/components/autosuggest_latex.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import PropTypes from 'prop-types';
import React from 'react';

export default class AutosuggestLatex extends React.PureComponent {

static propTypes = {
latex: PropTypes.object.isRequired,
};

setRef = (c) => {
this.node = c;
}

componentDidMount() {
try {
// Loaded in script tag on page. not great but we couldn't figure out
// How to use MathJax as a module
// eslint-disable-next-line no-undef
MathJax.typeset([this.node]);
} catch(e) {
console.error(e);
}

}

render () {
const { latex } = this.props;

return (
<div className='autosuggest-latex' ref={this.setRef}>
\({latex.expression}\)
<br />
<small>Convert to unicode</small>
</div>
);
}

}
24 changes: 22 additions & 2 deletions app/javascript/flavours/glitch/components/autosuggest_textarea.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,29 @@ import AutosuggestAccountContainer from 'flavours/glitch/features/compose/contai

import AutosuggestEmoji from './autosuggest_emoji';
import { AutosuggestHashtag } from './autosuggest_hashtag';
import AutosuggestLatex from './autosuggest_latex';

const textAtCursorMatchesToken = (str, caretPosition) => {
let word;
let left;
let right;

left = str.slice(0, caretPosition).search(/\\[([](?:(?!\\[)]]).)*(?:\\[)\]])?$/);
if (left >= 0) {
right = str.slice(caretPosition).search(/\\[)\]]/);
if (right < 0) {
word = str.slice(left);
} else {
word = str.slice(left, right + caretPosition + 2);
}
if (word.trim().length >= 3) {
return [left + 1, word];
}
}

left = str.slice(0, caretPosition).search(/[^\s\u200B]+$/);
right = str.slice(caretPosition).search(/[\s\u200B]/);

let left = str.slice(0, caretPosition).search(/[^\s\u200B]+$/);
let right = str.slice(caretPosition).search(/[\s\u200B]/);

if (right < 0) {
word = str.slice(left);
Expand Down Expand Up @@ -187,6 +204,9 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
} else if (suggestion.type === 'account') {
inner = <AutosuggestAccountContainer id={suggestion.id} />;
key = suggestion.id;
} else if (suggestion.type === 'latex') {
inner = <AutosuggestLatex latex={suggestion} />;
key = suggestion.expression;
}

return (
Expand Down
61 changes: 25 additions & 36 deletions app/javascript/flavours/glitch/components/status_content.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import classnames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';

import { Icon } from 'flavours/glitch/components/icon';
import { autoPlayGif, languages as preloadedLanguages } from 'flavours/glitch/initial_state';
import { decode as decodeIDNA } from 'flavours/glitch/utils/idna';

import Permalink from './permalink';
import StatusExpandButton from './status_expand_button';

const textMatchesTarget = (text, origin, host) => {
return (text === origin || text === host
Expand Down Expand Up @@ -235,12 +235,31 @@ class StatusContent extends PureComponent {
}
};

_renderMathJax() {
const {status} = this.props;
const contentHtml = status.get('contentHtml');
if(this.last_contentHtml === contentHtml) {
return;
}
this.last_contentHtml = contentHtml;
try {
// Loaded in script tag on page. not great but we couldn't figure out
// How to use MathJax as a module
// eslint-disable-next-line no-undef
MathJax.typeset([this.contentsNode]);
} catch(e) {
console.error(e);
}
}

componentDidMount () {
this._updateStatusLinks();
this._renderMathJax();
}

componentDidUpdate () {
this._updateStatusLinks();
this._renderMathJax();
if (this.props.onUpdate) this.props.onUpdate();
}

Expand Down Expand Up @@ -355,38 +374,6 @@ class StatusContent extends PureComponent {
</Permalink>
)).reduce((aggregate, item) => [...aggregate, item, ' '], []);

let toggleText = null;
if (hidden) {
toggleText = [
<FormattedMessage
id='status.show_more'
defaultMessage='Show more'
key='0'
/>,
];
if (mediaIcons) {
mediaIcons.forEach((mediaIcon, idx) => {
toggleText.push(
<Icon
fixedWidth
className='status__content__spoiler-icon'
id={mediaIcon}
aria-hidden='true'
key={`icon-${idx}`}
/>,
);
});
}
} else {
toggleText = (
<FormattedMessage
id='status.show_less'
defaultMessage='Show less'
key='0'
/>
);
}

if (hidden) {
mentionsPlaceholder = <div>{mentionLinks}</div>;
}
Expand All @@ -398,9 +385,11 @@ class StatusContent extends PureComponent {
>
<span dangerouslySetInnerHTML={spoilerContent} className='translate' lang={language} />
{' '}
<button type='button' className='status__content__spoiler-link' onClick={this.handleSpoilerClick} aria-expanded={!hidden}>
{toggleText}
</button>
<StatusExpandButton
hidden={hidden}
handleSpoilerClick={this.handleSpoilerClick}
mediaIcons={mediaIcons}
/>
</p>

{mentionsPlaceholder}
Expand Down
Loading
Loading