forked from getsentry/develop
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
278 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
const visit = require("unist-util-visit"); | ||
|
||
function getFullMeta(node) { | ||
if (node.lang && node.meta) { | ||
return node.lang + node.meta; | ||
} | ||
return node.lang || node.meta; | ||
} | ||
|
||
function getFilename(node) { | ||
const meta = getFullMeta(node); | ||
const match = (meta || "").match(/\{filename:([^\}]+)\}/); | ||
return (match && match[1]) || ""; | ||
} | ||
|
||
function getTabTitle(node) { | ||
const meta = getFullMeta(node); | ||
const match = (meta || "").match(/\{tabTitle:([^\}]+)\}/); | ||
return (match && match[1]) || ""; | ||
} | ||
|
||
function forcesTabBar(node) { | ||
const meta = getFullMeta(node); | ||
return meta && !!meta.match(/\{forceTabBar\}/); | ||
} | ||
|
||
function isFoldWithLast(node) { | ||
const meta = getFullMeta(node); | ||
return meta && !!meta.match(/\{foldWithLast\}/); | ||
} | ||
|
||
module.exports = ({ markdownAST }, { className = "code-tabs-wrapper" }) => { | ||
let pendingCode = []; | ||
let toRemove = []; | ||
|
||
function flushPendingCode() { | ||
if (pendingCode.length === 0) { | ||
return; | ||
} | ||
|
||
const hideTabBar = | ||
pendingCode.length === 1 && !forcesTabBar(pendingCode[0][0]); | ||
const rootNode = pendingCode[0][0]; | ||
const children = pendingCode.flatMap(([node]) => [ | ||
{ | ||
type: "jsx", | ||
value: `<CodeBlock language="${node.lang || ""}" title="${getTabTitle( | ||
node | ||
)}" filename="${getFilename(node)}">`, | ||
}, | ||
Object.assign({}, node), | ||
{ | ||
type: "jsx", | ||
value: "</CodeBlock>", | ||
}, | ||
]); | ||
|
||
rootNode.type = "element"; | ||
rootNode.data = { | ||
hName: "div", | ||
hProperties: { | ||
className, | ||
}, | ||
}; | ||
rootNode.children = [ | ||
{ | ||
type: "jsx", | ||
value: `<CodeTabs hideTabBar={${hideTabBar}}>`, | ||
}, | ||
...children, | ||
{ | ||
type: "jsx", | ||
value: "</CodeTabs>", | ||
}, | ||
]; | ||
|
||
toRemove = toRemove.concat(pendingCode.splice(1)); | ||
} | ||
|
||
visit(markdownAST, "code", (node, _index, parent) => { | ||
if (!isFoldWithLast(node)) { | ||
flushPendingCode(); | ||
pendingCode = []; | ||
} | ||
pendingCode.push([node, parent]); | ||
}); | ||
|
||
flushPendingCode(); | ||
|
||
toRemove.forEach(([node, parent], index) => { | ||
parent.children = parent.children.filter((n) => n !== node); | ||
}); | ||
|
||
return markdownAST; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ | ||
"name": "gatsby-plugin-code-tabs", | ||
"version": "1.0.0", | ||
"main": "index.js", | ||
"license": "MIT", | ||
"peerDependencies": { | ||
"gatsby": "^2.0.0" | ||
}, | ||
"dependencies": { | ||
"unist-util-visit": "^1.4.1" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
|
||
class CodeBlock extends React.Component { | ||
render() { | ||
return ( | ||
<div className="code-block"> | ||
{this.props.filename && <p class="filename">{this.props.filename}</p>} | ||
{this.props.children} | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
CodeBlock.propTypes = { | ||
language: PropTypes.string, | ||
filename: PropTypes.string, | ||
title: PropTypes.string, | ||
}; | ||
|
||
export default CodeBlock; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import React, { useState, useContext } from "react"; | ||
|
||
// human readable versions of names | ||
const LANGUAGES = { | ||
javascript: "JavaScript", | ||
typescript: "TypeScript", | ||
html: "HTML", | ||
coffee: "CoffeeScript", | ||
powershell: "PowerShell", | ||
json: "JSON", | ||
cpp: "C++", | ||
csharp: "C#", | ||
es6: "JavaScript (ES6)", | ||
yml: "YAML", | ||
yaml: "YAML", | ||
}; | ||
|
||
export const CodeContext = React.createContext(null); | ||
|
||
export function makeCodeContextState() { | ||
return useState(null); | ||
} | ||
|
||
function CodeTabs({ children, hideTabBar = false }) { | ||
if (!Array.isArray(children)) { | ||
children = [children]; | ||
} | ||
|
||
const [sharedSelection, setSharedSelection] = useContext(CodeContext); | ||
const [localSelection, setLocalSelection] = useState(null); | ||
|
||
const possibleChoices = children.map((x) => { | ||
const { title, language } = x.props; | ||
return ( | ||
title || | ||
LANGUAGES[language] || | ||
(language ? language[0].toUpperCase() + language.substr(1) : "Text") | ||
); | ||
}); | ||
|
||
const sharedSelectionChoice = sharedSelection | ||
? possibleChoices.find((x) => x === sharedSelection) | ||
: null; | ||
const localSelectionChoice = localSelection | ||
? possibleChoices.find((x) => x === localSelection) | ||
: null; | ||
|
||
const finalSelection = | ||
sharedSelectionChoice || localSelectionChoice || possibleChoices[0]; | ||
|
||
if (localSelection !== finalSelection) { | ||
setLocalSelection(finalSelection); | ||
} | ||
|
||
let code = null; | ||
|
||
const names = possibleChoices.map((choice, idx) => { | ||
const isSelected = choice === finalSelection; | ||
if (isSelected) { | ||
code = children[idx]; | ||
} | ||
|
||
return ( | ||
<button | ||
className={isSelected ? "active" : ""} | ||
onClick={() => { | ||
setSharedSelection(choice); | ||
setLocalSelection(choice); | ||
}} | ||
key={idx} | ||
> | ||
{choice} | ||
</button> | ||
); | ||
}); | ||
|
||
return ( | ||
<div className="code-tabs"> | ||
{!hideTabBar && <div class="tab-bar">{names}</div>} | ||
<div class="tab-content">{code}</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default CodeTabs; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* support for code blocks and tabs */ | ||
.code-tabs { | ||
border: 1px solid $lightPurple; | ||
margin-bottom: 1rem; | ||
|
||
.tab-bar { | ||
background: $lightPurple; | ||
|
||
button { | ||
padding: 3px 6px; | ||
display: inline-block; | ||
cursor: pointer; | ||
border: none; | ||
font-size: 0.95rem; | ||
background: transparent; | ||
} | ||
|
||
button.active { | ||
background: white; | ||
} | ||
} | ||
|
||
.tab-content { | ||
position: relative; | ||
|
||
.filename { | ||
position: absolute; | ||
right: 0; | ||
margin: 0; | ||
padding: 0 6px; | ||
background: $flame8; | ||
font-size: 0.85rem; | ||
border-bottom-left-radius: 3px; | ||
} | ||
|
||
pre { | ||
margin: 0; | ||
padding: 5px 10px; | ||
border-radius: 0; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters