├── .babelrc ├── .eslintignore ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── stale.yml ├── .gitignore ├── FUNDING.yml ├── LICENSE ├── README.md ├── app.py ├── docs ├── BrowserWindow.html ├── Builder.html ├── Cleaner.html ├── Dispatcher.html ├── Packager.html ├── Requests.html ├── Services.html ├── Starter.html ├── Theme.html ├── Titlebar.html ├── global.html ├── index.html ├── main.js.html ├── scripts │ ├── custom.js │ ├── linenumber.js │ ├── prettify │ │ ├── Apache-License-2.0.txt │ │ ├── lang-css.js │ │ └── prettify.js │ ├── search.js │ └── utils.min.js ├── scripts_build.js.html ├── scripts_clean.js.html ├── scripts_dispatch.js.html ├── scripts_package.js.html ├── scripts_start.js.html ├── src_components_titlebar_Titlebar.js.html ├── src_components_titlebar_TitlebarButtons.js.html ├── src_theme_palette.js.html ├── src_utils_requests.js.html ├── src_utils_services.js.html └── styles │ ├── custom.css │ ├── daybrush.css │ ├── jsdoc.css │ └── prettify.css ├── jsconfig.json ├── jsdoc.json ├── main.js ├── package.json ├── preload.js ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── renderer.js ├── requirements.txt ├── scripts ├── build.js ├── clean.js ├── dispatch.js ├── package.js └── start.js ├── src ├── components │ ├── App.js │ ├── App.module.scss │ ├── counter │ │ ├── Counter.js │ │ ├── Counter.module.scss │ │ └── counterSlice.js │ └── titlebar │ │ ├── Titlebar.js │ │ ├── TitlebarButtons.js │ │ ├── img │ │ └── favicon.png │ │ └── scss │ │ ├── Titlebar.module.scss │ │ └── TitlebarButtons.module.scss ├── index.js ├── index.scss ├── logo.svg ├── serviceWorker.js ├── state │ └── store.js ├── tests │ ├── App.test.js │ └── setupTests.js ├── theme │ ├── palette.js │ └── variables.scss └── utils │ ├── requests.js │ └── services.js ├── utilities ├── deb │ └── images │ │ ├── background.png │ │ ├── banner.png │ │ └── icon.ico ├── dmg │ └── images │ │ ├── background.png │ │ └── icon.icns ├── jsdoc │ ├── LICENSE.md │ ├── README.md │ ├── fixtures │ │ ├── base │ │ │ ├── chains.js │ │ │ └── index.js │ │ ├── documents │ │ │ ├── binder.js │ │ │ ├── collector.js │ │ │ ├── model.js │ │ │ ├── probe.js │ │ │ └── schema.js │ │ ├── fixtures.conf.json │ │ ├── mixins │ │ │ ├── bussable.js │ │ │ └── signalable.js │ │ ├── strings │ │ │ └── format.js │ │ ├── tutorials │ │ │ ├── Brush Teeth.md │ │ │ ├── Drive Car.md │ │ │ └── Fence Test.md │ │ └── utils │ │ │ └── logger.js │ ├── package.json │ ├── publish.js │ ├── static │ │ ├── scripts │ │ │ ├── custom.js │ │ │ ├── linenumber.js │ │ │ ├── prettify │ │ │ │ ├── Apache-License-2.0.txt │ │ │ │ ├── lang-css.js │ │ │ │ └── prettify.js │ │ │ ├── search.js │ │ │ └── utils.min.js │ │ └── styles │ │ │ ├── custom.css │ │ │ ├── daybrush.css │ │ │ ├── jsdoc.css │ │ │ └── prettify.css │ └── tmpl │ │ ├── augments.tmpl │ │ ├── container.tmpl │ │ ├── details.tmpl │ │ ├── example.tmpl │ │ ├── examples.tmpl │ │ ├── exceptions.tmpl │ │ ├── layout.tmpl │ │ ├── mainpage.tmpl │ │ ├── members.tmpl │ │ ├── method.tmpl │ │ ├── params.tmpl │ │ ├── properties.tmpl │ │ ├── returns.tmpl │ │ ├── source.tmpl │ │ ├── tutorial.tmpl │ │ └── type.tmpl ├── loaders │ ├── react │ │ ├── assets │ │ │ ├── logo.svg │ │ │ └── style.css │ │ └── index.html │ └── redux │ │ ├── assets │ │ ├── logo.svg │ │ └── style.css │ │ └── index.html └── msi │ └── images │ ├── background.png │ ├── banner.png │ └── icon.ico └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env", 4 | "@babel/react", 5 | ["minify", { 6 | "builtIns": false 7 | }] 8 | ], 9 | "plugins": [ 10 | "@babel/plugin-proposal-async-generator-functions", 11 | "@babel/plugin-proposal-class-properties", 12 | "@babel/plugin-proposal-object-rest-spread", 13 | "@babel/plugin-transform-arrow-functions", 14 | "@babel/plugin-transform-async-to-generator", 15 | "@babel/plugin-transform-classes", 16 | "@babel/plugin-transform-computed-properties", 17 | "@babel/plugin-transform-destructuring", 18 | "@babel/plugin-transform-for-of", 19 | "@babel/plugin-transform-parameters", 20 | "@babel/plugin-transform-shorthand-properties", 21 | "@babel/plugin-transform-spread", 22 | "@babel/plugin-transform-sticky-regex", 23 | "@babel/plugin-transform-template-literals" 24 | ] 25 | } -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | build/ 2 | dist/ 3 | node_modules/ 4 | stories/ 5 | .snapshots/ 6 | *.min.js -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | browser: true, 4 | es6: true, 5 | mocha: true 6 | }, 7 | extends: ['plugin:react/recommended', 'airbnb'], 8 | globals: { 9 | Atomics: 'readonly', 10 | SharedArrayBuffer: 'readonly' 11 | }, 12 | parser: 'babel-eslint', 13 | parserOptions: { 14 | ecmaFeatures: { 15 | jsx: true 16 | }, 17 | ecmaVersion: 12, 18 | sourceType: 'module' 19 | }, 20 | plugins: ['react'], 21 | rules: { 22 | 'array-bracket-spacing': [0], 23 | 'arrow-body-style': [0], 24 | 'arrow-parens': ['warn'], 25 | 'brace-style': [0], 26 | 'comma-dangle': ['warn', 'never'], 27 | 'consistent-return': [0], 28 | 'eol-last': [0], 29 | 'func-names': ['warn', 'always', { 30 | generators: 'as-needed' 31 | }], 32 | 'global-require': [0], 33 | 'implicit-arrow-linebreak': [0], 34 | 'import/no-dynamic-require': ['warn'], 35 | 'import/no-extraneous-dependencies': [0], 36 | 'import/order': ['warn'], 37 | 'import/prefer-default-export': [0], 38 | 'indent': ['warn', 2, { 39 | SwitchCase: 1 40 | }], 41 | 'jsx-a11y/anchor-is-valid': ['warn'], 42 | 'jsx-a11y/click-events-have-key-events': [0], 43 | 'jsx-a11y/interactive-supports-focus': [0], 44 | 'jsx-a11y/label-has-associated-control': [0], 45 | 'jsx-a11y/no-noninteractive-element-interactions': [0], 46 | 'keyword-spacing': ['warn'], 47 | 'linebreak-style': [0], 48 | 'max-len': ['warn'], 49 | 'no-console': ['warn', { 50 | allow: ['warn', 'error'] 51 | }], 52 | 'no-mixed-spaces-and-tabs': ['warn'], 53 | 'no-multi-spaces': ['warn'], 54 | 'no-multiple-empty-lines': [0], 55 | 'no-nested-ternary': [0], 56 | 'no-param-reassign': [0], 57 | 'no-restricted-syntax': [0], 58 | 'no-tabs': ['warn'], 59 | 'no-trailing-spaces': ['warn'], 60 | 'no-underscore-dangle': ['warn'], 61 | 'no-unneeded-ternary': ['warn'], 62 | 'no-unused-expressions': [0], 63 | 'no-unused-vars': ['warn', { 'argsIgnorePattern': '^_' }], 64 | 'no-use-before-define': ['error', { 65 | 'functions': false 66 | }], 67 | 'object-curly-newline': [0], 68 | 'object-curly-spacing': ['warn'], 69 | 'object-shorthand': ['warn', 'always'], 70 | 'one-var': ['warn', { 71 | 'initialized': 'never' 72 | }], 73 | 'one-var-declaration-per-line': ['warn', 'initializations'], 74 | 'operator-linebreak': ['warn'], 75 | 'padded-blocks': [0], 76 | 'prefer-arrow-callback': ['warn'], 77 | 'prefer-const': ['warn'], 78 | 'prefer-destructuring': [ 79 | 'warn', 80 | { 81 | array: true, 82 | object: true 83 | }, 84 | { 85 | enforceForRenamedProperties: false 86 | } 87 | ], 88 | 'prefer-template': ['warn'], 89 | 'quote-props': ['warn', 'consistent'], 90 | 'quotes': ['warn'], 91 | 'react/destructuring-assignment': [0], 92 | 'react/forbid-prop-types': [0], 93 | 'react/jsx-closing-bracket-location': ['warn'], 94 | 'react/jsx-curly-newline': ['warn'], 95 | 'react/jsx-curly-spacing': ['warn', 'always'], 96 | 'react/jsx-equals-spacing': ['warn'], 97 | 'react/jsx-filename-extension': [0], 98 | 'react/jsx-fragments': [0], 99 | 'react/jsx-indent': ['warn', 2], 100 | 'react/jsx-one-expression-per-line': ['warn'], 101 | 'react/jsx-props-no-spreading': [0], 102 | 'react/jsx-tag-spacing': ['warn'], 103 | 'react/jsx-wrap-multilines': ['warn'], 104 | 'react/no-access-state-in-setstate': [0], 105 | 'react/no-array-index-key': [0], 106 | 'react/no-unused-state': ['warn'], 107 | 'react/prefer-stateless-function': ['warn'], 108 | 'react/prop-types': ['warn'], 109 | 'react/require-default-props': ['warn'], 110 | 'react/sort-comp': [0], 111 | 'react/state-in-constructor': ['warn', 'never'], 112 | 'rest-spread-spacing': ['warn', 'never'], 113 | 'semi': ['warn'], 114 | 'sort-keys': ['error', 'asc', { 'caseSensitive': false }], 115 | 'space-before-function-paren': ['warn'], 116 | 'spaced-comment': ['warn'] 117 | }, 118 | settings: { 119 | 'import/resolver': { 120 | node: { 121 | paths: ['./', 'src'] 122 | } 123 | } 124 | } 125 | }; -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: "bug \U0001F99F" 6 | assignees: iPzard 7 | 8 | --- 9 | 10 | **🦟 Describe the bug**
11 | A clear and concise description of what the bug is. 12 | 13 | **Steps to Reproduce**
14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Additional context**
27 | Add any other context about the problem here. 28 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement ✨ 6 | assignees: iPzard 7 | 8 | --- 9 | 10 | **✨ Describe the feature**
11 | A clear and concise description of the feature you want. 12 | 13 | **Additional context**
14 | Add any other context or screenshots about the feature request here. 15 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 30 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pinned 8 | - security 9 | # Label to use when marking an issue as stale 10 | staleLabel: wontfix 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: This issue has been closed due to inactivity. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | #cache 4 | app.pyc 5 | app.spec 6 | __pycache__ 7 | 8 | # debug 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | 13 | # dependencies 14 | /node_modules 15 | /.pnp 16 | .pnp.js 17 | 18 | # testing 19 | /coverage 20 | 21 | # production 22 | /build 23 | /dist 24 | /resources/app 25 | /resources/app.app 26 | 27 | # misc 28 | .DS_Store 29 | .env.local 30 | .env.development.local 31 | .env.test.local 32 | .env.production.local 33 | -------------------------------------------------------------------------------- /FUNDING.yml: -------------------------------------------------------------------------------- 1 | # repo: your_github_handle/.github 2 | # filename: FUNDING.YML 3 | 4 | github: iPzard -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 iPzard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Electron, React & Python Template 2 | 3 | [![Build](https://img.shields.io/badge/build-passing-%23704cb6?style=for-the-badge)](https://github.com/iPzard/electron-react-python-template#readme) 4 | [![License](https://img.shields.io/github/license/iPzard/electron-react-python-template?color=704cb6&style=for-the-badge)](https://github.com/iPzard/electron-react-python-template/blob/master/LICENSE) 5 | 6 | > Multi-platform Electron template, using React & Redux Toolkit with Python/Flask microservices. 7 | 8 | ![electron_react_python](https://user-images.githubusercontent.com/8584126/95290114-59e42900-0821-11eb-8e43-a708959e8449.gif) 9 | 10 | ## 🛠️ Setup 11 | Ensure you have [Node](https://nodejs.org/en/download/) and [Python](https://www.python.org/downloads/) installed, then clone this repository. After it's cloned, navigate to the project's root directory on your computer and 12 | run the following scrips in a terminal application *(e.g., Git Bash)*: 13 | 14 | **Install Python dependencies:** 15 | ```bash 16 | pip3 install -r requirements.txt 17 | ``` 18 | 19 | **Install Node dependencies:** 20 | ```bash 21 | yarn install 22 | ``` 23 | 24 |
25 | 26 | ## ⚙️ Config 27 | 28 | **Electron:** Electron's `main.js`, `preload.js`, and `renderer.js` files can be found in the project's root directory. 29 | 30 | **React:** React files can be found in the `./src/` folder, the custom toolbar is in `./src/components/toolbar`. 31 | 32 | **Python:** Python scripts can be created in the `./app.py` file and used on events via [REST](https://developer.mozilla.org/en-US/docs/Glossary/REST) calls. 33 | 34 |
35 | 36 | ## 📜 Scripts 37 | 38 | Below are the scripts you'll need to run and package your application, as well as build out JSDoc documentation, if you choose to do so. An exhaustive list of scripts that are available can be found in the `package.json` file of the project's root directory, in the `scripts` section. 39 | 40 | | ⚠️  When packaging, you must install [PyInstaller](https://pypi.org/project/pyinstaller) and add its path in your environment variables.
The name of your package in [package.js](https://github.com/iPzard/electron-react-python-template/blob/master/scripts/package.js) must also match the name field in [package.json](https://github.com/iPzard/electron-react-python-template/blob/master/package.json). | 41 | | --- | 42 | 43 | **Start Developer Mode:** 44 | ```bash 45 | yarn run start 46 | ``` 47 | 48 | **Package Windows: *1*** 49 | ```bash 50 | yarn run build:package:windows 51 | ``` 52 | 53 | **Package macOS:** 54 | ```bash 55 | yarn run build:package:mac 56 | ``` 57 | 58 | **Package Linux:** 59 | ```bash 60 | yarn run build:package:linux 61 | ``` 62 | 63 | **Build Documentation:** 64 | ```bash 65 | yarn run build:docs 66 | ``` 67 | 68 | *1Windows uses [electron-wix-msi](https://github.com/felixrieseberg/electron-wix-msi), you must install and add its path to your environment variables.* 69 |

70 | 71 | ## 🐱‍👓 Docs 72 | Code documentation for this template, created with [JSDoc](https://github.com/jsdoc/jsdoc), can be found here:
73 | [Electron, React, & Python Template](https://ipzard.github.io/electron-react-python-template/) 74 |

75 | 76 | ## 🦟 Bugs 77 | Bugs reported on the project's [issues page](https://github.com/iPzard/electron-react-python-template/issues) will be exterminated as quickly as possible, be sure to include steps to reproduce so they can be spotted easily. 78 |

79 | 80 | ## 🏷️ License 81 | MIT © [iPzard](https://github.com/iPzard/electron-react-python-template/blob/master/LICENSE) -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from flask import Flask, jsonify, request 3 | from flask_cors import CORS 4 | 5 | app = Flask(__name__) 6 | app_config = {"host": "0.0.0.0", "port": sys.argv[1]} 7 | 8 | """ 9 | ---------------------- DEVELOPER MODE CONFIG ----------------------- 10 | """ 11 | # Developer mode uses app.py 12 | if "app.py" in sys.argv[0]: 13 | # Update app config 14 | app_config["debug"] = True 15 | 16 | # CORS settings 17 | cors = CORS( 18 | app, 19 | resources={r"/*": {"origins": "http://localhost*"}}, 20 | ) 21 | 22 | # CORS headers 23 | app.config["CORS_HEADERS"] = "Content-Type" 24 | 25 | 26 | """ 27 | --------------------------- REST CALLS ----------------------------- 28 | """ 29 | # Remove and replace with your own 30 | @app.route("/example") 31 | def example(): 32 | 33 | # See /src/components/App.js for frontend call 34 | return jsonify("Example response from Flask! Learn more in /app.py & /src/components/App.js") 35 | 36 | 37 | """ 38 | -------------------------- APP SERVICES ---------------------------- 39 | """ 40 | # Quits Flask on Electron exit 41 | @app.route("/quit") 42 | def quit(): 43 | shutdown = request.environ.get("werkzeug.server.shutdown") 44 | shutdown() 45 | 46 | return 47 | 48 | 49 | if __name__ == "__main__": 50 | app.run(**app_config) 51 | -------------------------------------------------------------------------------- /docs/Cleaner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Cleaner - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

Cleaner

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | 45 |
46 | 47 |

48 | Cleaner 49 |

50 | 51 | 52 |
53 | 54 |
55 |
56 | 57 | 58 | 59 |
60 | 61 | 62 |
Source:
63 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 |
See:
96 |
97 |
    98 |
  • scripts\dispatch.js cleanProject() for complete list
  • 99 |
100 |
101 | 102 | 103 | 104 |
105 | 106 | 107 | 108 | 109 | 110 |
    111 |
  • Cleans project by removing several files & folders.
  • 112 |
113 | 114 | 115 | 116 | 117 |
118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 |
137 | 138 |
139 | 140 | 141 | 142 | 143 | 144 | 154 | 155 |
156 | 157 |
158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /docs/Theme.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Theme - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

Theme

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | 45 |
46 | 47 |

48 | Theme 49 |

50 | 51 | 52 |
53 | 54 |
55 |
56 | 57 | 58 | 59 |
60 | 61 | 62 |
Source:
63 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 |
Tutorials:
94 |
95 |
    96 |
  • Tutorial: - https://www.aka.ms/themedesigner
  • 97 |
98 |
99 | 100 | 101 | 102 | 103 | 104 |
105 | 106 | 107 | 108 | 109 | 110 |
    111 |
  • Theme for Microsoft Fluent UI, which is built into the project.
  • 112 |
113 | 114 | 115 | 116 | 117 |
118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 |
137 | 138 |
139 | 140 | 141 | 142 | 143 | 144 | 154 | 155 |
156 | 157 |
158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /docs/scripts/custom.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/docs/scripts/custom.js -------------------------------------------------------------------------------- /docs/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /docs/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /docs/scripts/search.js: -------------------------------------------------------------------------------- 1 | 2 | (function () { 3 | var nav = document.querySelector("nav"); 4 | var searchBar = nav.querySelector(".search"); 5 | var input = searchBar.querySelector("input"); 6 | // var submit = searchBar.querySelector("button"); 7 | var groups = Array.prototype.slice.call(document.querySelectorAll("nav>ul .parent")).map(function (group) { 8 | var items = Array.prototype.slice.call(group.querySelectorAll("a")); 9 | var strings = items.map(function (a) { 10 | return a.innerText.toLowerCase(); 11 | }); 12 | 13 | return {el: group, items: items, strings, strings}; 14 | }); 15 | input.addEventListener("keyup", function (e) { 16 | var value = input.value.toLowerCase(); 17 | 18 | if (value) { 19 | utils.addClass(nav, "searching"); 20 | } else { 21 | utils.removeClass(nav, "searching"); 22 | return; 23 | } 24 | groups.forEach(function (group) { 25 | var isSearch = false; 26 | var items = group.items; 27 | 28 | group.strings.forEach(function (v, i) { 29 | var item = items[i]; 30 | if (utils.hasClass(item.parentNode, "parent")) { 31 | item = item.parentNode; 32 | } 33 | if (v.indexOf(value) > -1) { 34 | utils.addClass(item, "targeting"); 35 | isSearch = true; 36 | } else { 37 | utils.removeClass(item, "targeting"); 38 | } 39 | }); 40 | if (isSearch) { 41 | utils.addClass(group.el, "module-targeting"); 42 | } else { 43 | utils.removeClass(group.el, "module-targeting"); 44 | } 45 | }); 46 | }); 47 | })(); -------------------------------------------------------------------------------- /docs/scripts/utils.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Daybrush 3 | @name: @daybrush/utils 4 | license: MIT 5 | author: Daybrush 6 | repository: https://github.com/daybrush/utils 7 | @version 0.4.0 8 | */ 9 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.utils=t()}(this,function(){"use strict";var u="rgb",c="rgba",f="hsl",l="hsla",e=[u,c,f,l],t="function",n="object",r="string",i="undefined",a=typeof window!==i,o=["webkit","ms","moz","o"],s=function(e){if(typeof document===i)return"";var t=(document.body||document.documentElement).style,n=o.length;if(typeof t[e]!==i)return e;for(var r=0;r 2 | 3 | 4 | 5 | scripts/build.js - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

scripts/build.js

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
const { spawnSync } = require('child_process');
 46 | const spawnOptions = { detached: false, shell: true, stdio: 'inherit' };
 47 | 
 48 | /**
 49 |  * @namespace Builder
 50 |  * @description - Builds React & Python builds of project so Electron can be used.
 51 |  */
 52 | class Builder {
 53 | 
 54 |   /**
 55 |    * @description - Creates React and Python production builds.
 56 |    * @memberof Builder
 57 |    */
 58 |   buildAll = () => {
 59 |     const { buildPython, buildReact } = this;
 60 | 
 61 |     buildPython();
 62 |     buildReact();
 63 |   }
 64 | 
 65 |   /**
 66 |    * @description - Creates production build of Python back end.
 67 |    * @memberof Builder
 68 |    */
 69 |   buildPython = () => {
 70 |     console.log('Creating Python distribution files...');
 71 | 
 72 |     const app = 'app.py';
 73 |     const icon = './public/favicon.ico';
 74 | 
 75 |     const options = [
 76 |       '--noconsole', // No shell
 77 |       '--noconfirm', // Don't confirm overwrite
 78 |       '--distpath ./resources', // Dist (out) path
 79 |       `--icon ${icon}` // Icon to use
 80 |     ].join(' ');
 81 |     // TODO: Check if python is installed.. If not, prompt user
 82 |     // "Python is required but not installed, install it? (y/n)"
 83 |     spawnSync(`pyinstaller ${options} ${app}`, spawnOptions);
 84 |   }
 85 | 
 86 |   /**
 87 |    * @description - Creates production build of React front end.
 88 |    * @memberof Builder
 89 |    */
 90 |   buildReact = () => {
 91 |     console.log('Creating React distribution files...');
 92 |     spawnSync(`react-scripts build`, spawnOptions);
 93 |   }
 94 | }
 95 | 
 96 | module.exports.Builder = Builder;
97 |
98 |
99 | 100 | 101 | 102 | 103 | 104 | 114 | 115 |
116 | 117 |
118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /docs/scripts_clean.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | scripts/clean.js - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

scripts/clean.js

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
const {
 46 |   existsSync,
 47 |   readdirSync,
 48 |   rmdirSync,
 49 |   statSync,
 50 |   unlinkSync
 51 | } = require('fs');
 52 | 
 53 | /**
 54 |  * @namespace Cleaner
 55 |  * @description - Cleans project by removing several files & folders.
 56 |  * @see scripts\dispatch.js cleanProject() for complete list
 57 |  */
 58 | class Cleaner {
 59 |   removePath = (pathToRemove) => {
 60 | 
 61 |     if (existsSync(pathToRemove)) {
 62 |       console.log(`Removing: ${pathToRemove}`);
 63 | 
 64 |       if (statSync(pathToRemove).isFile()) unlinkSync(pathToRemove);
 65 |       else {
 66 |         const files = readdirSync(pathToRemove);
 67 | 
 68 |         files.forEach((file) => {
 69 |           const filePath = `${pathToRemove}/${file}`;
 70 | 
 71 |           if (statSync(filePath).isDirectory()) this.removePath(filePath);
 72 |           else unlinkSync(filePath);
 73 |         });
 74 |         rmdirSync(pathToRemove);
 75 |       }
 76 |     }
 77 |   };
 78 | }
 79 | 
 80 | module.exports.Cleaner = Cleaner;
 81 | 
82 |
83 |
84 | 85 | 86 | 87 | 88 | 89 | 99 | 100 |
101 | 102 |
103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /docs/src_components_titlebar_Titlebar.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src/components/titlebar/Titlebar.js - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

src/components/titlebar/Titlebar.js

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
import {
 46 |   CloseButton,
 47 |   ContractButton,
 48 |   MaximizeButton,
 49 |   MinimizeButton
 50 | } from 'components/titlebar/TitlebarButtons';
 51 | import React, { useState } from 'react';
 52 | 
 53 | import { app } from 'utils/services';
 54 | 
 55 | import favicon from 'components/titlebar/img/favicon.png';
 56 | import styles from 'components/titlebar/scss/Titlebar.module.scss';
 57 | 
 58 | 
 59 | /**
 60 |  * @namespace Titlebar
 61 |  * @description Title Component to use as an Electron customized titlebar.
 62 |  * electron-window-title-text used in main.js to set opacity on/off focus.
 63 |  * electron-window-title-buttons used in main.js to set opacity on/off focus.
 64 |  */
 65 | 
 66 | const Titlebar = () => {
 67 | 
 68 |   const [ maximized, setMaximized ] = useState(false);
 69 | 
 70 |   const handleMaximizeToggle = () => {
 71 |     !maximized ? app.maximize() : app.unmaximize();
 72 |     setMaximized(!maximized);
 73 |   };
 74 | 
 75 |   return (
 76 |     <section className={ styles.titlebar }>
 77 |       <div>
 78 |         <img src={ favicon } alt="favicon" />
 79 |         <span id="electron-window-title-text">{ document.title }</span>
 80 |       </div>
 81 | 
 82 |       <div id="electron-window-title-buttons">
 83 |         <MinimizeButton onClick={ app.minimize } />
 84 |         {
 85 |           maximized
 86 |             ? <ContractButton onClick={ handleMaximizeToggle } />
 87 |             : <MaximizeButton onClick={ handleMaximizeToggle } />
 88 |         }
 89 |         <CloseButton onClick={ app.quit } />
 90 |       </div>
 91 |     </section>
 92 |   );
 93 | };
 94 | 
 95 | export default Titlebar;
96 |
97 |
98 | 99 | 100 | 101 | 102 | 103 | 113 | 114 |
115 | 116 |
117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /docs/src_components_titlebar_TitlebarButtons.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src/components/titlebar/TitlebarButtons.js - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

src/components/titlebar/TitlebarButtons.js

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
import React from 'react';
 46 | 
 47 | import styles from 'components/titlebar/scss/TitlebarButtons.module.scss';
 48 | 
 49 | /**
 50 |  * @description Titlebar minimize button.
 51 |  * @memberof Titlebar
 52 |  */
 53 | export const MinimizeButton = (props) => (
 54 |   <button
 55 |     { ...props }
 56 |     aria-label="Minimize"
 57 |     className={ styles['minimize-button'] }
 58 |     title="Minimize"
 59 |     type="button"
 60 |   >
 61 |     <span />
 62 |   </button>
 63 | );
 64 | 
 65 | /**
 66 |  * @description Titlebar maximize button.
 67 |  * @memberof Titlebar
 68 |  */
 69 | export const MaximizeButton = (props) => (
 70 |   <button
 71 |     { ...props }
 72 |     aria-label="Maximize"
 73 |     className={ styles['maximize-button'] }
 74 |     title="Maximize"
 75 |     type="button"
 76 |   >
 77 |     <span />
 78 |   </button>
 79 | );
 80 | 
 81 | /**
 82 |  * @description Titlebar contract (unmaximize) button.
 83 |  * @memberof Titlebar
 84 |  */
 85 | export const ContractButton = (props) => (
 86 |   <button
 87 |     { ...props }
 88 |     aria-label="Contract"
 89 |     className={ styles['contract-button'] }
 90 |     title="Contract"
 91 |     type="button"
 92 |   >
 93 |     <span />
 94 |     <span />
 95 |   </button>
 96 | );
 97 | 
 98 | /**
 99 |  * @description Titlebar close button.
100 |  * @memberof Titlebar
101 |  */
102 | export const CloseButton = (props) => (
103 |   <button
104 |     { ...props }
105 |     aria-label="Close"
106 |     className={ styles['close-button'] }
107 |     title="Close"
108 |     type="button"
109 |   >
110 |     <span />
111 |     <span />
112 |   </button>
113 | );
114 |
115 |
116 | 117 | 118 | 119 | 120 | 121 | 131 | 132 |
133 | 134 |
135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /docs/src_theme_palette.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src/theme/palette.js - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

src/theme/palette.js

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
/**
 46 |  * @namespace Theme
 47 |  * @description - Theme for Microsoft Fluent UI, which is built into the project.
 48 |  *
 49 |  * @tutorial - https://www.aka.ms/themedesigner
 50 | */
 51 | 
 52 | export const customTheme = {
 53 |   themePrimary: '#57a9a9',
 54 |   themeLighterAlt: '#030707',
 55 |   themeLighter: '#0e1b1b',
 56 |   themeLight: '#1a3232',
 57 |   themeTertiary: '#336565',
 58 |   themeSecondary: '#4c9494',
 59 |   themeDarkAlt: '#63b1b1',
 60 |   themeDark: '#77bdbd',
 61 |   themeDarker: '#96cece',
 62 |   neutralLighterAlt: '#eeeeee',
 63 |   neutralLighter: '#eaeaea',
 64 |   neutralLight: '#e1e1e1',
 65 |   neutralQuaternaryAlt: '#d1d1d1',
 66 |   neutralQuaternary: '#c8c8c8',
 67 |   neutralTertiaryAlt: '#c0c0c0',
 68 |   neutralTertiary: '#b5b5b5',
 69 |   neutralSecondary: '#9d9d9d',
 70 |   neutralPrimaryAlt: '#868686',
 71 |   neutralPrimary: '#252525',
 72 |   neutralDark: '#565656',
 73 |   black: '#3e3e3e',
 74 |   white: '#f5f5f5'
 75 | };
76 |
77 |
78 | 79 | 80 | 81 | 82 | 83 | 93 | 94 |
95 | 96 |
97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /docs/src_utils_services.js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | src/utils/services.js - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

src/utils/services.js

36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 |
45 |
// Electron Inter Process Communication and dialog
46 | const { ipcRenderer } = window.require('electron');
47 | 
48 | /**
49 |  * @namespace Services
50 |  * @description - Methods from Electron Inter Process Communication.
51 |  * @property {function} maximize - Function to maximize the screen size of the program.
52 |  * @property {function} minimize - Function to minimize the screen size of the program.
53 |  * @property {function} quit - Function to close and exit the program.
54 |  * @property {function} unmaximize - Function to contract (unmaximize) the screen size of the program.
55 |  */
56 | export const app = {
57 |   maximize: () => ipcRenderer.send('app-maximize'),
58 |   minimize: () => ipcRenderer.send('app-minimize'),
59 |   quit: () => ipcRenderer.send('app-quit'),
60 |   unmaximize: () => ipcRenderer.send('app-unmaximize')
61 | };
62 |
63 |
64 | 65 | 66 | 67 | 68 | 69 | 79 | 80 |
81 | 82 |
83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/styles/custom.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/docs/styles/custom.css -------------------------------------------------------------------------------- /docs/styles/daybrush.css: -------------------------------------------------------------------------------- 1 | .readme table { 2 | border-spacing: 0; 3 | border-collapse: collapse; 4 | } 5 | .readme * { 6 | box-sizing: border-box; 7 | } 8 | .readme table th, .readme table td { 9 | padding: 6px 13px; 10 | border: 1px solid #ddd; 11 | } 12 | 13 | nav>ul>li:after { 14 | content: ""; 15 | position: absolute; 16 | right: 10px; 17 | top: 0; 18 | bottom: 0; 19 | width: 0; 20 | height: 0; 21 | margin: auto 0px; 22 | border-top: 7px solid #ccc; 23 | border-left: 6px solid transparent; 24 | border-right: 6px solid transparent; 25 | } 26 | nav li h4, nav li ul { 27 | display: none; 28 | } 29 | 30 | .name.typescript { 31 | background: #374E79; 32 | font-size: 14px; 33 | } 34 | .name.typescript .signature { 35 | color: #21de60; 36 | } 37 | .ts-params.typescript table .last { 38 | display: none; 39 | } 40 | table.params th, table.params tr td , table.params tr td.type{ 41 | word-break: break-word; 42 | white-space: normal; 43 | } 44 | 45 | nav .search { 46 | position: relative; 47 | margin: 0px 10px; 48 | border: 3px solid #333; 49 | height: 43px; 50 | } 51 | nav .search .input-area { 52 | position: absolute; 53 | left: 0; 54 | top: 0; 55 | right: 35px; 56 | height: 35px; 57 | } 58 | nav .search input { 59 | position: relative; 60 | width: 100%; 61 | height: 100%; 62 | border: 0; 63 | padding: 0; 64 | text-indent: 10px; 65 | font-weight: bold; 66 | font-size: 14px; 67 | outline: none; 68 | } 69 | nav .search button { 70 | position: absolute; 71 | top: 0; 72 | right: 0px; 73 | width: 35px; 74 | height: 35px; 75 | border: 0; 76 | padding: 0; 77 | outline: none; 78 | cursor: pointer; 79 | } 80 | nav .search button:before { 81 | position: absolute; 82 | content: ""; 83 | width: 18px; 84 | height: 18px; 85 | top: 7px; 86 | left: 7px; 87 | border: 3px solid #333; 88 | border-radius: 50%; 89 | box-sizing: border-box; 90 | } 91 | nav .search button:after { 92 | position: absolute; 93 | content: ""; 94 | width: 3px; 95 | height: 11px; 96 | top: 21px; 97 | left: 18px; 98 | background: #333; 99 | transform-origin: 50% 0%; 100 | -ms-transform-origin: 50% 0%; 101 | -webkit-transform-origin: 50% 0%; 102 | transform: rotate(-45deg); 103 | -ms-transform: rotate(-45deg); 104 | -webkit-transform: rotate(-45deg); 105 | } 106 | 107 | nav.searching li:after { 108 | display: none!important; 109 | } 110 | nav.searching li h4, nav.searching li ul { 111 | display: block!important; 112 | } 113 | 114 | nav.searching .parent { 115 | display: none; 116 | } 117 | nav.searching .parent ul li a { 118 | display: none; 119 | } 120 | 121 | nav.searching .parent.module-targeting { 122 | display: block; 123 | } 124 | nav.searching .parent.module-targeting ul li a { 125 | display: none; 126 | } 127 | nav.searching .parent.module-targeting ul li a.targeting { 128 | display: block; 129 | } 130 | nav.searching .parent.targeting ul li a { 131 | display: block; 132 | } 133 | 134 | nav>h2.custom>a { 135 | margin:12px 10px; 136 | } -------------------------------------------------------------------------------- /docs/styles/prettify.css: -------------------------------------------------------------------------------- 1 | .pln { 2 | color: #ddd; 3 | } 4 | 5 | /* string content */ 6 | .str { 7 | color: #61ce3c; 8 | } 9 | 10 | /* a keyword */ 11 | .kwd { 12 | color: #fbde2d; 13 | } 14 | 15 | /* a comment */ 16 | .com { 17 | color: #aeaeae; 18 | } 19 | 20 | /* a type name */ 21 | .typ { 22 | color: #8da6ce; 23 | } 24 | 25 | /* a literal value */ 26 | .lit { 27 | color: #fbde2d; 28 | } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #ddd; 33 | } 34 | 35 | /* lisp open bracket */ 36 | .opn { 37 | color: #000000; 38 | } 39 | 40 | /* lisp close bracket */ 41 | .clo { 42 | color: #000000; 43 | } 44 | 45 | /* a markup tag name */ 46 | .tag { 47 | color: #8da6ce; 48 | } 49 | 50 | /* a markup attribute name */ 51 | .atn { 52 | color: #fbde2d; 53 | } 54 | 55 | /* a markup attribute value */ 56 | .atv { 57 | color: #ddd; 58 | } 59 | 60 | /* a declaration */ 61 | .dec { 62 | color: #EF5050; 63 | } 64 | 65 | /* a variable name */ 66 | .var { 67 | color: #c82829; 68 | } 69 | 70 | /* a function name */ 71 | .fun { 72 | color: #4271ae; 73 | } 74 | 75 | /* Specify class=linenums on a pre to get line numbering */ 76 | ol.linenums { 77 | margin-top: 0; 78 | margin-bottom: 0; 79 | } 80 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "src" 4 | }, 5 | "include": ["src"] 6 | } -------------------------------------------------------------------------------- /jsdoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "source": { 3 | "include": ["main.js", "scripts", "src"], 4 | "includePattern": ".js$", 5 | "excludePattern": "(node_modules/|docs)" 6 | }, 7 | "plugins": ["plugins/markdown"], 8 | "templates": { 9 | "cleverLinks": true, 10 | "monospaceLinks": true 11 | }, 12 | "opts": { 13 | "recurse": true, 14 | "destination": "docs", 15 | "template": "utilities/jsdoc", 16 | "readme": "readme.md" 17 | } 18 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "Daniel Wade", 3 | "description": "Started template for Electron, React, Python app", 4 | "dependencies": { 5 | "@reduxjs/toolkit": "^1.1.0", 6 | "axios": "^0.21.1", 7 | "electron-is-dev": "^1.2.0", 8 | "get-port": "^5.1.1", 9 | "prop-types": "^15.7.2", 10 | "react": "^16.13.1", 11 | "react-dom": "^16.13.1", 12 | "react-redux": "^7.2.0", 13 | "react-scripts": "3.4.1" 14 | }, 15 | "devDependencies": { 16 | "@testing-library/jest-dom": "^4.2.4", 17 | "@testing-library/react": "^9.3.2", 18 | "@testing-library/user-event": "^7.1.2", 19 | "babel-eslint": "^10.1.0", 20 | "cross-env": "^7.0.3", 21 | "electron": "^13.0.1", 22 | "electron-devtools-installer": "^3.2.0", 23 | "electron-installer-dmg": "^3.0.0", 24 | "electron-packager": "^15.0.0", 25 | "electron-wix-msi": "^3.0.4", 26 | "eslint-config-airbnb": "^18.2.1", 27 | "eslint-plugin-import": "^2.23.4", 28 | "eslint-plugin-jsx-a11y": "^6.4.1", 29 | "eslint-plugin-react": "^7.24.0", 30 | "eslint-plugin-standard": "^5.0.0", 31 | "jsdoc": "^3.6.5", 32 | "sass": "^1.26.5" 33 | }, 34 | "optionalDependencies": { 35 | "electron-installer-debian": "^3.1.0" 36 | }, 37 | "browserslist": { 38 | "production": [ 39 | ">0.2%", 40 | "not dead", 41 | "not op_mini all" 42 | ], 43 | "development": [ 44 | "last 1 chrome version", 45 | "last 1 firefox version", 46 | "last 1 safari version" 47 | ] 48 | }, 49 | "build": { 50 | "extraResources": [ 51 | "./resources/app" 52 | ] 53 | }, 54 | "homepage": "./", 55 | "license": "MIT", 56 | "main": "main.js", 57 | "name": "electron-react-python-template", 58 | "private": true, 59 | "scripts": { 60 | "build": "node ./scripts/dispatch build all", 61 | "build:all": "node ./scripts/dispatch build all", 62 | "build:react": "node ./scripts/dispatch build react", 63 | "build:python": "node ./scripts/dispatch build python", 64 | "build:docs": "jsdoc -c jsdoc.json", 65 | "build:package:linux": "node ./scripts/dispatch package linux", 66 | "build:package:mac": "node ./scripts/dispatch package mac", 67 | "build:package:windows": "node ./scripts/dispatch package windows", 68 | "clean": "node ./scripts/dispatch clean", 69 | "eject": "react-scripts eject", 70 | "start": "node ./scripts/dispatch start", 71 | "start:electron": "electron .", 72 | "start:react": "react-scripts start", 73 | "test": "react-scripts test" 74 | }, 75 | "version": "1.0.0" 76 | } 77 | -------------------------------------------------------------------------------- /preload.js: -------------------------------------------------------------------------------- 1 | // All of the Node.js APIs are available in the preload process. 2 | // It has the same sandbox as a Chrome extension. 3 | window.addEventListener('DOMContentLoaded', () => { 4 | 5 | process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = true; 6 | 7 | const replaceText = (selector, text) => { 8 | const element = document.getElementById(selector); 9 | if (element) element.innerText = text; 10 | }; 11 | 12 | for (const type of ['chrome', 'node', 'electron']) { 13 | replaceText(`${type}-version`, process.versions[type]); 14 | } 15 | }); -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | Electron, React & Python App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /renderer.js: -------------------------------------------------------------------------------- 1 | // This file is required by the index.html file and will 2 | // be executed in the renderer process for that window. 3 | // No Node.js APIs are available in this process because 4 | // `nodeIntegration` is turned off. Use `preload.js` to 5 | // selectively enable features needed in the rendering 6 | // process. 7 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | Flask 2 | flask-cors 3 | pyinstaller -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | const { spawnSync } = require('child_process'); 2 | const spawnOptions = { detached: false, shell: true, stdio: 'inherit' }; 3 | 4 | /** 5 | * @namespace Builder 6 | * @description - Builds React & Python builds of project so Electron can be used. 7 | */ 8 | class Builder { 9 | 10 | /** 11 | * @description - Creates React and Python production builds. 12 | * @memberof Builder 13 | */ 14 | buildAll = () => { 15 | const { buildPython, buildReact } = this; 16 | 17 | buildPython(); 18 | buildReact(); 19 | } 20 | 21 | /** 22 | * @description - Creates production build of Python back end. 23 | * @memberof Builder 24 | */ 25 | buildPython = () => { 26 | console.log('Creating Python distribution files...'); 27 | 28 | const app = 'app.py'; 29 | const icon = './public/favicon.ico'; 30 | 31 | const options = [ 32 | '--noconsole', // No shell 33 | '--noconfirm', // Don't confirm overwrite 34 | '--distpath ./resources', // Dist (out) path 35 | `--icon ${icon}` // Icon to use 36 | ].join(' '); 37 | // TODO: Check if python is installed.. If not, prompt user 38 | // "Python is required but not installed, install it? (y/n)" 39 | spawnSync(`pyinstaller ${options} ${app}`, spawnOptions); 40 | } 41 | 42 | /** 43 | * @description - Creates production build of React front end. 44 | * @memberof Builder 45 | */ 46 | buildReact = () => { 47 | console.log('Creating React distribution files...'); 48 | spawnSync(`react-scripts build`, spawnOptions); 49 | } 50 | } 51 | 52 | module.exports.Builder = Builder; -------------------------------------------------------------------------------- /scripts/clean.js: -------------------------------------------------------------------------------- 1 | const { 2 | existsSync, 3 | readdirSync, 4 | rmdirSync, 5 | statSync, 6 | unlinkSync 7 | } = require('fs'); 8 | 9 | /** 10 | * @namespace Cleaner 11 | * @description - Cleans project by removing several files & folders. 12 | * @see scripts\dispatch.js cleanProject() for complete list 13 | */ 14 | class Cleaner { 15 | removePath = (pathToRemove) => { 16 | 17 | if (existsSync(pathToRemove)) { 18 | console.log(`Removing: ${pathToRemove}`); 19 | 20 | if (statSync(pathToRemove).isFile()) unlinkSync(pathToRemove); 21 | else { 22 | const files = readdirSync(pathToRemove); 23 | 24 | files.forEach((file) => { 25 | const filePath = `${pathToRemove}/${file}`; 26 | 27 | if (statSync(filePath).isDirectory()) this.removePath(filePath); 28 | else unlinkSync(filePath); 29 | }); 30 | rmdirSync(pathToRemove); 31 | } 32 | } 33 | }; 34 | } 35 | 36 | module.exports.Cleaner = Cleaner; 37 | -------------------------------------------------------------------------------- /scripts/dispatch.js: -------------------------------------------------------------------------------- 1 | const [ , , script, command ] = process.argv; 2 | const { existsSync, readdirSync } = require('fs'); 3 | const path = require('path'); 4 | 5 | const { Builder } = require('./build'); 6 | const { Cleaner } = require('./clean'); 7 | const { Packager } = require('./package'); 8 | const { Starter } = require('./start'); 9 | 10 | 11 | /** 12 | * @namespace Dispatcher 13 | * @description - Dispatches script commands to various scripts. 14 | * @argument script - Script manager to use (e.g., build or package). 15 | * @argument command - Command argument describing exact script to run. 16 | */ 17 | 18 | switch (script) { 19 | case 'build': 20 | return buildApp(); 21 | 22 | case 'clean': 23 | return cleanProject(); 24 | 25 | case 'package': 26 | return packageApp(); 27 | 28 | case 'start': 29 | return startDeveloperMode(); 30 | 31 | // no default 32 | } 33 | 34 | 35 | /** 36 | * @description - Builds various production builds (e.g., Python, React). 37 | * @memberof Dispatcher 38 | */ 39 | function buildApp() { 40 | const builder = new Builder(); 41 | 42 | switch (command) { 43 | case 'react': 44 | return builder.buildReact(); 45 | 46 | case 'python': 47 | return builder.buildPython(); 48 | 49 | case 'all': 50 | return builder.buildAll(); 51 | 52 | // no default 53 | } 54 | } 55 | 56 | 57 | /** 58 | * @description - Cleans project by removing various files and folders. 59 | * @memberof Dispatcher 60 | */ 61 | function cleanProject() { 62 | const cleaner = new Cleaner(); 63 | const getPath = (...filePaths) => path.join(__dirname, '..', ...filePaths); 64 | 65 | // Files to remove during cleaning 66 | [ 67 | // Cache 68 | getPath('app.pyc'), 69 | getPath('app.spec'), 70 | getPath('__pycache__'), 71 | 72 | // Debug 73 | getPath('npm-debug.log'), 74 | getPath('yarn-debug.log'), 75 | getPath('yarn-error.log'), 76 | 77 | // Dependencies 78 | getPath('.pnp'), 79 | getPath('.pnp.js'), 80 | getPath('node_modules'), 81 | getPath('package-lock.json'), 82 | getPath('yarn.lock'), 83 | 84 | // Testing 85 | getPath('coverage'), 86 | 87 | // Production 88 | getPath('build'), 89 | getPath('dist'), 90 | getPath('docs'), 91 | 92 | // Misc 93 | getPath('.DS_Store') 94 | ] 95 | // Iterate and remove process 96 | .forEach(cleaner.removePath); 97 | 98 | 99 | /** 100 | * Remove resources/app if it exists, then if the resources 101 | * folder isn't used for any other Python modules, delete it too. 102 | */ 103 | const resourcesDir = getPath('resources'); 104 | const isResourcesDirExist = existsSync(resourcesDir); 105 | 106 | if (isResourcesDirExist) { 107 | 108 | // Remove 'resources/app' directory if it exists 109 | const resourcesAppDir = path.join(resourcesDir, 'app'); 110 | const isResourcesAppDir = existsSync(resourcesAppDir); 111 | 112 | if (isResourcesAppDir) cleaner.removePath(resourcesAppDir); 113 | 114 | // Remove 'resources' directory if it's empty 115 | const isResourcesDirEmpty = Boolean(!readdirSync(resourcesDir).length); 116 | if (isResourcesDirEmpty) cleaner.removePath(resourcesDir); 117 | } 118 | 119 | console.log('Project is clean.'); 120 | } 121 | 122 | 123 | /** 124 | * @description - Builds various installers (e.g., DMG, MSI). 125 | * @memberof Dispatcher 126 | */ 127 | function packageApp() { 128 | const packager = new Packager(); 129 | 130 | switch (command) { 131 | case 'linux': 132 | return packager.packageLinux(); 133 | 134 | case 'mac': 135 | return packager.packageMacOS(); 136 | 137 | case 'windows': 138 | return packager.packageWindows(); 139 | 140 | // no default 141 | } 142 | } 143 | 144 | 145 | /** 146 | * @description - Starts developer mode of app. 147 | * Including; React, Electron, and Python/Flask. 148 | * @memberof Dispatcher 149 | */ 150 | function startDeveloperMode() { 151 | const start = new Starter(); 152 | start.developerMode(); 153 | } -------------------------------------------------------------------------------- /scripts/package.js: -------------------------------------------------------------------------------- 1 | const { spawnSync } = require('child_process'); 2 | const { Builder } = require('./build'); 3 | 4 | const builder = new Builder(); 5 | 6 | // Define input and output directories 7 | const path = (directory) => { 8 | return require('path').resolve(__dirname, directory); 9 | }; 10 | 11 | /** 12 | * @namespace Packager 13 | * @description - Packages app for various operating systems. 14 | */ 15 | class Packager { 16 | 17 | /** 18 | * @description - Creates DEB installer for linux. 19 | * @memberof Packager 20 | * 21 | * @tutorial https://github.com/electron-userland/electron-installer-debian 22 | */ 23 | packageLinux = () => { 24 | 25 | // Build Python & React distribution files 26 | builder.buildAll(); 27 | 28 | const options = { 29 | build: [ 30 | 'app', 31 | '--extra-resource=./resources', 32 | '--icon ./public/favicon.ico', 33 | '--platform linux', 34 | '--arch x64', 35 | '--out', 36 | './dist/linux', 37 | '--overwrite' 38 | ].join(' '), 39 | 40 | package: [ 41 | `--src ${path('../dist/linux/app-linux-x64/')}`, 42 | 'electron-react-python-template', 43 | `--dest ${path('../dist/linux/setup')}`, 44 | '--arch amd64', 45 | `--icon ${path('../utilities/deb/images/icon.ico')}`, 46 | `--background ${path('../utilities/deb/images/background.png')}`, 47 | '--title "Example app"', 48 | '--overwrite' 49 | ].join(' '), 50 | 51 | spawn: { detached: false, shell: true, stdio: 'inherit' } 52 | }; 53 | 54 | spawnSync(`electron-packager . ${options.build}`, options.spawn); 55 | spawnSync(`electron-installer-debian ${options.package}`, options.spawn); 56 | }; 57 | 58 | 59 | /** 60 | * @description - Creates DMG installer for macOS. 61 | * @memberof Packager 62 | * 63 | * @tutorial https://github.com/electron-userland/electron-installer-dmg 64 | */ 65 | packageMacOS = () => { 66 | 67 | // Build Python & React distribution files 68 | builder.buildAll(); 69 | 70 | const options = { 71 | build: [ 72 | 'app', 73 | '--extra-resource=./resources', 74 | '--icon ./public/favicon.ico', 75 | '--win32', 76 | '--out', 77 | './dist/mac', 78 | '--overwrite' 79 | ].join(' '), 80 | 81 | package: [ 82 | path('../dist/mac/app-darwin-x64/app.app'), 83 | 'electron-react-python-template', 84 | `--out=${path('../dist/mac/setup')}`, 85 | `--icon=${path('../utilities/dmg/images/icon.icns')}`, 86 | `--background=${path('../utilities/dmg/images/background.png')}`, 87 | '--title="Example app"', 88 | '--overwrite' 89 | ].join(' '), 90 | 91 | spawn: { detached: false, shell: true, stdio: 'inherit' } 92 | }; 93 | 94 | spawnSync(`electron-packager . ${options.build}`, options.spawn); 95 | spawnSync(`electron-installer-dmg ${options.package}`, options.spawn); 96 | }; 97 | 98 | 99 | /** 100 | * @description - Creates MSI installer for Windows. 101 | * @memberof Packager 102 | * 103 | * @tutorial https://github.com/felixrieseberg/electron-wix-msi 104 | */ 105 | packageWindows = () => { 106 | 107 | // eslint-disable-next-line no-console 108 | console.log('Building windows package...'); 109 | 110 | // Build Python & React distribution files 111 | builder.buildAll(); 112 | 113 | const options = { 114 | app: [ 115 | 'app', 116 | '--asar', 117 | '--extra-resource=./resources/app', 118 | '--icon ./public/favicon.ico', 119 | '--win32', 120 | '--out', 121 | './dist/windows', 122 | '--overwrite' 123 | ].join(' '), 124 | 125 | spawn: { detached: false, shell: true, stdio: 'inherit' } 126 | }; 127 | 128 | spawnSync(`electron-packager . ${options.app}`, options.spawn); 129 | 130 | const { MSICreator } = require('electron-wix-msi'); 131 | 132 | const msiCreator = new MSICreator({ 133 | appDirectory: path('../dist/windows/app-win32-x64'), 134 | appIconPath: path('../utilities/msi/images/icon.ico'), 135 | description: 'Example app', 136 | exe: 'app', 137 | manufacturer: 'Example Manufacturer', 138 | name: 'electron-react-python-template', 139 | outputDirectory: path('../dist/windows/setup'), 140 | ui: { 141 | chooseDirectory: true, 142 | images: { 143 | background: path('../utilities/msi/images/background.png'), 144 | banner: path('../utilities/msi/images/banner.png') 145 | } 146 | }, 147 | version: '1.0.0' 148 | }); 149 | 150 | // Customized MSI template 151 | msiCreator.wixTemplate = msiCreator.wixTemplate 152 | .replace(/ \(Machine - MSI\)/gi, '') 153 | .replace(/ \(Machine\)/gi, ''); 154 | 155 | 156 | // Create .wxs template and compile MSI 157 | msiCreator.create().then(() => msiCreator.compile()); 158 | }; 159 | 160 | } 161 | 162 | module.exports.Packager = Packager; -------------------------------------------------------------------------------- /scripts/start.js: -------------------------------------------------------------------------------- 1 | const { spawn, spawnSync } = require('child_process'); 2 | const getPort = require('get-port'); 3 | const { get } = require('axios'); 4 | 5 | /** 6 | * @namespace Starter 7 | * @description - Scripts to start Electron, React, and Python. 8 | */ 9 | class Starter { 10 | /** 11 | * @description - Starts developer mode. 12 | * @memberof Starter 13 | */ 14 | developerMode = async () => { 15 | // Child spawn options for console 16 | const spawnOptions = { 17 | hideLogs: { detached: false, shell: true, stdio: 'pipe' }, 18 | showLogs: { detached: false, shell: true, stdio: 'inherit' } 19 | }; 20 | 21 | /** 22 | * Method to get first port in range of 3001-3999, 23 | * Remains unused here so will be the same as the 24 | * port used in main.js 25 | */ 26 | const port = await getPort({ 27 | port: getPort.makeRange(3001, 3999) 28 | }); 29 | 30 | // Kill anything that might using required React port 31 | spawnSync('npx kill-port 3000', spawnOptions.hideLogs); 32 | 33 | // Start & identify React & Electron processes 34 | spawn('cross-env BROWSER=none react-scripts start', spawnOptions.showLogs); 35 | spawn('electron .', spawnOptions.showLogs); 36 | 37 | // Kill processes on exit 38 | const exitOnEvent = (event) => { 39 | process.once(event, () => { 40 | try { 41 | // These errors are expected since the connection is closing 42 | const expectedErrors = ['ECONNRESET', 'ECONNREFUSED']; 43 | 44 | // Send command to Flask server to quit and close 45 | get(`http://localhost:${port}/quit`).catch( 46 | (error) => !expectedErrors.includes(error.code) && console.log(error) 47 | ); 48 | } catch (error) { 49 | // This errors is expected since the process is closing 50 | if (error.code !== 'ESRCH') console.error(error); 51 | } 52 | }); 53 | }; 54 | 55 | // Set exit event handlers 56 | [ 57 | 'exit', 58 | 'SIGINT', 59 | 'SIGTERM', 60 | 'SIGUSR1', 61 | 'SIGUSR2', 62 | 'uncaughtException' 63 | ].forEach(exitOnEvent); 64 | }; 65 | } 66 | 67 | module.exports = { Starter }; 68 | -------------------------------------------------------------------------------- /src/components/App.js: -------------------------------------------------------------------------------- 1 | import React, { Fragment, useEffect } from 'react'; 2 | import { get } from 'utils/requests'; 3 | 4 | import { Counter } from 'components/counter/Counter'; 5 | import Titlebar from 'components/titlebar/Titlebar'; 6 | 7 | import logo from 'logo.svg'; 8 | import styles from 'components/App.module.scss'; 9 | 10 | function App() { 11 | 12 | useEffect(() => { 13 | 14 | /** 15 | * Example call to Flask 16 | * @see /src/utils/requests.js 17 | * @see /app.py 18 | */ 19 | setTimeout(() => get( 20 | 'example', // Route 21 | (response) => alert(response), // Response callback 22 | (error) => console.error(error) // Error callback 23 | ), 3000); 24 | }, []); 25 | 26 | return ( 27 | 28 | 29 | 30 |
31 |
32 | logo 33 | 34 |

35 | Edit 36 | {' '} 37 | src/App.js 38 | {' '} 39 | and save to reload. 40 |

41 | 42 | Learn 43 | 49 | React 50 | 51 | , 52 | 58 | Redux 59 | 60 | , 61 | 67 | Redux Toolkit 68 | 69 | , 70 | and 71 | 77 | React Redux 78 | 79 | 80 |
81 |
82 |
83 | ); 84 | } 85 | 86 | export default App; 87 | -------------------------------------------------------------------------------- /src/components/App.module.scss: -------------------------------------------------------------------------------- 1 | .app { 2 | text-align: center; 3 | } 4 | 5 | .app-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .app-logo { 12 | animation: app-logo-float infinite 3s ease-in-out; 13 | } 14 | } 15 | 16 | .app-header { 17 | min-height: 100vh; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: center; 21 | justify-content: center; 22 | font-size: calc(10px + 2vmin); 23 | } 24 | 25 | .app-link { 26 | color: rgb(112, 76, 182); 27 | } 28 | 29 | @keyframes app-logo-float { 30 | 0% { 31 | transform: translateY(0); 32 | } 33 | 50% { 34 | transform: translateY(10px) 35 | } 36 | 100% { 37 | transform: translateY(0px) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/components/counter/Counter.js: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react'; 2 | import { 3 | decrement, 4 | increment, 5 | incrementAsync, 6 | incrementByAmount, 7 | selectCount 8 | } from 'components/counter/counterSlice'; 9 | import { useDispatch, useSelector } from 'react-redux'; 10 | 11 | import styles from 'components/counter/Counter.module.scss'; 12 | 13 | export function Counter() { 14 | const count = useSelector(selectCount); 15 | const dispatch = useDispatch(); 16 | const [incrementAmount, setIncrementAmount] = useState('2'); 17 | 18 | return ( 19 |
20 |
21 | 28 | {count} 29 | 36 |
37 |
38 | setIncrementAmount(e.target.value) } 43 | /> 44 | 51 | 57 |
58 |
59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /src/components/counter/Counter.module.scss: -------------------------------------------------------------------------------- 1 | .row { 2 | display: flex; 3 | align-items: center; 4 | justify-content: center; 5 | } 6 | 7 | .row:not(:last-child) { 8 | margin-bottom: 16px; 9 | } 10 | 11 | .value { 12 | font-size: 78px; 13 | padding-left: 16px; 14 | padding-right: 16px; 15 | margin-top: 2px; 16 | font-family: 'Courier New', Courier, monospace; 17 | } 18 | 19 | .button { 20 | appearance: none; 21 | background: none; 22 | font-size: 32px; 23 | padding-left: 12px; 24 | padding-right: 12px; 25 | outline: none; 26 | border: 2px solid transparent; 27 | color: rgb(112, 76, 182); 28 | padding-bottom: 4px; 29 | cursor: pointer; 30 | background-color: rgba(112, 76, 182, 0.1); 31 | border-radius: 2px; 32 | transition: all 0.15s; 33 | } 34 | 35 | .textbox { 36 | font-size: 32px; 37 | padding: 2px; 38 | width: 64px; 39 | text-align: center; 40 | margin-right: 8px; 41 | } 42 | 43 | .button:hover, .button:focus { 44 | border: 2px solid rgba(112, 76, 182, 0.4); 45 | } 46 | 47 | .button:active { 48 | background-color: rgba(112, 76, 182, 0.2); 49 | } 50 | 51 | .asyncButton { 52 | composes: button; 53 | position: relative; 54 | margin-left: 8px; 55 | } 56 | 57 | .asyncButton:after { 58 | content: ""; 59 | background-color: rgba(112, 76, 182, 0.15); 60 | display: block; 61 | position: absolute; 62 | width: 100%; 63 | height: 100%; 64 | left: 0; 65 | top: 0; 66 | opacity: 0; 67 | transition: width 1s linear, opacity 0.5s ease 1s; 68 | } 69 | 70 | .asyncButton:active:after { 71 | width: 0%; 72 | opacity: 1; 73 | transition: 0s 74 | } 75 | -------------------------------------------------------------------------------- /src/components/counter/counterSlice.js: -------------------------------------------------------------------------------- 1 | import { createSlice } from '@reduxjs/toolkit'; 2 | 3 | export const counterSlice = createSlice({ 4 | name: 'counter', 5 | initialState: { 6 | value: 0 7 | }, 8 | reducers: { 9 | increment: (state) => { 10 | // Redux Toolkit allows us to write "mutating" logic in reducers. It 11 | // doesn't actually mutate the state because it uses the Immer library, 12 | // which detects changes to a "draft state" and produces a brand new 13 | // immutable state based off those changes 14 | state.value += 1; 15 | }, 16 | decrement: (state) => { 17 | state.value -= 1; 18 | }, 19 | incrementByAmount: (state, action) => { 20 | state.value += action.payload; 21 | } 22 | } 23 | }); 24 | 25 | export const { increment, decrement, incrementByAmount } = counterSlice.actions; 26 | 27 | // The function below is called a thunk and allows us to perform async logic. It 28 | // can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This 29 | // will call the thunk with the `dispatch` function as the first argument. Async 30 | // code can then be executed and other actions can be dispatched 31 | export const incrementAsync = (amount) => (dispatch) => { 32 | setTimeout(() => { 33 | dispatch(incrementByAmount(amount)); 34 | }, 1000); 35 | }; 36 | 37 | // The function below is called a selector and allows us to select a value from 38 | // the state. Selectors can also be defined inline where they're used instead of 39 | // in the slice file. For example: `useSelector((state) => state.counter.value)` 40 | export const selectCount = (state) => state.counter.value; 41 | 42 | export default counterSlice.reducer; 43 | -------------------------------------------------------------------------------- /src/components/titlebar/Titlebar.js: -------------------------------------------------------------------------------- 1 | import { 2 | CloseButton, 3 | ContractButton, 4 | MaximizeButton, 5 | MinimizeButton 6 | } from 'components/titlebar/TitlebarButtons'; 7 | import React, { useState } from 'react'; 8 | 9 | import { app } from 'utils/services'; 10 | 11 | import favicon from 'components/titlebar/img/favicon.png'; 12 | import styles from 'components/titlebar/scss/Titlebar.module.scss'; 13 | 14 | 15 | /** 16 | * @namespace Titlebar 17 | * @description Title Component to use as an Electron customized titlebar. 18 | * electron-window-title-text used in main.js to set opacity on/off focus. 19 | * electron-window-title-buttons used in main.js to set opacity on/off focus. 20 | */ 21 | 22 | const Titlebar = () => { 23 | 24 | const [ maximized, setMaximized ] = useState(false); 25 | 26 | const handleMaximizeToggle = () => { 27 | !maximized ? app.maximize() : app.unmaximize(); 28 | setMaximized(!maximized); 29 | }; 30 | 31 | return ( 32 |
33 |
34 | favicon 35 | { document.title } 36 |
37 | 38 |
39 | 40 | { 41 | maximized 42 | ? 43 | : 44 | } 45 | 46 |
47 |
48 | ); 49 | }; 50 | 51 | export default Titlebar; -------------------------------------------------------------------------------- /src/components/titlebar/TitlebarButtons.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import styles from 'components/titlebar/scss/TitlebarButtons.module.scss'; 4 | 5 | /** 6 | * @description Titlebar minimize button. 7 | * @memberof Titlebar 8 | */ 9 | export const MinimizeButton = (props) => ( 10 | 19 | ); 20 | 21 | /** 22 | * @description Titlebar maximize button. 23 | * @memberof Titlebar 24 | */ 25 | export const MaximizeButton = (props) => ( 26 | 35 | ); 36 | 37 | /** 38 | * @description Titlebar contract (unmaximize) button. 39 | * @memberof Titlebar 40 | */ 41 | export const ContractButton = (props) => ( 42 | 52 | ); 53 | 54 | /** 55 | * @description Titlebar close button. 56 | * @memberof Titlebar 57 | */ 58 | export const CloseButton = (props) => ( 59 | 69 | ); -------------------------------------------------------------------------------- /src/components/titlebar/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/src/components/titlebar/img/favicon.png -------------------------------------------------------------------------------- /src/components/titlebar/scss/Titlebar.module.scss: -------------------------------------------------------------------------------- 1 | body section.titlebar { 2 | display: flex; 3 | justify-content: space-between; 4 | align-items: center; 5 | height: 32px; 6 | padding: 0; 7 | position: fixed; 8 | top: 0; 9 | left: 0; 10 | width: 100vw; 11 | max-width: 100vw; 12 | -webkit-user-select: none; 13 | -webkit-app-region: drag; 14 | background-color: #eaeaea; 15 | 16 | div { 17 | display: flex; 18 | align-items: center; 19 | 20 | span { 21 | font-size: 14px; 22 | font-family: 'Roboto', sans-serif; 23 | color: #252525; 24 | } 25 | 26 | img { 27 | width: 20px; 28 | padding: 5px; 29 | } 30 | 31 | } 32 | } -------------------------------------------------------------------------------- /src/components/titlebar/scss/TitlebarButtons.module.scss: -------------------------------------------------------------------------------- 1 | .button { 2 | padding: 0 25px; 3 | -webkit-app-region: no-drag; 4 | color: #252525; 5 | border-radius: 0; 6 | 7 | &:hover { 8 | background-color: rgb(225, 225, 225); 9 | color: #252525; 10 | } 11 | 12 | &:last-child { 13 | &:hover { 14 | background-color: #ff0000; 15 | span { 16 | color: #f5f5f5; 17 | } 18 | } 19 | } 20 | 21 | span i { 22 | font-size: 12px; 23 | } 24 | } 25 | 26 | %button { 27 | -webkit-app-region: no-drag; 28 | border: none; 29 | background-color: transparent; 30 | height: 32px; 31 | width: 50px; 32 | cursor: pointer; 33 | display: flex; 34 | justify-content: center; 35 | align-items: center; 36 | 37 | &:hover { 38 | background-color: rgb(225, 225, 225); 39 | color: #252525; 40 | } 41 | } 42 | 43 | .minimize-button { 44 | @extend %button; 45 | 46 | span { 47 | width: 11px; 48 | border-top: solid 1px #252525; 49 | } 50 | } 51 | 52 | .maximize-button { 53 | @extend %button; 54 | 55 | span { 56 | width: 10px; 57 | height: 10px; 58 | border: solid 1px #252525; 59 | } 60 | } 61 | 62 | .contract-button { 63 | @extend %button; 64 | 65 | span { 66 | width: 7px; 67 | height: 7px; 68 | border: solid 1px #252525; 69 | 70 | &:first-child { 71 | margin-bottom: -4px; 72 | margin-right: -2.5px; 73 | background-color: #eaeaea; 74 | z-index: 2; 75 | } 76 | 77 | &:last-child { 78 | margin-top: -4px; 79 | margin-left: -2.5px; 80 | z-index: 1; 81 | } 82 | } 83 | 84 | &:hover { 85 | span:first-child { 86 | background-color: rgb(225, 225, 225); 87 | } 88 | } 89 | } 90 | 91 | .close-button { 92 | @extend %button; 93 | 94 | span { 95 | width: 15px; 96 | height: 1px; 97 | border-top: solid 1px #252525; 98 | 99 | &:first-child { 100 | transform: rotate(45deg); 101 | margin-right: -7px; 102 | } 103 | 104 | &:last-child { 105 | transform: rotate(-45deg); 106 | margin-left: -7px; 107 | } 108 | } 109 | 110 | &:hover { 111 | background-color: #ff0000; 112 | span { 113 | border-top: solid 2px #f5f5f5; 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import 'index.scss'; 2 | 3 | import * as serviceWorker from 'serviceWorker'; 4 | 5 | import App from 'components/App'; 6 | import { Provider } from 'react-redux'; 7 | import React from 'react'; 8 | import ReactDOM from 'react-dom'; 9 | import store from 'state/store'; 10 | 11 | ReactDOM.render( 12 | 13 | 14 | 15 | 16 | , 17 | document.getElementById('root') 18 | ); 19 | 20 | // If you want your app to work offline and load faster, you can change 21 | // unregister() to register() below. Note this comes with some pitfalls. 22 | // Learn more about service workers: https://bit.ly/CRA-PWA 23 | serviceWorker.unregister(); 24 | -------------------------------------------------------------------------------- /src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | overflow: hidden; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' 15 | // [::1] is the IPv6 localhost address. 16 | || window.location.hostname === '[::1]' 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | || window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' 46 | + 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then((registration) => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' 74 | + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch((error) => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' } 105 | }) 106 | .then((response) => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 111 | || (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then((registration) => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready.then((registration) => { 134 | registration.unregister(); 135 | }); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/state/store.js: -------------------------------------------------------------------------------- 1 | import { configureStore } from '@reduxjs/toolkit'; 2 | import counterReducer from 'components/counter/counterSlice'; 3 | 4 | export default configureStore({ 5 | reducer: { 6 | counter: counterReducer 7 | } 8 | }); 9 | -------------------------------------------------------------------------------- /src/tests/App.test.js: -------------------------------------------------------------------------------- 1 | import App from 'components/App'; 2 | import { Provider } from 'react-redux'; 3 | import React from 'react'; 4 | import { render } from '@testing-library/react'; 5 | import store from 'state/store'; 6 | 7 | test('renders learn react link', () => { 8 | const { getByText } = render( 9 | 10 | 11 | 12 | ); 13 | 14 | expect(getByText(/learn/i)).toBeInTheDocument(); 15 | }); 16 | -------------------------------------------------------------------------------- /src/tests/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /src/theme/palette.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @namespace Theme 3 | * @description - Theme for Microsoft Fluent UI, which is built into the project. 4 | * 5 | * @tutorial - https://www.aka.ms/themedesigner 6 | */ 7 | 8 | export const customTheme = { 9 | themePrimary: '#57a9a9', 10 | themeLighterAlt: '#030707', 11 | themeLighter: '#0e1b1b', 12 | themeLight: '#1a3232', 13 | themeTertiary: '#336565', 14 | themeSecondary: '#4c9494', 15 | themeDarkAlt: '#63b1b1', 16 | themeDark: '#77bdbd', 17 | themeDarker: '#96cece', 18 | neutralLighterAlt: '#eeeeee', 19 | neutralLighter: '#eaeaea', 20 | neutralLight: '#e1e1e1', 21 | neutralQuaternaryAlt: '#d1d1d1', 22 | neutralQuaternary: '#c8c8c8', 23 | neutralTertiaryAlt: '#c0c0c0', 24 | neutralTertiary: '#b5b5b5', 25 | neutralSecondary: '#9d9d9d', 26 | neutralPrimaryAlt: '#868686', 27 | neutralPrimary: '#252525', 28 | neutralDark: '#565656', 29 | black: '#3e3e3e', 30 | white: '#f5f5f5' 31 | }; -------------------------------------------------------------------------------- /src/theme/variables.scss: -------------------------------------------------------------------------------- 1 | $black: #252525; 2 | $grey: #565656; -------------------------------------------------------------------------------- /src/utils/requests.js: -------------------------------------------------------------------------------- 1 | // Electron Inter Process Communication and dialog 2 | const { ipcRenderer } = window.require('electron'); 3 | 4 | // Dynamically generated TCP (open) port between 3000-3999 5 | const port = ipcRenderer.sendSync('get-port-number'); 6 | 7 | /** 8 | * @namespace Requests 9 | * @description - Helper functions for network requests (e.g., get, post, put, delete, etc..) 10 | */ 11 | 12 | /** 13 | * @description - Helper GET method for sending requests to and from the Python/Flask services. 14 | * @param {string} route - Path of the Python/Flask service you want to use. 15 | * @param {Function} callback - Callback function which uses the returned data as an argument. 16 | * @return response data from Python/Flask service. 17 | * @memberof Requests 18 | */ 19 | export const get = (route, callback, errorCallback) => { 20 | fetch(`http://localhost:${port}/${route}`) 21 | .then((response) => response.json()) 22 | .then(callback) 23 | .catch((error) => (errorCallback ? errorCallback(error) : console.error(error))); 24 | }; 25 | 26 | 27 | /** 28 | * @description - Helper POST method for sending requests to and from the Python/Flask services. 29 | * @param body - request body of data that you want to pass. 30 | * @param route - URL route of the Python/Flask service you want to use. 31 | * @param callback - optional callback function to be invoked if provided. 32 | * @return response data from Python/Flask service. 33 | * @memberof Requests 34 | */ 35 | export const post = ( 36 | body, 37 | route, 38 | callback, 39 | errorCallback 40 | ) => { 41 | fetch(`http://localhost:${port}/${route}`, { 42 | body, 43 | method: 'POST', 44 | headers: { 'Content-type': 'application/json' } 45 | }) 46 | .then((response) => response.json()) 47 | .then(callback) 48 | .catch((error) => (errorCallback ? errorCallback(error) : console.error(error))); 49 | }; -------------------------------------------------------------------------------- /src/utils/services.js: -------------------------------------------------------------------------------- 1 | // Electron Inter Process Communication and dialog 2 | const { ipcRenderer } = window.require('electron'); 3 | 4 | /** 5 | * @namespace Services 6 | * @description - Methods from Electron Inter Process Communication. 7 | * @property {function} maximize - Function to maximize the screen size of the program. 8 | * @property {function} minimize - Function to minimize the screen size of the program. 9 | * @property {function} quit - Function to close and exit the program. 10 | * @property {function} unmaximize - Function to contract (unmaximize) the screen size of the program. 11 | */ 12 | export const app = { 13 | maximize: () => ipcRenderer.send('app-maximize'), 14 | minimize: () => ipcRenderer.send('app-minimize'), 15 | quit: () => ipcRenderer.send('app-quit'), 16 | unmaximize: () => ipcRenderer.send('app-unmaximize') 17 | }; -------------------------------------------------------------------------------- /utilities/deb/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/deb/images/background.png -------------------------------------------------------------------------------- /utilities/deb/images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/deb/images/banner.png -------------------------------------------------------------------------------- /utilities/deb/images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/deb/images/icon.ico -------------------------------------------------------------------------------- /utilities/dmg/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/dmg/images/background.png -------------------------------------------------------------------------------- /utilities/dmg/images/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/dmg/images/icon.icns -------------------------------------------------------------------------------- /utilities/jsdoc/LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Docdash is free software, licensed under the Apache License, Version 2.0 (the 4 | "License"). Commercial and non-commercial use are permitted in compliance with 5 | the License. 6 | 7 | Copyright (c) 2016 Clement Moron and the 8 | [contributors to docdash](https://github.com/clenemt/docdash/graphs/contributors). 9 | All rights reserved. 10 | 11 | You may obtain a copy of the License at: 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | In addition, a copy of the License is included with this distribution. 15 | 16 | As stated in Section 7, "Disclaimer of Warranty," of the License: 17 | 18 | > Licensor provides the Work (and each Contributor provides its Contributions) 19 | > on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 20 | > express or implied, including, without limitation, any warranties or 21 | > conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 22 | > PARTICULAR PURPOSE. You are solely responsible for determining the 23 | > appropriateness of using or redistributing the Work and assume any risks 24 | > associated with Your exercise of permissions under this License. 25 | 26 | The source code for docdash is available at: 27 | https://github.com/clenemt/docdash 28 | 29 | # Third-Party Software 30 | 31 | Docdash includes or depends upon the following third-party software, either in 32 | whole or in part. Each third-party software package is provided under its own 33 | license. 34 | 35 | ## JSDoc 3 36 | 37 | JSDoc 3 is free software, licensed under the Apache License, Version 2.0 (the 38 | "License"). Commercial and non-commercial use are permitted in compliance with 39 | the License. 40 | 41 | Copyright (c) 2011-2016 Michael Mathews and the 42 | [contributors to JSDoc](https://github.com/jsdoc3/jsdoc/graphs/contributors). 43 | All rights reserved. 44 | 45 | You may obtain a copy of the License at: 46 | http://www.apache.org/licenses/LICENSE-2.0 47 | 48 | In addition, a copy of the License is included with this distribution. 49 | 50 | As stated in Section 7, "Disclaimer of Warranty," of the License: 51 | 52 | > Licensor provides the Work (and each Contributor provides its Contributions) 53 | > on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 54 | > express or implied, including, without limitation, any warranties or 55 | > conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 56 | > PARTICULAR PURPOSE. You are solely responsible for determining the 57 | > appropriateness of using or redistributing the Work and assume any risks 58 | > associated with Your exercise of permissions under this License. 59 | 60 | The source code for JSDoc 3 is available at: 61 | https://github.com/jsdoc3/jsdoc 62 | -------------------------------------------------------------------------------- /utilities/jsdoc/README.md: -------------------------------------------------------------------------------- 1 | # daybrush-jsdoc-template 2 | [![npm package](https://img.shields.io/npm/v/daybrush-jsdoc-template.svg)](https://www.npmjs.com/package/daybrush-jsdoc-template) [![license](https://img.shields.io/npm/l/daybrush-jsdoc-template.svg)](LICENSE.md) 3 | 4 | **daybrush-jsdoc-template** is a template based on the [**docdash**](https://github.com/clenemt/docdash) template. 5 | 6 | * [Demo](http://daybrush.github.io/scenejs/release/latest/doc/) 7 | 8 | ## Install 9 | 10 | ```bash 11 | $ npm install daybrush-jsdoc-template 12 | ``` 13 | 14 | ## Usage 15 | Clone repository to your designated `jsdoc` template directory, then: 16 | 17 | ```bash 18 | $ jsdoc entry-file.js -t path/to/daybrush-jsdoc-template 19 | ``` 20 | 21 | ### scene.js 22 | ```bash 23 | $ jsdoc ./outjs ./README.md -d doc -t ./node_modules/daybrush-jsdoc-template 24 | ``` 25 | 26 | ## Usage (npm) 27 | In your projects `package.json` file add a new script: 28 | 29 | ```json 30 | "script": { 31 | "generate-docs": "node_modules/.bin/jsdoc -c jsdoc.json" 32 | } 33 | ``` 34 | 35 | In your `jsdoc.json` file, add a template option. 36 | 37 | ```json 38 | "opts": { 39 | "template": "node_modules/daybrush-jsdoc-template" 40 | } 41 | ``` 42 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/base/chains.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @fileOverview The chains define the primary composition elements (functions) that determine the order of execution. 4 | * 5 | * @module base/chains 6 | * @requires dcl 7 | */ 8 | var dcl = require( "dcl" ); 9 | /** 10 | * @classDesc Chains define the primary composition elements (functions) that determine the order of execution. 11 | * @exports base/chains 12 | * @constructor 13 | */ 14 | var Chains = dcl( null, {declaredClass : "base/chains"} ); 15 | /** 16 | * The `close` method asks an object to shut itself down in a way that will allow it to be reopened, unlike the 17 | * [end method]{@link base/chains#end} which will call the destroy method which should make the object unusable, but also 18 | * devoid of all resources whereas `close` may still keep some resources open. 19 | * 20 | * | Heading 1 | Heading 2 | Heading 3 | 21 | * |-----------|-----------|-----------------| 22 | * | Bar | Food | This is a table | 23 | * 24 | * This uses the `before` chain which means the last one defined in the first one destroyed 25 | * @memberOf base/chains# 26 | * @name close 27 | * @see base/chains#open 28 | */ 29 | dcl.chainBefore( Chains, "close" ); 30 | /** 31 | * The `end` method will call the destroy method which should make the object unusable and 32 | * devoid of all resources, unlike the 33 | * [close method]{@link base/chains#close} asks an object to shut itself down in a way that will allow it to be reopened. 34 | * 35 | * This uses the `before` chain which means the last one defined in the first one destroyed 36 | * @memberOf base/chains# 37 | * @name end 38 | * 39 | * @example Add *this* to your application.properties. 40 | * {@lang bash} 41 | * foo=bar 42 | * 43 | */ 44 | dcl.chainBefore( Chains, "end" ); 45 | /** 46 | * Destroy is called by the end method and it is here that you should clean up after yourself. The difference between 47 | * `destroy` and [end]{@link base/chains#end} is the `end` is the verb that you raise on an object to ask it to go away 48 | * and `destroy` is where you actually do the work to clean up. Think of this as the counterpart of `constructor` yet 49 | * not called automatically. 50 | * 51 | * This uses the `before` chain which means the last one defined is the first one destroyed 52 | * @private 53 | * @memberOf base/chains# 54 | * @name destroy 55 | */ 56 | dcl.chainBefore( Chains, "destroy" ); 57 | 58 | /** 59 | * If you are using the open/close paradigm for an object that can kind of go dormant on {@link base/chains#close} and can be "reopened" 60 | * again later, here is where the "open" code will go. 61 | * 62 | * This used the `after` chain which means that the first one defined is the first one destroyed. 63 | * 64 | * @memberOf base/chains# 65 | * @name open 66 | * @see base/chains#close 67 | */ 68 | dcl.chainAfter( Chains, "open" ); 69 | 70 | module.exports = Chains; 71 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/base/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @fileOverview This is base definition for all composed classes defined by the system 4 | * @module base 5 | * @requires base/chains 6 | * @requires dcl 7 | */ 8 | 9 | var dcl = require( "dcl" ); 10 | var chains = require( "./chains" ); 11 | 12 | /** 13 | * @classdesc The base of all classes in the system, this is one of the few pure "classes" in core the of the system. It is a 14 | * pretty clean little class whose primary purpose is to surface the composition chains and a basis for storing 15 | * options on mixin and subclass instances. Options are handled at the instance rather than the prototype level 16 | * so that multiple instances don't compete for default values. 17 | * 18 | * @exports base 19 | * @constructor 20 | * @extends base/chains 21 | */ 22 | var Base = dcl( [chains], /** @lends base# */{ 23 | declaredClass : "Base", 24 | /** 25 | * Add an option to a class. If any members of the hash already exist in `this.options`, they will be overwritten. 26 | * @param {hash} options A hash of options you want to set 27 | * @see {base#addDefaultOptions} 28 | */ 29 | addOptions : function ( options ) { 30 | options = options || {}; 31 | if ( this.options ) {options = sys.extend( {}, sys.result( this, 'options' ), options );} 32 | this.options = options; 33 | }, 34 | /** 35 | * Add a default option to a class. The default options are only set if there is not already a 36 | * value for the option. 37 | * @param {hash} options A hash of options you want to set 38 | * @see {base#addOptions} 39 | */ 40 | addDefaultOptions : function ( options ) { 41 | options = options || {}; 42 | if ( this.options ) {options = sys.defaults( {}, sys.result( this, 'options' ), options );} 43 | this.options = options; 44 | }, 45 | 46 | /** 47 | * Call this to close your object and dispose of all maintained resources. You can define this method on your 48 | * own classes without having to call the superclass instance, however it is reccomended that you put 49 | * all disposal code in `destroy()`. You must be disciplined about calling this on your instances. 50 | * @see {base/chains#end} 51 | * @see {base/chains#destroy} 52 | */ 53 | end : function () { 54 | this.destroy() 55 | }, 56 | 57 | /** 58 | * Called when it is time to get rid of all of your instance level references and objects and events. You can 59 | * define this method on your own classes without having to call the superclass instance. It is called by 60 | * `instance.end()` automatically 61 | * @see {base/chains#end} 62 | * @see {base/chains#destroy} 63 | */ 64 | destroy : function () { 65 | 66 | } 67 | 68 | 69 | } ); 70 | 71 | Base.compose = dcl; 72 | Base.mixin = dcl.mix; 73 | module.exports = Base; 74 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/documents/model.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @fileOverview A model is the first level if usable data-bearing entity in the system. It does NOT include any verbs for saving or anything like 4 | * that, it is a pure, in memory data container 5 | * @module documents/model 6 | * @require base 7 | * @require documents/probe 8 | * @require lodash 9 | */ 10 | 11 | var Base = require( "../base" ); 12 | var probe = require( "./probe" ); 13 | var sys = require( "lodash" ); 14 | /** 15 | * A model is the first level if usable data-bearing entity in the system. It does NOT include any verbs for saving or anything like 16 | * that, it is a pure, in memory data container 17 | * @exports documents/model 18 | * @constructor 19 | * @borrows module:documents/probe.get as get 20 | * @borrows module:documents/probe.set as set 21 | * @borrows module:documents/probe.any as any 22 | * @borrows module:documents/probe.all as all 23 | * @borrows module:documents/probe.remove as remove 24 | * @borrows module:documents/probe.seekKey as seekKey 25 | * @borrows module:documents/probe.seek as seek 26 | * @borrows module:documents/probe.findOne as findOne 27 | * @borrows module:documents/probe.findOneKey as findOneKey 28 | * @borrows module:documents/probe.findKeys as findKeys 29 | * @borrows module:documents/probe.find as find 30 | * @borrows module:documents/probe.update as update 31 | * @borrows module:documents/probe.some as some 32 | * @borrows module:documents/probe.every as every 33 | */ 34 | var Model = Base.compose( [Base], /** @lends documents/model# */{ 35 | constructor : function () { 36 | var that = this; 37 | probe.mixin( this ); 38 | 39 | var idField = "_id"; 40 | /** 41 | * The name of the field that uniquely identifies a record. When provided, some operations will take advantage of it 42 | * 43 | * @name _idField 44 | * @memberOf documents/model# 45 | * @type {string} 46 | * @private 47 | */ 48 | Object.defineProperty( this, "_idField", { 49 | get : function () { 50 | return idField; 51 | }, 52 | set : function ( val ) { 53 | idField = val; 54 | }, 55 | configurable : false, 56 | enumerable : true, 57 | writable : true 58 | } ); 59 | 60 | /** 61 | * The value of the primary key if {@link documents/model#_idField} is filled in. It will be null if none found 62 | * 63 | * @name _pkey 64 | * @memberOf documents/model# 65 | * @type {*} 66 | * @private 67 | */ 68 | Object.defineProperty( this, "_pkey", { 69 | get : function () { 70 | var val; 71 | if ( !sys.isEmpty( that._idField ) ) { 72 | val = that[that._idField]; 73 | } 74 | return val; 75 | }, 76 | set : function ( val ) { 77 | if ( !sys.isEmpty( that._idField ) ) { 78 | that[that._idField] = val; 79 | } 80 | }, 81 | configurable : false, 82 | enumerable : true, 83 | writable : true 84 | } ); 85 | 86 | /** 87 | * If {@link documents/model#_idField} is filled in and it's value is empty this will be true. 88 | * @type {boolean} 89 | * @name isNew 90 | * @memberOf documents/model# 91 | */ 92 | Object.defineProperty( this, "isNew", { 93 | get : function () { 94 | return !sys.isEmpty( that._idField ) && !sys.isEmpty( that[that._idField] ) 95 | }, 96 | configurable : false, 97 | enumerable : true, 98 | writable : false 99 | } ); 100 | 101 | /** 102 | * Returns true if this instance is empty 103 | * @type {boolean} 104 | * @name isEmpty 105 | * @memberOf documents/model# 106 | */ 107 | Object.defineProperty( this, "isEmpty", { 108 | get : function () { 109 | return sys.isEmpty( that ); 110 | }, 111 | configurable : false, 112 | enumerable : true, 113 | writable : false 114 | } ); 115 | } 116 | } ); 117 | module.exports = Model; 118 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/fixtures.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "tags": { 3 | "allowUnknownTags": true 4 | }, 5 | "source": { 6 | "include": [ 7 | "fixtures/", 8 | "./README.md" 9 | ] 10 | }, 11 | "plugins": ["plugins/markdown"], 12 | "opts": { 13 | "encoding": "utf8", 14 | "template": "../", 15 | "destination": "../fixtures-doc/", 16 | "recurse": true, 17 | "verbose": true 18 | }, 19 | "markdown": { 20 | "parser": "gfm", 21 | "hardwrap": true 22 | }, 23 | "templates": { 24 | "cleverLinks": false, 25 | "monospaceLinks": false, 26 | "default": { 27 | "outputSourceFiles": true, 28 | "includeDate": false 29 | } 30 | }, 31 | "docdash": { 32 | "static": false, 33 | "sort": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/mixins/bussable.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @fileOverview Provides easy access to the system bus and provides some helper methods for doing so 4 | * @module mixins/bussable 5 | * @requires postal 6 | * @requires lodash 7 | * @requires base 8 | */ 9 | var bus = require( "postal" ); 10 | var Base = require( "../base" ); 11 | var sys = require( "lodash" ); 12 | 13 | /** 14 | * @classDesc Provides easy access to the system bus and provides some helper methods for doing so 15 | * @exports mixins/bussable 16 | * @mixin 17 | */ 18 | var Bussable = Base.compose( [Base], /** @lends mixins/bussable# */{ 19 | declaredClass : "mixins/Bussable", 20 | constructor : function () { 21 | /** 22 | * The list of subscriptions maintained by the mixin 23 | * @type {Array} 24 | * @memberof mixins/bussable# 25 | * @name _subscriptions 26 | * @private 27 | */ 28 | this._subscriptions = {}; 29 | 30 | this.log.trace( "Bussable constructor" ); 31 | }, 32 | 33 | /** 34 | * Subscribe to an event 35 | * @param {string} channel The channel to subscribe to 36 | * @param {string} topic The topic to subscribe to 37 | * @param {callback} callback What to do when you get the event 38 | * @returns {object} The subscription definition 39 | */ 40 | subscribe : function ( channel, topic, callback ) { 41 | this.log.trace( "Bussable subscribe" ); 42 | var sub = bus.subscribe( {channel : channel, topic : topic, callback : callback} ); 43 | this.subscriptions[channel + "." + topic] = sub; 44 | return sub; 45 | }, 46 | 47 | /** 48 | * Subscribe to an event once 49 | * @param {string} channel The channel to subscribe to 50 | * @param {string} topic The topic to subscribe to 51 | * @param {callback} callback What to do when you get the event 52 | * @returns {object} The subscription definition 53 | */ 54 | once : function ( channel, topic, callback ) { 55 | this.log.trace( "Bussable once" ); 56 | var sub = this.subscribe( channel, topic, callback ); 57 | this.subscriptions[channel + "." + topic] = sub; 58 | sub.disposeAfter( 1 ); 59 | return sub; 60 | }, 61 | 62 | /** 63 | * Publish an event on the system bus 64 | * @param {string} channel The channel to publish to 65 | * @param {string} topic The topic to publish to 66 | * @param {object=} options What to pass to the event 67 | */ 68 | publish : function ( channel, topic, options ) { 69 | this.log.trace( "Bussable publish" ); 70 | bus.publish( {channel : channel, topic : topic, data : options} ); 71 | }, 72 | 73 | /** 74 | * Get a subscription definition 75 | * 76 | * @param {string} channel 77 | * @param {string} topic 78 | * @returns {object=} The subscription definition 79 | */ 80 | getSubscription : function ( channel, topic ) { 81 | this.log.trace( "Bussable getSubscription" ); 82 | return this.subscriptions[channel + "." + topic]; 83 | }, 84 | 85 | /** 86 | * Gets rid of all subscriptions for this object. 87 | * @private 88 | */ 89 | destroy : function () { 90 | this.log.trace( "Bussable destroy" ); 91 | 92 | sys.each( this.subscriptions, function ( sub ) { 93 | sub.unsubscribe(); 94 | } ); 95 | } 96 | } ); 97 | 98 | module.exports = Bussable; 99 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/strings/format.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @fileOverview String helper methods 4 | * 5 | * @module strings/format 6 | */ 7 | 8 | /** 9 | * Format a string quickly and easily using .net style format strings 10 | * @param {string} format A string format like "Hello {0}, now take off your {1}!" 11 | * @param {...?} args One argument per `{}` in the string, positionally replaced 12 | * @returns {string} 13 | * 14 | * @example 15 | * var strings = require("papyrus/strings"); 16 | * var s = strings.format("Hello {0}", "Madame Vastra"); 17 | * // s = "Hello Madame Vastra" 18 | * 19 | * @example {@lang xml} 20 | * 21 | * <%= strings.format("Hello {0}", "Madame Vastra") %> 22 | * 23 | */ 24 | module.exports = function ( format ) { 25 | var args = Array.prototype.slice.call( arguments, 1 ); 26 | return format.replace( /{(\d+)}/g, function ( match, number ) { 27 | return typeof args[number] != 'undefined' 28 | ? args[number] 29 | : match 30 | ; 31 | } ); 32 | }; 33 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/tutorials/Brush Teeth.md: -------------------------------------------------------------------------------- 1 | #Lorem ipsum dolor sit amet 2 | 3 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec viverra, tellus et fermentum tincidunt, massa ligula dignissim augue, ut aliquam tortor odio in odio. In faucibus metus metus. Curabitur est mi, fermentum lacinia tincidunt vitae, mattis sit amet neque. Quisque diam nisl, accumsan ac porta tincidunt, iaculis facilisis ipsum. Nulla facilisi. Aenean a metus tortor. Pellentesque congue, mauris vitae viverra varius, elit nunc dictum nisl, rhoncus ultrices nulla sapien at leo. Duis ultricies porttitor diam. Nulla facilisi. Nullam elementum, lorem eu imperdiet laoreet, est turpis sollicitudin velit, in porttitor justo dolor vel urna. Mauris in ante magna. Curabitur vitae lacus in magna mollis commodo. 4 | 5 | | Fusce lacinia | mauris ac aliquam | consequat | lacus urna feugiat erat | id viverra mi mi sit amet tortor | 6 | |---------------|-------------------|-------------|-------------------------------|---------------------------------------| 7 | | Etiam ac | 1 | 3 | 4.5 | 6.78910 | 8 | | Pellentesque e| 2 | 2 | 3 | 4 | 9 | 10 | neque lacus, quis posuere orci. Fusce molestie blandit velit, sit amet dictum eros pharetra vitae. In erat urna, condimentum ac feugiat id, rutrum et nisi. Cras ac velit lorem. Nulla facilisi. Maecenas dignissim nulla in turpis tempus sed rhoncus augue dapibus. Nulla feugiat, urna non sagittis laoreet, dolor metus rhoncus justo, sed semper ante lacus eget quam. Sed ac ligula magna. Sed tincidunt pulvinar neque in porta. Nullam quis lacus orci. Pellentesque ornare viverra lacus, id aliquam magna venenatis a. 11 | 12 | Sed id tristique lorem. Ut sodales turpis nec mauris gravida interdum. Cras pellentesque, purus at suscipit euismod, elit nunc cursus nisi, ut venenatis metus sapien id velit. Sed lectus orci, pharetra non pulvinar vel, ullamcorper id lorem. Donec vulputate tincidunt ipsum, ut lacinia tortor sollicitudin id. Nunc nec nibh ut felis venenatis egestas. Proin risus mauris, eleifend eget interdum in, venenatis sed velit. Praesent sodales elit ut odio viverra posuere. Donec sapien lorem, molestie in egestas eget, vulputate sed orci. Aenean elit sapien, pellentesque vitae tempor sit amet, sagittis et ligula. Mauris aliquam sapien sit amet lacus ultrices rutrum. Curabitur nec dolor sed elit varius dignissim a a lacus. Aliquam ac convallis enim. 13 | 14 | Suspendisse orci massa, hendrerit sagittis lacinia consectetur, sagittis vitae purus. Aliquam id eros diam, eget elementum turpis. Nullam tellus magna, mollis in molestie id, venenatis rhoncus est. Proin id diam justo. Nunc tempus gravida justo at lobortis. Nam vitae venenatis nisi. Donec vel odio massa. Quisque interdum metus sit amet est iaculis tincidunt. Donec bibendum blandit purus, id semper orci aliquam quis. Nam tincidunt dolor eu felis ultricies tempor. Nulla non consectetur erat. 15 | 16 | Nunc faucibus lacus eget odio ultricies nec ullamcorper risus pharetra. Nunc nec consequat urna. Curabitur condimentum ante vitae erat tristique vitae gravida quam dapibus. Cras ac justo dui, at faucibus urna. Nunc tristique, velit id feugiat fermentum, dolor enim egestas erat, at vestibulum ante ipsum vel orci. Duis quis ante id justo vehicula eleifend sed et urna. Sed sapien tortor, rutrum id ultrices eu, tincidunt tincidunt mi. Etiam blandit, neque eget interdum dignissim, lacus ante facilisis dolor, non viverra dui lorem vitae nibh. Morbi volutpat augue eget nulla luctus eu aliquam sem facilisis. Pellentesque sollicitudin commodo dolor sit amet vestibulum. Nam dictum posuere quam, in tincidunt erat rutrum eu. 17 | 18 | Etiam nec turpis purus, at lacinia sem. In commodo lacinia euismod. Curabitur tincidunt congue leo, eget iaculis orci volutpat pharetra. Fusce dignissim lacus lacus. Integer consectetur lacus rutrum risus malesuada at consectetur erat rutrum. Sed magna ipsum, fringilla eget auctor non, fringilla nec massa. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Vestibulum nec tortor id nisi luctus aliquam. Maecenas cursus tincidunt ornare. Nulla a vestibulum odio. Mauris malesuada commodo justo quis mattis. Suspendisse mauris ligula, placerat at egestas in, tincidunt quis nibh. Aliquam ullamcorper elit at augue cursus quis pellentesque purus viverra. 19 | 20 | Nulla ultricies justo ac nisi consectetur posuere. Donec ornare pharetra erat, nec facilisis dui cursus quis. Quisque porttitor porttitor orci, sed facilisis urna facilisis sed. Sed tincidunt adipiscing turpis et hendrerit. Cras posuere orci ut mauris ullamcorper vitae laoreet nisi luctus. In rutrum tristique augue. Nam eleifend dignissim dui. 21 | 22 | Donec viverra egestas tellus non viverra. Aenean est ante, egestas sed scelerisque quis, aliquet sed lacus. Praesent non mauris neque, et adipiscing ante. Vestibulum quis quam vitae ipsum aliquet blandit. Vivamus condimentum euismod orci, in tincidunt justo rutrum faucibus. Phasellus nec lorem arcu. Donec tortor dui, facilisis in rutrum sit amet, pulvinar vitae lacus. Nam sodales sem eu nunc scelerisque vitae ullamcorper dolor facilisis. Duis imperdiet nisi in magna tempor convallis. Fusce at metus augue. Quisque dictum tempus mauris, in mattis ligula dignissim ut. 23 | 24 | Proin sodales, mi at tincidunt ornare, mi dui sagittis velit, sed dictum risus orci eu erat. Sed nunc leo, congue sed rutrum eget, lobortis ac lectus. Etiam non arcu nulla. Vestibulum rutrum dolor pulvinar lorem posuere blandit. Sed quis sapien dui. Nunc sagittis erat commodo quam porta cursus in non erat. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin a molestie neque. Aliquam iaculis lacus sed neque hendrerit at dignissim ligula imperdiet. Suspendisse venenatis, lorem at luctus scelerisque, sem purus pellentesque sapien, vitae ornare ipsum quam nec dui. Mauris neque est, interdum nec pulvinar eget, dapibus eleifend tellus. Fusce non lorem tortor. Nullam eget nunc quis felis aliquam consectetur. Aliquam tristique, turpis in feugiat blandit, lectus erat condimentum tortor, non egestas nisl sapien eget nibh. 25 | 26 | Aliquam elit turpis, faucibus et porta et, egestas nec nibh. Sed nisl est, pharetra a eleifend a, pretium ac eros. Sed leo eros, pulvinar vel faucibus dictum, aliquet ut quam. Maecenas et felis non ligula fringilla pretium fringilla sit amet ante. Nam varius imperdiet interdum. Ut non metus mauris, vel volutpat lorem. Nullam sagittis est quis lacus feugiat fringilla. Quisque orci lorem, semper ac accumsan vitae, blandit quis velit. Proin luctus sodales ultrices. Fusce mauris erat, facilisis ut consectetur at, fringilla feugiat orci. Aliquam a nisi a neque interdum suscipit id eget purus. Pellentesque tincidunt justo ut urna posuere non molestie quam auctor. 27 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/tutorials/Drive Car.md: -------------------------------------------------------------------------------- 1 | #Lorem ipsum dolor sit amet 2 | 3 | Curabitur est mi, fermentum lacinia tincidunt vitae, mattis sit amet neque. Quisque diam nisl, accumsan ac porta tincidunt, iaculis facilisis ipsum. Nulla facilisi. Aenean a metus tortor. Pellentesque congue, mauris vitae viverra varius, elit nunc dictum nisl, rhoncus ultrices nulla sapien at leo. Duis ultricies porttitor diam. Nulla facilisi. Nullam elementum, lorem eu imperdiet laoreet, est turpis sollicitudin velit, in porttitor justo dolor vel urna. Mauris in ante magna. Curabitur vitae lacus in magna mollis commodo. 4 | 5 | ##Fusce lacinia, mauris ac aliquam consequat 6 | Fusce molestie blandit velit, sit amet dictum eros pharetra vitae. In erat urna, condimentum ac feugiat id, rutrum et nisi. Cras ac velit lorem. Nulla facilisi. Maecenas dignissim nulla in turpis tempus sed rhoncus augue dapibus. Nulla feugiat, urna non sagittis laoreet, dolor metus rhoncus justo, sed semper ante lacus eget quam. Sed ac ligula magna. Sed tincidunt pulvinar neque in porta. Nullam quis lacus orci. Pellentesque ornare viverra lacus, id aliquam magna venenatis a. 7 | 8 | Sed id tristique lorem. Ut sodales turpis nec mauris gravida interdum. Cras pellentesque, purus at suscipit euismod, elit nunc cursus nisi, ut venenatis metus sapien id velit. Sed lectus orci, pharetra non pulvinar vel, ullamcorper id lorem. Donec vulputate tincidunt ipsum, ut lacinia tortor sollicitudin id. Nunc nec nibh ut felis venenatis egestas. Proin risus mauris, eleifend eget interdum in, venenatis sed velit. Praesent sodales elit ut odio viverra posuere. Donec sapien lorem, molestie in egestas eget, vulputate sed orci. Aenean elit sapien, pellentesque vitae tempor sit amet, sagittis et ligula. Mauris aliquam sapien sit amet lacus ultrices rutrum. Curabitur nec dolor sed elit varius dignissim a a lacus. Aliquam ac convallis enim. 9 | 10 | Suspendisse orci massa, hendrerit sagittis lacinia consectetur, sagittis vitae purus. Aliquam id eros diam, eget elementum turpis. Nullam tellus magna, mollis in molestie id, venenatis rhoncus est. Proin id diam justo. Nunc tempus gravida justo at lobortis. Nam vitae venenatis nisi. Donec vel odio massa. Quisque interdum metus sit amet est iaculis tincidunt. Donec bibendum blandit purus, id semper orci aliquam quis. Nam tincidunt dolor eu felis ultricies tempor. Nulla non consectetur erat. 11 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/tutorials/Fence Test.md: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur non libero tristique, interdum quam in, fermentum massa. Aenean vestibulum velit eu massa faucibus accumsan. Aenean tempus quam ornare ligula gravida adipiscing. Suspendisse vestibulum diam quis quam lacinia convallis. Nunc rhoncus a elit ut dictum. Maecenas porta mi et risus convallis commodo. In hac habitasse platea dictumst. Morbi placerat sem nec eleifend hendrerit. Donec hendrerit pulvinar tristique. Pellentesque at nunc blandit, fringilla elit nec, dignissim arcu. Quisque sit amet enim urna. Nunc adipiscing lacinia justo. Pellentesque euismod nisi id elit auctor porttitor. Phasellus rutrum viverra felis, ac cursus ante vulputate ut. Donec laoreet felis ac risus vulputate sodales. 2 | 3 | Mauris sit amet risus non ligula lacinia iaculis. Sed ornare tellus velit, vel elementum quam porttitor tempus. Duis vestibulum augue eu diam malesuada auctor. Maecenas dignissim odio ut elit fermentum, id mollis leo mattis. Phasellus posuere augue sed interdum vestibulum. Etiam ac pharetra est. Integer tortor ligula, pharetra ac nisi nec, faucibus laoreet dolor. Nunc vehicula, enim et cursus tincidunt, nulla purus mollis urna, vel ultricies nisl mi a risus. Vestibulum sed urna sodales, pretium nisi sed, pretium sapien. Vivamus et massa tincidunt, semper nibh nec, eleifend urna. Integer auctor, eros at pharetra blandit, erat nibh mattis turpis, rhoncus elementum nisi mi vitae purus. 4 | 5 | Quisque elementum sapien id neque volutpat cursus non mattis velit. 6 | 7 | 8 | ``` 9 | $mod : function ( qu, value ) { 10 | var operands = sys.flatten( qu.operands ); 11 | if ( operands.length !== 2 ) { 12 | throw new Error( "$mod requires two operands" ); 13 | } 14 | var mod = operands[0]; 15 | var rem = operands[1]; 16 | return value % mod === rem; 17 | }, 18 | 19 | ``` 20 | 21 | 22 | ``` 23 | {@lang bash} 24 | #!/bin/bash 25 | echo Please, enter your firstname and lastname 26 | read FN LN 27 | echo "Hi! $LN, $FN !" 28 | ``` 29 | 30 | ```bash 31 | #!/bin/bash 32 | echo Please, enter your firstname and lastname 33 | read FN LN 34 | echo "Hi! $LN, $FN !" 35 | ``` 36 | 37 | -------------------------------------------------------------------------------- /utilities/jsdoc/fixtures/utils/logger.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | /** 3 | * @fileOverview The logging system for papyrus is based on [http://pimterry.github.io/loglevel/](loglevel) and slightly decorated 4 | * @module utils/logger 5 | * @requires dcl 6 | * @requires loglevel 7 | */ 8 | 9 | var dcl = require( "dcl" ); 10 | var log = require( 'loglevel' ); 11 | 12 | /** 13 | * A logger class that you can mix into your classes to handle logging settings and state at an object level. 14 | * See {@link utils/logger} for the members of this class 15 | * 16 | * @exports utils/logger.Logger 17 | * @class 18 | * @see utils/logger 19 | */ 20 | var Logger = dcl( null, /** @lends utils/logger.Logger# */{ 21 | declaredClass : "utils/Logger", 22 | 23 | /** 24 | * Turn off all logging. If you log something, it will not error, but will not do anything either 25 | * and the cycles are minimal. 26 | * 27 | */ 28 | silent : function () { 29 | log.disableAll(); 30 | }, 31 | /** 32 | * Turns on all logging levels 33 | * 34 | */ 35 | all : function () { 36 | log.enableAll(); 37 | }, 38 | /** 39 | * Sets the logging level to one of `trace`, `debug`, `info`, `warn`, `error`. 40 | * @param {string} lvl The level to set it to. Can be one of `trace`, `debug`, `info`, `warn`, `error`. 41 | * 42 | */ 43 | level : function ( lvl ) { 44 | if ( lvl.toLowerCase() === "none" ) { 45 | log.disableAll(); 46 | } else { 47 | log.setLevel( lvl ); 48 | } 49 | }, 50 | /** 51 | * Log a `trace` call 52 | * @method 53 | * @param {string} The value to log 54 | */ 55 | trace : log.trace, 56 | /** 57 | * Log a `debug` call 58 | * @method 59 | * @param {string} The value to log 60 | */ 61 | debug : log.debug, 62 | /** 63 | * Log a `info` call 64 | * @method 65 | * @param {string} The value to log 66 | */ 67 | info : log.info, 68 | /** 69 | * Log a `warn` call 70 | * @method 71 | * @param {string} The value to log 72 | */ 73 | warn : log.warn, 74 | /** 75 | * Log a `error` call 76 | * @method 77 | * @param {string} The value to log 78 | */ 79 | error : log.error 80 | } ); 81 | 82 | module.exports = new Logger(); 83 | /** 84 | * The system global, cross-platform logger 85 | * @name utils/logger 86 | * @static 87 | * @type {utils/logger.Logger} 88 | */ 89 | module.exports.Logger = Logger; 90 | -------------------------------------------------------------------------------- /utilities/jsdoc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "daybrush-jsdoc-template", 3 | "version": "1.6.0", 4 | "description": "A clean, responsive documentation template theme for JSDoc 3 inspired by lodash and minami", 5 | "main": "publish.js", 6 | "scripts": { 7 | "test": "jsdoc -c fixtures/fixtures.conf.json", 8 | "sync": "browser-sync start -s ../fixtures-doc -f ../fixtures-doc --reload-delay 1000 --no-ui --no-notify", 9 | "watch": "watch-run -d 1000 -p tmpl/**,static/** \"npm run test\"" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "https://github.com/daybrush/daybrush-jsdoc-template.git" 14 | }, 15 | "devDependencies": { 16 | "jsdoc": "latest", 17 | "browser-sync": "latest", 18 | "watch-run": "latest" 19 | }, 20 | "author": "Daybrush ", 21 | "license": "Apache-2.0", 22 | "keywords": [ 23 | "jsdoc", 24 | "template", 25 | "tsdoc", 26 | "javascript", 27 | "typescript" 28 | ], 29 | "dependencies": { 30 | "@daybrush/utils": "^0.10.0" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /utilities/jsdoc/static/scripts/custom.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/jsdoc/static/scripts/custom.js -------------------------------------------------------------------------------- /utilities/jsdoc/static/scripts/linenumber.js: -------------------------------------------------------------------------------- 1 | /*global document */ 2 | (function() { 3 | var source = document.getElementsByClassName('prettyprint source linenums'); 4 | var i = 0; 5 | var lineNumber = 0; 6 | var lineId; 7 | var lines; 8 | var totalLines; 9 | var anchorHash; 10 | 11 | if (source && source[0]) { 12 | anchorHash = document.location.hash.substring(1); 13 | lines = source[0].getElementsByTagName('li'); 14 | totalLines = lines.length; 15 | 16 | for (; i < totalLines; i++) { 17 | lineNumber++; 18 | lineId = 'line' + lineNumber; 19 | lines[i].id = lineId; 20 | if (lineId === anchorHash) { 21 | lines[i].className += ' selected'; 22 | } 23 | } 24 | } 25 | })(); 26 | -------------------------------------------------------------------------------- /utilities/jsdoc/static/scripts/prettify/lang-css.js: -------------------------------------------------------------------------------- 1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", 2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); 3 | -------------------------------------------------------------------------------- /utilities/jsdoc/static/scripts/search.js: -------------------------------------------------------------------------------- 1 | 2 | (function () { 3 | var nav = document.querySelector("nav"); 4 | var searchBar = nav.querySelector(".search"); 5 | var input = searchBar.querySelector("input"); 6 | // var submit = searchBar.querySelector("button"); 7 | var groups = Array.prototype.slice.call(document.querySelectorAll("nav>ul .parent")).map(function (group) { 8 | var items = Array.prototype.slice.call(group.querySelectorAll("a")); 9 | var strings = items.map(function (a) { 10 | return a.innerText.toLowerCase(); 11 | }); 12 | 13 | return {el: group, items: items, strings, strings}; 14 | }); 15 | input.addEventListener("keyup", function (e) { 16 | var value = input.value.toLowerCase(); 17 | 18 | if (value) { 19 | utils.addClass(nav, "searching"); 20 | } else { 21 | utils.removeClass(nav, "searching"); 22 | return; 23 | } 24 | groups.forEach(function (group) { 25 | var isSearch = false; 26 | var items = group.items; 27 | 28 | group.strings.forEach(function (v, i) { 29 | var item = items[i]; 30 | if (utils.hasClass(item.parentNode, "parent")) { 31 | item = item.parentNode; 32 | } 33 | if (v.indexOf(value) > -1) { 34 | utils.addClass(item, "targeting"); 35 | isSearch = true; 36 | } else { 37 | utils.removeClass(item, "targeting"); 38 | } 39 | }); 40 | if (isSearch) { 41 | utils.addClass(group.el, "module-targeting"); 42 | } else { 43 | utils.removeClass(group.el, "module-targeting"); 44 | } 45 | }); 46 | }); 47 | })(); -------------------------------------------------------------------------------- /utilities/jsdoc/static/scripts/utils.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2018 Daybrush 3 | @name: @daybrush/utils 4 | license: MIT 5 | author: Daybrush 6 | repository: https://github.com/daybrush/utils 7 | @version 0.4.0 8 | */ 9 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.utils=t()}(this,function(){"use strict";var u="rgb",c="rgba",f="hsl",l="hsla",e=[u,c,f,l],t="function",n="object",r="string",i="undefined",a=typeof window!==i,o=["webkit","ms","moz","o"],s=function(e){if(typeof document===i)return"";var t=(document.body||document.documentElement).style,n=o.length;if(typeof t[e]!==i)return e;for(var r=0;rul>li:after { 14 | content: ""; 15 | position: absolute; 16 | right: 10px; 17 | top: 0; 18 | bottom: 0; 19 | width: 0; 20 | height: 0; 21 | margin: auto 0px; 22 | border-top: 7px solid #ccc; 23 | border-left: 6px solid transparent; 24 | border-right: 6px solid transparent; 25 | } 26 | nav li h4, nav li ul { 27 | display: none; 28 | } 29 | 30 | .name.typescript { 31 | background: #374E79; 32 | font-size: 14px; 33 | } 34 | .name.typescript .signature { 35 | color: #21de60; 36 | } 37 | .ts-params.typescript table .last { 38 | display: none; 39 | } 40 | table.params th, table.params tr td , table.params tr td.type{ 41 | word-break: break-word; 42 | white-space: normal; 43 | } 44 | 45 | nav .search { 46 | position: relative; 47 | margin: 0px 10px; 48 | border: 3px solid #333; 49 | height: 43px; 50 | } 51 | nav .search .input-area { 52 | position: absolute; 53 | left: 0; 54 | top: 0; 55 | right: 35px; 56 | height: 35px; 57 | } 58 | nav .search input { 59 | position: relative; 60 | width: 100%; 61 | height: 100%; 62 | border: 0; 63 | padding: 0; 64 | text-indent: 10px; 65 | font-weight: bold; 66 | font-size: 14px; 67 | outline: none; 68 | } 69 | nav .search button { 70 | position: absolute; 71 | top: 0; 72 | right: 0px; 73 | width: 35px; 74 | height: 35px; 75 | border: 0; 76 | padding: 0; 77 | outline: none; 78 | cursor: pointer; 79 | } 80 | nav .search button:before { 81 | position: absolute; 82 | content: ""; 83 | width: 18px; 84 | height: 18px; 85 | top: 7px; 86 | left: 7px; 87 | border: 3px solid #333; 88 | border-radius: 50%; 89 | box-sizing: border-box; 90 | } 91 | nav .search button:after { 92 | position: absolute; 93 | content: ""; 94 | width: 3px; 95 | height: 11px; 96 | top: 21px; 97 | left: 18px; 98 | background: #333; 99 | transform-origin: 50% 0%; 100 | -ms-transform-origin: 50% 0%; 101 | -webkit-transform-origin: 50% 0%; 102 | transform: rotate(-45deg); 103 | -ms-transform: rotate(-45deg); 104 | -webkit-transform: rotate(-45deg); 105 | } 106 | 107 | nav.searching li:after { 108 | display: none!important; 109 | } 110 | nav.searching li h4, nav.searching li ul { 111 | display: block!important; 112 | } 113 | 114 | nav.searching .parent { 115 | display: none; 116 | } 117 | nav.searching .parent ul li a { 118 | display: none; 119 | } 120 | 121 | nav.searching .parent.module-targeting { 122 | display: block; 123 | } 124 | nav.searching .parent.module-targeting ul li a { 125 | display: none; 126 | } 127 | nav.searching .parent.module-targeting ul li a.targeting { 128 | display: block; 129 | } 130 | nav.searching .parent.targeting ul li a { 131 | display: block; 132 | } 133 | 134 | nav>h2.custom>a { 135 | margin:12px 10px; 136 | } -------------------------------------------------------------------------------- /utilities/jsdoc/static/styles/prettify.css: -------------------------------------------------------------------------------- 1 | .pln { 2 | color: #ddd; 3 | } 4 | 5 | /* string content */ 6 | .str { 7 | color: #61ce3c; 8 | } 9 | 10 | /* a keyword */ 11 | .kwd { 12 | color: #fbde2d; 13 | } 14 | 15 | /* a comment */ 16 | .com { 17 | color: #aeaeae; 18 | } 19 | 20 | /* a type name */ 21 | .typ { 22 | color: #8da6ce; 23 | } 24 | 25 | /* a literal value */ 26 | .lit { 27 | color: #fbde2d; 28 | } 29 | 30 | /* punctuation */ 31 | .pun { 32 | color: #ddd; 33 | } 34 | 35 | /* lisp open bracket */ 36 | .opn { 37 | color: #000000; 38 | } 39 | 40 | /* lisp close bracket */ 41 | .clo { 42 | color: #000000; 43 | } 44 | 45 | /* a markup tag name */ 46 | .tag { 47 | color: #8da6ce; 48 | } 49 | 50 | /* a markup attribute name */ 51 | .atn { 52 | color: #fbde2d; 53 | } 54 | 55 | /* a markup attribute value */ 56 | .atv { 57 | color: #ddd; 58 | } 59 | 60 | /* a declaration */ 61 | .dec { 62 | color: #EF5050; 63 | } 64 | 65 | /* a variable name */ 66 | .var { 67 | color: #c82829; 68 | } 69 | 70 | /* a function name */ 71 | .fun { 72 | color: #4271ae; 73 | } 74 | 75 | /* Specify class=linenums on a pre to get line numbering */ 76 | ol.linenums { 77 | margin-top: 0; 78 | margin-bottom: 0; 79 | } 80 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/augments.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |
    8 |
  • 9 |
10 | 11 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/container.tmpl: -------------------------------------------------------------------------------- 1 | 0) return; 7 | ?> 8 | 9 | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 |

26 | 27 | 28 | 29 | 30 | 31 |

32 | 33 |
34 | 35 | 36 | 37 | 38 |
39 | 40 | 41 | 42 |
43 | 44 |
45 |
46 | 47 | 48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 |
61 | 62 | 63 | 64 |

Example 1? 's':'' ?>

65 | 66 | 67 | 68 |
69 | 70 | 71 |

Extends

72 | 73 | 74 | 75 | 76 | 77 |

Requires

78 | 79 |
    80 |
  • 81 |
82 | 83 | 84 | 88 |

Classes

89 | 90 |
91 |
92 |
93 |
94 | 95 | 96 | 100 |

Mixins

101 | 102 |
103 |
104 |
105 |
106 | 107 | 108 | 112 |

Namespaces

113 | 114 |
115 |
116 |
117 |
118 | 119 | 120 | 131 |

Members

132 | 133 | 134 | 135 | 136 | 137 | 138 | 142 |

Methods

143 | 144 | 145 | 146 | 147 | 148 | 149 | 153 |

Type Definitions

154 | 155 | 158 | 159 | 163 | 164 | 167 | 168 | 169 | 173 |

Events

174 | 175 | 176 | 177 | 178 | 179 |
180 | 181 |
182 | 183 | 184 | 185 | 186 | 187 | 206 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/details.tmpl: -------------------------------------------------------------------------------- 1 | " + data.defaultvalue + ""; 13 | defaultObjectClass = ' class="object-value"'; 14 | } 15 | ?> 16 | 17 |
18 | 19 | 20 |
Source:
21 |
  • 22 | , 23 |
24 | 25 | 26 | 27 |
Version:
28 |
29 | 30 | 31 | 32 |
Since:
33 |
34 | 35 | 36 | 37 |
Inherited From:
38 |
  • 39 | 40 |
41 | 42 | 43 | 44 |
Overrides:
45 |
  • 46 | 47 |
48 | 49 | 50 | 51 |
Implementations:
52 |
    53 | 54 |
  • 55 | 56 |
57 | 58 | 59 | 60 |
Implements:
61 |
    62 | 63 |
  • 64 | 65 |
66 | 67 | 68 | 69 |
Mixes In:
70 | 71 |
    72 | 73 |
  • 74 | 75 |
76 | 77 | 78 | 79 |
Deprecated:
  • Yes
83 | 84 | 85 | 86 |
Author:
87 |
88 |
    89 |
  • 90 |
91 |
92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |
License:
101 |
102 | 103 | 104 | 105 |
Default Value:
106 |
    107 | > 108 |
109 | 110 | 111 | 112 |
Tutorials:
113 |
114 |
    115 |
  • 116 |
117 |
118 | 119 | 120 | 121 |
See:
122 |
123 |
    124 |
  • 125 |
126 |
127 | 128 | 129 | 130 |
To Do:
131 |
132 |
    133 |
  • 134 |
135 |
136 | 137 |
138 | 139 | 143 | 144 |
Properties:
145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/example.tmpl: -------------------------------------------------------------------------------- 1 | 2 |
3 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/examples.tmpl: -------------------------------------------------------------------------------- 1 | 8 |

9 | 10 |
11 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/exceptions.tmpl: -------------------------------------------------------------------------------- 1 | 4 | 5 |
6 |
7 |
8 | 9 |
10 |
11 |
12 |
13 |
14 |
15 | Type 16 |
17 |
18 | 19 |
20 |
21 |
22 |
23 |
24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/layout.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | <?js= title ?> - Documentation 6 | 7 | 8 | 9 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 32 | 33 |
34 | 35 |

36 | 37 | 38 | 39 |
40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/mainpage.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |
8 |
9 |
10 | 11 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/members.tmpl: -------------------------------------------------------------------------------- 1 | 5 |

6 | 7 | 8 |

9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 |
17 | 18 | 19 | 20 |
Type:
21 |
    22 |
  • 23 | 24 |
  • 25 |
26 | 27 | 28 | 29 |
Fires:
30 |
    31 |
  • 32 |
33 | 34 | 35 | 36 |
Example 1? 's':'' ?>
37 | 38 | 39 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/method.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 |

Constructor

8 | 9 | 10 |

12 | 13 | 14 |

15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 |
24 | 25 | 26 | 27 |
Extends:
28 | 29 | 30 | 31 | 32 |
Type:
33 |
    34 |
  • 35 | 36 |
  • 37 |
38 | 39 | 40 | 41 |
This:
42 |
43 | 44 | 45 | 46 | 47 | 48 | 49 | 56 |

57 | () 58 | → {} 59 |

60 |
61 | 62 |
63 | 67 | 68 | 69 |
Example 1? 's':'' ?>
70 | 71 | 72 | 73 | 74 | 75 |
Requires:
76 |
    77 |
  • 78 |
79 | 80 | 81 | 82 |
Fires:
83 |
    84 |
  • 85 |
86 | 87 | 88 | 89 |
Listens to Events:
90 |
    91 |
  • 92 |
93 | 94 | 95 | 96 |
Listeners of This Event:
97 |
    98 |
  • 99 |
100 | 101 | 102 | 103 |
Throws:
104 | 1) { ?>
    106 |
  • 107 |
110 | 111 | 113 | 114 | 115 |
Returns:
116 | 1) { ?>
    118 |
  • 119 |
122 | 123 | 125 | 126 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/params.tmpl: -------------------------------------------------------------------------------- 1 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 91 | 92 | 93 | 103 | 104 | 105 | 106 | 111 | 112 | 113 | 117 | 118 | 119 | 120 | 121 |
NameTypeAttributesDefaultDescription
? 87 | 88 | 89 | 90 | 94 | 95 | 96 | <nullable>
97 | 98 | 99 | 100 | <repeatable>
101 | 102 |
107 | 108 | 109 | 110 | 114 |
Properties
115 | 116 |
122 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/properties.tmpl: -------------------------------------------------------------------------------- 1 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 87 | 88 | 89 | 90 | 95 | 96 | 97 | 100 | 101 | 102 | 103 | 104 |
NameTypeAttributesDefaultDescription
? 76 | 77 | 78 | 79 | 83 | 84 | <nullable>
85 | 86 |
91 | 92 | 93 | 94 | 98 |
Properties
99 |
105 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/returns.tmpl: -------------------------------------------------------------------------------- 1 | 5 |
6 | 7 |
8 | 9 | 10 | 11 |
12 |
13 | Type 14 |
15 |
16 | 17 |
18 |
19 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/source.tmpl: -------------------------------------------------------------------------------- 1 | 4 |
5 |
6 |
7 |
8 |
-------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/tutorial.tmpl: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 0) { ?> 5 |
    8 |
  • 9 |
10 | 11 | 12 |

13 |
14 | 15 |
16 | 17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /utilities/jsdoc/tmpl/type.tmpl: -------------------------------------------------------------------------------- 1 | 5 | 6 | | 7 | -------------------------------------------------------------------------------- /utilities/loaders/react/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /utilities/loaders/react/assets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | min-height: 100vh; 3 | text-align: center; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | font-size: calc(10px + 2vmin); 9 | overflow: hidden; 10 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 11 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 12 | sans-serif; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | background-color: #252525; 16 | } 17 | 18 | .app-logo { 19 | height: 48vmin; 20 | pointer-events: none; 21 | animation-name: rotate; 22 | animation-duration: 15s; 23 | animation-iteration-count: infinite; 24 | animation-timing-function: linear; 25 | } 26 | 27 | .loading-header { 28 | margin-top: -10px; 29 | color: #6adefc; 30 | } 31 | 32 | @keyframes rotate { 33 | from { 34 | -webkit-transform: rotate(0deg); 35 | } 36 | to { 37 | -webkit-transform: rotate(360deg); 38 | } 39 | } -------------------------------------------------------------------------------- /utilities/loaders/react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Loading Screen 6 | 7 | 8 | 9 | 10 |

Starting React
Development Server

11 | 12 | 13 | -------------------------------------------------------------------------------- /utilities/loaders/redux/assets/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /utilities/loaders/redux/assets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | min-height: 100vh; 3 | text-align: center; 4 | display: flex; 5 | flex-direction: column; 6 | justify-content: center; 7 | align-items: center; 8 | font-size: calc(10px + 2vmin); 9 | overflow: hidden; 10 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 11 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 12 | sans-serif; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | } 16 | 17 | .app-logo { 18 | height: 40vmin; 19 | pointer-events: none; 20 | } 21 | 22 | .loading-header { 23 | color: rgb(112, 76, 182); 24 | } 25 | 26 | @media (prefers-reduced-motion: no-preference) { 27 | .app-logo { 28 | animation: app-logo-float infinite 3s ease-in-out; 29 | } 30 | } 31 | 32 | @keyframes app-logo-float { 33 | 0% { 34 | transform: translateY(0); 35 | } 36 | 50% { 37 | transform: translateY(10px) 38 | } 39 | 100% { 40 | transform: translateY(0px) 41 | } 42 | } -------------------------------------------------------------------------------- /utilities/loaders/redux/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Loading Screen 6 | 7 | 8 | 9 | 10 |

Starting React
Development Server

11 | 12 | 13 | -------------------------------------------------------------------------------- /utilities/msi/images/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/msi/images/background.png -------------------------------------------------------------------------------- /utilities/msi/images/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/msi/images/banner.png -------------------------------------------------------------------------------- /utilities/msi/images/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/iPzard/electron-react-python-template/c78c0d0578bf6e6b0c96564fe7291ca6871d29ae/utilities/msi/images/icon.ico --------------------------------------------------------------------------------