mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-30 11:40:27 +02:00
dual rendering possible using --singles
This commit is contained in:
47
article.js
47
article.js
File diff suppressed because one or more lines are too long
@@ -1,13 +1,5 @@
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
var Article = require("./Article.jsx");
|
||||
|
||||
require("../stylesheets/style.less");
|
||||
|
||||
ReactDOM.render(<Article/>, document.getElementById("article"), function() {
|
||||
// trigger a #hash navigation
|
||||
if (window.location.hash) {
|
||||
var hash = window.location.hash;
|
||||
window.location.hash = hash;
|
||||
}
|
||||
});
|
||||
var FullArticle = require("./FullArticle.jsx");
|
||||
var generateSingleSection = require("../pages/generateSingleSection");
|
||||
ReactDOM.render(<FullArticle/>, document.getElementById("article"));
|
||||
|
@@ -1,62 +0,0 @@
|
||||
var React = require("react");
|
||||
var ReactDOM = require("react-dom");
|
||||
var Ribbon = require("./Ribbon.jsx");
|
||||
|
||||
var Article = React.createClass({
|
||||
|
||||
getInitialState: function() {
|
||||
return {
|
||||
sections: require("./sections")
|
||||
};
|
||||
},
|
||||
|
||||
setSectionId: function(name, entry) {
|
||||
ReactDOM.findDOMNode(this.refs[name]).setAttribute("id", name);
|
||||
},
|
||||
|
||||
componentDidMount: function() {
|
||||
// Not sure why this doesn't just work by passing a props.id
|
||||
this.sectionMap(this.setSectionId);
|
||||
},
|
||||
|
||||
sectionMap: function(mapping) {
|
||||
return this.getSectionNames().map(mapping);
|
||||
},
|
||||
|
||||
getSectionNames: function() {
|
||||
return Object.keys(this.state.sections);
|
||||
},
|
||||
|
||||
generateSection: function(name, entry) {
|
||||
var Type = this.state.sections[name];
|
||||
return <Type key={name} ref={name} name={name} number={entry}/>;
|
||||
},
|
||||
|
||||
generateNavItem: function(section, entry) {
|
||||
var name = section.props.name;
|
||||
var title = section.props.title;
|
||||
return <li key={name} data-number={entry}><a href={'#' + name}>{ title }</a></li>;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var sections = this.sectionMap(this.generateSection);
|
||||
return (<div>
|
||||
<Ribbon />
|
||||
<div ref="navigation">
|
||||
<navigation>
|
||||
<ul className="navigation">
|
||||
{ sections.map(this.generateNavItem) }
|
||||
</ul>
|
||||
</navigation>
|
||||
</div>
|
||||
<div ref="sections">{ sections }</div>
|
||||
<footer class="copyright">
|
||||
This article is © 2011-2016 to me, Mike "Pomax" Kamermans, but the text, code,
|
||||
and images are <a href="https://github.com/Pomax/bezierinfo/blob/gh-pages/LICENSE.md">almost
|
||||
no rights reserved</a>. Go do something cool with it!
|
||||
</footer>
|
||||
</div>);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Article;
|
17
components/Footer.jsx
Normal file
17
components/Footer.jsx
Normal file
@@ -0,0 +1,17 @@
|
||||
var React = require('react');
|
||||
|
||||
var Footer = React.createClass({
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<footer className="copyright">
|
||||
This article is © 2011-2016 to me, Mike "Pomax" Kamermans, but the text, code,
|
||||
and images are <a href="https://github.com/Pomax/bezierinfo/blob/gh-pages/LICENSE.md">almost
|
||||
no rights reserved</a>. Go do something cool with it!
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
module.exports = Footer;
|
19
components/FullArticle.jsx
Normal file
19
components/FullArticle.jsx
Normal file
@@ -0,0 +1,19 @@
|
||||
var React = require("react");
|
||||
var Page = require("./Page.jsx");
|
||||
|
||||
var sectionList = require("./sections"),
|
||||
sectionMap = function(mapping) {
|
||||
return Object.keys(sectionList).map(mapping);
|
||||
},
|
||||
allSections = sectionMap(function(name, entry) {
|
||||
var Type = sectionList[name];
|
||||
return <Type key={name} name={name} number={entry} />;
|
||||
});
|
||||
|
||||
var FullArticle = React.createClass({
|
||||
render: function() {
|
||||
return <Page content={ allSections }/>;
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = FullArticle;
|
14
components/Header.jsx
Normal file
14
components/Header.jsx
Normal file
@@ -0,0 +1,14 @@
|
||||
var React = require('react');
|
||||
|
||||
var Header = React.createClass({
|
||||
render: function() {
|
||||
return (
|
||||
<header>
|
||||
<h1>A Primer on Bézier Curves</h1>
|
||||
<h2>A free, online book for when you really need to know how to do Bézier things.</h2>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Header;
|
38
components/Navigation.jsx
Normal file
38
components/Navigation.jsx
Normal file
@@ -0,0 +1,38 @@
|
||||
var React = require('react');
|
||||
var ReactRouter = require('react-router');
|
||||
var Link = ReactRouter.Link;
|
||||
|
||||
var sections = require("./sections");
|
||||
var sectionPages = Object.keys(sections);
|
||||
|
||||
// LESS is automatically turned into CSS and bundled in:
|
||||
require("../stylesheets/style.less");
|
||||
|
||||
var Navigation = React.createClass({
|
||||
generateNavItem: function(name, entry) {
|
||||
var Type = sections[name];
|
||||
var title = Type.getDefaultProps().title;
|
||||
var link = <a href={'#' + name}>{ title }</a>;
|
||||
if (this.props.fullNav) { link = <Link to={(name!=="preface") ? name : "/"}>{title}</Link>; }
|
||||
return <li key={name} data-number={entry}>{link}</li>;
|
||||
},
|
||||
|
||||
generateNav: function() {
|
||||
if (this.props.compact) return null;
|
||||
return (
|
||||
<div ref="navigation">
|
||||
<navigation className={ this.props.compact ? "compact" : null }>
|
||||
<ul className="navigation">
|
||||
{ sectionPages.map(this.generateNavItem) }
|
||||
</ul>
|
||||
</navigation>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return this.generateNav();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Navigation;
|
31
components/Page.jsx
Normal file
31
components/Page.jsx
Normal file
@@ -0,0 +1,31 @@
|
||||
var React = require("react");
|
||||
|
||||
var Ribbon = require("./Ribbon.jsx");
|
||||
var Header = require("./Header.jsx");
|
||||
var Relatives = require("./Relatives.jsx");
|
||||
var Navigation = require("./Navigation.jsx");
|
||||
var Footer = require("./Footer.jsx");
|
||||
|
||||
var Page = React.createClass({
|
||||
render: function() {
|
||||
var nav = <Navigation compact={this.props.compact}/>;
|
||||
var orderedContent = [nav].concat();
|
||||
if (this.props.compact) {
|
||||
orderedContent.splice(0,1);
|
||||
orderedContent.push(nav);
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<Ribbon/>
|
||||
<Header/>
|
||||
{nav}
|
||||
<Relatives prev={this.props.prev} next={this.props.next} position="before" />
|
||||
{this.props.content}
|
||||
<Relatives prev={this.props.prev} next={this.props.next} position="after" />
|
||||
<Footer/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Page;
|
46
components/Relatives.jsx
Normal file
46
components/Relatives.jsx
Normal file
@@ -0,0 +1,46 @@
|
||||
var React = require('react');
|
||||
var ReactRouter = require('react-router');
|
||||
var Link = ReactRouter.Link;
|
||||
|
||||
var sections = require("./sections");
|
||||
var pageIDs = Object.keys(sections);
|
||||
|
||||
var Relatives = React.createClass({
|
||||
getInitialState() {
|
||||
console.log(this.props);
|
||||
|
||||
var prev = this.props.prev;
|
||||
if (prev > -1) {
|
||||
prev = {
|
||||
to: pageIDs[prev],
|
||||
title: sections[pageIDs[prev]].getDefaultProps().title
|
||||
};
|
||||
} else { prev = false; }
|
||||
|
||||
var next = this.props.next;
|
||||
if (next < pageIDs.length) {
|
||||
next = {
|
||||
to: pageIDs[next],
|
||||
title: sections[pageIDs[next]].getDefaultProps().title
|
||||
};
|
||||
} else { next = false; }
|
||||
|
||||
return {
|
||||
prev: prev,
|
||||
next: next
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
if (!this.props.prev && !this.props.next) return null;
|
||||
return (
|
||||
<div className={"relatives " + this.props.position}>
|
||||
{ !this.state.next ? null : <Link className="next" to={this.state.next.to}>{this.props.next + ". " + this.state.next.title}</Link> }
|
||||
{ this.state.prev ? <Link to="/">Index</Link> : null }
|
||||
{ !this.state.prev ? null : <Link className="prev" to={this.state.prev.to}>{this.props.prev + ". " + this.state.prev.title}</Link> }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = Relatives;
|
@@ -6,7 +6,8 @@ module.exports = function(Component) {
|
||||
propName = options.propName || "",
|
||||
values = options.values || {},
|
||||
controller = options.controller || noop,
|
||||
getDefaultProps = Component.getDefaultProps;
|
||||
getDefaultProps = Component.getDefaultProps,
|
||||
ref = "wrappedComponent";
|
||||
|
||||
return React.createClass({
|
||||
values: values,
|
||||
@@ -26,8 +27,16 @@ module.exports = function(Component) {
|
||||
}
|
||||
},
|
||||
|
||||
getComponent: function() {
|
||||
var wrappedComponent = this.refs[ref];
|
||||
if (wrappedComponent.getComponent) {
|
||||
return wrappedComponent.getComponent();
|
||||
}
|
||||
return wrappedComponent;
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return <Component {...this.props} onKeyDown={this.onKeyDown} />;
|
||||
return <Component {...this.props} onKeyDown={this.onKeyDown} ref={ref} />;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
31
index.html
31
index.html
@@ -43,20 +43,20 @@
|
||||
</div>
|
||||
|
||||
<article>
|
||||
<!-- these rules will get overwritten by the style in the article.js React bundle -->
|
||||
<style>
|
||||
header h1, header h2 { text-align: center; }
|
||||
header h1 { font-size: 300%; margin: 0.2em; }
|
||||
p.jsnote { margin: 2em; text-align: justify; }
|
||||
p.jsnote:first-child { width: 13em; margin: auto; }
|
||||
</style>
|
||||
|
||||
<header>
|
||||
<h1>A Primer on Bézier Curves</h1>
|
||||
<h2>A free, online book for when you really need to know how to do Bézier things.</h2>
|
||||
</header>
|
||||
|
||||
<div id="article">
|
||||
<!-- these rules will get overwritten by the style in the article.js React bundle -->
|
||||
<style>
|
||||
header h1, header h2 { text-align: center; }
|
||||
header h1 { font-size: 300%; margin: 0.2em; }
|
||||
p.jsnote { margin: 2em; text-align: justify; }
|
||||
p.jsnote:first-child { width: 13em; margin: auto; }
|
||||
</style>
|
||||
|
||||
<header>
|
||||
<h1>A Primer on Bézier Curves</h1>
|
||||
<h2>A free, online book for when you really need to know how to do Bézier things.</h2>
|
||||
</header>
|
||||
|
||||
<!-- This content only shows for as long as JS/React hasn't loaded the page content -->
|
||||
<p class="jsnote">Loading book content<span id="loader">...</span></p>
|
||||
|
||||
@@ -66,9 +66,10 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<script src="article.js" async></script>
|
||||
|
||||
<!-- referral tracking, because I like knowing who's linking to my book -->
|
||||
<script src="lib/site/referrer.js" async></script>
|
||||
|
||||
<!-- the actual article is a JS bundle -->
|
||||
<script src="article.js" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
2209
lgvalues-abscissa.php
Normal file
2209
lgvalues-abscissa.php
Normal file
File diff suppressed because it is too large
Load Diff
2209
lgvalues-weights.php
Normal file
2209
lgvalues-weights.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,10 +4,11 @@
|
||||
"description": "pomax.github.io/bezierinfo",
|
||||
"scripts": {
|
||||
"build": "webpack --prod",
|
||||
"dev": "webpack-dev-server --progress --colors --hot --inline",
|
||||
"latex": "node tools/mathjax",
|
||||
"start": "webpack-dev-server --progress --colors --hot --inline",
|
||||
"style": "webpack --jscs",
|
||||
"test": "npm run lint"
|
||||
"singles": "npm start -- --singles",
|
||||
"start": "npm run dev",
|
||||
"style": "webpack --jscs"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -40,6 +41,7 @@
|
||||
"eslint-loader": "^1.2.0",
|
||||
"eslint-plugin-react": "^3.15.0",
|
||||
"file-loader": "^0.8.5",
|
||||
"history": "^1.17.0",
|
||||
"image-size": "^0.4.0",
|
||||
"jsmin": "^1.0.1",
|
||||
"json-loader": "^0.5.4",
|
||||
@@ -52,6 +54,7 @@
|
||||
"react": "^0.14.3",
|
||||
"react-component-visibility": "0.0.8",
|
||||
"react-dom": "^0.14.3",
|
||||
"react-router": "^1.0.3",
|
||||
"sha1": "^1.1.1",
|
||||
"style-loader": "^0.13.0",
|
||||
"uglify-loader": "^1.3.0",
|
||||
|
27
pages/Routed.jsx
Normal file
27
pages/Routed.jsx
Normal file
@@ -0,0 +1,27 @@
|
||||
var React = require('react');
|
||||
var ReactRouter = require('react-router');
|
||||
var Router = ReactRouter.Router;
|
||||
var Route = ReactRouter.Route;
|
||||
var Page = require("../components/Page.jsx");
|
||||
|
||||
// get all the sections, and generate <Route> objects for each.
|
||||
var sections = require("../components/sections");
|
||||
var generateSingleSection = require("./generateSingleSection");
|
||||
var pageIDs = Object.keys(sections);
|
||||
|
||||
// mind you, "preface" is our root page, so we take it out before generating named routes.
|
||||
pageIDs.splice(pageIDs.indexOf("preface"), 1);
|
||||
|
||||
// Then we generate each page's <Route>
|
||||
var pages = [
|
||||
<Route path="/" component={generateSingleSection("preface")} key="preface"/>
|
||||
].concat(
|
||||
pageIDs.map(id => <Route path={id} component={generateSingleSection(id)} key={id}/>)
|
||||
);
|
||||
|
||||
// And finally, the full app's route set.
|
||||
var RouteSet = <Router>{pages}</Router>;
|
||||
|
||||
// Done, let's run this thing.
|
||||
var ReactDOM = require('react-dom');
|
||||
ReactDOM.render(RouteSet, document.getElementById("article"));
|
23
pages/generateSingleSection.js
Normal file
23
pages/generateSingleSection.js
Normal file
@@ -0,0 +1,23 @@
|
||||
var React = require('react');
|
||||
var sections = require('../components/sections');
|
||||
var Page = require('../components/Page.jsx');
|
||||
|
||||
module.exports = function generateSingleSection(name) {
|
||||
var Type, entry;
|
||||
|
||||
Object.keys(sections).map((n,idx) => {
|
||||
if (name!==n) return;
|
||||
entry = idx;
|
||||
Type = sections[name];
|
||||
});
|
||||
|
||||
var section = <Type key={name} name={name} number={entry}/>,
|
||||
content = [section],
|
||||
SingleSection = React.createClass({
|
||||
render: function() {
|
||||
return <Page content={content} compact={true} prev={entry-1} next={entry+1}/>;
|
||||
}
|
||||
});
|
||||
|
||||
return SingleSection;
|
||||
};
|
@@ -2,6 +2,7 @@ footer {
|
||||
font-size: 85%;
|
||||
font-family: Verdana;
|
||||
border-top: 1px solid grey;
|
||||
padding: 2em 2em 0;
|
||||
box-sizing: border-box;
|
||||
padding: 2em 1.25em 0;
|
||||
box-sizing: content-box;
|
||||
margin-left: -1rem;
|
||||
}
|
||||
|
@@ -19,4 +19,23 @@ navigation {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.compact {
|
||||
width: 100%;
|
||||
border: none;
|
||||
border-top: 1px solid grey;
|
||||
padding-top: 2em;
|
||||
margin-top: 2em;
|
||||
|
||||
ul {
|
||||
background: inherit;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
&:not(:last-child) {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
stylesheets/relatives.less
Normal file
26
stylesheets/relatives.less
Normal file
@@ -0,0 +1,26 @@
|
||||
.relatives {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between;
|
||||
|
||||
border: 1px solid #CCC;
|
||||
padding: 0.25rem 1rem;
|
||||
margin-left: -1rem;
|
||||
box-sizing: content-box;
|
||||
|
||||
&.before {
|
||||
border-width: 1px 0px;
|
||||
margin-bottom: -2rem;
|
||||
}
|
||||
|
||||
&.after {
|
||||
margin-top: 2em;
|
||||
border-width: 1px 0 0 0;
|
||||
border-color: grey;
|
||||
margin-bottom: -1.5rem;
|
||||
}
|
||||
|
||||
.prev:before { content: "← "; }
|
||||
.next:after { content: " →"; }
|
||||
}
|
@@ -61,3 +61,4 @@ footer {
|
||||
@import "latex.less";
|
||||
@import "table.less";
|
||||
@import "footer.less";
|
||||
@import "relatives.less";
|
||||
|
@@ -3,6 +3,11 @@ var webpack = require('webpack');
|
||||
// Bundle entry point
|
||||
var entry = ['./components/App.jsx'];
|
||||
|
||||
// However, do we want one full page, or single pages with react-router?
|
||||
if(process.argv.indexOf("--singles") !== -1 ) {
|
||||
entry = ['./pages/Routed.jsx'];
|
||||
}
|
||||
|
||||
// Necessary webpack loaders for converting our content:
|
||||
var webpackLoaders = [
|
||||
'babel-loader',
|
||||
@@ -41,7 +46,7 @@ module.exports = {
|
||||
{ test: /\.json$/, loader: "json" },
|
||||
{
|
||||
test: /.jsx?$/,
|
||||
include: /components/,
|
||||
include: /(components|pages)/,
|
||||
loaders: webpackLoaders
|
||||
}
|
||||
]
|
||||
|
Reference in New Issue
Block a user