Repository: jaredpetersen/codeprinter
Branch: master
Commit: 3850412a767d
Files: 54
Total size: 59.4 KB
Directory structure:
gitextract_yqxvaw7a/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── .storybook/
│ ├── addons.js
│ ├── config.js
│ └── preview-head.html
├── .travis.yml
├── LICENSE
├── README.md
├── package.json
├── public/
│ ├── index.html
│ └── manifest.json
└── src/
├── App.jsx
├── App.test.jsx
├── common/
│ └── dropdown-toggle-select/
│ ├── index.css
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── editor/
│ ├── document/
│ │ ├── index.css
│ │ ├── index.jsx
│ │ ├── index.story.jsx
│ │ └── index.test.jsx
│ ├── index.jsx
│ ├── index.story.jsx
│ ├── index.test.jsx
│ └── toolbar/
│ ├── font-dropdown/
│ │ ├── __snapshots__/
│ │ │ └── index.test.jsx.snap
│ │ ├── index.jsx
│ │ ├── index.story.jsx
│ │ └── index.test.jsx
│ ├── index.jsx
│ ├── index.story.jsx
│ ├── index.test.jsx
│ ├── size-dropdown/
│ │ ├── __snapshots__/
│ │ │ └── index.test.jsx.snap
│ │ ├── index.jsx
│ │ ├── index.story.jsx
│ │ └── index.test.jsx
│ └── theme-dropdown/
│ ├── __snapshots__/
│ │ └── index.test.jsx.snap
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── heart/
│ ├── __snapshots__/
│ │ └── index.test.jsx.snap
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── index.css
├── index.jsx
├── navbar/
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── not-found/
│ ├── __snapshots__/
│ │ └── index.test.jsx.snap
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── registerServiceWorker.js
└── setupTests.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: jaredpetersen
custom: https://paypal.me/jaredtpetersen
================================================
FILE: .gitignore
================================================
# See https://help.github.com/ignore-files/ for more about ignoring files.
# dependencies
/node_modules
# testing
/coverage
/storybook-static
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: .storybook/addons.js
================================================
import '@storybook/addon-actions/register';
import '@storybook/addon-links/register';
================================================
FILE: .storybook/config.js
================================================
import { configure } from '@storybook/react';
function loadStories() {
require('../src/common/dropdown-toggle-select/index.story.jsx');
require('../src/navbar/index.story.jsx');
require('../src/editor/index.story.jsx');
require('../src/editor/toolbar/index.story.jsx');
require('../src/editor/toolbar/font-dropdown/index.story.jsx');
require('../src/editor/toolbar/size-dropdown/index.story.jsx');
require('../src/editor/toolbar/theme-dropdown/index.story.jsx');
require('../src/editor/document/index.story.jsx');
require('../src/heart/index.story.jsx');
require('../src/not-found/index.story.jsx');
}
configure(loadStories, module);
================================================
FILE: .storybook/preview-head.html
================================================
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/solid.css" integrity="sha384-TbilV5Lbhlwdyc4RuIV/JhD8NR+BfMrvz4BL5QFa2we1hQu6wvREr3v6XSRfCTRp" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/brands.css" integrity="sha384-7xAnn7Zm3QC1jFjVc1A6v/toepoG3JXboQYzbM0jrPzou9OFXm/fY6Z/XiIebl/k" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/fontawesome.css" integrity="sha384-ozJwkrqb90Oa3ZNb+yKFW2lToAWYdTiF1vt8JiH5ptTGHTGcN7qdoR1F95e0kYyG" crossorigin="anonymous">
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "node"
- "lts/*"
- "9"
- "8"
script:
- npm run build
- npm test -- --coverage
================================================
FILE: LICENSE
================================================
The MIT License (MIT)
Copyright (c) 2018 Jared Petersen
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# codeprinter
[](https://travis-ci.org/jaredpetersen/codeprinter) [](https://paypal.me/jaredtpetersen)
codeprinter's goal is pretty self-explanatory: to make it easier to print out code on paper. Many IDE's either don't allow you to print or have some weird quirks like adding unnecessary headers and footers, not allowing you to change your font size, or not providing syntax highlighting on your printout.
codeprinter makes it easy. Simply copy your code into the text box, select your desired font, font size, syntax highlighting theme, and whether or not you would like line numbers and then hit print.
## Usage
codeprinter is currently hosted by GitHub Pages at http://jaredpetersen.github.io/codeprinter/.
If you're concerned about pasting code into some website, you can use it locally as well. codeprinter is a React project that uses NPM and Node.js, so [you'll need both installed](https://nodejs.org/en/download/) in order to do so. Right now, codeprinter supports Node 8.x or higher, but the latest LTS version is always recommended.
Once that's out of the way, run the following commands to install the dependencies, build the application, and run it:
```
npm install
npm run build
npm start
```
## Screenshots



## How to Contribute
Find a bug? Want to request a new feature? Awesome! Create an [issue](https://github.com/jaredpetersen/codeprinter/issues) and/or submit a [pull request](https://github.com/jaredpetersen/codeprinter/pulls). Just want to show your support for the project? [Buy me a cup of coffee](https://paypal.me/jaredtpetersen).
================================================
FILE: package.json
================================================
{
"name": "codeprinter",
"version": "1.1.2",
"private": true,
"homepage": "http://jaredpetersen.github.io/codeprinter",
"engines": {
"node": ">=8.6.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --watchAll=false",
"pretty": "prettier --print-width 120 --single-quote --write \"**/*.{js,jsx,css,json,md}\"",
"build-storybook": "build-storybook -s public",
"storybook": "start-storybook -p 9009 -s public",
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
},
"jest": {
"collectCoverageFrom": [
"src/**/*.{js,jsx}",
"!<rootDir>/node_modules/",
"!src/index.jsx",
"!src/registerServiceWorker.js",
"!setupTests.js",
"!src/**/*.story.{js,jsx}"
],
"coverageReporters": [
"json",
"lcov",
"html",
"text"
],
"transformIgnorePatterns": [
"/node_modules/(?!(react-syntax-highlighter)/)"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"**/*.{js,jsx,css,json,md}": [
"prettier --print-width 120 --single-quote --write",
"git add"
]
},
"dependencies": {
"bootstrap": "^4.4.1",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router-dom": "^5.1.2",
"react-scripts": "^3.3.0",
"react-syntax-highlighter": "^11.0.2",
"reactstrap": "^8.2.0"
},
"devDependencies": {
"@storybook/addon-actions": "^5.2.8",
"@storybook/addon-links": "^5.2.8",
"@storybook/addons": "^5.2.8",
"@storybook/react": "^5.2.8",
"enzyme": "^3.10.0",
"enzyme-adapter-react-16": "^1.15.1",
"gh-pages": "^2.1.1",
"husky": "^3.1.0",
"lint-staged": "^9.5.0",
"prettier": "1.19.1"
},
"browserslist": [
">0.2%",
"not dead",
"not ie <= 11",
"not op_mini all"
]
}
================================================
FILE: public/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="description" content="Print out code easily">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="theme-color" content="#343a40">
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link href="https://fonts.googleapis.com/css?family=Anonymous+Pro|Cousine|Cutive+Mono|Fira+Mono|IBM+Plex+Mono|Inconsolata|Nanum+Gothic+Coding|Nova+Mono|Overpass+Mono:300,400|Oxygen+Mono|PT+Mono|Roboto+Mono|Share+Tech+Mono|Source+Code+Pro|Space+Mono|Ubuntu+Mono" rel="stylesheet">
<title>codeprinter</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/solid.css" integrity="sha384-TbilV5Lbhlwdyc4RuIV/JhD8NR+BfMrvz4BL5QFa2we1hQu6wvREr3v6XSRfCTRp" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/brands.css" integrity="sha384-7xAnn7Zm3QC1jFjVc1A6v/toepoG3JXboQYzbM0jrPzou9OFXm/fY6Z/XiIebl/k" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/fontawesome.css" integrity="sha384-ozJwkrqb90Oa3ZNb+yKFW2lToAWYdTiF1vt8JiH5ptTGHTGcN7qdoR1F95e0kYyG" crossorigin="anonymous">
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
</body>
</html>
================================================
FILE: public/manifest.json
================================================
{
"short_name": "codeprinter",
"name": "codeprinter",
"description": "Print out code easily",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
}
],
"start_url": "/",
"display": "standalone",
"theme_color": "#343a40",
"background_color": "#ffffff"
}
================================================
FILE: src/App.jsx
================================================
import React, { Component } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Navbar from './navbar';
import Editor from './editor';
import Heart from './heart';
import NotFound from './not-found';
class App extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
return (
<Router basename={process.env.PUBLIC_URL}>
<div className="h-100">
<Navbar />
<Switch>
<Route exact path="/" component={Editor} />
<Route exact path="/heart" component={Heart} />
<Route component={NotFound} />
</Switch>
</div>
</Router>
);
}
}
export default App;
================================================
FILE: src/App.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import App from './App';
describe('App', () => {
it('renders without crashing', () => {
shallow(<App />);
});
});
================================================
FILE: src/common/dropdown-toggle-select/index.css
================================================
.dropdown-toggle-select::after {
display: inline-block;
width: 0;
height: 0;
margin-left: 0.255em;
vertical-align: 0.255em;
content: '';
border-top: 0.3em solid;
border-right: 0.3em solid transparent;
border-bottom: 0;
border-left: 0.3em solid transparent;
position: absolute;
right: 12px;
top: 45%;
}
.btn-outline-dropdown-toggle-select {
background-color: transparent;
background-image: none;
border-color: #ced4da;
}
.btn-outline-dropdown-toggle-select:hover {
}
================================================
FILE: src/common/dropdown-toggle-select/index.jsx
================================================
import React from 'react';
import PropTypes from 'prop-types';
import { DropdownToggle } from 'reactstrap';
import './index.css';
const DropdownToggleSelect = props => {
const style = Object.assign({}, { textAlign: 'left' }, props.style);
return (
<DropdownToggle
outline
color="dropdown-toggle-select"
block
{...props}
className="dropdown-toggle-select"
style={style}
/>
);
};
// Rely on the propTypes provided by reacstrap
DropdownToggleSelect.propTypes = {
className: PropTypes.string,
style: PropTypes.object,
disabled: PropTypes.bool,
onClick: PropTypes.func,
'data-toggle': PropTypes.string,
'aria-haspopup': PropTypes.bool,
// For DropdownToggle usage inside a Nav
nav: PropTypes.bool,
// Defaults to Button component
tag: PropTypes.any
};
export default DropdownToggleSelect;
================================================
FILE: src/common/dropdown-toggle-select/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import 'bootstrap/dist/css/bootstrap.css';
import { UncontrolledDropdown, DropdownMenu, DropdownItem } from 'reactstrap';
import DropdownToggleSelect from './index.jsx';
storiesOf('Common/DropdownToggleSelect', module).add('default', () => (
<UncontrolledDropdown inNavbar>
<DropdownToggleSelect>Dropdown</DropdownToggleSelect>
<DropdownMenu>
<DropdownItem onClick={action('onClick - Item 1')}>Item 1</DropdownItem>
<DropdownItem onClick={action('onClick - Item 2')}>Item 2</DropdownItem>
<DropdownItem onClick={action('onClick - Item 3')}>Item 3</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
));
================================================
FILE: src/common/dropdown-toggle-select/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import DropdownToggleSelect from './index.jsx';
describe('Common DropdownToggleSelect', () => {
it('renders without crashing', () => {
shallow(<DropdownToggleSelect>Dropdown</DropdownToggleSelect>);
});
});
================================================
FILE: src/editor/document/index.css
================================================
@media only print {
.no-print {
display: none !important;
}
}
@media only screen {
.only-print {
display: none !important;
}
}
code {
counter-reset: line;
}
.code-line {
counter-increment: line;
position: relative;
display: block;
margin-left: 2.5em;
padding-left: 1em;
border-left: 1px solid transparent;
}
.code-line:before {
content: ' ' counter(line);
position: absolute;
margin-left: -3.5em;
color: #212529;
}
.code-line:nth-child(n + 10):before {
content: ' ' counter(line);
}
.code-line:nth-child(n + 100):before {
content: counter(line);
}
.code-line-vertical {
counter-increment: line;
position: relative;
display: block;
margin-left: 2.5em;
padding-left: 1em;
border-left: 1px solid #212529;
}
.code-line-vertical:before {
content: ' ' counter(line);
position: absolute;
margin-left: -3.5em;
color: #212529;
}
.code-line-vertical:nth-child(n + 10):before {
content: ' ' counter(line);
}
.code-line-vertical:nth-child(n + 100):before {
content: counter(line);
}
================================================
FILE: src/editor/document/index.jsx
================================================
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Row, Col, Input } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter';
import {
defaultStyle,
arduinoLight,
ascetic,
docco,
githubGist,
grayscale,
idea,
tomorrow,
vs,
xcode
} from 'react-syntax-highlighter/dist/esm/styles/hljs';
import './index.css';
const themeMap = {
Arduino: arduinoLight,
Ascetic: ascetic,
Docco: docco,
GitHub: githubGist,
Grayscale: grayscale,
hljs: defaultStyle,
Idea: idea,
Tomorrow: tomorrow,
VS: vs,
Xcode: xcode
};
const themes = Object.keys(themeMap);
class Document extends Component {
constructor(props) {
super(props);
this.defaultCode =
'// Welcome to codeprinter!\n' +
'const foo = () => {\n' +
" console.log('This is where your code will be printed out!');\n" +
'};';
this.state = {
code: this.defaultCode
};
this.onChange = this.onChange.bind(this);
}
onChange(event) {
const code = event.target.value === '' ? this.defaultCode : event.target.value;
this.setState({ code });
}
render() {
let placeholder = 'Paste your code in here!';
const lineNumberStyle = lineNumbers => {
switch (lineNumbers) {
case 'standard':
return { className: 'code-line' };
case 'vertical':
return { className: 'code-line-vertical' };
default:
return null;
}
};
return (
<div className="h-100 d-flex flex-column">
<Row className="no-print flex-grow-1">
<Col className="flex-grow-1">
<Input
type="textarea"
id="typeSpace"
placeholder={placeholder}
onChange={this.onChange}
style={{ height: '100%', resize: 'none' }}
/>
</Col>
</Row>
<div id="printSpace" className="only-print" style={{ fontSize: '62.5%' }}>
<SyntaxHighlighter
lineProps={lineNumberStyle(this.props.lineNumbers)}
wrapLines={true}
style={themeMap[this.props.theme] || ''}
codeTagProps={{
style: { fontFamily: `"${this.props.font}", monospace`, fontSize: `${this.props.size}pt` }
}}
lineNumberStyle={{ fontFamily: `"${this.props.font}", monospace`, fontSize: `${this.props.size}pt` }}
customStyle={{ border: 'none' }}
>
{this.state.code}
</SyntaxHighlighter>
</div>
</div>
);
}
}
Document.propTypes = {
font: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
theme: PropTypes.oneOf(['None', ...Object.keys(themeMap)]).isRequired,
lineNumbers: PropTypes.oneOf(['none', 'standard', 'vertical']).isRequired
};
export default Document;
export { Document, themes };
================================================
FILE: src/editor/document/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import 'bootstrap/dist/css/bootstrap.css';
import Document from './index';
storiesOf('Editor/Document', module).add('default', () => (
<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} numbers={true} />
));
================================================
FILE: src/editor/document/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import { Document, themes } from './index';
import { Input } from 'reactstrap';
import SyntaxHighlighter from 'react-syntax-highlighter';
describe('Editor Document', () => {
it('renders without crashing', () => {
shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={'standard'} />);
});
it('renders the print section with some default code when text is not provided', () => {
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={'standard'} />);
const expectedDefaultCode =
'// Welcome to codeprinter!\n' +
'const foo = () => {\n' +
" console.log('This is where your code will be printed out!');\n" +
'};';
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.children().text()).toEqual(expectedDefaultCode);
});
it('adds text to the print section when typing in the text area', () => {
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={'standard'} />);
const expectedCode = 'some code';
document.find(Input).simulate('change', { target: { value: expectedCode } });
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.children().text()).toEqual(expectedCode);
});
it('renders the placeholder', () => {
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={'none'} />);
const expectedPlaceholder = 'Paste your code in here!';
const textarea = document.find(Input);
expect(textarea.prop('placeholder')).toEqual(expectedPlaceholder);
});
it('renders the code with the specified font', () => {
const expectedFont = 'Space Mono';
const document = shallow(<Document font={expectedFont} size={12} theme={'GitHub'} lineNumbers={'standard'} />);
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.prop('codeTagProps').style.fontFamily).toEqual(`"${expectedFont}", monospace`);
});
it('renders the code with the specified font size', () => {
const expectedSize = 14;
const document = shallow(
<Document font={'Anonymous Pro'} size={expectedSize} theme={'GitHub'} lineNumbers={'standard'} />
);
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.prop('codeTagProps').style.fontSize).toEqual(`${expectedSize}pt`);
});
it('renders the code with the specified theme', () => {
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={'none'} />);
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.prop('style')).not.toEqual('');
});
it('renders the code with no theme if the theme passed is None', () => {
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'None'} lineNumbers={'none'} />);
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.prop('style')).toEqual('');
});
it('renders the code without line numbers', () => {
const lineNumbers = 'none';
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={lineNumbers} />);
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.prop('lineProps')).toBeNull();
});
it('renders the code with standard line numbers', () => {
const lineNumbers = 'standard';
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={lineNumbers} />);
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.prop('lineProps')).toEqual({ className: 'code-line' });
});
it('renders the code with vertical line numbers', () => {
const lineNumbers = 'vertical';
const document = shallow(<Document font={'Anonymous Pro'} size={12} theme={'GitHub'} lineNumbers={lineNumbers} />);
const syntaxHighlighter = document.find(SyntaxHighlighter);
expect(syntaxHighlighter.prop('lineProps')).toEqual({ className: 'code-line-vertical' });
});
});
describe('Editor Document Theme Map', () => {
it('returns a map of the available themes', () => {
const expectedThemes = [
'Arduino',
'Ascetic',
'Docco',
'GitHub',
'Grayscale',
'hljs',
'Idea',
'Tomorrow',
'VS',
'Xcode'
];
expect(themes).toEqual(expectedThemes);
});
});
================================================
FILE: src/editor/index.jsx
================================================
import React, { Component } from 'react';
import { Container } from 'reactstrap';
import Toolbar from './toolbar';
import { Document, themes } from './document';
class Editor extends Component {
constructor(props) {
super(props);
this.fonts = [
'Anonymous Pro',
'Cousine',
'Cutive Mono',
'Fira Mono',
'IBM Plex Mono',
'Inconsolata',
'Nanum Gothic Coding',
'Nova Mono',
'Overpass Mono',
'Oxygen Mono',
'PT Mono',
'Roboto Mono',
'Share Tech Mono',
'Source Code Pro',
'Space Mono',
'Ubuntu Mono'
];
this.sizes = [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];
this.themes = ['None', ...themes];
this.state = {
style: {
font: this.fonts[11],
size: this.sizes[2],
theme: this.themes[0],
lineNumbers: 'none'
}
};
this.onChange = this.onChange.bind(this);
}
onPrint() {
window.print();
}
onChange(toolbar) {
const style = {
font: toolbar.activeFont,
size: toolbar.activeSize,
theme: toolbar.activeTheme,
lineNumbers: toolbar.lineNumbers
};
this.setState({ style });
}
render() {
return (
<div className="responsive-container">
<Toolbar
fonts={this.fonts}
activeFont={this.state.style.font}
sizes={this.sizes}
activeSize={this.state.style.size}
themes={this.themes}
activeTheme={this.state.style.theme}
lineNumbers={this.state.style.lineNumbers}
onChange={this.onChange}
onPrint={this.onPrint}
/>
<Container fluid={true} className="h-100">
<Document
font={this.state.style.font}
size={this.state.style.size}
theme={this.state.style.theme}
lineNumbers={this.state.style.lineNumbers}
/>
</Container>
</div>
);
}
}
Editor.propTypes = {};
export default Editor;
================================================
FILE: src/editor/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import 'bootstrap/dist/css/bootstrap.css';
import Editor from './index';
storiesOf('Editor', module).add('default', () => <Editor />);
================================================
FILE: src/editor/index.test.jsx
================================================
import React from 'react';
import { shallow, mount } from 'enzyme';
import Editor from './index';
import Toolbar from './toolbar';
import Document from './document';
import FontDropdown from './toolbar/font-dropdown';
import SizeDropdown from './toolbar/size-dropdown';
import ThemeDropdown from './toolbar/theme-dropdown';
import { Button, DropdownItem } from 'reactstrap';
describe('Editor', () => {
it('renders without crashing', () => {
shallow(<Editor />);
});
it('renders a toolbar', () => {
const editor = shallow(<Editor />);
const toolbar = editor.find(Toolbar);
const expectedFonts = [
'Anonymous Pro',
'Cousine',
'Cutive Mono',
'Fira Mono',
'IBM Plex Mono',
'Inconsolata',
'Nanum Gothic Coding',
'Nova Mono',
'Overpass Mono',
'Oxygen Mono',
'PT Mono',
'Roboto Mono',
'Share Tech Mono',
'Source Code Pro',
'Space Mono',
'Ubuntu Mono'
];
expect(toolbar.prop('fonts')).toEqual(expectedFonts);
expect(toolbar.prop('activeFont')).toEqual(expectedFonts[11]);
const expectedSizes = [8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18];
expect(toolbar.prop('sizes')).toEqual(expectedSizes);
expect(toolbar.prop('activeSize')).toEqual(expectedSizes[2]);
const expectedThemes = [
'None',
'Arduino',
'Ascetic',
'Docco',
'GitHub',
'Grayscale',
'hljs',
'Idea',
'Tomorrow',
'VS',
'Xcode'
];
expect(toolbar.prop('themes')).toEqual(expectedThemes);
expect(toolbar.prop('activeTheme')).toEqual(expectedThemes[0]);
expect(toolbar.prop('lineNumbers')).toEqual('none');
});
it('renders a document', () => {
const editor = shallow(<Editor />);
const document = editor.find(Document);
expect(document.prop('font')).toEqual('Roboto Mono');
expect(document.prop('size')).toEqual(10);
expect(document.prop('theme')).toEqual('None');
expect(document.prop('lineNumbers')).toEqual('none');
});
it('prints the page when the print button is pressed', () => {
global.print = jest.fn();
const editor = shallow(<Editor />);
const toolbar = editor.find(Toolbar);
const printButton = toolbar
.dive()
.find(Button)
.find('#print');
printButton.simulate('click');
expect(global.print).toHaveBeenCalledTimes(1);
});
it('renders a font change on toolbar font select', () => {
const editor = shallow(<Editor />);
const toolbar = editor.find(Toolbar);
const fontDropdown = toolbar.dive().find(FontDropdown);
const dropdownItems = fontDropdown.dive().find(DropdownItem);
dropdownItems.at(2).simulate('click');
editor.update();
const document = editor.find(Document);
expect(document.prop('font')).not.toEqual('Roboto Mono');
});
it('renders a size change on toolbar size select', () => {
const editor = shallow(<Editor />);
const toolbar = editor.find(Toolbar);
const sizeDropdown = toolbar.dive().find(SizeDropdown);
const dropdownItems = sizeDropdown.dive().find(DropdownItem);
dropdownItems.at(6).simulate('click');
editor.update();
const document = editor.find(Document);
expect(document.prop('size')).not.toEqual(10);
});
it('renders a theme change on toolbar theme select', () => {
const editor = shallow(<Editor />);
const toolbar = editor.find(Toolbar);
const themeDropdown = toolbar.dive().find(ThemeDropdown);
const dropdownItems = themeDropdown.dive().find(DropdownItem);
dropdownItems.at(2).simulate('click');
editor.update();
const document = editor.find(Document);
expect(document.prop('size')).not.toEqual('None');
});
});
================================================
FILE: src/editor/toolbar/font-dropdown/__snapshots__/index.test.jsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Editor Toolbar FontDropdown renders all of the fonts as dropdown options 1`] = `
<div
className="dropdown"
onKeyDown={[Function]}
>
<button
aria-expanded={false}
aria-haspopup={true}
aria-label={null}
className="dropdown-toggle-select btn btn-outline-dropdown-toggle-select btn-block"
onClick={[Function]}
style={
Object {
"fontFamily": "\\"sans-serif\\", monospace",
"textAlign": "left",
}
}
type="button"
>
sans-serif
</button>
<div
aria-hidden={true}
className="dropdown-menu"
role="menu"
tabIndex="-1"
>
<button
className="dropdown-item"
onClick={[Function]}
role="menuitem"
style={
Object {
"fontFamily": "\\"serif\\", monospace",
}
}
tabIndex="0"
type="button"
>
serif
</button>
<button
className="dropdown-item active"
onClick={[Function]}
role="menuitem"
style={
Object {
"fontFamily": "\\"sans-serif\\", monospace",
}
}
tabIndex="0"
type="button"
>
sans-serif
</button>
</div>
</div>
`;
================================================
FILE: src/editor/toolbar/font-dropdown/index.jsx
================================================
import React from 'react';
import PropTypes from 'prop-types';
import { UncontrolledDropdown, DropdownMenu, DropdownItem } from 'reactstrap';
import DropdownToggleSelect from '../../../common/dropdown-toggle-select';
const FontDropdown = ({ fonts, active, onSelect }) => {
const dropdownItems = fonts.map(font => {
return (
<DropdownItem
key={font}
active={font === active}
onClick={() => onSelect(font)}
style={{ fontFamily: `"${font}", monospace` }}
>
{font}
</DropdownItem>
);
});
return (
<UncontrolledDropdown inNavbar>
<DropdownToggleSelect style={{ fontFamily: `"${active}", monospace` }}>{active}</DropdownToggleSelect>
<DropdownMenu>{dropdownItems}</DropdownMenu>
</UncontrolledDropdown>
);
};
FontDropdown.propTypes = {
fonts: PropTypes.arrayOf(PropTypes.string).isRequired,
active: PropTypes.string.isRequired,
onSelect: PropTypes.func
};
export default FontDropdown;
================================================
FILE: src/editor/toolbar/font-dropdown/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import 'bootstrap/dist/css/bootstrap.css';
import FontDropdown from './index';
storiesOf('Editor/Toolbar/FontDropdown', module).add('default', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
return <FontDropdown fonts={fonts} active={fonts[0]} onSelect={action('selected')} />;
});
================================================
FILE: src/editor/toolbar/font-dropdown/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import renderer from 'react-test-renderer';
import FontDropdown from './index';
import { DropdownItem } from 'reactstrap';
describe('Editor Toolbar FontDropdown', () => {
it('renders without crashing', () => {
const fonts = ['serif', 'sans-serif'];
shallow(<FontDropdown fonts={fonts} active={fonts[0]} onSelect={() => {}} />);
});
it('renders all of the fonts as dropdown options', () => {
const fonts = ['serif', 'sans-serif'];
const tree = renderer.create(<FontDropdown fonts={fonts} active={fonts[1]} onSelect={() => {}} />).toJSON();
expect(tree).toMatchSnapshot();
});
it('calls the onSelect function on selecting a dropdown option', () => {
const fonts = ['serif', 'sans-serif'];
const onSelect = jest.fn();
const fontDropdown = shallow(<FontDropdown fonts={fonts} active={fonts[0]} onSelect={onSelect} />);
fontDropdown
.find(DropdownItem)
.last()
.simulate('click');
expect(onSelect).toHaveBeenCalledTimes(1);
});
});
================================================
FILE: src/editor/toolbar/index.jsx
================================================
import React from 'react';
import PropTypes from 'prop-types';
import { Col, Navbar, Button } from 'reactstrap';
import FontDropdown from './font-dropdown';
import SizeDropdown from './size-dropdown';
import ThemeDropdown from './theme-dropdown';
const Toolbar = ({ fonts, activeFont, sizes, activeSize, themes, activeTheme, lineNumbers, onChange, onPrint }) => {
return (
<Navbar color="#FFFFFF" light expand="sm" style={{ marginBottom: 5 }}>
<div className="form-row" style={{ width: '100%' }}>
<Col xs="9" md="4" className="my-2 my-md-0">
<FontDropdown
fonts={fonts}
active={activeFont}
onSelect={activeFont => onChange({ activeFont, activeSize, activeTheme, lineNumbers })}
/>
</Col>
<Col xs="3" md="2" className="my-2 my-md-0">
<SizeDropdown
sizes={sizes}
active={activeSize}
onSelect={activeSize => onChange({ activeFont, activeSize, activeTheme, lineNumbers })}
/>
</Col>
<Col xs="12" md="3" className="my-2 my-md-0">
<ThemeDropdown
themes={themes}
active={activeTheme}
onSelect={activeTheme => onChange({ activeFont, activeSize, activeTheme, lineNumbers })}
/>
</Col>
<Col xs="4" md="auto" className="my-2 my-md-0">
<Button
id="line-numbers-none"
active={lineNumbers === 'none'}
outline
color="secondary"
style={{ width: '100%' }}
onClick={() => onChange({ activeFont, activeSize, activeTheme, lineNumbers: 'none' })}
>
-
</Button>
</Col>
<Col xs="4" md="auto" className="my-2 my-md-0">
<Button
id="line-numbers-standard"
active={lineNumbers === 'standard'}
outline
color="secondary"
style={{ width: '100%' }}
onClick={() => onChange({ activeFont, activeSize, activeTheme, lineNumbers: 'standard' })}
>
#
</Button>
</Col>
<Col xs="4" md="auto" className="my-2 my-md-0">
<Button
id="line-numbers-vertical"
active={lineNumbers === 'vertical'}
outline
color="secondary"
style={{ width: '100%' }}
onClick={() => onChange({ activeFont, activeSize, activeTheme, lineNumbers: 'vertical' })}
>
#|
</Button>
</Col>
<Col xs="12" md="auto" className="my-2 my-md-0">
<Button id="print" outline color="success" onClick={onPrint} style={{ width: '100%' }}>
Print
</Button>
</Col>
</div>
</Navbar>
);
};
Toolbar.propTypes = {
fonts: PropTypes.arrayOf(PropTypes.string).isRequired,
activeFont: PropTypes.string.isRequired,
sizes: PropTypes.arrayOf(PropTypes.number).isRequired,
activeSize: PropTypes.number.isRequired,
themes: PropTypes.arrayOf(PropTypes.string).isRequired,
activeTheme: PropTypes.string.isRequired,
lineNumbers: PropTypes.oneOf(['none', 'standard', 'vertical']).isRequired,
onChange: PropTypes.func,
onPrint: PropTypes.func
};
export default Toolbar;
================================================
FILE: src/editor/toolbar/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import 'bootstrap/dist/css/bootstrap.css';
import Toolbar from './index';
storiesOf('Editor/Toolbar', module).add('default', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
return (
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
linNumbers={'none'}
onChange={action('changed')}
onPrint={action('print')}
/>
);
});
================================================
FILE: src/editor/toolbar/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import Toolbar from './index';
import FontDropdown from './font-dropdown';
import SizeDropdown from './size-dropdown';
import ThemeDropdown from './theme-dropdown';
describe('Editor Toolbar', () => {
it('renders without crashing', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
shallow(
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
lineNumbers={'none'}
onChange={() => {}}
onPrint={() => {}}
/>
);
});
it('renders the fonts in a dropdown', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
const toolbar = shallow(
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
lineNumbers={'none'}
onChange={() => {}}
onPrint={() => {}}
/>
);
const fontDropdown = toolbar.find(FontDropdown);
expect(fontDropdown.prop('fonts')).toEqual(fonts);
expect(fontDropdown.prop('active')).toEqual(fonts[0]);
});
it('renders the sizes in a dropdown', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
const toolbar = shallow(
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
lineNumbers={'none'}
onChange={() => {}}
onPrint={() => {}}
/>
);
const sizeDropdown = toolbar.find(SizeDropdown);
expect(sizeDropdown.prop('sizes')).toEqual(sizes);
expect(sizeDropdown.prop('active')).toEqual(sizes[0]);
});
it('renders the themes in a dropdown', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
const toolbar = shallow(
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
lineNumbers={'none'}
onChange={() => {}}
onPrint={() => {}}
/>
);
const themeDropdown = toolbar.find(ThemeDropdown);
expect(themeDropdown.prop('themes')).toEqual(themes);
expect(themeDropdown.prop('active')).toEqual(themes[0]);
});
it('renders none line numbers (none)', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
const toolbar = shallow(
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
lineNumbers={'none'}
onChange={() => {}}
onPrint={() => {}}
/>
);
const lineNumbersNoneButton = toolbar.find('#line-numbers-none');
const lineNumbersStandardButton = toolbar.find('#line-numbers-standard');
const lineNumbersVerticalButton = toolbar.find('#line-numbers-vertical');
expect(lineNumbersNoneButton.prop('active')).toEqual(true);
expect(lineNumbersStandardButton.prop('active')).toEqual(false);
expect(lineNumbersVerticalButton.prop('active')).toEqual(false);
});
it('renders none line numbers (standard)', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
const toolbar = shallow(
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
lineNumbers={'standard'}
onChange={() => {}}
onPrint={() => {}}
/>
);
const lineNumbersNoneButton = toolbar.find('#line-numbers-none');
const lineNumbersStandardButton = toolbar.find('#line-numbers-standard');
const lineNumbersVerticalButton = toolbar.find('#line-numbers-vertical');
expect(lineNumbersNoneButton.prop('active')).toEqual(false);
expect(lineNumbersStandardButton.prop('active')).toEqual(true);
expect(lineNumbersVerticalButton.prop('active')).toEqual(false);
});
it('renders none line numbers (none)', () => {
const fonts = ['Anonymous Pro', 'Cousine', 'Cutive Mono'];
const sizes = [8, 9, 10, 11, 12];
const themes = ['GitHub', 'VS', 'Xcode'];
const toolbar = shallow(
<Toolbar
fonts={fonts}
activeFont={fonts[0]}
sizes={sizes}
activeSize={sizes[0]}
themes={themes}
activeTheme={themes[0]}
lineNumbers={'vertical'}
onChange={() => {}}
onPrint={() => {}}
/>
);
const lineNumbersNoneButton = toolbar.find('#line-numbers-none');
const lineNumbersStandardButton = toolbar.find('#line-numbers-standard');
const lineNumbersVerticalButton = toolbar.find('#line-numbers-vertical');
expect(lineNumbersNoneButton.prop('active')).toEqual(false);
expect(lineNumbersStandardButton.prop('active')).toEqual(false);
expect(lineNumbersVerticalButton.prop('active')).toEqual(true);
});
});
================================================
FILE: src/editor/toolbar/size-dropdown/__snapshots__/index.test.jsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Editor Toolbar SizeDropdown renders all of the sizes as dropdown options 1`] = `
<div
className="dropdown"
onKeyDown={[Function]}
>
<button
aria-expanded={false}
aria-haspopup={true}
aria-label={null}
className="dropdown-toggle-select btn btn-outline-dropdown-toggle-select btn-block"
onClick={[Function]}
style={
Object {
"textAlign": "left",
}
}
type="button"
>
9
</button>
<div
aria-hidden={true}
className="dropdown-menu"
role="menu"
tabIndex="-1"
>
<button
className="dropdown-item"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
8
</button>
<button
className="dropdown-item active"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
9
</button>
<button
className="dropdown-item"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
10
</button>
<button
className="dropdown-item"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
11
</button>
<button
className="dropdown-item"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
12
</button>
</div>
</div>
`;
================================================
FILE: src/editor/toolbar/size-dropdown/index.jsx
================================================
import React from 'react';
import PropTypes from 'prop-types';
import { UncontrolledDropdown, DropdownMenu, DropdownItem } from 'reactstrap';
import DropdownToggleSelect from '../../../common/dropdown-toggle-select';
const SizeDropdown = ({ sizes, active, onSelect }) => {
const dropdownItems = sizes.map(size => (
<DropdownItem key={size} active={size === active} onClick={() => onSelect(size)}>
{size}
</DropdownItem>
));
return (
<UncontrolledDropdown inNavbar>
<DropdownToggleSelect>{active}</DropdownToggleSelect>
<DropdownMenu>{dropdownItems}</DropdownMenu>
</UncontrolledDropdown>
);
};
SizeDropdown.propTypes = {
sizes: PropTypes.arrayOf(PropTypes.number).isRequired,
active: PropTypes.number.isRequired,
onSelect: PropTypes.func
};
export default SizeDropdown;
================================================
FILE: src/editor/toolbar/size-dropdown/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import 'bootstrap/dist/css/bootstrap.css';
import SizeDropdown from './index';
storiesOf('Editor/Toolbar/SizeDropdown', module).add('default', () => {
const sizes = [8, 9, 10, 11, 12];
return <SizeDropdown sizes={sizes} active={sizes[0]} onSelect={action('selected')} />;
});
================================================
FILE: src/editor/toolbar/size-dropdown/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import renderer from 'react-test-renderer';
import SizeDropdown from './index';
import { DropdownItem } from 'reactstrap';
describe('Editor Toolbar SizeDropdown', () => {
it('renders without crashing', () => {
const sizes = [8, 9, 10, 11, 12];
shallow(<SizeDropdown sizes={sizes} active={sizes[0]} onSelect={() => {}} />);
});
it('renders all of the sizes as dropdown options', () => {
const sizes = [8, 9, 10, 11, 12];
const tree = renderer.create(<SizeDropdown sizes={sizes} active={sizes[1]} onSelect={() => {}} />).toJSON();
expect(tree).toMatchSnapshot();
});
it('calls the onSelect function on selecting a dropdown option', () => {
const sizes = [8, 9, 10, 11, 12];
const onSelect = jest.fn();
const sizeDropdown = shallow(<SizeDropdown sizes={sizes} active={sizes[0]} onSelect={onSelect} />);
sizeDropdown
.find(DropdownItem)
.last()
.simulate('click');
expect(onSelect).toHaveBeenCalledTimes(1);
});
});
================================================
FILE: src/editor/toolbar/theme-dropdown/__snapshots__/index.test.jsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Editor Toolbar ThemeDropdown renders all of the themes as dropdown options 1`] = `
<div
className="dropdown"
onKeyDown={[Function]}
>
<button
aria-expanded={false}
aria-haspopup={true}
aria-label={null}
className="dropdown-toggle-select btn btn-outline-dropdown-toggle-select btn-block"
onClick={[Function]}
style={
Object {
"textAlign": "left",
}
}
type="button"
>
VS
</button>
<div
aria-hidden={true}
className="dropdown-menu"
role="menu"
tabIndex="-1"
>
<button
className="dropdown-item"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
GitHub
</button>
<button
className="dropdown-item active"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
VS
</button>
<button
className="dropdown-item"
onClick={[Function]}
role="menuitem"
tabIndex="0"
type="button"
>
Xcode
</button>
</div>
</div>
`;
================================================
FILE: src/editor/toolbar/theme-dropdown/index.jsx
================================================
import React from 'react';
import PropTypes from 'prop-types';
import { UncontrolledDropdown, DropdownMenu, DropdownItem } from 'reactstrap';
import DropdownToggleSelect from '../../../common/dropdown-toggle-select';
const ThemeDropdown = ({ themes, active, onSelect }) => {
const dropdownItems = themes.map(theme => (
<DropdownItem key={theme} active={theme === active} onClick={() => onSelect(theme)}>
{theme}
</DropdownItem>
));
return (
<UncontrolledDropdown inNavbar>
<DropdownToggleSelect>{active}</DropdownToggleSelect>
<DropdownMenu>{dropdownItems}</DropdownMenu>
</UncontrolledDropdown>
);
};
ThemeDropdown.propTypes = {
themes: PropTypes.arrayOf(PropTypes.string).isRequired,
active: PropTypes.string.isRequired,
onSelect: PropTypes.func
};
export default ThemeDropdown;
================================================
FILE: src/editor/toolbar/theme-dropdown/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import 'bootstrap/dist/css/bootstrap.css';
import ThemeDropdown from './index';
storiesOf('Editor/Toolbar/ThemeDropdown', module).add('default', () => {
const themes = ['GitHub', 'VS', 'Xcode'];
return <ThemeDropdown themes={themes} active={themes[0]} onSelect={action('selected')} />;
});
================================================
FILE: src/editor/toolbar/theme-dropdown/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import renderer from 'react-test-renderer';
import ThemeDropdown from './index';
import { DropdownItem } from 'reactstrap';
describe('Editor Toolbar ThemeDropdown', () => {
it('renders without crashing', () => {
const themes = ['GitHub', 'VS', 'Xcode'];
shallow(<ThemeDropdown themes={themes} active={themes[0]} onSelect={() => {}} />);
});
it('renders all of the themes as dropdown options', () => {
const themes = ['GitHub', 'VS', 'Xcode'];
const tree = renderer.create(<ThemeDropdown themes={themes} active={themes[1]} onSelect={() => {}} />).toJSON();
expect(tree).toMatchSnapshot();
});
it('calls the onSelect function on selecting a dropdown option ', () => {
const themes = ['GitHub', 'VS', 'Xcode'];
const onSelect = jest.fn();
const themeDropdown = shallow(<ThemeDropdown themes={themes} active={themes[0]} onSelect={onSelect} />);
themeDropdown
.find(DropdownItem)
.last()
.simulate('click');
expect(onSelect).toHaveBeenCalledTimes(1);
});
});
================================================
FILE: src/heart/__snapshots__/index.test.jsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Heart renders correctly 1`] = `
<div
className="responsive-container container-fluid"
style={
Object {
"marginTop": 10,
}
}
>
<div
className="row"
>
<div
className="col"
>
<h2>
<i
className="fas fa-heart text-danger"
title="Heart"
/>
codeprinter?
</h2>
<hr />
<p>
That's awesome! Let the developer know on
<a
href="https://twitter.com/jaredtpetersen"
rel="noopener noreferrer"
target="_blank"
>
Twitter
</a>
,
<a
href="https://paypal.me/jaredtpetersen"
rel="noopener noreferrer"
target="_blank"
>
donate
</a>
, or star the repository on
<a
href="https://github.com/jaredpetersen/codeprinter"
rel="noopener noreferrer"
target="_blank"
>
GitHub
</a>
.
</p>
<p>
Found a bug? Want to request a new feature? Great! Just create an issue on GitHub. We're welcome to pull requests.
</p>
<h2>
<i
className="fas fa-info-circle text-primary"
title="Info"
/>
About the Developer
</h2>
<hr />
<p>
This software was developed by Jared Petersen.
</p>
<p>
You can check out his other repositories on
<a
href="https://github.com/jaredpetersen"
rel="noopener noreferrer"
target="_blank"
>
GitHub
</a>
or look at his résumé on
<a
href="https://www.linkedin.com/in/petersenjared"
rel="noopener noreferrer"
target="_blank"
>
LinkedIn
</a>
</p>
</div>
</div>
</div>
`;
================================================
FILE: src/heart/index.jsx
================================================
import React from 'react';
import { Container, Row, Col } from 'reactstrap';
const Heart = () => {
return (
<Container fluid={true} className="responsive-container" style={{ marginTop: 10 }}>
<Row>
<Col>
<h2>
<i className="fas fa-heart text-danger" title="Heart" /> codeprinter?
</h2>
<hr />
<p>
That's awesome! Let the developer know on{' '}
<a href="https://twitter.com/jaredtpetersen" target="_blank" rel="noopener noreferrer">
Twitter
</a>
,{' '}
<a href="https://paypal.me/jaredtpetersen" target="_blank" rel="noopener noreferrer">
donate
</a>
, or star the repository on{' '}
<a href="https://github.com/jaredpetersen/codeprinter" target="_blank" rel="noopener noreferrer">
GitHub
</a>
.
</p>
<p>
Found a bug? Want to request a new feature? Great! Just create an issue on GitHub. We're welcome to pull
requests.
</p>
<h2>
<i className="fas fa-info-circle text-primary" title="Info" /> About the Developer
</h2>
<hr />
<p>This software was developed by Jared Petersen.</p>
<p>
You can check out his other repositories on{' '}
<a href="https://github.com/jaredpetersen" target="_blank" rel="noopener noreferrer">
GitHub
</a>{' '}
or look at his résumé on{' '}
<a href="https://www.linkedin.com/in/petersenjared" target="_blank" rel="noopener noreferrer">
LinkedIn
</a>
</p>
</Col>
</Row>
</Container>
);
};
Heart.propTypes = {};
export default Heart;
================================================
FILE: src/heart/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import 'bootstrap/dist/css/bootstrap.css';
import Heart from './index';
storiesOf('Heart', module).add('default', () => <Heart />);
================================================
FILE: src/heart/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import renderer from 'react-test-renderer';
import Heart from './index';
describe('Heart', () => {
it('renders without crashing', () => {
shallow(<Heart />);
});
it('renders correctly', () => {
const tree = renderer.create(<Heart />).toJSON();
expect(tree).toMatchSnapshot();
});
});
================================================
FILE: src/index.css
================================================
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
body,
html,
#root {
height: 100%;
}
@media screen and (max-width: 767px) {
.responsive-container {
height: calc(100% - 254px);
}
}
@media screen and (min-width: 768px) {
.responsive-container {
height: calc(100% - 130px);
}
}
================================================
FILE: src/index.jsx
================================================
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import 'bootstrap/dist/css/bootstrap.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render(<App />, document.getElementById('root'));
registerServiceWorker();
================================================
FILE: src/navbar/index.jsx
================================================
import React from 'react';
import { Collapse, Navbar, NavbarToggler, NavbarBrand, Nav, NavItem, NavLink, Badge } from 'reactstrap';
import { Link } from 'react-router-dom';
class CustomNavbar extends React.Component {
constructor(props) {
super(props);
this.state = {
isOpen: false,
sizes: Array.from({ length: 9 }, (x, i) => i + 8)
};
this.toggle = this.toggle.bind(this);
}
toggle() {
this.setState({ isOpen: !this.state.isOpen });
}
render() {
return (
<Navbar color="dark" dark expand="sm" className="flex-shrink-0">
<NavbarBrand tag={Link} to="/">
<Badge color="success">codeprinter</Badge>
</NavbarBrand>
<NavbarToggler onClick={this.toggle} />
<Collapse isOpen={this.state.isOpen} navbar>
<Nav className="ml-auto" navbar>
<NavItem>
<NavLink href="https://github.com/jaredpetersen/codeprinter" target="_blank">
<i className="fab fa-github-alt text-white" title="GitHub" />
</NavLink>
</NavItem>
<NavItem>
<NavLink tag={Link} to="/heart">
<i className="fas fa-heart text-danger" title="Heart" />
</NavLink>
</NavItem>
</Nav>
</Collapse>
</Navbar>
);
}
}
CustomNavbar.propTypes = {};
export default CustomNavbar;
================================================
FILE: src/navbar/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import { BrowserRouter as Router } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.css';
import Navbar from './index';
storiesOf('Navbar', module).add('default', () => (
<Router>
<Navbar />
</Router>
));
================================================
FILE: src/navbar/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import Navbar from './index';
import { NavbarToggler, Collapse } from 'reactstrap';
describe('Navbar', () => {
it('renders without crashing', () => {
shallow(<Navbar />);
});
it('toggles the navbar when clicking on the navbar toggler', () => {
const navbar = shallow(<Navbar />);
const navbarToggler = navbar.find(NavbarToggler);
expect(navbar.find(Collapse).prop('isOpen')).toEqual(false);
navbarToggler.simulate('click');
expect(navbar.find(Collapse).prop('isOpen')).toEqual(true);
});
});
================================================
FILE: src/not-found/__snapshots__/index.test.jsx.snap
================================================
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`NotFound renders correctly 1`] = `
<div
className="responsive-container container-fluid"
style={
Object {
"marginTop": 10,
}
}
>
<div
className="row"
>
<div
className="col"
>
<h2>
<i
className="fas fa-map-signs text-warning"
/>
404 Not Found
</h2>
<hr />
<p>
It looks like you're lost. Let's go
<a
href="/"
onClick={[Function]}
>
home
</a>
.
</p>
</div>
</div>
</div>
`;
================================================
FILE: src/not-found/index.jsx
================================================
import React from 'react';
import { Container, Row, Col } from 'reactstrap';
import { Link } from 'react-router-dom';
const NotFound = () => {
return (
<Container fluid={true} className="responsive-container" style={{ marginTop: 10 }}>
<Row>
<Col>
<h2>
<i className="fas fa-map-signs text-warning" /> 404 Not Found
</h2>
<hr />
<p>
It looks like you're lost. Let's go <Link to="/">home</Link>.
</p>
</Col>
</Row>
</Container>
);
};
NotFound.propTypes = {};
export default NotFound;
================================================
FILE: src/not-found/index.story.jsx
================================================
import React from 'react';
import { storiesOf } from '@storybook/react';
import { BrowserRouter as Router } from 'react-router-dom';
import 'bootstrap/dist/css/bootstrap.css';
import NotFound from './index';
storiesOf('Not Found', module).add('default', () => (
<Router>
<NotFound />
</Router>
));
================================================
FILE: src/not-found/index.test.jsx
================================================
import React from 'react';
import { shallow } from 'enzyme';
import renderer from 'react-test-renderer';
import NotFound from './index';
import { BrowserRouter as Router } from 'react-router-dom';
describe('NotFound', () => {
it('renders without crashing', () => {
shallow(<NotFound />);
});
it('renders correctly', () => {
const tree = renderer
.create(
<Router>
<NotFound />
</Router>
)
.toJSON();
expect(tree).toMatchSnapshot();
});
});
================================================
FILE: src/registerServiceWorker.js
================================================
// In production, we register a service worker to serve assets from local cache.
// This lets the app load faster on subsequent visits in production, and gives
// it offline capabilities. However, it also means that developers (and users)
// will only see deployed updates on the "N+1" visit to a page, since previously
// cached resources are updated in the background.
// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
// This link also includes instructions on opting out of this behavior.
const isLocalhost = Boolean(
window.location.hostname === 'localhost' ||
// [::1] is the IPv6 localhost address.
window.location.hostname === '[::1]' ||
// 127.0.0.1/8 is considered localhost for IPv4.
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
);
export default function register() {
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
// The URL constructor is available in all browsers that support SW.
const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
if (publicUrl.origin !== window.location.origin) {
// Our service worker won't work if PUBLIC_URL is on a different origin
// from what our page is served on. This might happen if a CDN is used to
// serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
return;
}
window.addEventListener('load', () => {
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
if (isLocalhost) {
// This is running on localhost. Lets check if a service worker still exists or not.
checkValidServiceWorker(swUrl);
// Add some additional logging to localhost, pointing developers to the
// service worker/PWA documentation.
navigator.serviceWorker.ready.then(() => {
console.log(
'This web app is being served cache-first by a service ' +
'worker. To learn more, visit https://goo.gl/SC7cgQ'
);
});
} else {
// Is not local host. Just register service worker
registerValidSW(swUrl);
}
});
}
}
function registerValidSW(swUrl) {
navigator.serviceWorker
.register(swUrl)
.then(registration => {
registration.onupdatefound = () => {
const installingWorker = registration.installing;
installingWorker.onstatechange = () => {
if (installingWorker.state === 'installed') {
if (navigator.serviceWorker.controller) {
// At this point, the old content will have been purged and
// the fresh content will have been added to the cache.
// It's the perfect time to display a "New content is
// available; please refresh." message in your web app.
console.log('New content is available; please refresh.');
} else {
// At this point, everything has been precached.
// It's the perfect time to display a
// "Content is cached for offline use." message.
console.log('Content is cached for offline use.');
}
}
};
};
})
.catch(error => {
console.error('Error during service worker registration:', error);
});
}
function checkValidServiceWorker(swUrl) {
// Check if the service worker can be found. If it can't reload the page.
fetch(swUrl)
.then(response => {
// Ensure service worker exists, and that we really are getting a JS file.
if (response.status === 404 || response.headers.get('content-type').indexOf('javascript') === -1) {
// No service worker found. Probably a different app. Reload the page.
navigator.serviceWorker.ready.then(registration => {
registration.unregister().then(() => {
window.location.reload();
});
});
} else {
// Service worker found. Proceed as normal.
registerValidSW(swUrl);
}
})
.catch(() => {
console.log('No internet connection found. App is running in offline mode.');
});
}
export function unregister() {
if ('serviceWorker' in navigator) {
navigator.serviceWorker.ready.then(registration => {
registration.unregister();
});
}
}
================================================
FILE: src/setupTests.js
================================================
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });
gitextract_yqxvaw7a/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── .storybook/
│ ├── addons.js
│ ├── config.js
│ └── preview-head.html
├── .travis.yml
├── LICENSE
├── README.md
├── package.json
├── public/
│ ├── index.html
│ └── manifest.json
└── src/
├── App.jsx
├── App.test.jsx
├── common/
│ └── dropdown-toggle-select/
│ ├── index.css
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── editor/
│ ├── document/
│ │ ├── index.css
│ │ ├── index.jsx
│ │ ├── index.story.jsx
│ │ └── index.test.jsx
│ ├── index.jsx
│ ├── index.story.jsx
│ ├── index.test.jsx
│ └── toolbar/
│ ├── font-dropdown/
│ │ ├── __snapshots__/
│ │ │ └── index.test.jsx.snap
│ │ ├── index.jsx
│ │ ├── index.story.jsx
│ │ └── index.test.jsx
│ ├── index.jsx
│ ├── index.story.jsx
│ ├── index.test.jsx
│ ├── size-dropdown/
│ │ ├── __snapshots__/
│ │ │ └── index.test.jsx.snap
│ │ ├── index.jsx
│ │ ├── index.story.jsx
│ │ └── index.test.jsx
│ └── theme-dropdown/
│ ├── __snapshots__/
│ │ └── index.test.jsx.snap
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── heart/
│ ├── __snapshots__/
│ │ └── index.test.jsx.snap
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── index.css
├── index.jsx
├── navbar/
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── not-found/
│ ├── __snapshots__/
│ │ └── index.test.jsx.snap
│ ├── index.jsx
│ ├── index.story.jsx
│ └── index.test.jsx
├── registerServiceWorker.js
└── setupTests.js
SYMBOL INDEX (21 symbols across 6 files)
FILE: .storybook/config.js
function loadStories (line 3) | function loadStories() {
FILE: src/App.jsx
class App (line 8) | class App extends Component {
method constructor (line 9) | constructor(props) {
method render (line 15) | render() {
FILE: src/editor/document/index.jsx
class Document (line 34) | class Document extends Component {
method constructor (line 35) | constructor(props) {
method onChange (line 51) | onChange(event) {
method render (line 56) | render() {
FILE: src/editor/index.jsx
class Editor (line 6) | class Editor extends Component {
method constructor (line 7) | constructor(props) {
method onPrint (line 45) | onPrint() {
method onChange (line 49) | onChange(toolbar) {
method render (line 59) | render() {
FILE: src/navbar/index.jsx
class CustomNavbar (line 5) | class CustomNavbar extends React.Component {
method constructor (line 6) | constructor(props) {
method toggle (line 17) | toggle() {
method render (line 21) | render() {
FILE: src/registerServiceWorker.js
function register (line 19) | function register() {
function registerValidSW (line 53) | function registerValidSW(swUrl) {
function checkValidServiceWorker (line 82) | function checkValidServiceWorker(swUrl) {
function unregister (line 104) | function unregister() {
Condensed preview — 54 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (67K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 109,
"preview": "# These are supported funding model platforms\n\ngithub: jaredpetersen\ncustom: https://paypal.me/jaredtpetersen"
},
{
"path": ".gitignore",
"chars": 303,
"preview": "# See https://help.github.com/ignore-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n\n# testing\n/cov"
},
{
"path": ".storybook/addons.js",
"chars": 86,
"preview": "import '@storybook/addon-actions/register';\nimport '@storybook/addon-links/register';\n"
},
{
"path": ".storybook/config.js",
"chars": 656,
"preview": "import { configure } from '@storybook/react';\n\nfunction loadStories() {\n require('../src/common/dropdown-toggle-select/"
},
{
"path": ".storybook/preview-head.html",
"chars": 598,
"preview": "<link rel=\"stylesheet\" href=\"https://use.fontawesome.com/releases/v5.1.0/css/solid.css\" integrity=\"sha384-TbilV5Lbhlwdyc"
},
{
"path": ".travis.yml",
"chars": 119,
"preview": "language: node_js\nnode_js:\n - \"node\"\n - \"lts/*\"\n - \"9\"\n - \"8\"\nscript:\n - npm run build\n - npm test -- --coverage\n"
},
{
"path": "LICENSE",
"chars": 1081,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2018 Jared Petersen\n\nPermission is hereby granted, free of charge, to any person ob"
},
{
"path": "README.md",
"chars": 1883,
"preview": "# codeprinter\n\n[](https://travis-ci.or"
},
{
"path": "package.json",
"chars": 1929,
"preview": "{\n \"name\": \"codeprinter\",\n \"version\": \"1.1.2\",\n \"private\": true,\n \"homepage\": \"http://jaredpetersen.github.io/codepr"
},
{
"path": "public/index.html",
"chars": 1465,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <meta name=\"description\" content=\"Print out cod"
},
{
"path": "public/manifest.json",
"chars": 338,
"preview": "{\n \"short_name\": \"codeprinter\",\n \"name\": \"codeprinter\",\n \"description\": \"Print out code easily\",\n \"icons\": [\n {\n "
},
{
"path": "src/App.jsx",
"chars": 734,
"preview": "import React, { Component } from 'react';\nimport { BrowserRouter as Router, Switch, Route } from 'react-router-dom';\nimp"
},
{
"path": "src/App.test.jsx",
"chars": 184,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport App from './App';\n\ndescribe('App', () => {\n it('ren"
},
{
"path": "src/common/dropdown-toggle-select/index.css",
"chars": 500,
"preview": ".dropdown-toggle-select::after {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 0.255em;\n vertical-al"
},
{
"path": "src/common/dropdown-toggle-select/index.jsx",
"chars": 858,
"preview": "import React from 'react';\nimport PropTypes from 'prop-types';\nimport { DropdownToggle } from 'reactstrap';\nimport './in"
},
{
"path": "src/common/dropdown-toggle-select/index.story.jsx",
"chars": 765,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport { action } from '@storybook/addon-action"
},
{
"path": "src/common/dropdown-toggle-select/index.test.jsx",
"chars": 277,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport DropdownToggleSelect from './index.jsx';\n\ndescribe('"
},
{
"path": "src/editor/document/index.css",
"chars": 1049,
"preview": "@media only print {\n .no-print {\n display: none !important;\n }\n}\n\n@media only screen {\n .only-print {\n display:"
},
{
"path": "src/editor/document/index.jsx",
"chars": 2877,
"preview": "import React, { Component } from 'react';\nimport PropTypes from 'prop-types';\nimport { Row, Col, Input } from 'reactstra"
},
{
"path": "src/editor/document/index.story.jsx",
"chars": 293,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport 'bootstrap/dist/css/bootstrap.css';\nimpo"
},
{
"path": "src/editor/document/index.test.jsx",
"chars": 4601,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport { Document, themes } from './index';\nimport { Input "
},
{
"path": "src/editor/index.jsx",
"chars": 1995,
"preview": "import React, { Component } from 'react';\nimport { Container } from 'reactstrap';\nimport Toolbar from './toolbar';\nimpor"
},
{
"path": "src/editor/index.story.jsx",
"chars": 209,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport 'bootstrap/dist/css/bootstrap.css';\nimpo"
},
{
"path": "src/editor/index.test.jsx",
"chars": 3735,
"preview": "import React from 'react';\nimport { shallow, mount } from 'enzyme';\nimport Editor from './index';\nimport Toolbar from '."
},
{
"path": "src/editor/toolbar/font-dropdown/__snapshots__/index.test.jsx.snap",
"chars": 1217,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Editor Toolbar FontDropdown renders all of the fonts as dropdown op"
},
{
"path": "src/editor/toolbar/font-dropdown/index.jsx",
"chars": 983,
"preview": "import React from 'react';\nimport PropTypes from 'prop-types';\nimport { UncontrolledDropdown, DropdownMenu, DropdownItem"
},
{
"path": "src/editor/toolbar/font-dropdown/index.story.jsx",
"chars": 431,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport { action } from '@storybook/addon-action"
},
{
"path": "src/editor/toolbar/font-dropdown/index.test.jsx",
"chars": 1064,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport renderer from 'react-test-renderer';\nimport FontDrop"
},
{
"path": "src/editor/toolbar/index.jsx",
"chars": 3260,
"preview": "import React from 'react';\nimport PropTypes from 'prop-types';\nimport { Col, Navbar, Button } from 'reactstrap';\nimport "
},
{
"path": "src/editor/toolbar/index.story.jsx",
"chars": 683,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport { action } from '@storybook/addon-action"
},
{
"path": "src/editor/toolbar/index.test.jsx",
"chars": 5625,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport Toolbar from './index';\nimport FontDropdown from './"
},
{
"path": "src/editor/toolbar/size-dropdown/__snapshots__/index.test.jsx.snap",
"chars": 1422,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Editor Toolbar SizeDropdown renders all of the sizes as dropdown op"
},
{
"path": "src/editor/toolbar/size-dropdown/index.jsx",
"chars": 822,
"preview": "import React from 'react';\nimport PropTypes from 'prop-types';\nimport { UncontrolledDropdown, DropdownMenu, DropdownItem"
},
{
"path": "src/editor/toolbar/size-dropdown/index.story.jsx",
"chars": 406,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport { action } from '@storybook/addon-action"
},
{
"path": "src/editor/toolbar/size-dropdown/index.test.jsx",
"chars": 1049,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport renderer from 'react-test-renderer';\nimport SizeDrop"
},
{
"path": "src/editor/toolbar/theme-dropdown/__snapshots__/index.test.jsx.snap",
"chars": 1112,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Editor Toolbar ThemeDropdown renders all of the themes as dropdown "
},
{
"path": "src/editor/toolbar/theme-dropdown/index.jsx",
"chars": 833,
"preview": "import React from 'react';\nimport PropTypes from 'prop-types';\nimport { UncontrolledDropdown, DropdownMenu, DropdownItem"
},
{
"path": "src/editor/toolbar/theme-dropdown/index.story.jsx",
"chars": 420,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport { action } from '@storybook/addon-action"
},
{
"path": "src/editor/toolbar/theme-dropdown/index.test.jsx",
"chars": 1091,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport renderer from 'react-test-renderer';\nimport ThemeDro"
},
{
"path": "src/heart/__snapshots__/index.test.jsx.snap",
"chars": 1966,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`Heart renders correctly 1`] = `\n<div\n className=\"responsive-contai"
},
{
"path": "src/heart/index.jsx",
"chars": 1839,
"preview": "import React from 'react';\nimport { Container, Row, Col } from 'reactstrap';\n\nconst Heart = () => {\n return (\n <Cont"
},
{
"path": "src/heart/index.story.jsx",
"chars": 206,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport 'bootstrap/dist/css/bootstrap.css';\nimpo"
},
{
"path": "src/heart/index.test.jsx",
"chars": 368,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport renderer from 'react-test-renderer';\nimport Heart fr"
},
{
"path": "src/index.css",
"chars": 310,
"preview": "body {\n margin: 0;\n padding: 0;\n font-family: sans-serif;\n}\n\nbody,\nhtml,\n#root {\n height: 100%;\n}\n\n@media screen and"
},
{
"path": "src/index.jsx",
"chars": 297,
"preview": "import React from 'react';\nimport ReactDOM from 'react-dom';\nimport './index.css';\nimport 'bootstrap/dist/css/bootstrap."
},
{
"path": "src/navbar/index.jsx",
"chars": 1394,
"preview": "import React from 'react';\nimport { Collapse, Navbar, NavbarToggler, NavbarBrand, Nav, NavItem, NavLink, Badge } from 'r"
},
{
"path": "src/navbar/index.story.jsx",
"chars": 300,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport { BrowserRouter as Router } from 'react-"
},
{
"path": "src/navbar/index.test.jsx",
"chars": 590,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport Navbar from './index';\nimport { NavbarToggler, Colla"
},
{
"path": "src/not-found/__snapshots__/index.test.jsx.snap",
"chars": 608,
"preview": "// Jest Snapshot v1, https://goo.gl/fbAQLP\n\nexports[`NotFound renders correctly 1`] = `\n<div\n className=\"responsive-con"
},
{
"path": "src/not-found/index.jsx",
"chars": 599,
"preview": "import React from 'react';\nimport { Container, Row, Col } from 'reactstrap';\nimport { Link } from 'react-router-dom';\n\nc"
},
{
"path": "src/not-found/index.story.jsx",
"chars": 307,
"preview": "import React from 'react';\nimport { storiesOf } from '@storybook/react';\nimport { BrowserRouter as Router } from 'react-"
},
{
"path": "src/not-found/index.test.jsx",
"chars": 507,
"preview": "import React from 'react';\nimport { shallow } from 'enzyme';\nimport renderer from 'react-test-renderer';\nimport NotFound"
},
{
"path": "src/registerServiceWorker.js",
"chars": 4332,
"preview": "// In production, we register a service worker to serve assets from local cache.\n\n// This lets the app load faster on su"
},
{
"path": "src/setupTests.js",
"chars": 123,
"preview": "import { configure } from 'enzyme';\nimport Adapter from 'enzyme-adapter-react-16';\n\nconfigure({ adapter: new Adapter() }"
}
]
About this extraction
This page contains the full source code of the jaredpetersen/codeprinter GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 54 files (59.4 KB), approximately 16.7k tokens, and a symbol index with 21 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.