Fixes: JS error when no heading
Fixes: Reduce hover zone Fixes: Add H1s into TOC
This commit is contained in:
@ -26,9 +26,12 @@ type Props = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateActiveHeading = () => {
|
updateActiveHeading = () => {
|
||||||
let activeHeading = this.headingElements[0].id;
|
const elements = this.headingElements;
|
||||||
|
if (!elements.length) return;
|
||||||
|
|
||||||
for (const element of this.headingElements) {
|
let activeHeading = elements[0].id;
|
||||||
|
|
||||||
|
for (const element of elements) {
|
||||||
const bounds = element.getBoundingClientRect();
|
const bounds = element.getBoundingClientRect();
|
||||||
if (bounds.top <= 0) activeHeading = element.id;
|
if (bounds.top <= 0) activeHeading = element.id;
|
||||||
}
|
}
|
||||||
@ -38,7 +41,7 @@ type Props = {
|
|||||||
|
|
||||||
get headingElements(): HTMLElement[] {
|
get headingElements(): HTMLElement[] {
|
||||||
const elements = [];
|
const elements = [];
|
||||||
const tagNames = ['h2', 'h3', 'h4', 'h5', 'h6'];
|
const tagNames = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
|
||||||
|
|
||||||
for (const tagName of tagNames) {
|
for (const tagName of tagNames) {
|
||||||
for (const ele of document.getElementsByTagName(tagName)) {
|
for (const ele of document.getElementsByTagName(tagName)) {
|
||||||
@ -54,7 +57,6 @@ type Props = {
|
|||||||
|
|
||||||
return state.document.nodes.filter((node: Block) => {
|
return state.document.nodes.filter((node: Block) => {
|
||||||
if (!node.text) return false;
|
if (!node.text) return false;
|
||||||
if (node.type === 'heading1') return false;
|
|
||||||
return node.type.match(/^heading/);
|
return node.type.match(/^heading/);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -67,7 +69,7 @@ type Props = {
|
|||||||
<Wrapper>
|
<Wrapper>
|
||||||
<Sections>
|
<Sections>
|
||||||
{this.headings.map(heading => {
|
{this.headings.map(heading => {
|
||||||
const slug = headingToSlug(heading.type, heading.text);
|
const slug = headingToSlug(heading);
|
||||||
const active = this.activeHeading === slug;
|
const active = this.activeHeading === slug;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -84,6 +86,13 @@ type Props = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Wrapper = styled.div`
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
top: 150px;
|
||||||
|
z-index: 100;
|
||||||
|
`;
|
||||||
|
|
||||||
const Anchor = styled.a`
|
const Anchor = styled.a`
|
||||||
color: ${props => (props.active ? color.slateDark : color.slate)};
|
color: ${props => (props.active ? color.slateDark : color.slate)};
|
||||||
font-weight: ${props => (props.active ? 500 : 400)};
|
font-weight: ${props => (props.active ? 500 : 400)};
|
||||||
@ -91,6 +100,8 @@ const Anchor = styled.a`
|
|||||||
transition: all 100ms ease-in-out;
|
transition: all 100ms ease-in-out;
|
||||||
margin-right: -5px;
|
margin-right: -5px;
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
|
pointer-events: none;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: ${color.primary};
|
color: ${color.primary};
|
||||||
@ -99,14 +110,15 @@ const Anchor = styled.a`
|
|||||||
|
|
||||||
const ListItem = styled.li`
|
const ListItem = styled.li`
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-left: ${props => (props.type === 'heading2' ? '8px' : '16px')};
|
margin-left: ${props => (props.type.match(/heading[12]/) ? '8px' : '16px')};
|
||||||
text-align: right;
|
text-align: right;
|
||||||
color: ${color.slate};
|
color: ${color.slate};
|
||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
color: ${props => (props.active ? color.slateDark : color.slate)};
|
color: ${props => (props.active ? color.slateDark : color.slate)};
|
||||||
content: "${props => (props.type === 'heading2' ? '—' : '–')}";
|
content: "${props => (props.type.match(/heading[12]/) ? '—' : '–')}";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
@ -117,21 +129,21 @@ const Sections = styled.ol`
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
width: 100px;
|
||||||
|
transition-delay: 1s;
|
||||||
|
transition: width 100ms ease-in-out;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
width: 300px;
|
||||||
|
transition-delay: 0s;
|
||||||
|
|
||||||
${Anchor} {
|
${Anchor} {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
background: ${color.white};
|
background: ${color.white};
|
||||||
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
|
||||||
position: fixed;
|
|
||||||
right: 0;
|
|
||||||
top: 160px;
|
|
||||||
z-index: 100;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default Contents;
|
export default Contents;
|
||||||
|
@ -30,7 +30,7 @@ function Heading(props: Props) {
|
|||||||
const parentIsDocument = parent instanceof Document;
|
const parentIsDocument = parent instanceof Document;
|
||||||
const firstHeading = parentIsDocument && parent.nodes.first() === node;
|
const firstHeading = parentIsDocument && parent.nodes.first() === node;
|
||||||
const showPlaceholder = placeholder && firstHeading && !node.text;
|
const showPlaceholder = placeholder && firstHeading && !node.text;
|
||||||
const slugish = headingToSlug(node.type, node.text);
|
const slugish = headingToSlug(node);
|
||||||
const showHash = readOnly && !!slugish;
|
const showHash = readOnly && !!slugish;
|
||||||
const Component = component;
|
const Component = component;
|
||||||
const emoji = editor.props.emoji || '';
|
const emoji = editor.props.emoji || '';
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { escape } from 'lodash';
|
import { escape } from 'lodash';
|
||||||
|
import type { Node } from './types';
|
||||||
import slug from 'slug';
|
import slug from 'slug';
|
||||||
|
|
||||||
export default function headingToSlug(heading: string, title: string) {
|
export default function headingToSlug(node: Node) {
|
||||||
const level = heading.replace('heading', 'h');
|
const level = node.type.replace('heading', 'h');
|
||||||
return escape(`${level}-${slug(title)}`);
|
return escape(`${level}-${slug(node.text)}-${node.key}`);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user