Skip to content

Commit

Permalink
Support paragraphs and code inside lists
Browse files Browse the repository at this point in the history
  • Loading branch information
01binary committed Jul 20, 2024
1 parent 0e7ec01 commit 086b792
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 40 deletions.
8 changes: 4 additions & 4 deletions src/articles/kalman-filter.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ There are a few ways to come up with an initial estimate uncertainty:

Each element of `dx0` is squared to convert standard deviation to variance by using the "dot" notation in Matlab.

> Multiplying variance by another quantity requires squaring that quantity. In order for this to work with matrix multiplication, the variance is pre-multiplied by the matrix and post-multiplied by the transpose of the same matrix. This is why you'll often see the pattern `X * y * X'`.
Multiplying variance by another quantity requires squaring that quantity. In order for this to work with matrix multiplication, the variance is pre-multiplied by the matrix and post-multiplied by the transpose of the same matrix. This is why you'll often see the pattern `X * y * X'`.

+ If you have a data set that records system state over time you could use Matlab's [cov](https://www.mathworks.com/help/matlab/ref/cov.html) function to get initial estimate covariance:

Expand Down Expand Up @@ -488,7 +488,7 @@ A process *noise* or *disturbance* covariance matrix usually denoted by `Q` look
noiseCovariance = A * noiseVariance * A'
```

For systems identified with System Identification Toolbox, the noise variance is available in `NoiseVariance` property of the identified model:
For systems identified with System Identification Toolbox, the noise variance is available in `NoiseVariance` property of the model:

```matlab
% ss1 - linear system model
Expand All @@ -512,7 +512,7 @@ A process *noise* or *disturbance* covariance matrix usually denoted by `Q` look
noiseCovariance = B * inputNoiseVariance * B'
```

+ If the system was identified with [Control System Toolbox](https://www.mathworks.com/products/control.html), the [covar](https://www.mathworks.com/help/control/ref/dynamicsystem.covar.html?s_tid=doc_ta) function (not to be confused with [cov](https://www.mathworks.com/help/matlab/ref/cov.html)) will output the disturbance covariance:
+ If the system was identified with [Control System Toolbox](https://www.mathworks.com/products/control.html), the [covar](https://www.mathworks.com/help/control/ref/dynamicsystem.covar.html?s_tid=doc_ta) function will output its disturbance covariance:

```matlab
noiseVariance = 200;
Expand All @@ -529,7 +529,7 @@ A process *noise* or *disturbance* covariance matrix usually denoted by `Q` look

Since the system model includes a *measurement* matrix which maps system state to system output, you could multiply the difference between the original measurement and the model prediction by the inverse of this matrix to calculate the noise affecting each state variable at each iteration.

With these results recorded in a separate vector for each state variable, you could then use `cov` to generate a noise or disturbance matrix.
With these results recorded in a separate vector for each state variable, you could then use `cov` to generate a disturbance matrix.

## covariance transition

Expand Down
2 changes: 1 addition & 1 deletion src/auth/cognito.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const authenticate = async (
}
} = await axios.post(`${AUTH_URL}/token`, payload);

console.log(
console.debug(
'/token',
{
userId,
Expand Down
2 changes: 1 addition & 1 deletion src/auth/useFacebook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const useFacebook = (
}) => {
authenticate(Providers.Facebook, token)
.then((awsSignature) => {
console.log({ provider: Providers.Facebook, name, awsSignature })
console.debug({ provider: Providers.Facebook, name, awsSignature })
setCredentials(awsSignature);
setUser({
provider: Providers.Facebook,
Expand Down
2 changes: 1 addition & 1 deletion src/auth/useGithub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ const useGitHub = (
const { id: providerUserId, login: name, avatar_url: avatarUrl } = data;
authenticate(Providers.GitHub, oauth_access_token)
.then((awsSignature) => {
console.log({ provider: Providers.GitHub, name, awsSignature })
console.debug({ provider: Providers.GitHub, name, awsSignature })
setCredentials(awsSignature);
setUser({
provider: Providers.GitHub,
Expand Down
2 changes: 1 addition & 1 deletion src/auth/useGoogle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const useGoogle = (

authenticate(Providers.Google, access_token)
.then((awsSignature) => {
console.log({ provider: Providers.Google, name, awsSignature })
console.debug({ provider: Providers.Google, name, awsSignature })
setCredentials(awsSignature);
setUser({
provider: Providers.Google,
Expand Down
2 changes: 1 addition & 1 deletion src/auth/useTwitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ const useTwitter = (
oauth_access_token_secret
)
.then((awsSignature) => {
console.log({ provider: Providers.Twitter, name, awsSignature })
console.debug({ provider: Providers.Twitter, name, awsSignature })
setCredentials(awsSignature);
setUser({
provider: Providers.Twitter,
Expand Down
3 changes: 3 additions & 0 deletions src/components/Paragraph/Paragraph.styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {
NARROW_NO_MARKER_LABELS,
NARROW_NO_RULERS,
} from '../../constants';
import React from 'react';

export const ParagraphPassThru = React.Fragment;

export const ParagraphWrapper = styled.section<{
showCommentsSidebar: boolean;
Expand Down
64 changes: 46 additions & 18 deletions src/components/Paragraph/Paragraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import stringHash from 'string-hash';
import RulerHighlightIcon from '../../images/highlight.svg';
import RulerCommentIcon from '../../images/comment.svg';
import AddCommentIcon from '../../images/add-comment.svg';
import { isInsideList } from '../../utils';
import { RulerMarker, RulerMarkerBadge } from '../RulerMarker';
import { InlineComments } from './InlineComments';
import {
Expand All @@ -31,6 +32,7 @@ import {
SelectionAnchor,
ActiveParagraphTextHighlight,
ActiveParagraphListHighlight,
ParagraphPassThru,
} from './Paragraph.styles';
import {
ParagraphSelection,
Expand Down Expand Up @@ -212,6 +214,7 @@ const Paragraph: FC = ({ children }) => {

const hash = useMemo<string>(() => getHash(innerText), [innerText]);

const isPassThru = isInsideList(paragraphRef.current)
const isList = useMemo(() => textContainsList(innerText), [innerText]);
const isImage = useMemo(() => textContainsImage(innerText), [innerText]);
const isVideo = useMemo(() => textContainsVideo(innerText), [innerText]);
Expand Down Expand Up @@ -264,6 +267,11 @@ const Paragraph: FC = ({ children }) => {
);

const updateSelection = useCallback((): ParagraphSelection | undefined => {
if (isPassThru) {
// Cannot interact directly with this paragraph, only its parent
return
}

// Track selected text to enable highlighting or commenting on this paragraph
const selection = window.getSelection();
if (selection?.rangeCount !== 1 || !paragraphRef.current) return;
Expand Down Expand Up @@ -299,7 +307,7 @@ const Paragraph: FC = ({ children }) => {
break;
}

if (node.nodeType === 1) pos += (node as HTMLElement).innerText.length;
if (node.nodeType === 1) pos += (node as HTMLElement)?.innerText?.length;
else if (node.nodeType === 3) pos += node.nodeValue?.length ?? 0;
}
};
Expand Down Expand Up @@ -333,18 +341,27 @@ const Paragraph: FC = ({ children }) => {
setParagraphSelection(paragraphSel);

return paragraphSel;
}, [hash, setParagraphSelection]);
}, [hash, setParagraphSelection, isPassThru]);

const clearSelection = useCallback(() => {
// Hide paragraph menu when text selection is cleared
setHighlightedParagraph(null);
setParagraphSelection(null);
hideParagraphMenu();
}, [setHighlightedParagraph, setParagraphSelection, hideParagraphMenu]);
}, [
setHighlightedParagraph,
setParagraphSelection,
hideParagraphMenu
]);

const handleSelection = useCallback(
// Let user select a portion of the paragraph to show paragraph comment/highlight menu
(e: MouseEvent) => {
if (isPassThru) {
// Paragraph cannot be interacted with, only its parent
return
}

if (window?.getSelection()?.type !== 'Range') {
clearSelection();
return;
Expand Down Expand Up @@ -394,6 +411,7 @@ const Paragraph: FC = ({ children }) => {
setHighlightedParagraph,
updateSelection,
clearSelection,
isPassThru
]
);

Expand Down Expand Up @@ -461,7 +479,7 @@ const Paragraph: FC = ({ children }) => {

useEffect(() => {
// Show paragraph menu on mouse over if this paragraph is highlighted
if (showHighlightMark && paragraphRef.current) {
if (showHighlightMark && paragraphRef.current && !isPassThru) {
const element = paragraphRef.current.getElementsByTagName('mark')[0];
if (!element) return;
element.addEventListener('mouseover', handleHighlightMouseOver);
Expand All @@ -487,13 +505,14 @@ const Paragraph: FC = ({ children }) => {
inlineCommentParagraph,
handleHighlightMouseOver,
handleHighlightMouseOut,
isPassThru
]);

useEffect(() => {
// Show paragraph menu when text is selected
if (paragraphSelection && paragraphSelection?.hash === hash)
if (paragraphSelection && paragraphSelection?.hash === hash && !isPassThru)
showParagraphMenu(null, selectionRef);
}, [hash, paragraphSelection, showParagraphMenu]);
}, [hash, paragraphSelection, showParagraphMenu, isPassThru]);

useEffect(() => {
// Clear selection and hide paragraph menu when no longer highlighted
Expand All @@ -513,15 +532,24 @@ const Paragraph: FC = ({ children }) => {
hideParagraphMenu,
]);

const Wrapper = isPassThru ? ParagraphPassThru : ParagraphWrapper;
const ParagraphBlock = isText ? ParagraphText : ParagraphNonText;

const wrapperProps = isPassThru
? null
: {
className: 'paragraph__wrapper',
showCommentsSidebar,
editingComment: showInlineCommentForm,
}

return (
<ParagraphWrapper
className="paragraph__wrapper"
showCommentsSidebar={showCommentsSidebar}
editingComment={showInlineCommentForm}
>
<ParagraphBlock id={hash} onMouseUp={handleSelection} ref={paragraphRef}>
<Wrapper {...wrapperProps}>
<ParagraphBlock
id={hash}
onMouseUp={handleSelection}
ref={paragraphRef}
>
{showInlineCommentForm ? (
<ActiveParagraphHighlight
isList={isList}
Expand All @@ -541,21 +569,21 @@ const Paragraph: FC = ({ children }) => {
)}
</ParagraphBlock>

{paragraphSelection?.hash === hash && (
{!isPassThru && paragraphSelection?.hash === hash && (
<SelectionAnchor ref={selectionRef} {...paragraphSelection} />
)}

<CommentButton
{!isPassThru && <CommentButton
className="paragraph__comment-button"
ref={commentButtonRef}
onClick={() => toggleInlineComment(hash)}
onMouseOver={() => showTipFor('comment', commentButtonRef)}
onMouseOut={() => hideTip()}
>
<AddCommentIcon />
</CommentButton>
</CommentButton>}

{inlineCommentParagraph && showInlineCommentThread && (
{!isPassThru && inlineCommentParagraph && showInlineCommentThread && (
<InlineComments
{...{
className: 'paragraph__comment-thread',
Expand All @@ -578,7 +606,7 @@ const Paragraph: FC = ({ children }) => {
/>
)}

{showMarker && (
{!isPassThru && showMarker && (
<RulerMarker className="paragraph__ruler-marker">
{hasHighlights && (
<>
Expand All @@ -602,7 +630,7 @@ const Paragraph: FC = ({ children }) => {
)}
</RulerMarker>
)}
</ParagraphWrapper>
</Wrapper>
);
};

Expand Down
53 changes: 49 additions & 4 deletions src/components/Post/Code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Highlight, { Prism, defaultProps } from 'prism-react-renderer';
import { useStyledDarkMode } from 'gatsby-styled-components-dark-mode';
import light from 'prism-react-renderer/themes/github';
import dark from 'prism-react-renderer/themes/vsDark';
import { isInsideList } from '../../utils';
import { Tooltip, Arrow } from '../../components/Tooltip';
import { RULER_ENDMARK_WIDTH, RULER_OFFSET } from '../../components/Ruler';
import {
Expand All @@ -38,13 +39,18 @@ const DARK_MODE_OVERRIDE = 'darkCode';
const CodeToolbar = styled.div<{
isDark: boolean;
isCodeDark: boolean;
isPassThru: boolean;
}>`
position: absolute;
display: flex;
flex-direction: row-reverse;
top: ${(props) => props.theme.spacingThird};
right: calc(30% + ${(props) => props.theme.spacingHalf});
right: ${(props) =>
props.isPassThru
? `0`
: `calc(30% + ${props.theme.spacingHalf})`
};
border-radius: ${(props) => props.theme.borderThick};
background: ${(props) =>
Expand Down Expand Up @@ -125,6 +131,33 @@ const CodeButton: FC<CodeButtonProps> = ({
);
};

const PassThruWrapper = styled.section<{
isDark: boolean;
isCodeDark: boolean;
}>`
position: relative;
margin-left: ${(props) => props.theme.spacingHalf};
button {
right: 0;
}
.stroke-foreground {
stroke: ${(props) =>
props.isCodeDark
? props.isDark
? props.theme.foregroundColor
: props.theme.backgroundColor
: props.theme.foregroundColor};
}
&:hover {
button {
opacity: 1;
}
}
`

const CodeWrapper = styled.section<{
isDark: boolean;
isCodeDark: boolean;
Expand Down Expand Up @@ -222,6 +255,10 @@ const Code: FC = ({ children }) => {
const [isCopied, setCopied] = useState(false);
const [isCodeDark, setCodeDark] = useState(isDark || darkOverride);

const isPassThru = useMemo(
() => isInsideList(snippetRef.current),
[snippetRef.current])

const {
showTip,
hideTip,
Expand Down Expand Up @@ -272,8 +309,12 @@ const Code: FC = ({ children }) => {
[children]
);

const Wrapper = isPassThru
? PassThruWrapper
: CodeWrapper

return (
<CodeWrapper isDark={isDark} isCodeDark={isCodeDark}>
<Wrapper {...{ isDark, isCodeDark }}>
<Highlight
{...defaultProps}
theme={isDark || isCodeDark ? dark : light}
Expand Down Expand Up @@ -301,7 +342,11 @@ const Code: FC = ({ children }) => {
))}
</span>
</Pre>
<CodeToolbar isDark={isDark} isCodeDark={isCodeDark}>
<CodeToolbar
isDark={isDark}
isCodeDark={isCodeDark}
isPassThru={isPassThru}
>
<CodeButton
tipId={'copy'}
tipRef={tipRef}
Expand Down Expand Up @@ -333,7 +378,7 @@ const Code: FC = ({ children }) => {
{tipId === 'mode' && (isCodeDark ? 'light theme' : 'dark theme')}
<Arrow />
</Tooltip>
</CodeWrapper>
</Wrapper>
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useApiClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const configureApiGatewayLink = (signature: AWSSignature | null) => {
return new HttpLink({
fetch: (input, init) => {
const { headers, body } = init;
console.log('fetch called with input', input, 'init', init);
console.debug('fetch called with input', input, 'init', init);
const res = apigClient
.graphqlPost({ headers }, JSON.parse(body.toString()))
.then((res) => {
Expand Down
Loading

0 comments on commit 086b792

Please sign in to comment.