diff --git a/__tests__/Layout.test.js b/__tests__/Layout.test.js index b7a44fe..936fb35 100644 --- a/__tests__/Layout.test.js +++ b/__tests__/Layout.test.js @@ -65,8 +65,8 @@ describe('Layout', () => { expect(tree.find('header h1').text()).toMatch('Design Patterns'); }); - it('renders 1 link', () => { - expect(tree.find('header a')).toHaveLength(1); + it('renders 2 links', () => { + expect(tree.find('header a')).toHaveLength(2); }); it('renders 1 span', () => { @@ -108,8 +108,8 @@ describe('Layout', () => { expect(tree.find('header h1').text()).toMatch('Design Patterns'); }); - it('renders 1 link', () => { - expect(tree.find('header a')).toHaveLength(1); + it('renders 2 links', () => { + expect(tree.find('header a')).toHaveLength(2); }); it('renders 1 span', () => { diff --git a/__tests__/components/Pattern.test.js b/__tests__/components/Pattern.test.js new file mode 100644 index 0000000..c401b06 --- /dev/null +++ b/__tests__/components/Pattern.test.js @@ -0,0 +1,43 @@ +import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import renderer from 'react-test-renderer'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import 'jest-styled-components'; +import Pattern from '../../src/components/Pattern'; + +const mockStore = configureMockStore(); + +describe('REFERENCE - Pattern component', () => { + it('renders the individual pattern (Singleton) details in DARK mode', () => { + const store = mockStore({ + mode: 'dark' + }); + const tree = renderer + .create( + + + + + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); + + xit('renders the individual pattern (Singleton) details in LIGHT mode', () => { + const store = mockStore({ + mode: 'light' + }); + const tree = renderer + .create( + + + + + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/__tests__/components/PatternsList.test.js b/__tests__/components/PatternsList.test.js new file mode 100644 index 0000000..b59f189 --- /dev/null +++ b/__tests__/components/PatternsList.test.js @@ -0,0 +1,18 @@ +import React from 'react'; +import renderer from 'react-test-renderer'; +import { MemoryRouter } from 'react-router-dom'; +import 'jest-styled-components'; +import PatternsList from '../../src/components/PatternsList'; + +describe('REFERENCE - Patterns List', () => { + it('renders all the patterns', () => { + const tree = renderer + .create( + + + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/__tests__/components/__snapshots__/Code.test.js.snap b/__tests__/components/__snapshots__/Code.test.js.snap index 34eb48a..627960d 100644 --- a/__tests__/components/__snapshots__/Code.test.js.snap +++ b/__tests__/components/__snapshots__/Code.test.js.snap @@ -2,13 +2,13 @@ exports[` component renders ES5 code in LIGHT mode 1`] = `
 component renders ES5 code in LIGHT mode 1`] = `
 
 exports[` component renders ES6 code in DARK mode 1`] = `
 
 component renders with DARK theme 1`] = `
         Game
       
       
+        Pattern Reference
+      
+       component renders with LIGHT theme 1`] = `
         Game
       
       
+        Pattern Reference
+      
+      
+  
+    ← Back to Patterns List
+  
+  

+ Singleton +

+

+ + Type: + + + creational + pattern + +

+

+ + Description: + + This pattern restricts object creation for a class to only one instance. +

+

+ ES5 +

+
+    
+      
+        
+          function
+        
+         
+        
+          Person
+        
+        (
+        
+        ) 
+      
+      {
+  
+      
+        if
+      
+       (
+      
+        typeof
+      
+       Person.instance === 
+      
+        'object'
+      
+      ) 
+      
+        return
+      
+       Person.instance;
+
+  Person.instance = 
+      
+        this
+      
+      ;
+
+  
+      
+        return
+      
+       
+      
+        this
+      
+      ;
+}
+
+
+      
+        module
+      
+      .exports = Person;
+    
+  
+

+ ES6 +

+
+    
+      
+        
+          class
+        
+         
+        
+          Person
+        
+         
+      
+      {
+  
+      
+        constructor
+      
+      () {
+    
+      
+        if
+      
+       (
+      
+        typeof
+      
+       Person.instance === 
+      
+        'object'
+      
+      ) {
+      
+      
+        return
+      
+       Person.instance;
+    }
+
+    Person.instance = 
+      
+        this
+      
+      ;
+
+    
+      
+        return
+      
+       
+      
+        this
+      
+      ;
+  }
+}
+
+
+      
+        export
+      
+       
+      
+        default
+      
+       Person;
+    
+  
+ +`; diff --git a/__tests__/components/__snapshots__/PatternsList.test.js.snap b/__tests__/components/__snapshots__/PatternsList.test.js.snap new file mode 100644 index 0000000..b0dac56 --- /dev/null +++ b/__tests__/components/__snapshots__/PatternsList.test.js.snap @@ -0,0 +1,237 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`REFERENCE - Patterns List renders all the patterns 1`] = ` +.c0 a { + border-bottom: 1px solid transparent; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c0 a:hover { + border-bottom: 1px solid; +} + +.c0 h2, +.c0 h3 { + margin-top: 2.5rem; +} + +
+

+ Design Patterns +

+

+ In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. +

+

+ Creational Design Patterns +

+

+ These design patterns are all about class instantiation. This pattern can be further divided into class-creation patterns and object-creational patterns. While class-creation patterns use inheritance effectively in the instantiation process, object-creation patterns use delegation effectively to get the job done. +

+ +

+ Structural Design Patterns +

+

+ These design patterns are all about Class and Object composition. Structural class-creation patterns use inheritance to compose interfaces. Structural object-patterns define ways to compose objects to obtain new functionality. +

+ +

+ Behavioral Design Patterns +

+

+ These design patterns are all about Class's objects communication. Behavioral patterns are those patterns that are most specifically concerned with communication between objects. +

+ +
+`; diff --git a/__tests__/pages/Patterns.test.js b/__tests__/pages/Patterns.test.js new file mode 100644 index 0000000..8a02449 --- /dev/null +++ b/__tests__/pages/Patterns.test.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import renderer from 'react-test-renderer'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +import 'jest-styled-components'; +import Patterns from '../../src/pages/Patterns'; + +const mockStore = configureMockStore(); +const store = mockStore({ + mode: 'dark' +}); + +describe('Patterns page', () => { + it('renders the Patterns list', () => { + const tree = renderer + .create( + + + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); + + it('renders the individual Pattern (Singleton) info', () => { + const tree = renderer + .create( + + + + + + ) + .toJSON(); + expect(tree).toMatchSnapshot(); + }); +}); diff --git a/__tests__/pages/__snapshots__/Game.test.js.snap b/__tests__/pages/__snapshots__/Game.test.js.snap index 1b3ba8b..bf29e24 100644 --- a/__tests__/pages/__snapshots__/Game.test.js.snap +++ b/__tests__/pages/__snapshots__/Game.test.js.snap @@ -23,7 +23,6 @@ exports[`Game page - GAME - DARK style renders a component 1`] = ` "border": "1px solid #555", "color": "#ebdbb2", "display": "block", - "height": 375, "overflowX": "auto", "padding": "1em", }, @@ -165,6 +164,7 @@ exports[`Game page - GAME - DARK style renders a component 1`] = ` } > component 1`] = ` "border": "1px solid #555", "color": "#ebdbb2", "display": "block", - "height": 375, "overflowX": "auto", "padding": "1em", }, @@ -315,13 +314,13 @@ exports[`Game page - GAME - DARK style renders a component 1`] = ` } >
 component 1`] = `
         "border": "1px solid #d8d8d8",
         "color": "#383a42",
         "display": "block",
-        "height": 375,
         "overflowX": "auto",
         "padding": "1em",
       },
@@ -594,6 +592,7 @@ exports[`Game page - GAME - LIGHT style renders a  component 1`] = `
   }
 >
    component 1`] = `
           "border": "1px solid #d8d8d8",
           "color": "#383a42",
           "display": "block",
-          "height": 375,
           "overflowX": "auto",
           "padding": "1em",
         },
@@ -715,13 +713,13 @@ exports[`Game page - GAME - LIGHT style renders a  component 1`] = `
     }
   >
     
+  

+ Design Patterns +

+

+ In software engineering, a design pattern is a general repeatable solution to a commonly occurring problem in software design. +

+

+ Creational Design Patterns +

+

+ These design patterns are all about class instantiation. This pattern can be further divided into class-creation patterns and object-creational patterns. While class-creation patterns use inheritance effectively in the instantiation process, object-creation patterns use delegation effectively to get the job done. +

+ +

+ Structural Design Patterns +

+

+ These design patterns are all about Class and Object composition. Structural class-creation patterns use inheritance to compose interfaces. Structural object-patterns define ways to compose objects to obtain new functionality. +

+ +

+ Behavioral Design Patterns +

+

+ These design patterns are all about Class's objects communication. Behavioral patterns are those patterns that are most specifically concerned with communication between objects. +

+ + +`; + +exports[`Patterns page renders the individual Pattern (Singleton) info 1`] = ` +.c0 h2, +.c0 h3 { + margin-top: 2.5rem; +} + +.c2 { + display: block; + margin-bottom: 8px; + padding: 4px; + text-transform: uppercase; +} + +.c3 { + text-transform: capitalize; +} + +.c1 { + border-bottom: 1px solid; + display: inline-block; + margin-top: 2rem; + -webkit-text-decoration: none; + text-decoration: none; +} + +.c1:hover { + border-bottom: 1px solid transparent; +} + +
+ + ← Back to Patterns List + +

+ Singleton +

+

+ + Type: + + + creational + pattern + +

+

+ + Description: + + This pattern restricts object creation for a class to only one instance. +

+

+ ES5 +

+
+    
+      
+        
+          function
+        
+         
+        
+          Person
+        
+        (
+        
+        ) 
+      
+      {
+  
+      
+        if
+      
+       (
+      
+        typeof
+      
+       Person.instance === 
+      
+        'object'
+      
+      ) 
+      
+        return
+      
+       Person.instance;
+
+  Person.instance = 
+      
+        this
+      
+      ;
+
+  
+      
+        return
+      
+       
+      
+        this
+      
+      ;
+}
+
+
+      
+        module
+      
+      .exports = Person;
+    
+  
+

+ ES6 +

+
+    
+      
+        
+          class
+        
+         
+        
+          Person
+        
+         
+      
+      {
+  
+      
+        constructor
+      
+      () {
+    
+      
+        if
+      
+       (
+      
+        typeof
+      
+       Person.instance === 
+      
+        'object'
+      
+      ) {
+      
+      
+        return
+      
+       Person.instance;
+    }
+
+    Person.instance = 
+      
+        this
+      
+      ;
+
+    
+      
+        return
+      
+       
+      
+        this
+      
+      ;
+  }
+}
+
+
+      
+        export
+      
+       
+      
+        default
+      
+       Person;
+    
+  
+
+`; diff --git a/__tests__/styles/__snapshots__/global.test.js.snap b/__tests__/styles/__snapshots__/global.test.js.snap index 429629f..6f99fcc 100644 --- a/__tests__/styles/__snapshots__/global.test.js.snap +++ b/__tests__/styles/__snapshots__/global.test.js.snap @@ -8,8 +8,8 @@ exports[`Global style renders with a DARK theme 1`] = ` > -/* sc-component-id: sc-global-3505832014 */ -body{background:#222222;font-family:'Karla',sans-serif;margin:0;padding:0;} #root{-webkit-box-pack:start;-webkit-justify-content:start;-ms-flex-pack:start;justify-content:start;max-width:640px;margin:auto;padding:0 1rem;} @media (min-width:769px){#root{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:0;}} +/* sc-component-id: sc-global-1470103548 */ +body{background:#222222;font-family:'Karla',sans-serif;margin:0;padding:0;} #root{-webkit-box-pack:start;-webkit-justify-content:start;-ms-flex-pack:start;justify-content:start;max-width:640px;margin:auto;padding:0 1rem 3rem;} @media (min-width:769px){#root{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:0 0 3rem;}} .fixed{height:375px;} `; @@ -22,8 +22,8 @@ exports[`Global style renders with a LIGHT theme 1`] = ` > -/* sc-component-id: sc-global-3505832014 */ -body{background:#FFFFFF;font-family:'Karla',sans-serif;margin:0;padding:0;} #root{-webkit-box-pack:start;-webkit-justify-content:start;-ms-flex-pack:start;justify-content:start;max-width:640px;margin:auto;padding:0 1rem;} @media (min-width:769px){#root{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:0;}} +/* sc-component-id: sc-global-1470103548 */ +body{background:#FFFFFF;font-family:'Karla',sans-serif;margin:0;padding:0;} #root{-webkit-box-pack:start;-webkit-justify-content:start;-ms-flex-pack:start;justify-content:start;max-width:640px;margin:auto;padding:0 1rem 3rem;} @media (min-width:769px){#root{-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;padding:0 0 3rem;}} .fixed{height:375px;} `; diff --git a/index.js b/index.js index db0ec1a..16fadb5 100644 --- a/index.js +++ b/index.js @@ -1,15 +1,18 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { Provider } from 'react-redux'; -import { BrowserRouter } from 'react-router-dom'; +import { BrowserRouter as Router } from 'react-router-dom'; import store from './src/store'; import Layout from './src/Layout'; +import ScrollToTop from './src/components/ScrollToTop'; const App = () => ( - - - + + + + + ); diff --git a/src/Layout.jsx b/src/Layout.jsx index fcf0644..6d5fdc2 100644 --- a/src/Layout.jsx +++ b/src/Layout.jsx @@ -1,6 +1,6 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { Route, withRouter } from 'react-router-dom'; +import { Switch, Route, Redirect, withRouter } from 'react-router-dom'; import { ThemeProvider } from 'styled-components'; import { connect } from 'react-redux'; import styleLight from './styles/hljs/hljs.light'; @@ -12,6 +12,7 @@ import { themeLight } from './styles/themes/theme.light'; import { themeDark } from './styles/themes/theme.dark'; import Game from './pages/Game'; import About from './pages/About'; +import Patterns from './pages/Patterns'; import { getMode } from './selectors'; const Layout = props => { @@ -31,8 +32,12 @@ const Layout = props => {
- } /> - + + } /> + + + + ); diff --git a/src/components/Code.jsx b/src/components/Code.jsx index 8dc42b2..558698c 100644 --- a/src/components/Code.jsx +++ b/src/components/Code.jsx @@ -13,13 +13,13 @@ const Code = props => { return ( {js === 'es5' && ( - + {current.codeES5} )} {js === 'es6' && ( - + {current.codeES6} )} diff --git a/src/components/Header.jsx b/src/components/Header.jsx index 3946e1d..4de2e2d 100644 --- a/src/components/Header.jsx +++ b/src/components/Header.jsx @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import styled, { css } from 'styled-components'; -import { Route, withRouter, Link } from 'react-router-dom'; +import { Route, withRouter, NavLink as Link } from 'react-router-dom'; import Toggle from './Toggle'; import Title from './Title'; @@ -58,6 +58,10 @@ const Header = props => { path: '/', page: 'Game' }, + { + path: '/patterns', + page: 'Pattern Reference' + }, { path: '/about', page: 'About' @@ -68,7 +72,7 @@ const Header = props => { {paths.map(({ path, page }) => - pathname === path ? ( + pathname === path || (path === '/patterns' && pathname.includes(path)) ? ( {page} ) : ( diff --git a/src/components/Pattern.jsx b/src/components/Pattern.jsx new file mode 100644 index 0000000..12429e2 --- /dev/null +++ b/src/components/Pattern.jsx @@ -0,0 +1,109 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import { Light as SyntaxHighlighter } from 'react-syntax-highlighter'; +import js from 'react-syntax-highlighter/dist/languages/hljs/javascript'; +import styleLight from '../styles/hljs/hljs.light'; +import styleDark from '../styles/hljs/hljs.dark'; +import { patterns } from '../static/patterns'; +import { restart } from '../actions/restart'; +import { getMode } from '../selectors'; + +SyntaxHighlighter.registerLanguage('javascript', js); + +const StyledPattern = styled.div` + color: ${props => props.theme.text}; + + h2, + h3 { + color: ${props => props.theme.header}; + margin-top: 2.5rem; + } +`; + +const SubHeader = styled.span` + background-color: ${props => props.theme.titleBackground}; + color: ${props => props.theme.header}; + display: block; + margin-bottom: 8px; + padding: 4px; + text-transform: uppercase; +`; + +const Type = styled.span` + text-transform: capitalize; +`; + +const StyledLink = styled(Link)` + border-bottom: 1px solid ${props => props.theme.CRIMSON}; + color: ${props => props.theme.CRIMSON}; + display: inline-block; + margin-top: 2rem; + text-decoration: none; + + &:hover { + border-bottom: 1px solid transparent; + } +`; + +class Pattern extends React.Component { + componentDidMount() { + this.props.reset(); + } + + render() { + const { + params: { id } + } = this.props.match; + + const pattern = patterns.filter(item => item.id === id)[0]; + + const style = this.props.mode === 'dark' ? styleDark : styleLight; + + return ( + + ← Back to Patterns List + {pattern && ( + +

{pattern.name}

+

+ Type: + {pattern.type} pattern +

+

+ Description: + {`This pattern ${pattern.hint}.`} +

+ +

ES5

+ + {pattern.codeES5} + + +

ES6

+ + {pattern.codeES6} + +
+ )} +
+ ); + } +} + +Pattern.propTypes = { + match: PropTypes.object.isRequired, + mode: PropTypes.string.isRequired, + reset: PropTypes.func.isRequired +}; + +export default connect( + state => ({ + mode: getMode(state) + }), + { + reset: () => restart() + } +)(Pattern); diff --git a/src/components/PatternsList.jsx b/src/components/PatternsList.jsx new file mode 100644 index 0000000..2e50978 --- /dev/null +++ b/src/components/PatternsList.jsx @@ -0,0 +1,77 @@ +import React from 'react'; +import styled from 'styled-components'; +import { Link } from 'react-router-dom'; +import { patterns } from '../static/patterns'; + +const StyledPatterns = styled.div` + color: ${props => props.theme.text}; + + a { + border-bottom: 1px solid transparent; + color: ${props => props.theme.CRIMSON}; + text-decoration: none; + + &:hover { + border-bottom: 1px solid ${props => props.theme.CRIMSON}; + } + } + + h2, + h3 { + color: ${props => props.theme.header}; + margin-top: 2.5rem; + } +`; + +const PatternsList = () => { + const lister = patternType => ( +
    + {patterns.map(({ id, name, type }) => { + if (type === patternType) { + return ( +
  • + {name} +
  • + ); + } + })} +
+ ); + + return ( + +

Design Patterns

+ +

+ In software engineering, a design pattern is a general repeatable solution to a commonly + occurring problem in software design. +

+ +

Creational Design Patterns

+

+ These design patterns are all about class instantiation. This pattern can be further divided + into class-creation patterns and object-creational patterns. While class-creation patterns + use inheritance effectively in the instantiation process, object-creation patterns use + delegation effectively to get the job done. +

+ {lister('creational')} + +

Structural Design Patterns

+

+ These design patterns are all about Class and Object composition. Structural class-creation + patterns use inheritance to compose interfaces. Structural object-patterns define ways to + compose objects to obtain new functionality. +

+ {lister('structural')} + +

Behavioral Design Patterns

+

+ These design patterns are all about Class's objects communication. Behavioral patterns are + those patterns that are most specifically concerned with communication between objects. +

+ {lister('behavioral')} +
+ ); +}; + +export default PatternsList; diff --git a/src/components/ScrollToTop.js b/src/components/ScrollToTop.js new file mode 100644 index 0000000..e4ca817 --- /dev/null +++ b/src/components/ScrollToTop.js @@ -0,0 +1,22 @@ +import React, { Component } from 'react'; +import PropTypes from 'prop-types'; +import { withRouter } from 'react-router-dom'; + +class ScrollToTop extends Component { + componentDidUpdate(prevProps) { + if (this.props.location.pathname !== prevProps.location.pathname) { + window.scrollTo(0, 0); + } + } + + render() { + return this.props.children; + } +} + +ScrollToTop.propTypes = { + location: PropTypes.object.isRequired, + children: PropTypes.object.isRequired +}; + +export default withRouter(ScrollToTop); diff --git a/src/pages/Patterns.jsx b/src/pages/Patterns.jsx new file mode 100644 index 0000000..9c1b6e5 --- /dev/null +++ b/src/pages/Patterns.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import PatternsList from '../components/PatternsList'; +import Pattern from '../components/Pattern'; + +const Patterns = () => ( + + + + +); + +export default Patterns; diff --git a/src/static/patterns/behavioral_chainOfResponsibility.js b/src/static/patterns/behavioral_chainOfResponsibility.js index 7477a7c..c5772b4 100644 --- a/src/static/patterns/behavioral_chainOfResponsibility.js +++ b/src/static/patterns/behavioral_chainOfResponsibility.js @@ -4,125 +4,126 @@ const CHAIN_OF_RESPONSIBILITY = { type: 'behavioral', hint: 'delegates commands to a chain of processing objects', codeES5: `function ShoppingCart() { -this.products = []; + this.products = []; -this.addProduct = function(p) { - this.products.push(p); -}; + this.addProduct = function(p) { + this.products.push(p); + }; } function Discount() { -this.calc = function(products) { - var ndiscount = new NumberDiscount(); - var pdiscount = new PriceDiscount(); - var none = new NoneDiscount(); + this.calc = function(products) { + var ndiscount = new NumberDiscount(); + var pdiscount = new PriceDiscount(); + var none = new NoneDiscount(); - ndiscount.setNext(pdiscount); - pdiscount.setNext(none); + ndiscount.setNext(pdiscount); + pdiscount.setNext(none); - return ndiscount.exec(products); -}; + return ndiscount.exec(products); + }; } function NumberDiscount() { -this.next = null; -this.setNext = function(fn) { - this.next = fn; -}; + this.next = null; + this.setNext = function(fn) { + this.next = fn; + }; -this.exec = function(products) { - var result = 0; - if (products.length > 3) result = 0.05; + this.exec = function(products) { + var result = 0; + if (products.length > 3) result = 0.05; - return result + this.next.exec(products); -}; + return result + this.next.exec(products); + }; } function PriceDiscount() { -this.next = null; -this.setNext = function(fn) { - this.next = fn; -}; -this.exec = function(products) { - var result = 0; - var total = products.reduce(function(a, b) { - return a + b; - }); + this.next = null; + this.setNext = function(fn) { + this.next = fn; + }; + this.exec = function(products) { + var result = 0; + var total = products.reduce(function(a, b) { + return a + b; + }); - if (total >= 500) result = 0.1; + if (total >= 500) result = 0.1; - return result + this.next.exec(products); -}; + return result + this.next.exec(products); + }; } function NoneDiscount() { -this.exec = function() { - return 0; -}; + this.exec = function() { + return 0; + }; } module.exports = [ShoppingCart, Discount];`, codeES6: `class ShoppingCart { -constructor() { - this.products = []; -} + constructor() { + this.products = []; + } -addProduct(p) { - this.products.push(p); -} + addProduct(p) { + this.products.push(p); + } } class Discount { -calc(products) { - let ndiscount = new NumberDiscount(); - let pdiscount = new PriceDiscount(); - let none = new NoneDiscount(); - ndiscount.setNext(pdiscount); - pdiscount.setNext(none); - return ndiscount.exec(products); -} + calc(products) { + let ndiscount = new NumberDiscount(); + let pdiscount = new PriceDiscount(); + let none = new NoneDiscount(); + ndiscount.setNext(pdiscount); + pdiscount.setNext(none); + + return ndiscount.exec(products); + } } class NumberDiscount { -constructor() { - this.next = null; -} + constructor() { + this.next = null; + } -setNext(fn) { - this.next = fn; -} + setNext(fn) { + this.next = fn; + } -exec(products) { - let result = 0; - if (products.length > 3) result = 0.05; + exec(products) { + let result = 0; + if (products.length > 3) result = 0.05; - return result + this.next.exec(products); -} + return result + this.next.exec(products); + } } class PriceDiscount { -constructor() { - this.next = null; -} + constructor() { + this.next = null; + } -setNext(fn) { - this.next = fn; -} + setNext(fn) { + this.next = fn; + } -exec(products) { - let result = 0; - let total = products.reduce((a, b) => a + b); + exec(products) { + let result = 0; + let total = products.reduce((a, b) => a + b); - if (total >= 500) result = 0.1; + if (total >= 500) result = 0.1; - return result + this.next.exec(products); -} + return result + this.next.exec(products); + } } class NoneDiscount { -exec() { - return 0; -} + exec() { + return 0; + } } export { ShoppingCart, Discount };` diff --git a/src/static/patterns/behavioral_command.js b/src/static/patterns/behavioral_command.js index 16cd307..2a68d23 100644 --- a/src/static/patterns/behavioral_command.js +++ b/src/static/patterns/behavioral_command.js @@ -4,105 +4,115 @@ const COMMAND = { type: 'behavioral', hint: 'creates objects which encapsulate actions and parameters', codeES5: `function Cockpit(instruction) { -this.instruction = instruction; + this.instruction = instruction; } + Cockpit.prototype.execute = function() { -this.instruction.execute(); + this.instruction.execute(); }; function Turbine() { -this.speed = 0; -this.state = false; + this.speed = 0; + this.state = false; } Turbine.prototype.on = function() { -this.state = true; -this.speed = 100; + this.state = true; + this.speed = 100; }; Turbine.prototype.off = function() { -this.speed = 0; -this.state = false; + this.speed = 0; + this.state = false; }; Turbine.prototype.speedDown = function() { -if (!this.state) return; + if (!this.state) return; -this.speed -= 100; + this.speed -= 100; }; Turbine.prototype.speedUp = function() { -if (!this.state) return; + if (!this.state) return; -this.speed += 100; + this.speed += 100; }; function OnInstruction(turbine) { -this.turbine = turbine; + this.turbine = turbine; } + OnInstruction.prototype.execute = function() { -this.turbine.on(); + this.turbine.on(); }; function OffInstruction(turbine) { -this.turbine = turbine; + this.turbine = turbine; } + OffInstruction.prototype.execute = function() { -this.turbine.off(); + this.turbine.off(); }; function SpeedUpInstruction(turbine) { -this.turbine = turbine; + this.turbine = turbine; } + SpeedUpInstruction.prototype.execute = function() { -this.turbine.speedUp(); + this.turbine.speedUp(); }; function SpeedDownInstruction(turbine) { -this.turbine = turbine; + this.turbine = turbine; } + SpeedDownInstruction.prototype.execute = function() { -this.turbine.speedDown(); + this.turbine.speedDown(); }; module.exports = [Cockpit, Turbine, OnInstruction, OffInstruction, SpeedUpInstruction, SpeedDownInstruction];`, codeES6: `class Cockpit { -constructor(instruction) { - this.instruction = instruction; -} -execute() { - this.instruction.execute(); -} + constructor(instruction) { + this.instruction = instruction; + } + + execute() { + this.instruction.execute(); + } } class Turbine { -constructor() { - this.state = false; -} -on() { - this.state = true; -} -off() { - this.state = false; -} + constructor() { + this.state = false; + } + + on() { + this.state = true; + } + + off() { + this.state = false; + } } class OnInstruction { -constructor(turbine) { - this.turbine = turbine; -} -execute() { - this.turbine.on(); -} + constructor(turbine) { + this.turbine = turbine; + } + + execute() { + this.turbine.on(); + } } class OffInstruction { -constructor(turbine) { - this.turbine = turbine; -} -execute() { - this.turbine.off(); -} + constructor(turbine) { + this.turbine = turbine; + } + + execute() { + this.turbine.off(); + } } export { Cockpit, Turbine, OnInstruction, OffInstruction };` diff --git a/src/static/patterns/behavioral_interpreter.js b/src/static/patterns/behavioral_interpreter.js index f7dbe49..734c99c 100644 --- a/src/static/patterns/behavioral_interpreter.js +++ b/src/static/patterns/behavioral_interpreter.js @@ -4,62 +4,62 @@ const INTERPRETER = { type: 'behavioral', hint: 'implements a specialized language', codeES5: `function Sum(left, right) { -this.left = left; -this.right = right; + this.left = left; + this.right = right; } Sum.prototype.pattern = function() { -return this.left.pattern() + this.right.pattern(); + return this.left.pattern() + this.right.pattern(); }; function Min(left, right) { -this.left = left; -this.right = right; + this.left = left; + this.right = right; } Min.prototype.pattern = function() { -return this.left.pattern() - this.right.pattern(); + return this.left.pattern() - this.right.pattern(); }; function Num(val) { -this.val = val; + this.val = val; } Num.prototype.pattern = function() { -return this.val; + return this.val; }; module.exports = [Num, Min, Sum];`, codeES6: `class Sum { -constructor(left, right) { - this.left = left; - this.right = right; -} + constructor(left, right) { + this.left = left; + this.right = right; + } -pattern() { - return this.left.pattern() + this.right.pattern(); -} + pattern() { + return this.left.pattern() + this.right.pattern(); + } } class Min { -constructor(left, right) { - this.left = left; - this.right = right; -} + constructor(left, right) { + this.left = left; + this.right = right; + } -pattern() { - return this.left.pattern() - this.right.pattern(); -} + pattern() { + return this.left.pattern() - this.right.pattern(); + } } class Num { -constructor(val) { - this.val = val; -} + constructor(val) { + this.val = val; + } -pattern() { - return this.val; -} + pattern() { + return this.val; + } } export { Num, Min, Sum };` diff --git a/src/static/patterns/behavioral_iterator.js b/src/static/patterns/behavioral_iterator.js index 30272b1..6f91d3c 100644 --- a/src/static/patterns/behavioral_iterator.js +++ b/src/static/patterns/behavioral_iterator.js @@ -5,33 +5,33 @@ const ITERATOR = { hint: 'accesses the elements of an object sequentially without exposing its underlying representation', codeES5: `function Pattern(el) { -this.index = 0; -this.elements = el; + this.index = 0; + this.elements = el; } Pattern.prototype = { -next: function() { - return this.elements[this.index++]; -}, -hasNext: function() { - return this.index < this.elements.length; -} + next: function() { + return this.elements[this.index++]; + }, + hasNext: function() { + return this.index < this.elements.length; + } }; module.exports = Pattern;`, codeES6: `class Pattern { -constructor(el) { - this.index = 0; - this.elements = el; -} + constructor(el) { + this.index = 0; + this.elements = el; + } -next() { - return this.elements[this.index++]; -} + next() { + return this.elements[this.index++]; + } -hasNext() { - return this.index < this.elements.length; -} + hasNext() { + return this.index < this.elements.length; + } } export default Pattern;` diff --git a/src/static/patterns/behavioral_mediator.js b/src/static/patterns/behavioral_mediator.js index fff02ce..c1914b3 100644 --- a/src/static/patterns/behavioral_mediator.js +++ b/src/static/patterns/behavioral_mediator.js @@ -5,48 +5,48 @@ const MEDIATOR = { hint: 'allows loose coupling between classes by being the only class that has detailed knowledge of their methods', codeES5: `function TrafficTower() { -this.airplanes = []; + this.airplanes = []; } TrafficTower.prototype.requestPositions = function() { -return this.airplanes.map(function(airplane) { - return airplane.position; -}); + return this.airplanes.map(function(airplane) { + return airplane.position; + }); }; function Airplane(position, trafficTower) { -this.position = position; -this.trafficTower = trafficTower; -this.trafficTower.airplanes.push(this); + this.position = position; + this.trafficTower = trafficTower; + this.trafficTower.airplanes.push(this); } Airplane.prototype.requestPositions = function() { -return this.trafficTower.requestPositions(); + return this.trafficTower.requestPositions(); }; module.exports = [TrafficTower, Airplane];`, codeES6: `class TrafficTower { -constructor() { - this.airplanes = []; -} + constructor() { + this.airplanes = []; + } -requestPositions() { - return this.airplanes.map(airplane => { - return airplane.position; - }); -} + requestPositions() { + return this.airplanes.map(airplane => { + return airplane.position; + }); + } } class Airplane { -constructor(position, trafficTower) { - this.position = position; - this.trafficTower = trafficTower; - this.trafficTower.airplanes.push(this); -} - -requestPositions() { - return this.trafficTower.requestPositions(); -} + constructor(position, trafficTower) { + this.position = position; + this.trafficTower = trafficTower; + this.trafficTower.airplanes.push(this); + } + + requestPositions() { + return this.trafficTower.requestPositions(); + } } export { TrafficTower, Airplane };` diff --git a/src/static/patterns/behavioral_memento.js b/src/static/patterns/behavioral_memento.js index 1cef9c1..d59898b 100644 --- a/src/static/patterns/behavioral_memento.js +++ b/src/static/patterns/behavioral_memento.js @@ -4,58 +4,58 @@ const MEMENTO = { type: 'behavioral', hint: 'provides the ability to restore an object to its previous state', codeES5: `function Pattern(value) { -this.value = value; + this.value = value; } var originator = { -store: function(val) { - return new Pattern(val); -}, -restore: function(pattern) { - return pattern.value; -} + store: function(val) { + return new Pattern(val); + }, + restore: function(pattern) { + return pattern.value; + } }; function Caretaker() { -this.values = []; + this.values = []; } Caretaker.prototype.addPattern = function(pattern) { -this.values.push(pattern); + this.values.push(pattern); }; Caretaker.prototype.getPattern = function(index) { -return this.values[index]; + return this.values[index]; }; module.exports = [originator, Caretaker];`, codeES6: `class Pattern { -constructor(value) { - this.value = value; -} + constructor(value) { + this.value = value; + } } const originator = { -store: function(val) { - return new Pattern(val); -}, -restore: function(pattern) { - return pattern.value; -} + store: function(val) { + return new Pattern(val); + }, + restore: function(pattern) { + return pattern.value; + } }; class Caretaker { -constructor() { - this.values = []; -} + constructor() { + this.values = []; + } -addPattern(pattern) { - this.values.push(pattern); -} + addPattern(pattern) { + this.values.push(pattern); + } -getPattern(index) { - return this.values[index]; -} + getPattern(index) { + return this.values[index]; + } } export { originator, Caretaker };` diff --git a/src/static/patterns/behavioral_observer.js b/src/static/patterns/behavioral_observer.js index 29f1aa1..ff95a23 100644 --- a/src/static/patterns/behavioral_observer.js +++ b/src/static/patterns/behavioral_observer.js @@ -4,86 +4,86 @@ const OBSERVER = { type: 'behavioral', hint: 'is a publish/subscribe pattern which allows a number of observer objects to see an event', codeES5: `function Product() { -this.price = 0; -this.actions = []; + this.price = 0; + this.actions = []; } Product.prototype.setBasePrice = function(val) { -this.price = val; -this.notifyAll(); + this.price = val; + this.notifyAll(); }; Product.prototype.register = function(observer) { -this.actions.push(observer); + this.actions.push(observer); }; Product.prototype.unregister = function(observer) { -this.actions.remove.filter(function(el) { - return el !== observer; -}); + this.actions.remove.filter(function(el) { + return el !== observer; + }); }; Product.prototype.notifyAll = function() { -return this.actions.forEach( - function(el) { - el.update(this); - }.bind(this) -); + return this.actions.forEach( + function(el) { + el.update(this); + }.bind(this) + ); }; var fees = { -update: function(product) { - product.price = product.price * 1.2; -} + update: function(product) { + product.price = product.price * 1.2; + } }; var proft = { -update: function(product) { - product.price = product.price * 2; -} + update: function(product) { + product.price = product.price * 2; + } }; module.exports = [Product, fees, proft];`, codeES6: `class Product { -constructor() { - this.price = 0; - this.actions = []; -} + constructor() { + this.price = 0; + this.actions = []; + } -setBasePrice(val) { - this.price = val; - this.notifyAll(); -} + setBasePrice(val) { + this.price = val; + this.notifyAll(); + } -register(observer) { - this.actions.push(observer); -} + register(observer) { + this.actions.push(observer); + } -unregister(observer) { - this.actions.remove.filter(function(el) { - return el !== observer; - }); -} + unregister(observer) { + this.actions.remove.filter(function(el) { + return el !== observer; + }); + } -notifyAll() { - return this.actions.forEach( - function(el) { - el.update(this); - }.bind(this) - ); -} + notifyAll() { + return this.actions.forEach( + function(el) { + el.update(this); + }.bind(this) + ); + } } class fees { -update(product) { - product.price = product.price * 1.2; -} + update(product) { + product.price = product.price * 1.2; + } } class proft { -update(product) { - product.price = product.price * 2; -} + update(product) { + product.price = product.price * 2; + } } export { Product, fees, proft };` diff --git a/src/static/patterns/behavioral_state.js b/src/static/patterns/behavioral_state.js index c89ed61..8ac4e76 100644 --- a/src/static/patterns/behavioral_state.js +++ b/src/static/patterns/behavioral_state.js @@ -4,72 +4,72 @@ const STATE = { type: 'behavioral', hint: 'allows an object to alter its behavior when its internal state changes', codeES5: `function Order() { -this.pattern = new WaitingForPayment(); + this.pattern = new WaitingForPayment(); -this.nextPattern = function() { - this.pattern = this.pattern.next(); -}; + this.nextPattern = function() { + this.pattern = this.pattern.next(); + }; } function WaitingForPayment() { -this.name = 'waitingForPayment'; -this.next = function() { - return new Shipping(); -}; + this.name = 'waitingForPayment'; + this.next = function() { + return new Shipping(); + }; } function Shipping() { -this.name = 'shipping'; -this.next = function() { - return new Delivered(); -}; + this.name = 'shipping'; + this.next = function() { + return new Delivered(); + }; } function Delivered() { -this.name = 'delivered'; -this.next = function() { - return this; -}; + this.name = 'delivered'; + this.next = function() { + return this; + }; } module.exports = Order;`, codeES6: `class OrderStatus { -constructor(name, nextStatus) { - this.name = name; - this.nextStatus = nextStatus; -} + constructor(name, nextStatus) { + this.name = name; + this.nextStatus = nextStatus; + } -next() { - return new this.nextStatus(); -} + next() { + return new this.nextStatus(); + } } class WaitingForPayment extends OrderStatus { -constructor() { - super('waitingForPayment', Shipping); -} + constructor() { + super('waitingForPayment', Shipping); + } } class Shipping extends OrderStatus { -constructor() { - super('shipping', Delivered); -} + constructor() { + super('shipping', Delivered); + } } class Delivered extends OrderStatus { -constructor() { - super('delivered', Delivered); -} + constructor() { + super('delivered', Delivered); + } } class Order { -constructor() { - this.pattern = new WaitingForPayment(); -} + constructor() { + this.pattern = new WaitingForPayment(); + } -nextPattern() { - this.pattern = this.pattern.next(); -} + nextPattern() { + this.pattern = this.pattern.next(); + } } export default Order;` diff --git a/src/static/patterns/behavioral_strategy.js b/src/static/patterns/behavioral_strategy.js index 3d0cbc2..a3f6f7f 100644 --- a/src/static/patterns/behavioral_strategy.js +++ b/src/static/patterns/behavioral_strategy.js @@ -4,56 +4,56 @@ const STRATEGY = { type: 'behavioral', hint: 'allows one of a family of algorithms to be selected on-the-fly at runtime', codeES5: `function ShoppingCart(discount) { -this.discount = discount; -this.amount = 0; + this.discount = discount; + this.amount = 0; } ShoppingCart.prototype.setAmount = function(amount) { -this.amount = amount; + this.amount = amount; }; ShoppingCart.prototype.checkout = function() { -return this.discount(this.amount); + return this.discount(this.amount); }; function guestPattern(amount) { -return amount; + return amount; } function regularPattern(amount) { -return amount * 0.9; + return amount * 0.9; } function premiumPattern(amount) { -return amount * 0.8; + return amount * 0.8; } module.exports = [ShoppingCart, guestPattern, regularPattern, premiumPattern];`, codeES6: `class ShoppingCart { -constructor(discount) { - this.discount = discount; - this.amount = 0; -} + constructor(discount) { + this.discount = discount; + this.amount = 0; + } -checkout() { - return this.discount(this.amount); -} + checkout() { + return this.discount(this.amount); + } -setAmount(amount) { - this.amount = amount; -} + setAmount(amount) { + this.amount = amount; + } } function guestPattern(amount) { -return amount; + return amount; } function regularPattern(amount) { -return amount * 0.9; + return amount * 0.9; } function premiumPattern(amount) { -return amount * 0.8; + return amount * 0.8; } export { ShoppingCart, guestPattern, regularPattern, premiumPattern };` diff --git a/src/static/patterns/behavioral_template.js b/src/static/patterns/behavioral_template.js index 1fd1bd3..1ad0020 100644 --- a/src/static/patterns/behavioral_template.js +++ b/src/static/patterns/behavioral_template.js @@ -7,58 +7,60 @@ const TEMPLATE = { codeES5: `function Tax() {} Tax.prototype.calc = function(value) { -if (value >= 1000) value = this.overThousand(value); + if (value >= 1000) value = this.overThousand(value); -return this.complementaryFee(value); + return this.complementaryFee(value); }; Tax.prototype.complementaryFee = function(value) { -return value + 10; + return value + 10; }; function Tax1() {} -Tax1.prototype = Object.create(Tax.prototype); + Tax1.prototype = Object.create(Tax.prototype); -Tax1.prototype.overThousand = function(value) { -return value * 1.1; + Tax1.prototype.overThousand = function(value) { + return value * 1.1; }; function Tax2() {} -Tax2.prototype = Object.create(Tax.prototype); + Tax2.prototype = Object.create(Tax.prototype); -Tax2.prototype.overThousand = function(value) { -return value * 1.2; + Tax2.prototype.overThousand = function(value) { + return value * 1.2; }; module.exports = [Tax1, Tax2];`, codeES6: `class Tax { -calc(value) { - if (value >= 1000) value = this.overThousand(value); + calc(value) { + if (value >= 1000) value = this.overThousand(value); - return this.complementaryFee(value); -} + return this.complementaryFee(value); + } -complementaryFee(value) { - return value + 10; -} + complementaryFee(value) { + return value + 10; + } } class Tax1 extends Tax { -constructor() { - super(); -} -overThousand(value) { - return value * 1.1; -} + constructor() { + super(); + } + + overThousand(value) { + return value * 1.1; + } } class Tax2 extends Tax { -constructor() { - super(); -} -overThousand(value) { - return value * 1.2; -} + constructor() { + super(); + } + + overThousand(value) { + return value * 1.2; + } } export { Tax1, Tax2 };` diff --git a/src/static/patterns/behavioral_visitor.js b/src/static/patterns/behavioral_visitor.js index 42f4eb9..d7e4a49 100644 --- a/src/static/patterns/behavioral_visitor.js +++ b/src/static/patterns/behavioral_visitor.js @@ -5,57 +5,57 @@ const VISITOR = { hint: 'separates an algorithm from an object structure by moving the hierarchy of methods into one object', codeES5: `function bonusPattern(employee) { -if (employee instanceof Manager) employee.bonus = employee.salary * 2; -if (employee instanceof Developer) employee.bonus = employee.salary; + if (employee instanceof Manager) employee.bonus = employee.salary * 2; + if (employee instanceof Developer) employee.bonus = employee.salary; } function Employee() { -this.bonus = 0; + this.bonus = 0; } Employee.prototype.accept = function(item) { -item(this); + item(this); }; function Manager(salary) { -this.salary = salary; + this.salary = salary; } Manager.prototype = Object.create(Employee.prototype); function Developer(salary) { -this.salary = salary; + this.salary = salary; } Developer.prototype = Object.create(Employee.prototype); module.exports = [Developer, Manager, bonusPattern];`, codeES6: `function bonusPattern(employee) { -if (employee instanceof Manager) employee.bonus = employee.salary * 2; -if (employee instanceof Developer) employee.bonus = employee.salary; + if (employee instanceof Manager) employee.bonus = employee.salary * 2; + if (employee instanceof Developer) employee.bonus = employee.salary; } class Employee { -constructor(salary) { - this.bonus = 0; - this.salary = salary; -} + constructor(salary) { + this.bonus = 0; + this.salary = salary; + } -accept(item) { - item(this); -} + accept(item) { + item(this); + } } class Manager extends Employee { -constructor(salary) { - super(salary); -} + constructor(salary) { + super(salary); + } } class Developer extends Employee { -constructor(salary) { - super(salary); -} + constructor(salary) { + super(salary); + } } export { Developer, Manager, bonusPattern };` diff --git a/src/static/patterns/creational_abstractFactory.js b/src/static/patterns/creational_abstractFactory.js index dd8eaff..d34604c 100644 --- a/src/static/patterns/creational_abstractFactory.js +++ b/src/static/patterns/creational_abstractFactory.js @@ -4,52 +4,52 @@ const ABSTRACT_FACTORY = { type: 'creational', hint: 'groups object factories that have a common theme', codeES5: `function droidProducer(kind) { -if (kind === 'battle') return battleDroidPattern; -return pilotDroidPattern; + if (kind === 'battle') return battleDroidPattern; + return pilotDroidPattern; } function battleDroidPattern() { -return new B1(); + return new B1(); } function pilotDroidPattern() { -return new Rx24(); + return new Rx24(); } function B1() {} -B1.prototype.info = function() { -return 'B1, Battle Droid'; + B1.prototype.info = function() { + return 'B1, Battle Droid'; }; function Rx24() {} -Rx24.prototype.info = function() { -return 'Rx24, Pilot Droid'; + Rx24.prototype.info = function() { + return 'Rx24, Pilot Droid'; }; module.exports = droidProducer;`, codeES6: `function droidProducer(kind) { -if (kind === 'battle') return battleDroidPattern; -return pilotDroidPattern; + if (kind === 'battle') return battleDroidPattern; + return pilotDroidPattern; } function battleDroidPattern() { -return new B1(); + return new B1(); } function pilotDroidPattern() { -return new Rx24(); + return new Rx24(); } class B1 { -info() { - return 'B1, Battle Droid'; -} + info() { + return 'B1, Battle Droid'; + } } class Rx24 { -info() { - return 'Rx24, Pilot Droid'; -} + info() { + return 'Rx24, Pilot Droid'; + } } export default droidProducer;` diff --git a/src/static/patterns/creational_builder.js b/src/static/patterns/creational_builder.js index 4a5ec31..aa805bc 100644 --- a/src/static/patterns/creational_builder.js +++ b/src/static/patterns/creational_builder.js @@ -4,66 +4,66 @@ const BUILDER = { type: 'creational', hint: 'constructs complex objects by separating construction and representation', codeES5: `function Request() { -this.url = ''; -this.method = ''; -this.payload = {}; + this.url = ''; + this.method = ''; + this.payload = {}; } function RequestPattern() { -this.request = new Request(); + this.request = new Request(); -this.forUrl = function(url) { - this.request.url = url; - return this; -}; + this.forUrl = function(url) { + this.request.url = url; + return this; + }; -this.useMethod = function(method) { - this.request.method = method; - return this; -}; + this.useMethod = function(method) { + this.request.method = method; + return this; + }; -this.payload = function(payload) { - this.request.payload = payload; - return this; -}; + this.payload = function(payload) { + this.request.payload = payload; + return this; + }; -this.build = function() { - return this.request; -}; + this.build = function() { + return this.request; + }; } module.exports = RequestPattern;`, codeES6: `class Request { -constructor() { - this.url = ''; - this.method = ''; - this.payload = {}; -} + constructor() { + this.url = ''; + this.method = ''; + this.payload = {}; + } } class RequestPattern { -constructor() { - this.request = new Request(); -} + constructor() { + this.request = new Request(); + } -forUrl(url) { - this.request.url = url; - return this; -} + forUrl(url) { + this.request.url = url; + return this; + } -useMethod(method) { - this.request.method = method; - return this; -} + useMethod(method) { + this.request.method = method; + return this; + } -payload(payload) { - this.request.payload = payload; - return this; -} + payload(payload) { + this.request.payload = payload; + return this; + } -build() { - return this.request; -} + build() { + return this.request; + } } export default RequestPattern;` diff --git a/src/static/patterns/creational_factory.js b/src/static/patterns/creational_factory.js index f56d807..9f9c2db 100644 --- a/src/static/patterns/creational_factory.js +++ b/src/static/patterns/creational_factory.js @@ -4,30 +4,30 @@ const FACTORY = { type: 'creational', hint: 'creates objects without specifying the exact class to create', codeES5: `function teslaPattern(type) { -if (type === 'ModelX') return new Tesla(type, 108000, 300); -if (type === 'ModelS') return new Tesla(type, 111000, 320); + if (type === 'ModelX') return new Tesla(type, 108000, 300); + if (type === 'ModelS') return new Tesla(type, 111000, 320); } function Tesla(model, price, maxSpeed) { -this.model = model; -this.price = price; -this.maxSpeed = maxSpeed; + this.model = model; + this.price = price; + this.maxSpeed = maxSpeed; } module.exports = teslaPattern;`, codeES6: `class TeslaPattern { -create(type) { - if (type === 'ModelX') return new Tesla(type, 108000, 300); - if (type === 'ModelS') return new Tesla(type, 111000, 320); -} + create(type) { + if (type === 'ModelX') return new Tesla(type, 108000, 300); + if (type === 'ModelS') return new Tesla(type, 111000, 320); + } } class Tesla { -constructor(model, price, maxSpeed) { - this.model = model; - this.price = price; - this.maxSpeed = maxSpeed; -} + constructor(model, price, maxSpeed) { + this.model = model; + this.price = price; + this.maxSpeed = maxSpeed; + } } export default TeslaPattern;` diff --git a/src/static/patterns/creational_prototype.js b/src/static/patterns/creational_prototype.js index c6e5437..b3e2c2d 100644 --- a/src/static/patterns/creational_prototype.js +++ b/src/static/patterns/creational_prototype.js @@ -4,24 +4,24 @@ const PROTOTYPE = { type: 'creational', hint: 'creates objects by cloning an existing object', codeES5: `function Sheep(name, weight) { -this.name = name; -this.weight = weight; + this.name = name; + this.weight = weight; } Sheep.prototype.clone = function() { -return new Sheep(this.name, this.weight); + return new Sheep(this.name, this.weight); }; module.exports = Sheep;`, codeES6: `class Sheep { -constructor(name, weight) { - this.name = name; - this.weight = weight; -} + constructor(name, weight) { + this.name = name; + this.weight = weight; + } -clone() { - return new Sheep(this.name, this.weight); -} + clone() { + return new Sheep(this.name, this.weight); + } } export default Sheep;` diff --git a/src/static/patterns/creational_singleton.js b/src/static/patterns/creational_singleton.js index dfaa7dd..b4aeaa8 100644 --- a/src/static/patterns/creational_singleton.js +++ b/src/static/patterns/creational_singleton.js @@ -4,22 +4,24 @@ const SINGLETON = { type: 'creational', hint: 'restricts object creation for a class to only one instance', codeES5: `function Person() { -if (typeof Person.instance === 'object') return Person.instance; + if (typeof Person.instance === 'object') return Person.instance; -Person.instance = this; + Person.instance = this; -return this; + return this; } module.exports = Person;`, codeES6: `class Person { -constructor() { - if (typeof Person.instance === 'object') { - return Person.instance; + constructor() { + if (typeof Person.instance === 'object') { + return Person.instance; + } + + Person.instance = this; + + return this; } - Person.instance = this; - return this; -} } export default Person;` diff --git a/src/static/patterns/index.js b/src/static/patterns/index.js index f5df231..a9591ae 100644 --- a/src/static/patterns/index.js +++ b/src/static/patterns/index.js @@ -22,7 +22,7 @@ import STRATEGY from './behavioral_strategy'; import TEMPLATE from './behavioral_template'; import VISITOR from './behavioral_visitor'; -const patterns = [ +export const patterns = [ ABSTRACT_FACTORY, BUILDER, FACTORY, @@ -50,9 +50,10 @@ const patterns = [ VISITOR ]; -for (let i = patterns.length - 1; i > 0; i--) { +const mixed = [...patterns]; +for (let i = mixed.length - 1; i > 0; i--) { const rand = Math.floor(Math.random() * (i + 1)); - [patterns[i], patterns[rand]] = [patterns[rand], patterns[i]]; + [mixed[i], mixed[rand]] = [mixed[rand], mixed[i]]; } -export default patterns; +export default mixed; diff --git a/src/static/patterns/structural_adapter.js b/src/static/patterns/structural_adapter.js index 87cfc25..6ff8842 100644 --- a/src/static/patterns/structural_adapter.js +++ b/src/static/patterns/structural_adapter.js @@ -5,58 +5,58 @@ const ADAPTER = { hint: `allows classes with incompatible interfaces to work together by wrapping its own interface around that of an already existing class`, codeES5: `function Soldier(lvl) { -this.lvl = lvl; + this.lvl = lvl; } Soldier.prototype.attack = function() { -return this.lvl * 1; + return this.lvl * 1; }; function Jedi(lvl) { -this.lvl = lvl; + this.lvl = lvl; } Jedi.prototype.attackWithSaber = function() { -return this.lvl * 100; + return this.lvl * 100; }; function JediPattern(jedi) { -this.jedi = jedi; + this.jedi = jedi; } JediPattern.prototype.attack = function() { -return this.jedi.attackWithSaber(); + return this.jedi.attackWithSaber(); }; module.exports = [Soldier, Jedi, JediPattern];`, codeES6: `class Soldier { -constructor(level) { - this.level = level; -} + constructor(level) { + this.level = level; + } -attack() { - return this.level * 1; -} + attack() { + return this.level * 1; + } } class Jedi { -constructor(level) { - this.level = level; -} + constructor(level) { + this.level = level; + } -attackWithSaber() { - return this.level * 100; -} + attackWithSaber() { + return this.level * 100; + } } class JediPattern { -constructor(jedi) { - this.jedi = jedi; -} + constructor(jedi) { + this.jedi = jedi; + } -attack() { - return this.jedi.attackWithSaber(); -} + attack() { + return this.jedi.attackWithSaber(); + } } export { Soldier, Jedi, JediPattern };` diff --git a/src/static/patterns/structural_bridge.js b/src/static/patterns/structural_bridge.js index 9268f97..2e07900 100644 --- a/src/static/patterns/structural_bridge.js +++ b/src/static/patterns/structural_bridge.js @@ -4,73 +4,76 @@ const BRIDGE = { type: 'structural', hint: 'decouples an abstraction from its implementation so that the two can vary independently', codeES5: `function EpsonPrinter(ink) { -this.ink = ink(); + this.ink = ink(); } + EpsonPrinter.prototype.print = function() { -return 'Printer: Epson, Ink: ' + this.ink; + return 'Printer: Epson, Ink: ' + this.ink; }; function HPprinter(ink) { -this.ink = ink(); + this.ink = ink(); } + HPprinter.prototype.print = function() { -return 'Printer: HP, Ink: ' + this.ink; + return 'Printer: HP, Ink: ' + this.ink; }; function acrylicInk() { -return 'acrylic-based'; + return 'acrylic-based'; } function alcoholInk() { -return 'alcohol-based'; + return 'alcohol-based'; } module.exports = [EpsonPrinter, HPprinter, acrylicInk, alcoholInk];`, codeES6: `class Printer { -constructor(ink) { - this.ink = ink; -} + constructor(ink) { + this.ink = ink; + } } class EpsonPrinter extends Printer { -constructor(ink) { - super(ink); -} + constructor(ink) { + super(ink); + } -print() { - return 'Printer: Epson, Ink: ' + this.ink.get(); -} + print() { + return 'Printer: Epson, Ink: ' + this.ink.get(); + } } class HPprinter extends Printer { -constructor(ink) { - super(ink); -} + constructor(ink) { + super(ink); + } -print() { - return 'Printer: HP, Ink: ' + this.ink.get(); -} + print() { + return 'Printer: HP, Ink: ' + this.ink.get(); + } } class Ink { -constructor(type) { - this.type = type; -} -get() { - return this.type; -} + constructor(type) { + this.type = type; + } + + get() { + return this.type; + } } class AcrylicInk extends Ink { -constructor() { - super('acrylic-based'); -} + constructor() { + super('acrylic-based'); + } } class AlcoholInk extends Ink { -constructor() { - super('alcohol-based'); -} + constructor() { + super('alcohol-based'); + } } export { EpsonPrinter, HPprinter, AcrylicInk, AlcoholInk };` diff --git a/src/static/patterns/structural_composite.js b/src/static/patterns/structural_composite.js index 9fad8bf..1cf4215 100644 --- a/src/static/patterns/structural_composite.js +++ b/src/static/patterns/structural_composite.js @@ -4,116 +4,116 @@ const COMPOSITE = { type: 'structural', hint: 'composes zero-or-more similar objects so that they can be manipulated as one object', codeES5: `function EquipmentPattern(name) { -this.equipments = []; -this.name = name; + this.equipments = []; + this.name = name; } EquipmentPattern.prototype.add = function(equipment) { -this.equipments.push(equipment); + this.equipments.push(equipment); }; EquipmentPattern.prototype.getPrice = function() { -return this.equipments - .map(function(equipment) { - return equipment.getPrice(); - }) - .reduce(function(a, b) { - return a + b; - }); + return this.equipments + .map(function(equipment) { + return equipment.getPrice(); + }) + .reduce(function(a, b) { + return a + b; + }); }; function Equipment() {} Equipment.prototype.getPrice = function() { -return this.price; + return this.price; }; // -- leafs function FloppyDisk() { -this.name = 'Floppy Disk'; -this.price = 70; + this.name = 'Floppy Disk'; + this.price = 70; } FloppyDisk.prototype = Object.create(Equipment.prototype); function HardDrive() { -this.name = 'Hard Drive'; -this.price = 250; + this.name = 'Hard Drive'; + this.price = 250; } HardDrive.prototype = Object.create(Equipment.prototype); function Memory() { -this.name = '8gb memomry'; -this.price = 280; + this.name = '8gb memomry'; + this.price = 280; } Memory.prototype = Object.create(Equipment.prototype); module.exports = [EquipmentPattern, FloppyDisk, HardDrive, Memory];`, codeES6: `//Equipment class Equipment { -getPrice() { - return this.price || 0; -} + getPrice() { + return this.price || 0; + } -getName() { - return this.name; -} + getName() { + return this.name; + } -setName(name) { - this.name = name; -} + setName(name) { + this.name = name; + } } class Pattern extends Equipment { -constructor() { - super(); - this.equipments = []; -} - -add(equipment) { - this.equipments.push(equipment); -} - -getPrice() { - return this.equipments - .map(equipment => { - return equipment.getPrice(); - }) - .reduce((a, b) => { - return a + b; - }); -} + constructor() { + super(); + this.equipments = []; + } + + add(equipment) { + this.equipments.push(equipment); + } + + getPrice() { + return this.equipments + .map(equipment => { + return equipment.getPrice(); + }) + .reduce((a, b) => { + return a + b; + }); + } } class Cabbinet extends Pattern { -constructor() { - super(); - this.setName('cabbinet'); -} + constructor() { + super(); + this.setName('cabbinet'); + } } // --- leafs --- class FloppyDisk extends Equipment { -constructor() { - super(); - this.setName('Floppy Disk'); - this.price = 70; -} + constructor() { + super(); + this.setName('Floppy Disk'); + this.price = 70; + } } class HardDrive extends Equipment { -constructor() { - super(); - this.setName('Hard Drive'); - this.price = 250; -} + constructor() { + super(); + this.setName('Hard Drive'); + this.price = 250; + } } class Memory extends Equipment { -constructor() { - super(); - this.setName('Memory'); - this.price = 280; -} + constructor() { + super(); + this.setName('Memory'); + this.price = 280; + } } export { Cabbinet, FloppyDisk, HardDrive, Memory };` diff --git a/src/static/patterns/structural_decorator.js b/src/static/patterns/structural_decorator.js index 10249dd..c492e7c 100644 --- a/src/static/patterns/structural_decorator.js +++ b/src/static/patterns/structural_decorator.js @@ -4,79 +4,82 @@ const DECORATOR = { type: 'structural', hint: 'dynamically adds/overrides behaviour in an existing method of an object', codeES5: `function Pasta() { -this.price = 0; + this.price = 0; } + Pasta.prototype.getPrice = function() { -return this.price; + return this.price; }; function Penne() { -this.price = 8; + this.price = 8; } + Penne.prototype = Object.create(Pasta.prototype); function SaucePattern(pasta) { -this.pasta = pasta; + this.pasta = pasta; } SaucePattern.prototype.getPrice = function() { -return this.pasta.getPrice() + 5; + return this.pasta.getPrice() + 5; }; function CheesePattern(pasta) { -this.pasta = pasta; + this.pasta = pasta; } CheesePattern.prototype.getPrice = function() { -return this.pasta.getPrice() + 3; + return this.pasta.getPrice() + 3; }; module.exports = [Penne, SaucePattern, CheesePattern];`, codeES6: `class Pasta { -constructor() { - this.price = 0; -} -getPrice() { - return this.price; -} + constructor() { + this.price = 0; + } + + getPrice() { + return this.price; + } } class Penne extends Pasta { -constructor() { - super(); - this.price = 8; -} + constructor() { + super(); + this.price = 8; + } } class PastaPattern extends Pasta { -constructor(pasta) { - super(); - this.pasta = pasta; -} + constructor(pasta) { + super(); + this.pasta = pasta; + } -getPrice() { - return this.pasta.getPrice(); -} + getPrice() { + return this.pasta.getPrice(); + } } class SaucePattern extends PastaPattern { -constructor(pasta) { - super(pasta); -} + constructor(pasta) { + super(pasta); + } -getPrice() { - return super.getPrice() + 5; -} + getPrice() { + return super.getPrice() + 5; + } } class CheesePattern extends PastaPattern { -constructor(pasta) { - super(pasta); -} + constructor(pasta) { + super(pasta); + } -getPrice() { - return super.getPrice() + 3; -} + getPrice() { + return super.getPrice() + 3; + } } export { Penne, SaucePattern, CheesePattern };` diff --git a/src/static/patterns/structural_facade.js b/src/static/patterns/structural_facade.js index 40c1f84..809105d 100644 --- a/src/static/patterns/structural_facade.js +++ b/src/static/patterns/structural_facade.js @@ -4,58 +4,60 @@ const FACADE = { type: 'structural', hint: 'provides a simplified interface to a large body of code', codeES5: `var shopPattern = { -calc: function(price) { - price = discount(price); - price = fees(price); - price += shipping(); - return price; -} + calc: function(price) { + price = discount(price); + price = fees(price); + price += shipping(); + + return price; + } }; function discount(value) { -return value * 0.9; + return value * 0.9; } function shipping() { -return 5; + return 5; } function fees(value) { -return value * 1.05; + return value * 1.05; } module.exports = shopPattern;`, codeES6: `class ShopPattern { -constructor() { - this.discount = new Discount(); - this.shipping = new Shipping(); - this.fees = new Fees(); -} + constructor() { + this.discount = new Discount(); + this.shipping = new Shipping(); + this.fees = new Fees(); + } -calc(price) { - price = this.discount.calc(price); - price = this.fees.calc(price); - price += this.shipping.calc(); - return price; -} + calc(price) { + price = this.discount.calc(price); + price = this.fees.calc(price); + price += this.shipping.calc(); + + return price; + } } class Discount { -calc(value) { - return value * 0.9; -} + calc(value) { + return value * 0.9; + } } class Shipping { -calc() { - return 5; -} + calc() { + return 5; + } } class Fees { -calc(value) { - return value * 1.05; -} + calc(value) { + return value * 1.05; + } } export default ShopPattern;` diff --git a/src/static/patterns/structural_flyweight.js b/src/static/patterns/structural_flyweight.js index 3adb6c6..f547607 100644 --- a/src/static/patterns/structural_flyweight.js +++ b/src/static/patterns/structural_flyweight.js @@ -4,37 +4,41 @@ const FLYWEIGHT = { type: 'structural', hint: 'reduces the cost of creating and manipulating a large number of similar objects', codeES5: `function Color(name) { -this.name = name; + this.name = name; } var colorCreator = { -colors: {}, -create: function(name) { - var color = this.colors[name]; - if (color) return color; + colors: {}, + create: function(name) { + var color = this.colors[name]; + if (color) return color; - this.colors[name] = new Color(name); - return this.colors[name]; -} + this.colors[name] = new Color(name); + + return this.colors[name]; + } }; module.exports = colorCreator;`, codeES6: `class Color { -constructor(name) { - this.name = name; -} + constructor(name) { + this.name = name; + } } class colorCreator { -constructor(name) { - this.colors = {}; -} -create(name) { - let color = this.colors[name]; - if (color) return color; - this.colors[name] = new Color(name); - return this.colors[name]; -} + constructor(name) { + this.colors = {}; + } + + create(name) { + let color = this.colors[name]; + if (color) return color; + + this.colors[name] = new Color(name); + + return this.colors[name]; + } } export { colorCreator };` diff --git a/src/static/patterns/structural_proxy.js b/src/static/patterns/structural_proxy.js index 91b76e2..c1831b7 100644 --- a/src/static/patterns/structural_proxy.js +++ b/src/static/patterns/structural_proxy.js @@ -5,43 +5,45 @@ const PROXY = { hint: 'provides a placeholder for another object to control access, reduce cost, and reduce complexity', codeES5: `function Car() { -this.drive = function() { - return 'driving'; -}; + this.drive = function() { + return 'driving'; + }; } function CarPattern(driver) { -this.driver = driver; -this.drive = function() { - if (driver.age < 18) return 'too young to drive'; - return new Car().drive(); -}; + this.driver = driver; + this.drive = function() { + if (driver.age < 18) return 'too young to drive'; + + return new Car().drive(); + }; } function Driver(age) { -this.age = age; + this.age = age; } module.exports = [Car, CarPattern, Driver];`, codeES6: `class Car { -drive() { - return 'driving'; -} + drive() { + return 'driving'; + } } class CarPattern { -constructor(driver) { - this.driver = driver; -} -drive() { - return this.driver.age < 18 ? 'too young to drive' : new Car().drive(); -} + constructor(driver) { + this.driver = driver; + } + + drive() { + return this.driver.age < 18 ? 'too young to drive' : new Car().drive(); + } } class Driver { -constructor(age) { - this.age = age; -} + constructor(age) { + this.age = age; + } } export { Car, CarPattern, Driver };` diff --git a/src/styles/global.js b/src/styles/global.js index ffec272..4f2a566 100644 --- a/src/styles/global.js +++ b/src/styles/global.js @@ -12,13 +12,17 @@ const GlobalStyle = createGlobalStyle` justify-content: start; max-width: 640px; margin: auto; - padding: 0 1rem; + padding: 0 1rem 3rem; @media (min-width: 769px) { justify-content: space-between; - padding: 0; + padding: 0 0 3rem; } } + + .fixed { + height: 375px + } `; export default GlobalStyle; diff --git a/src/styles/hljs/hljs.dark.js b/src/styles/hljs/hljs.dark.js index d520dfd..0bdd897 100644 --- a/src/styles/hljs/hljs.dark.js +++ b/src/styles/hljs/hljs.dark.js @@ -5,8 +5,7 @@ const styles = { overflowX: 'auto', padding: '1em', background: '#282828', - color: '#ebdbb2', - height: 375 + color: '#ebdbb2' }, 'hljs-subst': { color: '#ebdbb2' diff --git a/src/styles/hljs/hljs.light.js b/src/styles/hljs/hljs.light.js index 51300b7..50a2791 100644 --- a/src/styles/hljs/hljs.light.js +++ b/src/styles/hljs/hljs.light.js @@ -5,8 +5,7 @@ const styles = { overflowX: 'auto', padding: '1em', color: '#383a42', - background: '#fafafa', - height: 375 + background: '#fafafa' }, 'hljs-comment': { color: '#a0a1a7',