This commit is contained in:
Rico Sta. Cruz 2017-08-24 11:57:09 +08:00
parent 016c36bb96
commit 7405cbeb0d
No known key found for this signature in database
GPG Key ID: CAAD38AE2962619A
14 changed files with 1046 additions and 564 deletions

View File

@ -1 +1,15 @@
:) :)
---
## Notes
H2's support these:
{: .-two-column}
{: .-three-column}
{: .-left-reference}
Tables support these:
{: .-shortcuts}

View File

@ -9,6 +9,7 @@
<script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.min.js"></script> <script src="https://unpkg.com/isotope-layout@3/dist/isotope.pkgd.min.js"></script>
<script src="https://unpkg.com/prismjs@1.6.0"></script> <script src="https://unpkg.com/prismjs@1.6.0"></script>
<script src="https://unpkg.com/prismjs@1.6.0/components/prism-jsx.min.js"></script> <script src="https://unpkg.com/prismjs@1.6.0/components/prism-jsx.min.js"></script>
<script src="https://unpkg.com/prismjs@1.6.0/components/prism-bash.min.js"></script>
<link rel='stylesheet' href='https://unpkg.com/prismjs@1.6.0/themes/prism-solarizedlight.css' /> <link rel='stylesheet' href='https://unpkg.com/prismjs@1.6.0/themes/prism-solarizedlight.css' />
<!-- 2017 layout --> <!-- 2017 layout -->

21
_sass/2017/base/base.scss Normal file
View File

@ -0,0 +1,21 @@
/*
* Base
*/
html, body {
background: #fcfcfc;
font-family: $body-font;
font-size: 14px;
line-height: 1.6;
color: $text-color;
}
body {
padding: 16px;
max-width: $column * 3 + 32px;
margin: 0 auto;
}
pre, code {
font-family: $monospace-font;
}

View File

@ -0,0 +1,14 @@
/*
* h2 section
*/
/* Hide the first h2 heading */
.h2-section {
& > h2 {
margin-top: 64px;
}
&:first-child > h2 {
display: none;
}
}

View File

@ -0,0 +1,116 @@
/*
* H3 section list:
* The body that is isotoped.
*/
.h3-section-list {
& {
margin: 0 auto;
}
// Clearfix
&::after {
content: '';
display: table;
clear: both;
zoom: 1;
}
// Each section
& > .h3-section {
float: left;
padding: $gutter / 2;
width: 100%;
}
@media (min-width: 768px) {
& > .h3-section {
width: 50%;
}
& > .h3-section.-wide {
width: 100%;
}
& > .h3-section.-halfwide {
width: 100%;
}
}
@media (min-width: 960px) {
& > .h3-section {
width: 33.33%;
}
& > .h3-section.-wide {
width: 66.67%;
}
& > .h3-section.-halfwide {
width: 50%;
}
}
}
/*
* Two column (default)
*/
.h3-section-list,
.h3-section-list.-two-column {
@media (min-width: 768px) {
& > .h3-section {
width: 50%;
}
}
}
/*
* One column
*/
.h3-section-list.-one-column {
& > .h3-section {
width: 100%;
}
}
/*
* Three column
*/
.h3-section-list.-three-column {
@media (min-width: 768px) {
& > .h3-section {
width: 50%;
}
}
@media (min-width: 960px) {
& > .h3-section {
width: 33.33%;
}
}
}
/*
* Three column, left reference
*/
.h3-section-list.-left-reference {
@media (min-width: 768px) {
& > .h3-section {
width: 50%;
}
}
@media (min-width: 960px) {
& > .h3-section {
width: 66.67%;
}
& > .h3-section:first-child {
width: 33.33%;
}
}
}

View File

@ -0,0 +1,80 @@
/*
* H3 section
*/
.h3-section > .body {
& > pre {
margin: 0;
padding: 16px;
font-size: 12px;
overflow: auto;
background: white;
}
& {
background: white;
box-shadow:
0 4px 5px rgba(80, 100, 150, 0.05),
0 2px 3px rgba(80, 100, 150, 0.1);
}
& > ul {
margin: 0;
padding: 0;
list-style-type: none;
}
& > ul > li {
padding: 8px 16px;
padding-left: 32px;
position: relative;
}
& > ul > li::before {
content: '';
position: absolute;
display: inline-block;
width: 8px;
height: 8px;
background: #666;
border-radius: 50%;
left: 16px;
top: 16px;
}
& > ul > li + li {
border-top: solid 1px $line-color;
}
/* Paragraphs */
& > p {
padding: 16px;
margin: 0;
}
/* Description paragraphs */
& > pre ~ p,
& > ul ~ p,
& > iframe ~ p,
& > table ~ p {
background: $gray-bg;
color: $gray-text;
/* Links */
& a,
& a:visited {
color: $text-color;
text-decoration: none;
border-bottom: solid 1px $line-color;
}
& a:hover {
color: $baseB-400;
}
}
/* Line divisions */
& > *:not(:first-child) {
border-top: solid 1px $line-color;
}
}

View File

@ -0,0 +1,57 @@
/*
* MarkdownBody context
*/
.main-heading,
.MarkdownBody h1,
.MarkdownBody h2 {
font-weight: 300;
font-family: $body-font;
margin: $gutter / 2;
padding: 0;
margin-bottom: 16px;
padding-bottom: 16px;
border-bottom: solid 1px $line-color;
}
.main-heading,
.MarkdownBody h1 {
font-size: 3.2em;
}
.MarkdownBody h2 {
font-size: 2.4em;
}
.MarkdownBody h3 {
margin: 0;
padding: 0;
margin-bottom: 16px;
font-family: $body-font;
font-size: 1.66em;
font-weight: 300;
color: $baseA-400;
}
.MarkdownBody {
a,
a:visited {
color: $baseB-400;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
em {
font-style: normal;
color: $gray-text;
}
iframe {
border: 0;
margin: 0;
width: 100%;
}
}

View File

@ -0,0 +1,64 @@
/*
* Table
*/
.MarkdownBody table {
& {
width: 100%;
}
& tr + tr {
border-top: solid 1px $line-color;
}
/* Horizontal lines */
& tbody + tbody {
border-top: solid 1px $dark-line-color;
}
& td,
& th {
padding: 8px 16px;
}
& tr td:last-child {
text-align: right;
}
& td:first-child > code {
font-size: 0.86em;
color: #35a;
}
& a,
& a:visited {
color: #35a;
text-decoration: none;
}
& td:first-child > code ~ em {
font-style: normal;
font-size: 0.86em;
color: $gray-text;
}
& thead {
display: none;
}
}
.MarkdownBody table.-shortcuts {
code {
font-size: 1em;
padding: 3px 8px;
background: #fafafa;
box-shadow:
0 2px 0 rgba(0, 0, 0, 0.2),
inset 0 0 0 1px rgba(0, 0, 0, 0.05);
border-radius: 3px;
margin-right: 2px;
letter-spacing: 0.2em;
font-family: roboto;
color: $text-color;
}
}

22
_sass/2017/style.scss Normal file
View File

@ -0,0 +1,22 @@
$gutter: 32px;
$column: 400px;
$body-font: roboto, sans-serif;
$monospace-font: menlo, monospace;
$gray-bg: #fcfcfc;
$gray-text: #678;
$text-color: #333;
$baseA-400: #53a;
$baseB-400: #35a;
$line-color: #f5f5f5;
$dark-line-color: #ccc;
@import url('https://unpkg.com/sanitize.css@5.0.0/sanitize.css');
@import './base/base';
@import './markdown/headings';
@import './markdown/table';
@import './components/h2-section';
@import './components/h3-section-list';
@import './components/h3-section';

View File

@ -1,248 +0,0 @@
@import url('https://unpkg.com/sanitize.css@5.0.0/sanitize.css');
:root {
--gutter: 32px;
--column: 400px;
--body-font: roboto, sans-serif;
--monospace-font: menlo, monospace;
--gray-bg: #fcfcfc;
--gray-text: #678;
--text-color: #333;
--baseA-400: #53a;
--line-color: #f5f5f5;
--dark-line-color: #ccc;
}
/*
* Base
*/
html, body {
background: #fcfcfc;
font-family: var(--body-font);
font-size: 14px;
line-height: 1.6;
color: var(--text-color);
}
body {
padding: 16px;
max-width: calc(var(--column) * 3 + 32px);
margin: 0 auto;
}
pre, code {
font-family: var(--monospace-font);
}
/*
* MarkdownBody context
*/
.main-heading,
.MarkdownBody h1,
.MarkdownBody h2 {
font-weight: 300;
font-family: var(--body-font);
margin: calc(var(--gutter) / 2);
padding: 0;
margin-bottom: 16px;
padding-bottom: 16px;
border-bottom: solid 1px var(--line-color);
}
.main-heading,
.MarkdownBody h1 {
font-size: 3.2em;
}
.MarkdownBody h2 {
font-size: 2.4em;
}
.MarkdownBody h3 {
margin: 0;
padding: 0;
margin-bottom: 16px;
font-family: var(--body-font);
font-size: 1.66em;
font-weight: 300;
color: var(--baseA-400);
}
/*
* h2 section
*/
/* Hide the first h2 heading */
.h2-section > h2 {
margin-top: 64px;
}
.h2-section:first-child > h2 {
display: none;
}
/*
* H3 section list:
* The body that is isotoped.
*/
.h3-section-list {
margin: 0 auto;
}
.h3-section-list::after {
content: '';
display: table;
clear: both;
zoom: 1;
}
.h3-section-list > .h3-section {
float: left;
padding: calc(var(--gutter) / 2);
width: 100%;
}
@media (min-width: 768px) {
.h3-section-list > .h3-section {
width: 50%;
}
.h3-section-list > .h3-section.-wide {
width: 100%;
}
.h3-section-list > .h3-section.-halfwide {
width: 100%;
}
}
@media (min-width: 960px) {
.h3-section-list > .h3-section {
width: 33.33%;
}
.h3-section-list > .h3-section.-wide {
width: 66.67%;
}
.h3-section-list > .h3-section.-halfwide {
width: 50%;
}
}
/*
* H3 section
*/
.h3-section > .body > pre {
margin: 0;
padding: 16px;
font-size: 12px;
overflow: auto;
background: white;
}
.h3-section > .body {
background: white;
box-shadow: 0 4px 5px rgba(80, 100, 150, 0.05), 0 2px 3px rgba(80, 100, 150, 0.1);
}
.h3-section > .body > ul {
margin: 0;
padding: 0;
list-style-type: none;
}
.h3-section > .body > ul > li {
padding: 8px 16px;
padding-left: 32px;
position: relative;
}
.h3-section > .body > ul > li::before {
content: '';
position: absolute;
display: inline-block;
width: 8px;
height: 8px;
background: #666;
border-radius: 50%;
left: 16px;
top: 16px;
}
.h3-section > .body > ul > li + li {
border-top: solid 1px var(--line-color);
}
/* Description paragraphs */
.h3-section > .body > pre ~ p,
.h3-section > .body > ul ~ p,
.h3-section > .body > table ~ p {
padding: 16px;
margin: 0;
background: var(--gray-bg);
color: var(--gray-text);
}
.h3-section > .body > p > a,
.h3-section > .body > p > a:visited {
color: var(--text-color);
text-decoration: none;
border-bottom: solid 1px var(--line-color);
}
.h3-section > .body > *:not(:first-child) {
border-top: solid 1px var(--line-color);
}
/*
* Table
*/
table {
width: 100%;
}
table tr + tr {
border-top: solid 1px var(--line-color);
}
/* Horizontal lines */
table tbody + tbody {
border-top: solid 1px var(--dark-line-color);
}
table td,
table th {
padding: 8px 16px;
}
table tr td:last-child {
text-align: right;
}
table code {
font-size: 0.86em;
color: #35a;
}
table a,
table a:visited {
color: #35a;
text-decoration: none;
}
table code ~ em {
font-style: normal;
font-size: 0.86em;
color: var(--gray-text);
}
table thead {
display: none;
}

3
assets/2017/style.scss Normal file
View File

@ -0,0 +1,3 @@
---
---
@import '2017/style.scss';

219
react.md
View File

@ -6,14 +6,41 @@ layout: 2017/sheet
{%raw%} {%raw%}
Getting started Example
--------------- -------
{: .-left-reference}
{:.-three-column} ### Basic example
<!-- .-three-column --> ```jsx
class Hello extends React.Component {
render () {
return <div className='message-box'>
Hello {this.props.name}
</div>
}
}
```
### Getting started ```jsx
const el = document.body
ReactDOM.render(<Hello name='John' />, el)
```
Use the [React.js jsfiddle](http://jsfiddle.net/reactjs/69z2wepo/) to start hacking. (or the unofficial [jsbin](http://jsbin.com/yafixat/edit?js,output)).
### Try it
<iframe src="http://jsbin.com/yafixat/edit?js,output" height="400"></iframe>
[Open in jsbin](http://jsbin.com/yafixat/edit?js,output)
{: target="_blank"}
Components
----------
{: .-three-column}
### Class components
```jsx ```jsx
class MyComponent extends React.Component { class MyComponent extends React.Component {
@ -30,8 +57,6 @@ const el = document.body
ReactDOM.render(<MyComponent name='John' />, el) ReactDOM.render(<MyComponent name='John' />, el)
``` ```
Use the [React.js jsfiddle](http://jsfiddle.net/reactjs/69z2wepo/) to start hacking. (or the unofficial [jsbin](http://jsbin.com/yafixat/edit?js,output)).
### Functional components ### Functional components
```jsx ```jsx
@ -66,34 +91,19 @@ Nest components to separate concerns. See: [multiple components](http://facebook
```jsx ```jsx
this.forceUpdate() this.forceUpdate()
this.isMounted() ```
```jsx
this.setState({ ... }) this.setState({ ... })
this.replaceState({ ... }) this.replaceState({ ... })
```
```jsx
this.state this.state
this.props this.props
``` ```
These are methods available for `Component` instances. See [Component API](http://facebook.github.io/react/docs/component-api.html). These methods and properies are available for `Component` instances. See [Component API](http://facebook.github.io/react/docs/component-api.html).
### Component specs
| Method | What |
| ---- | ---- |
| [`render()`](http://facebook.github.io/react/docs/component-specs.html#render) | |
| ---- | ---- |
| [`getInitialState()`](http://facebook.github.io/react/docs/component-specs.html#getinitialstate) | |
| [`getDefaultProps()`](http://facebook.github.io/react/docs/component-specs.html#getdefaultprops) | |
| ---- | ---- |
| [`mixins: [ ... ]`](http://facebook.github.io/react/docs/component-specs.html#mixins) | Mixins ... [more](#mixins) |
| [`propTypes: { ... }`](http://facebook.github.io/react/docs/component-specs.html#proptypes) | Validation ... [more](#property-validation) |
| [`statics: { ... }`](http://facebook.github.io/react/docs/component-specs.html#statics) | Static methods |
| [`displayName: "..."`](http://facebook.github.io/react/docs/component-specs.html#displayname) | Automatically filled by JSX |
{:.greycode.no-head}
Methods and properties you can override. See [component specs](http://facebook.github.io/react/docs/component-specs.html).
### Properties ### Properties
@ -116,7 +126,6 @@ Use [props](https://facebook.github.io/react/docs/tutorial.html#using-props) (`t
```jsx ```jsx
this.setState({ username: 'rstacruz' }) this.setState({ username: 'rstacruz' })
this.replaceState({ ... })
``` ```
```jsx ```jsx
@ -126,18 +135,19 @@ render () {
} }
``` ```
Use [states](https://facebook.github.io/react/docs/tutorial.html#reactive-state) (`this.state`) to manage dynamic data. Use states (`this.state`) to manage dynamic data.
See [States](https://facebook.github.io/react/docs/tutorial.html#reactive-state).
### Setting default props ### Setting default props
```jsx ```jsx
class Hello extends React.Component { Hello.defaultProps = {
constructor (props) { color: 'blue'
super({ shown: true, ...props })
}
} }
``` ```
See [defaultProps](https://facebook.github.io/react/docs/react-component.html#defaultprops).
### Setting default state ### Setting default state
```jsx ```jsx
@ -151,32 +161,32 @@ class Hello extends React.Component {
Lifecycle Lifecycle
--------- ---------
{: .-two-column}
{:.-two-column}
### Mounting ### Mounting
| `componentWillMount()` | Before rendering (no DOM yet) | | `constructor` _(props)_ | Before rendering [#](https://facebook.github.io/react/docs/react-component.html#constructor) |
| `componentDidMount()` | After rendering | | `componentWillMount()` | _Don't use this_ [#](https://facebook.github.io/react/docs/react-component.html#componentwillmount) |
| `componentWillUnmount()` | Invoked before DOM removal | | `render()` | Render [#](https://facebook.github.io/react/docs/react-component.html#render) |
| `componentDidMount()` | After rendering (DOM available) [#](https://facebook.github.io/react/docs/react-component.html#componentdidmount) |
| `componentWillUnmount()` | Before DOM removal [#](https://facebook.github.io/react/docs/react-component.html#componentwillunmount) |
Before initial rendering occurs. Add your DOM stuff on didMount (events, timers, etc). See [reference](http://facebook.github.io/react/docs/component-specs.html#mounting-componentwillmount). Set initial the state on `constructor()`.
Add DOM event handlers, timers (etc) on `componentDidMount()`, then remove them on `componentWillUnmount()`.
Clear your DOM stuff in componentWillMount (probably done on didMount). See [reference](http://facebook.github.io/react/docs/component-specs.html#unmounting-componentwillunmount).
### Updating ### Updating
| `componentWillReceiveProps`*(newProps={})* | Use `setState()` here | | `componentWillReceiveProps` *(newProps)* | Use `setState()` here |
| `shouldComponentUpdate`*(newProps={}, newState={})* | Skips `render()` if returns false | | `shouldComponentUpdate` *(newProps, newState)* | Skips `render()` if returns false |
| `componentWillUpdate`*(newProps={}, newState={})* | Can't use `setState()` here | | `componentWillUpdate` *(newProps, newState)* | Can't use `setState()` here |
| `componentDidUpdate`*(prevProps={}, prevState={})* | Operate on the DOM here | | `render()` | Render |
| `componentDidUpdate` *(prevProps, prevState)* | Operate on the DOM here |
Called when parents change properties and `.setState()`. These are not called for initial renders. See [reference](http://facebook.github.io/react/docs/component-specs.html#updating-componentwillreceiveprops). Called when parents change properties and `.setState()`. These are not called for initial renders. See [reference](http://facebook.github.io/react/docs/component-specs.html#updating-componentwillreceiveprops).
DOM nodes DOM nodes
--------- ---------
{: .-two-column}
{:.-two-column}
### References ### References
@ -195,7 +205,7 @@ this.input.focus()
this.input.value() this.input.value()
``` ```
Allows access to DOM nodes. See [References](http://facebook.github.io/react/docs/more-about-refs.html). Allows access to DOM nodes. See [Refs and the DOM](https://facebook.github.io/react/docs/refs-and-the-dom.html).
### DOM Events ### DOM Events
@ -204,7 +214,6 @@ Allows access to DOM nodes. See [References](http://facebook.github.io/react/doc
value={this.state.value} value={this.state.value}
onChange={this.handleChange} /> onChange={this.handleChange} />
``` ```
{:.light}
```jsx ```jsx
handleChange: function(event) { handleChange: function(event) {
@ -216,6 +225,7 @@ Add attributes like `onChange`. See [events](https://facebook.github.io/react/do
Property validation Property validation
------------------- -------------------
{: .-three-column}
### React.PropTypes ### React.PropTypes
@ -258,60 +268,51 @@ MyComponent.propTypes = {
} }
``` ```
See [propTypes](http://facebook.github.io/react/docs/reusable-components.html#prop-validation).
### Required types ### Required types
```jsx ```jsx
MyComponent.propTypes = { MyCo.propTypes = {
requiredFunc: React.PropTypes.func.isRequired, name: React.PropTypes.string.isRequired
requiredAny: React.PropTypes.any.isRequired
} }
``` ```
Add `.isRequired`. ### Elements
### React elements
```jsx ```jsx
MyComponent.propTypes = { MyCo.propTypes = {
// React element // React element
element: React.PropTypes.element, element: React.PropTypes.element,
// num, string, element, or an array of those // num, string, element, or an array of those
node: React.PropTypes.node node: React.PropTypes.node
} }
``` ```
Use `.element`, `.node`. ### Enumerables (oneOf)
### Enumerables
```jsx
MyCo.propTypes = {
direction: React.PropTypes.oneOf([
'left', 'right'
])
}
``` ```
propTypes: {
enum: React.PropTypes.oneOf(['M','F']), // enum
union: React.PropTypes.oneOfType([ // any
React.PropTypes.string,
React.PropTypes.number ]),
```
Use `.oneOf`, `.oneOfType`.
### Arrays and objects ### Arrays and objects
```jsx ```jsx
propTypes: { MyCo.propTypes = {
array: React.PropTypes.array, array: React.PropTypes.array,
arrayOf: React.PropTypes.arrayOf(React.PropTypes.number), arrayOf: React.PropTypes.arrayOf(React.PropTypes.number),
object: React.PropTypes.object, object: React.PropTypes.object,
objectOf: React.PropTypes.objectOf(React.PropTypes.number), objectOf: React.PropTypes.objectOf(React.PropTypes.number),
message: React.PropTypes.instanceOf(Message), message: React.PropTypes.instanceOf(Message),
object2: React.PropTypes.shape({ object2: React.PropTypes.shape({
color: React.PropTypes.string, color: React.PropTypes.string,
size: React.PropTypes.number size: React.PropTypes.number
}), })
}
``` ```
Use `.array[Of]`, `.object[Of]`, `.instanceOf`, `.shape`. Use `.array[Of]`, `.object[Of]`, `.instanceOf`, `.shape`.
@ -319,20 +320,18 @@ Use `.array[Of]`, `.object[Of]`, `.instanceOf`, `.shape`.
### Custom validation ### Custom validation
```jsx ```jsx
propTypes: { MyCo.propTypes = {
customProp: function(props, propName, componentName) { customProp: (props, key, componentName) => {
if (!/matchme/.test(props[propName])) { if (!/matchme/.test(props[key])) {
return new Error('Validation failed!'); return new Error('Validation failed!')
} }
} }
} }
``` ```
Supply your own function.
## Other features ## Other features
### Propagating properties ### Transfering props
```html ```html
<VideoPlayer src="video.mp4" /> <VideoPlayer src="video.mp4" />
@ -347,32 +346,34 @@ class VideoPlayer extends React.Component {
``` ```
Propagates `src="..."` down to the sub-component. Propagates `src="..."` down to the sub-component.
See [Transferring props](http://facebook.github.io/react/docs/transferring-props.html). See [Transferring props](http://facebook.github.io/react/docs/transferring-props.html).
### Top-level API ### Top-level API
```jsx ```jsx
React.createClass({ ... }) React.createClass({ ... })
React.isValidElement(c) React.isValidElement(c)
```
ReactDOM.findDOMNode(c) // 0.14+ ```jsx
ReactDOM.render(<Component />, domnode, [callback]) // 0.14+ ReactDOM.render(<Component />, domnode, [callback])
ReactDOM.unmountComponentAtNode(domnode) // 0.14+ ReactDOM.unmountComponentAtNode(domnode)
```
ReactDOMServer.renderToString(<Component />) // 0.14+ ```jsx
ReactDOMServer.renderToStaticMarkup(<Component />) // 0.14+ ReactDOMServer.renderToString(<Component />)
ReactDOMServer.renderToStaticMarkup(<Component />)
``` ```
JSX patterns JSX patterns
------------ ------------
{: .-two-column}
### Style shorthand ### Style shorthand
```jsx ```jsx
var style = { backgroundImage: 'url(x.jpg)', height: 10 }; var style = { height: 10 }
return <div style={style}></div>; return <div style={style}></div>
``` ```
See [inline styles](https://facebook.github.io/react/tips/inline-styles.html). See [inline styles](https://facebook.github.io/react/tips/inline-styles.html).
@ -389,23 +390,37 @@ See [dangerously set innerHTML](https://facebook.github.io/react/tips/dangerousl
### Lists ### Lists
```jsx ```jsx
var TodoList = React.createClass({ class TodoList extends React.Component {
render: function() { render () {
function item(itemText) { const { items } = this.props
return <li>{itemText}</li>;
}; return <ul>
return <ul>{this.props.items.map(item)}</ul>; {items.map(item =>
<TodoItem item={item} key={item.key} />)}
</ul>
} }
}); }
``` ```
See also Always supply a `key` property.
### Conditionals
```jsx
<div>
{showPopup
? <Popup />
: null}
</div>
```
Also see
-------- --------
{: .-one-column}
{:.-two-column} This reference was made for React v15.
### Also see * [React website](http://facebook.github.io/react) _(facebook.github.io)_
* [Animations](http://facebook.github.io/react/docs/animation.html) _(facebook.github.io)_
* [Animations](http://facebook.github.io/react/docs/animation.html)
{%endraw%} {%endraw%}

677
sh.md
View File

@ -1,261 +1,572 @@
--- ---
title: Bash scripting title: Bash scripting
category: CLI category: CLI
layout: 2017/sheet
--- ---
Getting started
---------------
{: .-three-column}
### Example
```bash
#!/usr/bin/env bash
NAME="John"
echo "Hello $NAME!"
```
### Variables
```bash
NAME="John"
echo $NAME
echo "$NAME"
echo "${NAME}!"
```
### String quotes
```bash
NAME="John"
echo "Hi $NAME" #=> Hi John
echo 'Hi $NAME' #=> Hi $NAME
```
### Shell execution
```bash
echo "I'm in $(pwd)"
echo "I'm in `pwd`"
# Same
```
See [Command substitution](http://wiki.bash-hackers.org/syntax/expansion/cmdsubst)
### Conditional execution
```bash
git commit && git push
git commit || echo "Commit failed"
```
### Functions
{: id='functions-example'}
```bash
get_name() {
echo "John"
}
echo "You are $(get_name)"
```
See: [Functions](#functions)
### Conditionals
{: id='conditionals-example'}
```bash
if [ -z "$string" ]; then
echo "String is empty"
elsif [ -n "$string" ]; then
echo "String is not empty"
fi
```
See: [Conditionals](#conditionals)
### Strict mode
```bash
set -euo pipefail
IFS=$'\n\t'
```
See: [Unofficial bash strict mode](http://redsymbol.net/articles/unofficial-bash-strict-mode/)
### Brace expansion
```bash
echo {A,B}.js
```
| `{A,B}` | Same as `A B` |
| `{A,B}.js` | Same as `A.js B.js` |
| `{1..5}` | Same as `1 2 3 4 5` |
See: [Brace expansion](http://wiki.bash-hackers.org/syntax/expansion/brace)
Parameter expansions
--------------------
{: .-three-column}
### Basics
```bash
name="John"
echo ${name}
echo ${name/J/j} #=> "john" (substitution)
echo ${name:0:2} #=> "jo" (slicing)
echo ${food:-Cake} #=> $food or "Cake"
```
```bash
length=2
echo ${name:0:length} #=> "jo"
```
See: [Parameter expansion](http://wiki.bash-hackers.org/syntax/pe)
### Pattern substitution ### Pattern substitution
STR=/path/to/foo.c ```bash
STR="/path/to/foo.cpp"
```
echo ${STR%.c} #=> "/path/to/foo" | `${STR%.cpp}` | `/path/to/foo` |
echo ${STR%.c}.o #=> "/path/to/foo.o" | `${STR%.cpp}.o` | `/path/to/foo.o` |
echo ${STR##*.} #=> "c" (extension) | `${STR##*.}` | `cpp` _(extension)_ |
| `${STR##*/}` | `foo.cpp` _(basepath)_ |
BASE=${STR##*/} #=> "foo.c" (basepath) ### Directory name
DIR=${SRC%$BASE} #=> "/path/to"
### Substitutions by regex ```bash
SRC="/path/to/foo.cpp"
BASE=${STR##*/} #=> "foo.cpp" (basepath)
DIR=${SRC%$BASE} #=> "/path/to" (dirpath)
```
echo ${STR/hi/hello} # Replace first match ### Regexp-like substitution
echo ${STR//hi/hello} # Replace all matches
echo ${STR/#hi/hello} # ^hi
echo ${STR/%hi/hello} # hi$
echo "${STR:0:3}" # .substr(0, 3) -- position, length ```bash
echo "${STR:-3:3}" # Negative position = from the right STR="Hey world"
```
echo ${#line} # Length of $line | `${STR/Hey/Hello}` | Replace first match |
| `${STR//Hey/Hello}` | Replace all |
| `${STR/#Hey/Hello}` | Like `^Hey` |
| `${STR/%world/mundo}` | Like `world$` |
[ -z "$CC" ] && CC=gcc # CC ||= "gcc" assignment ### Substrings
${CC:=gcc} # $CC || "gcc"
${CC:-gcc} # same as above
### Reading input | `${STR:0:3}` | Substring: `"Hey"` _(position, length)_ |
| `${STR:-3:3}` | Substring from the right |
echo -n "Proceed? [y/n]: " ```bash
read ans STR="Hello world"
echo $ans echo ${STR:6:5} # "world"
echo ${STR:-5:5} # "world"
```
read -n 1 ans # Just one character ### Length
Loops | `${#STR}` | Length of `$STR` |
-----
### Basic for loop ### Default values
for i in /etc/rc.*; do | `${CC:-gcc}` | `$CC || "gcc"` |
echo $i
done
### Ranges
for i in {1..5}; do
echo "Welcome $i"
done
### Reading lines
cat file.txt | while read line; do
echo $line
done
Functions
---------
### Defining functions
myfunc() { ... }
fuction myfunc { ... }
fuction myfunc() { ... }
### Returning strings
myfunc() {
local myresult='some value'
echo $myresult
}
result=$(myfunc)
### Errors
myfunc() { return 1; }
### Arguments
$# # Number of arguments
$* # All args
$1 # First argument
Ifs - files
-----------
# File conditions
if [ -a FILE ]; then # -e exists -d directory -f file
fi # -r readable -w writeable -x executable
# -h symlink -s size > 0
# File comparisons
if [ FILE1 -nt FILE2 ] # -nt 1 more recent than 2
# -ot 2 more recent than 1
# -ef same files
Ifs
---
# String
if [ -z STRING ] # empty?
if [ -n STRING ] # not empty?
# Numeric
if [ $? -eq 0 ] # -eq -ne -lt -le -gt -ge
# $? is exit status by the way
# Etc
if [ -o noclobber ] # if OPTIONNAME is enabled
if [ ! EXPR ] # not
if [ ONE -a TWO ] # and
if [ ONE -o TWO ] # or
# Regex
if [[ "A" =~ "." ]]
### Numeric comparisons
if (( $a < $b ))
### Unset variables ### Unset variables
Assume `$FOO` is not set. Doing *this* will result in *that*: Assuming `$FOO` is not set:
${FOO:-word} # Returns word | `${FOO:-word}` | Returns `word` |
${FOO:+word} # Returns empty, or word if set | `${FOO:+word}` | Returns empty (or `word` if set) |
${FOO:=word} # Sets parameter to word, returns word | `${FOO:=word}` | Sets `$FOO` to `word`, returns `word` |
${FOO:?message} # Echoes message and exits | `${FOO:?message}` | Echoes message and exits |
${FOO=word} # : is optional in all of the above The `:` is optional (eg, `${FOO=word}` works)
Loops
-----
{: .-three-column}
### Basic for loop
```bash
for i in /etc/rc.*; do
echo $i
done
```
### Ranges
```bash
for i in {1..5}; do
echo "Welcome $i"
done
```
### Reading lines
```bash
cat file.txt | while read line; do
echo $line
done
```
### Forever
```bash
while true; do
···
done
```
Functions
---------
{: .-three-column}
### Defining functions
```bash
myfunc() {
echo "hello $1"
}
```
```bash
# Same as above (alternate syntax)
function myfunc() {
echo "hello $1"
}
```
```bash
myfunc "John"
```
### Returning values
```bash
myfunc() {
local myresult='some value'
echo $myresult
}
```
```bash
result=$(myfunc)
```
### Raising errors
```bash
myfunc() {
return 1
}
```
```bash
if myfunc; then
echo "success"
else
echo "failure"
fi
```
### Arguments
| Expression | Description |
| --- | --- |
| `$#` | Number of arguments |
| `$*` | All arguments |
| `$@` | All arguments, starting from first |
| `$1` | First argument |
See [Special parameters](http://wiki.bash-hackers.org/syntax/shellvars#special_parameters_and_shell_variables).
Conditionals
------------
{: .-three-column}
### Conditions
| Condition | Description |
| --- | --- |
| `[ -z STRING ]` | Empty string |
| `[ -n STRING ]` | Not empty string |
| --- | --- |
| `[ NUM -eq NUM ]` | Equal |
| `[ NUM -ne NUM ]` | Not equal |
| `[ NUM -lt NUM ]` | Less than |
| `[ NUM -le NUM ]` | Less than or equal |
| `[ NUM -gt NUM ]` | Greater than |
| `[ NUM -ge NUM ]` | Greater than or equal |
| --- | --- |
| `[[ STRING =~ STRING ]]` | Regexp |
| --- | --- |
| `(( NUM < NUM ))` | Numeric conditions |
| Condition | Description |
| --- | --- |
| `[ -o noclobber ]` | If OPTIONNAME is enabled |
| --- | --- |
| `[ ! EXPR ]` | Not |
| `[ X ] && [ Y ]` | And |
| `[ X ] || [ Y ]` | Or |
### File conditions
| Condition | Description |
| --- | --- |
| `[ -e FILE ]` | Exists |
| `[ -r FILE ]` | Readable |
| `[ -h FILE ]` | Symlink |
| `[ -d FILE ]` | Directory |
| `[ -w FILE ]` | Writable |
| `[ -s FILE ]` | Size is > 0 bytes |
| `[ -f FILE ]` | File |
| `[ -x FILE ]` | Executable |
| --- | --- |
| `[ FILE1 -nt FILE2 ]` | 1 is more recent than 2 |
| `[ FILE1 -ot FILE2 ]` | 2 is more recent than 1 |
| `[ FILE1 -ef FILE2 ]` | Same files |
### Example
```bash
# String
if [ -z "$string" ]; then
echo "String is empty"
elsif [ -n "$string" ]; then
echo "String is not empty"
fi
```
```bash
# Combinations
if [ X ] && [ Y ]; then
...
fi
```
```bash
# Regex
if [[ "A" =~ "." ]]
```
```bash
if (( $a < $b ))
```
```bash
if [ -e "file.txt" ]; then
echo "file exists"
fi
```
Numeric calculations Numeric calculations
-------------------- --------------------
$((RANDOM%=200)) # Random number 0..200 ```bash
$((a + 200)) # $ is optional $((RANDOM%=200)) # Random number 0..200
$((a + 200)) # $ is optional
```
Arrays Arrays
------ ------
# Declaring using declare -a ### Defining arrays
declare -a Fruits=('Apple' 'Banana' 'Orange')
Fruits[0]="Apple" ```bash
Fruits[1]="Banana" Fruits=('Apple' 'Banana' 'Orange')
Fruits[2]="Orange" ```
echo ${Fruits[0]} # Element #0 ```bash
echo ${Fruits[@]} # All elements, space-separated Fruits[0]="Apple"
echo ${#Fruits[@]} # Number of elements Fruits[1]="Banana"
echo ${#Fruits} # String length of the 1st element Fruits[2]="Orange"
echo ${#Fruits[3]} # String length of the Nth element ```
echo ${Fruits[@]:3:2} # Range (from position 3, length 2)
### Working with arrays
```bash
echo ${Fruits[0]} # Element #0
echo ${Fruits[@]} # All elements, space-separated
echo ${#Fruits[@]} # Number of elements
echo ${#Fruits} # String length of the 1st element
echo ${#Fruits[3]} # String length of the Nth element
echo ${Fruits[@]:3:2} # Range (from position 3, length 2)
```
### Operations ### Operations
Fruits=("${Fruits[@]}" "Watermelon") # Push ```bash
Fruits=( ${Fruits[@]/Ap*/} ) # Remove by regex match Fruits=("${Fruits[@]}" "Watermelon") # Push
unset Fruits[2] # Remove one item Fruits=( ${Fruits[@]/Ap*/} ) # Remove by regex match
Fruits=("${Fruits[@]}") # Duplicate unset Fruits[2] # Remove one item
Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate Fruits=("${Fruits[@]}") # Duplicate
lines=(`cat "logfile"`) # Read from file Fruits=("${Fruits[@]}" "${Veggies[@]}") # Concatenate
lines=(`cat "logfile"`) # Read from file
```
### Iteration ### Iteration
for i in "${arrayName[@]}"; do ```bash
echo $i for i in "${arrayName[@]}"; do
done echo $i
done
```
Misc crap Options
--------- -------
command -V cd #=> "cd is a function/alias/whatever"
### Options ### Options
set -o noclobber # Avoid overlay files (echo "hi" > foo) ```bash
set -o errexit # Used to exit upon error, avoiding cascading errors set -o noclobber # Avoid overlay files (echo "hi" > foo)
set -o pipefail # Unveils hidden failures set -o errexit # Used to exit upon error, avoiding cascading errors
set -o nounset # Exposes unset variables set -o pipefail # Unveils hidden failures
set -o nounset # Exposes unset variables
```
### Glob options ### Glob options
set -o nullglob # Non-matching globs are removed ('*.foo' => '') ```bash
set -o failglob # Non-matching globs throw errors set -o nullglob # Non-matching globs are removed ('*.foo' => '')
set -o nocaseglob # Case insensitive globs set -o failglob # Non-matching globs throw errors
set -o globdots # Wildcards match dotfiles ("*.sh" => ".foo.sh") set -o nocaseglob # Case insensitive globs
set -o globstar # Allow ** for recursive matches ('lib/**/*.rb' => 'lib/a/b/c.rb') set -o globdots # Wildcards match dotfiles ("*.sh" => ".foo.sh")
set -o globstar # Allow ** for recursive matches ('lib/**/*.rb' => 'lib/a/b/c.rb')
```
set GLOBIGNORE as a colon-separated list of patterns to be removed from glob Set `GLOBIGNORE` as a colon-separated list of patterns to be removed from glob
matches. matches.
Miscellaneous
-------------
### Subshells
```bash
(cd somedir; echo "I'm now in $PWD")
pwd # still in first directory
```
### Redirection
```bash
python hello.py > output.txt # stdout to (file)
python hello.py >> output.txt # stdout to (file), append
python hello.py 2> error.log # stderr to (file)
python hello.py 2>&1 # stdout to stderr
python hello.py 2>/dev/null # stderr to (null)
```
```bash
python hello.py < foo.txt
```
### Inspecting commands
```bash
command -V cd
#=> "cd is a function/alias/whatever"
```
### Trap errors ### Trap errors
trap 'echo Error at about $LINENO' ERR ```bash
trap 'echo Error at about $LINENO' ERR
```
or or
traperr() { ```bash
echo "ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}" traperr() {
} echo "ERROR: ${BASH_SOURCE[1]} at about ${BASH_LINENO[0]}"
}
set -o errtrace set -o errtrace
trap traperr ERR trap traperr ERR
```
### Case/switch ### Case/switch
case $1 in ```bash
start | up) case "$1" in
vagrant up start | up)
;; vagrant up
;;
*) *)
echo "Usage: $0 {start|stop|ssh}" echo "Usage: $0 {start|stop|ssh}"
;; ;;
esac esac
```
### Source relative ### Source relative
source "${0%/*}/../share/foo.sh" ```bash
source "${0%/*}/../share/foo.sh"
```
### printf ### printf
printf "Hello %s, I'm %s" Sven Olga ```bash
printf "Hello %s, I'm %s" Sven Olga
#=> "Hello Sven, I'm Olga
```
### Directory of script ### Directory of script
DIR="${0%/*}" ```bash
DIR="${0%/*}"
```
### Getting options ### Getting options
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in ```bash
-V | --version ) while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in
echo $version -V | --version )
exit echo $version
;; exit
-s | --string ) ;;
shift; string=$1 -s | --string )
;; shift; string=$1
-f | --flag ) ;;
flag=1 -f | --flag )
;; flag=1
esac; shift; done ;;
if [[ "$1" == '--' ]]; then shift; fi esac; shift; done
if [[ "$1" == '--' ]]; then shift; fi
```
### Heredoc ### Heredoc
cat <<END ```sh
hello world cat <<END
END hello world
END
```
## Reference ### Reading input
* [Bash-hackers wiki](http://wiki.bash-hackers.org/) (back-hackers.org) ```bash
* [Shell vars](http://wiki.bash-hackers.org/syntax/shellvars) (back-hackers.org) echo -n "Proceed? [y/n]: "
read ans
echo $ans
```
```bash
read -n 1 ans # Just one character
```
### Process IDs
| `$?` | PID of last foreground task |
| `$!` | PID of last background task |
| `$$` | PID of shell |
See [Special parameters](http://wiki.bash-hackers.org/syntax/shellvars#special_parameters_and_shell_variables).
## Also see
{: .-one-column}
* [Bash-hackers wiki](http://wiki.bash-hackers.org/) _(bash-hackers.org)_
* [Shell vars](http://wiki.bash-hackers.org/syntax/shellvars) _(bash-hackers.org)_
* [Learn bash in y minutes](https://learnxinyminutes.com/docs/bash/) _(learnxinyminutes.com)_

View File

@ -4,58 +4,70 @@ category: Apps
layout: 2017/sheet layout: 2017/sheet
--- ---
Shortcuts
---------
{: .-three-column}
### Insert ### Insert
| `V` | vector | | `V` | Vector |
| `P` | pencil | | `P` | Pencil |
| `T` | text | | `T` | Text |
| `L` | line | | `L` | Line |
| `R` | rect | | `R` | Rectangle |
| `O` | oval | | `O` | Oval |
| `U` | rounded | | `U` | Rounded |
{: .-shortcuts}
### Show ### Show
| `^G` | grid | | `^G` | Show grid |
| `^L` | layout | | `^L` | Show layout |
| `^P` | pixels | | `^P` | Show pixels |
| `^H` | selection handles | | `^H` | Show selection handles |
| `^R` | rulers | | `^R` | Show rulers |
{: .-shortcuts}
### Sidebars ### Sidebars
| `⌘⌥1` | toggle left (layers) | | `⌘⌥1` | Toggle left (layers) |
| `⌘⌥2` | toggle right (inspector) | | `⌘⌥2` | Toggle right (inspector) |
| `⌘⌥3` | toggle both | | `⌘⌥3` | Toggle both |
| `⌘.` | presentation | | `⌘.` | Presentation mode |
{: .-shortcuts}
### Zoom ### Zoom
| `⌘0` | 100% | | `⌘0` | 100% |
| `⌘1` | fit to screen | | `⌘1` | Fit to screen |
| `⌘2` | fit selection to screen | | `⌘2` | Fit selection to screen |
| `⌘3` | center selection | | `⌘3` | Center selection |
{: .-shortcuts}
### Arrange ### Arrange
| `⌘⌥ up/dn` | forward or backward | | `⌘⌥↑` _/_ `↓` | Forward or backward |
| `^⌘⌥ up/dn` | front or back | | `^⌘⌥↑` _/_ `↓` | Front or back |
{: .-shortcuts}
### Distribute ### Distribute
| `^⌘H` | horizontal | | `^⌘H` | Horizontal |
| `^⌘V` | vertical | | `^⌘V` | Vertical |
{: .-shortcuts}
### Layers ### Layers
| `⌘R` | rename | | `⌘R` | Rename layer |
| `⌘F` | find | | `⌘F` | Find layer |
| `⌘G` | group | | `⌘G` | Group |
| `⌘⇧G` | ungroup | | `⌘⇧G` | Ungroup |
{: .-shortcuts}
### Font ### Font
| `⌘⌥ +/-` | bigger/smaller | | `⌘⌥ +` _/_ `-` | Bigger/smaller |
| `⌘⇧[` | left align | | `⌘⇧[` | Left align |
| `⌘⇧\` | center align | | `⌘⇧\` | Center align |
| `⌘⇧]` | right align | | `⌘⇧]` | Right align |
{: .-shortcuts}