Added anchors for document headings
This commit is contained in:
@ -1,14 +1,27 @@
|
||||
import slug from 'slug';
|
||||
import truncate from 'truncate-html';
|
||||
import marked, { Renderer } from 'marked';
|
||||
import highlight from 'highlight.js';
|
||||
|
||||
slug.defaults.mode ='rfc3986';
|
||||
|
||||
const renderer = new Renderer();
|
||||
renderer.code = (code, language) => {
|
||||
const validLang = !!(language && highlight.getLanguage(language));
|
||||
const highlighted = validLang ? highlight.highlight(language, code).value : code;
|
||||
return `<pre><code class="hljs ${language}">${highlighted}</code></pre>`;
|
||||
};
|
||||
|
||||
renderer.heading = (text, level) => {
|
||||
const headingSlug = slug(text);
|
||||
return `
|
||||
<h${level}>
|
||||
<a name="${headingSlug}" class="anchor" href="#${headingSlug}">
|
||||
<span class="header-link"> </span>
|
||||
</a>
|
||||
${text}
|
||||
</h${level}>
|
||||
`;
|
||||
},
|
||||
|
||||
marked.setOptions({
|
||||
renderer: renderer,
|
||||
|
1
src/assets/icons/anchor.svg
Normal file
1
src/assets/icons/anchor.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" x="0px" y="0px" viewBox="0 0 100 125" enable-background="new 0 0 100 100" xml:space="preserve"><path d="M82.641,40.452L69.984,53.109c-1.164,1.164-3.054,1.164-4.218,0s-1.164-3.054,0-4.218l12.657-12.657 c3.489-3.489,3.489-9.165,0-12.657s-9.165-3.489-12.657,0L48.891,40.452c-1.035,1.059-5.955,6.702,0,12.657 c1.164,1.164,1.164,3.054,0,4.218s-3.054,1.164-4.218,0c-8.343-8.343-3.648-17.445,0-21.093l16.875-16.875 c5.814-5.814,15.279-5.814,21.093,0C88.455,25.173,88.452,34.638,82.641,40.452z M57.327,44.673c-1.164-1.164-3.054-1.164-4.218,0 c-1.164,1.164-1.164,3.054,0,4.218c5.955,5.955,1.035,11.595,0,12.657L36.234,78.423c-3.489,3.489-9.165,3.489-12.657,0 c-3.492-3.489-3.489-9.165,0-12.657l12.657-12.657c1.164-1.164,1.164-3.054,0-4.218s-3.054-1.164-4.218,0L19.359,61.548 c-5.814,5.814-5.814,15.279,0,21.093c5.814,5.814,15.279,5.814,21.093,0l16.875-16.875C60.975,62.118,65.67,53.013,57.327,44.673z"/></svg>
|
After Width: | Height: | Size: 1003 B |
@ -20,7 +20,10 @@ class Document extends React.Component {
|
||||
name={ this.props.document.user.name }
|
||||
timestamp={ this.props.document.createdAt }
|
||||
/>
|
||||
<div dangerouslySetInnerHTML={{ __html: this.props.document.html }} />
|
||||
<div
|
||||
className={ styles.document }
|
||||
dangerouslySetInnerHTML={{ __html: this.props.document.html }}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -2,3 +2,28 @@
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.document {
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
:global {
|
||||
.anchor {
|
||||
visibility: hidden;
|
||||
background-image: url('../../assets/icons/anchor.svg');
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100%;
|
||||
background-position: 0 center;
|
||||
margin-left: -26px;
|
||||
width: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
:global {
|
||||
.anchor {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,19 @@ class DocumentScene extends React.Component {
|
||||
this.props.fetchDocumentAsync(documentId);
|
||||
}
|
||||
|
||||
componentWillReceiveProps = (nextProps) => {
|
||||
// Scroll to anchor after loading
|
||||
const hash = this.props.location.hash;
|
||||
|
||||
if (nextProps.document && hash) {
|
||||
const name = hash.split('#')[1];
|
||||
setTimeout(() => {
|
||||
const element = document.getElementsByName(name)[0];
|
||||
if (element) element.scrollIntoView()
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const document = this.props.document;
|
||||
let title;
|
||||
|
Reference in New Issue
Block a user