├── .babelrc
├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── stale.yml
├── .gitignore
├── FUNDING.yml
├── LICENSE
├── README.md
├── app.py
├── docs
├── App.html
├── BrowserWindow.html
├── Builder.html
├── Cleaner.html
├── Dispatcher.html
├── Footer.html
├── MainPage.LoadingScreen.html
├── Navigation.html
├── Notice.html
├── Packager.html
├── Pages.MainPage.html
├── Pages.SettingsPage.html
├── Requests.html
├── Services.html
├── Settings.html
├── Starter.html
├── Themes.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_App.js.html
├── src_components_dialog_Notice.js.html
├── src_components_footer_Footer.js.html
├── src_components_navigation_Navigation.js.html
├── src_components_pages_main_InputField.js.html
├── src_components_pages_main_LoadingScreen.js.html
├── src_components_pages_main_MainPage.js.html
├── src_components_pages_settings_LanguageSettings.js.html
├── src_components_pages_settings_SettingsPage.js.html
├── src_components_pages_settings_util_supportedLanguages.js.html
├── src_components_titlebar_Favicon.js.html
├── src_components_titlebar_Titlebar.js.html
├── src_components_titlebar_TitlebarButtons.js.html
├── src_theme_palettes.js.html
├── src_utils_requests.js.html
├── src_utils_services.js.html
├── src_utils_settings.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
├── manifest.json
└── robots.txt
├── renderer.js
├── requirements.txt
├── resources
├── __init__.py
├── ffmpeg
│ ├── LICENSE
│ ├── README.txt
│ ├── ffmpeg.exe
│ ├── ffprobe.exe
│ └── presets
│ │ ├── libvpx-1080p.ffpreset
│ │ ├── libvpx-1080p50_60.ffpreset
│ │ ├── libvpx-360p.ffpreset
│ │ ├── libvpx-720p.ffpreset
│ │ └── libvpx-720p50_60.ffpreset
├── mkvtoolnix
│ ├── LICENSE
│ ├── README.md
│ ├── mkvmerge.exe
│ └── source.zip
└── modules
│ ├── filewalker.py
│ └── mkvtoolnix.py
├── scripts
├── build.js
├── clean.js
├── dispatch.js
├── package.js
└── start.js
├── src
├── components
│ ├── App.js
│ ├── App.module.scss
│ ├── dialog
│ │ └── Notice.js
│ ├── footer
│ │ ├── Footer.js
│ │ └── assets
│ │ │ └── styles
│ │ │ └── Footer.module.scss
│ ├── navigation
│ │ ├── Navigation.js
│ │ └── assets
│ │ │ ├── icons
│ │ │ ├── FoldersIcon.js
│ │ │ ├── SettingsIcon.js
│ │ │ └── ThemeIcon.js
│ │ │ └── styles
│ │ │ └── Navigation.module.scss
│ ├── pages
│ │ ├── main
│ │ │ ├── InputField.js
│ │ │ ├── LoadingScreen.js
│ │ │ ├── MainPage.js
│ │ │ └── assets
│ │ │ │ ├── icons
│ │ │ │ └── Spinner.js
│ │ │ │ └── styles
│ │ │ │ ├── InputField.module.scss
│ │ │ │ ├── LoadingScreen.module.scss
│ │ │ │ └── MainPage.module.scss
│ │ └── settings
│ │ │ ├── LanguageSettings.js
│ │ │ ├── SettingsPage.js
│ │ │ ├── assets
│ │ │ └── styles
│ │ │ │ └── SettingsPage.module.scss
│ │ │ └── util
│ │ │ └── supportedLanguages.js
│ └── titlebar
│ │ ├── Favicon.js
│ │ ├── Titlebar.js
│ │ ├── TitlebarButtons.js
│ │ └── scss
│ │ ├── Titlebar.module.scss
│ │ └── TitlebarButtons.module.scss
├── index.js
├── index.scss
├── logo.svg
├── serviceWorker.js
├── tests
│ ├── App.test.js
│ └── setupTests.js
├── theme
│ ├── overrides.scss
│ ├── palettes.js
│ └── variables.scss
└── utils
│ ├── requests.js
│ ├── services.js
│ └── settings.js
├── utilities
├── 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 | [
6 | "minify", {
7 | "builtIns": false
8 | }
9 | ]
10 | ],
11 | "plugins": [
12 | "@babel/plugin-proposal-async-generator-functions",
13 | "@babel/plugin-proposal-class-properties",
14 | "@babel/plugin-proposal-object-rest-spread",
15 | "@babel/plugin-transform-arrow-functions",
16 | "@babel/plugin-transform-async-to-generator",
17 | "@babel/plugin-transform-classes",
18 | "@babel/plugin-transform-computed-properties",
19 | "@babel/plugin-transform-destructuring",
20 | "@babel/plugin-transform-for-of",
21 | "@babel/plugin-transform-parameters",
22 | "@babel/plugin-transform-shorthand-properties",
23 | "@babel/plugin-transform-spread",
24 | "@babel/plugin-transform-sticky-regex",
25 | "@babel/plugin-transform-template-literals"
26 | ]
27 | }
--------------------------------------------------------------------------------
/.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': ['warn'],
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-nested-ternary': [0],
53 | 'no-param-reassign': [0],
54 | 'no-mixed-spaces-and-tabs': ['warn'],
55 | 'no-multi-spaces': ['warn'],
56 | 'no-multiple-empty-lines': [0],
57 | 'no-restricted-syntax': [0],
58 | 'no-tabs': ['warn'],
59 | 'no-trailing-spaces': ['warn'],
60 | 'no-unneeded-ternary': ['warn'],
61 | 'no-underscore-dangle': ['warn'],
62 | 'no-unused-expressions': [0],
63 | 'no-unused-vars': ['warn'],
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 | 'quotes': ['warn'],
90 | 'quote-props': ['warn', 'consistent'],
91 | 'rest-spread-spacing': ['warn', 'never'],
92 | 'semi': ['warn'],
93 | 'spaced-comment': ['warn'],
94 | 'space-before-function-paren': ['warn'],
95 | 'react/destructuring-assignment': [0],
96 | 'react/forbid-prop-types': [0],
97 | 'react/jsx-closing-bracket-location': ['warn'],
98 | 'react/jsx-curly-newline': ['warn'],
99 | 'react/jsx-curly-spacing': ['warn', 'always'],
100 | 'react/jsx-filename-extension': [0],
101 | 'react/jsx-fragments': [0],
102 | 'react/jsx-indent': ['warn', 2],
103 | 'react/jsx-equals-spacing': ['warn'],
104 | 'react/jsx-one-expression-per-line': ['warn'],
105 | 'react/jsx-props-no-spreading': [0],
106 | 'react/jsx-tag-spacing': ['warn'],
107 | 'react/jsx-wrap-multilines': ['warn'],
108 | 'react/no-access-state-in-setstate': [0],
109 | 'react/no-array-index-key': [0],
110 | 'react/no-unused-state': ['warn'],
111 | 'react/prop-types': ['warn'],
112 | 'react/prefer-stateless-function': ['warn'],
113 | 'react/require-default-props': ['warn'],
114 | 'react/sort-comp': [0],
115 | 'react/state-in-constructor': ['warn', 'never']
116 | },
117 | settings: {
118 | 'import/resolver': {
119 | node: {
120 | paths: ['./', 'src']
121 | }
122 | }
123 | }
124 | };
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.exe filter=lfs diff=lfs merge=lfs -text
2 | resources/ffmpeg/ffprobe.exe filter=lfs diff=lfs merge=lfs -text
3 | resources/ffmpeg/ffmerge.exe filter=lfs diff=lfs merge=lfs -text
4 |
--------------------------------------------------------------------------------
/.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 | - preserved 💾
9 | - security
10 | # Label to use when marking an issue as stale
11 | staleLabel: wontfix
12 | # Comment to post when marking an issue as stale. Set to `false` to disable
13 | markComment: >
14 | This issue has been automatically marked as stale because it has not had
15 | recent activity. It will be closed if no further activity occurs. Thank you
16 | for your contributions.
17 | # Comment to post when closing a stale issue. Set to `false` to disable
18 | 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 | app.debug.spec
7 | __pycache__
8 |
9 | # debug
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 |
14 | # dependencies
15 | /node_modules
16 | /.pnp
17 | .pnp.js
18 |
19 | # testing
20 | /coverage
21 |
22 | # production
23 | /build
24 | /dist
25 | app/
26 |
27 | # resources
28 | resources/app/
29 | resources/app.debug/
30 | *.pyo
31 |
32 | # misc
33 | .DS_Store
34 | .env.local
35 | .env.development.local
36 | .env.test.local
37 | .env.production.local
38 |
--------------------------------------------------------------------------------
/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # repo: your_github_handle/.github
2 | # filename: FUNDING.YML
3 |
4 | github: iPzard
--------------------------------------------------------------------------------
/docs/App.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | App - 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 |
App
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | App
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 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 | - Controls global state and page navigation
105 |
106 |
107 |
108 |
109 |
110 |
111 |
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 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
--------------------------------------------------------------------------------
/docs/scripts/custom.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/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/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 the following files and folders:
56 | * docs, node_modules, yarn.lock, and package-lock.json.
57 | */
58 | class Cleaner {
59 |
60 | removePath = (pathToRemove) => {
61 | if (existsSync(pathToRemove)) {
62 | // eslint-disable-next-line no-console
63 | console.log(`Removing: ${pathToRemove}`);
64 | if (statSync(pathToRemove).isFile()) unlinkSync(pathToRemove);
65 |
66 | else {
67 | const files = readdirSync(pathToRemove);
68 |
69 | files.forEach((file) => {
70 | const filePath = `${pathToRemove}/${file}`;
71 |
72 | if (statSync(filePath).isDirectory()) this.removePath(filePath);
73 | else unlinkSync(filePath);
74 | });
75 | rmdirSync(pathToRemove);
76 | }
77 | }
78 | };
79 | }
80 |
81 | module.exports.Cleaner = Cleaner;
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/docs/styles/custom.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/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 | "browserslist": {
4 | "production": [
5 | ">0.2%",
6 | "not dead",
7 | "not op_mini all"
8 | ],
9 | "development": [
10 | "last 1 chrome version",
11 | "last 1 firefox version",
12 | "last 1 safari version"
13 | ]
14 | },
15 | "build": {
16 | "extraResources": [
17 | "./resources/app",
18 | "./resources/app.debug",
19 | "./resources/mkvtoolnix",
20 | "./resources/modules",
21 | "./resources/__init__.py"
22 | ]
23 | },
24 | "dependencies": {
25 | "axios": "0.21.1",
26 | "electron-is-dev": "1.2.0",
27 | "get-port": "5.1.1",
28 | "socket.io-client": "2.3.1"
29 | },
30 | "description": "MKVToolNix batch processing tool",
31 | "devDependencies": {
32 | "@fluentui/react": "7.160.1",
33 | "@testing-library/jest-dom": "4.2.4",
34 | "@testing-library/react": "9.3.2",
35 | "@testing-library/user-event": "7.1.2",
36 | "babel-eslint": "10.1.0",
37 | "cross-env": "7.0.3",
38 | "electron": "10.1.3",
39 | "electron-installer-dmg": "3.0.0",
40 | "electron-packager": "15.0.0",
41 | "electron-wix-msi": "5.0.0",
42 | "eslint-config-airbnb": "18.2.1",
43 | "eslint-plugin-import": "2.23.4",
44 | "eslint-plugin-jsx-a11y": "6.4.1",
45 | "eslint-plugin-react": "7.24.0",
46 | "eslint-plugin-standard": "5.0.0",
47 | "exe-icon-extractor": "1.0.8",
48 | "jsdoc": "3.6.5",
49 | "prop-types": "15.7.2",
50 | "react": "16.13.1",
51 | "react-dom": "16.13.1",
52 | "react-scripts": "3.4.1",
53 | "sass": "1.26.5"
54 | },
55 | "eslintConfig": {
56 | "extends": "react-app"
57 | },
58 | "homepage": "./",
59 | "license": "MIT",
60 | "main": "main.js",
61 | "name": "mkvtoolnix-batch-tool",
62 | "private": true,
63 | "productName": "MKVToolNix Batch Tool",
64 | "scripts": {
65 | "build": "node ./scripts/dispatch build all",
66 | "build:all": "node ./scripts/dispatch build all",
67 | "build:react": "node ./scripts/dispatch build react",
68 | "build:python": "node ./scripts/dispatch build python",
69 | "build:docs": "jsdoc -c jsdoc.json",
70 | "build:package:mac": "node ./scripts/dispatch package mac",
71 | "build:package:windows": "node ./scripts/dispatch package windows",
72 | "clean": "node ./scripts/dispatch clean",
73 | "eject": "react-scripts eject",
74 | "start": "node ./scripts/dispatch start",
75 | "start:electron": "electron .",
76 | "start:react": "react-scripts start",
77 | "test": "react-scripts test"
78 | },
79 | "version": "2.5.4"
80 | }
81 |
--------------------------------------------------------------------------------
/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/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/public/favicon.ico
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
17 |
18 |
27 | MKVToolNix Batch Tool
28 |
29 |
30 |
31 |
32 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "MKVToolNix Batch tool",
3 | "name": "MKVToolNix Batch tool",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#bf7e45",
14 | "background_color": "#252525"
15 | }
16 |
--------------------------------------------------------------------------------
/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 | chardet==4.0.0
2 | ffmpeg-python==0.2.0
3 | Flask==2.0.1
4 | Flask-Cors==3.0.10
5 | Flask-SocketIO==3.1.2
6 | python-socketio==2.1.2
7 | jsonify==0.5
8 | langdetect==1.16.0
9 | pyinstaller==4.3
10 | python-engineio==3.1.0
11 |
--------------------------------------------------------------------------------
/resources/__init__.py:
--------------------------------------------------------------------------------
1 | from .modules import filewalker
2 | from .modules import mkvtoolnix
--------------------------------------------------------------------------------
/resources/ffmpeg/README.txt:
--------------------------------------------------------------------------------
1 | FFmpeg 64-bit static Windows build from www.gyan.dev
2 |
3 | Version: 2021-05-16-git-f53414a038-full_build-www.gyan.dev
4 |
5 | License: GPL v3
6 |
7 | Source Code: https://github.com/FFmpeg/FFmpeg/commit/f53414a038
8 |
9 | git-full build configuration:
10 |
11 | --enable-gpl
12 | --enable-version3
13 | --enable-static
14 | --disable-w32threads
15 | --disable-autodetect
16 | --enable-fontconfig
17 | --enable-iconv
18 | --enable-gnutls
19 | --enable-libxml2
20 | --enable-gmp
21 | --enable-lzma
22 | --enable-libsnappy
23 | --enable-zlib
24 | --enable-librist
25 | --enable-libsrt
26 | --enable-libssh
27 | --enable-libzmq
28 | --enable-avisynth
29 | --enable-libbluray
30 | --enable-libcaca
31 | --enable-sdl2
32 | --enable-libdav1d
33 | --enable-libzvbi
34 | --enable-librav1e
35 | --enable-libsvtav1
36 | --enable-libwebp
37 | --enable-libx264
38 | --enable-libx265
39 | --enable-libxvid
40 | --enable-libaom
41 | --enable-libopenjpeg
42 | --enable-libvpx
43 | --enable-libass
44 | --enable-frei0r
45 | --enable-libfreetype
46 | --enable-libfribidi
47 | --enable-libvidstab
48 | --enable-libvmaf
49 | --enable-libzimg
50 | --enable-amf
51 | --enable-cuda-llvm
52 | --enable-cuvid
53 | --enable-ffnvcodec
54 | --enable-nvdec
55 | --enable-nvenc
56 | --enable-d3d11va
57 | --enable-dxva2
58 | --enable-libmfx
59 | --enable-libglslang
60 | --enable-vulkan
61 | --enable-opencl
62 | --enable-libcdio
63 | --enable-libgme
64 | --enable-libmodplug
65 | --enable-libopenmpt
66 | --enable-libopencore-amrwb
67 | --enable-libmp3lame
68 | --enable-libshine
69 | --enable-libtheora
70 | --enable-libtwolame
71 | --enable-libvo-amrwbenc
72 | --enable-libilbc
73 | --enable-libgsm
74 | --enable-libopencore-amrnb
75 | --enable-libopus
76 | --enable-libspeex
77 | --enable-libvorbis
78 | --enable-ladspa
79 | --enable-libbs2b
80 | --enable-libflite
81 | --enable-libmysofa
82 | --enable-librubberband
83 | --enable-libsoxr
84 | --enable-chromaprint
85 |
86 |
--------------------------------------------------------------------------------
/resources/ffmpeg/ffmpeg.exe:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:3e5420a8efef8cf92c65961e646893d6b6c370f11c1d172b0b3535ee1ceb53fb
3 | size 112782336
4 |
--------------------------------------------------------------------------------
/resources/ffmpeg/ffprobe.exe:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:8cd5a20b7e150380e29417e9d39ad221a6804d68245db38d8ebd7013edbfda83
3 | size 112684544
4 |
--------------------------------------------------------------------------------
/resources/ffmpeg/presets/libvpx-1080p.ffpreset:
--------------------------------------------------------------------------------
1 | vcodec=libvpx
2 |
3 | g=120
4 | lag-in-frames=16
5 | deadline=good
6 | cpu-used=0
7 | vprofile=1
8 | qmax=51
9 | qmin=11
10 | slices=4
11 | b=2M
12 |
13 | #ignored unless using -pass 2
14 | maxrate=24M
15 | minrate=100k
16 | auto-alt-ref=1
17 | arnr-maxframes=7
18 | arnr-strength=5
19 | arnr-type=centered
20 |
--------------------------------------------------------------------------------
/resources/ffmpeg/presets/libvpx-1080p50_60.ffpreset:
--------------------------------------------------------------------------------
1 | vcodec=libvpx
2 |
3 | g=120
4 | lag-in-frames=25
5 | deadline=good
6 | cpu-used=0
7 | vprofile=1
8 | qmax=51
9 | qmin=11
10 | slices=4
11 | b=2M
12 |
13 | #ignored unless using -pass 2
14 | maxrate=24M
15 | minrate=100k
16 | auto-alt-ref=1
17 | arnr-maxframes=7
18 | arnr-strength=5
19 | arnr-type=centered
20 |
--------------------------------------------------------------------------------
/resources/ffmpeg/presets/libvpx-360p.ffpreset:
--------------------------------------------------------------------------------
1 | vcodec=libvpx
2 |
3 | g=120
4 | lag-in-frames=16
5 | deadline=good
6 | cpu-used=0
7 | vprofile=0
8 | qmax=63
9 | qmin=0
10 | b=768k
11 |
12 | #ignored unless using -pass 2
13 | maxrate=1.5M
14 | minrate=40k
15 | auto-alt-ref=1
16 | arnr-maxframes=7
17 | arnr-strength=5
18 | arnr-type=centered
19 |
--------------------------------------------------------------------------------
/resources/ffmpeg/presets/libvpx-720p.ffpreset:
--------------------------------------------------------------------------------
1 | vcodec=libvpx
2 |
3 | g=120
4 | lag-in-frames=16
5 | deadline=good
6 | cpu-used=0
7 | vprofile=0
8 | qmax=51
9 | qmin=11
10 | slices=4
11 | b=2M
12 |
13 | #ignored unless using -pass 2
14 | maxrate=24M
15 | minrate=100k
16 | auto-alt-ref=1
17 | arnr-maxframes=7
18 | arnr-strength=5
19 | arnr-type=centered
20 |
--------------------------------------------------------------------------------
/resources/ffmpeg/presets/libvpx-720p50_60.ffpreset:
--------------------------------------------------------------------------------
1 | vcodec=libvpx
2 |
3 | g=120
4 | lag-in-frames=25
5 | deadline=good
6 | cpu-used=0
7 | vprofile=0
8 | qmax=51
9 | qmin=11
10 | slices=4
11 | b=2M
12 |
13 | #ignored unless using -pass 2
14 | maxrate=24M
15 | minrate=100k
16 | auto-alt-ref=1
17 | arnr-maxframes=7
18 | arnr-strength=5
19 | arnr-type=centered
20 |
--------------------------------------------------------------------------------
/resources/mkvtoolnix/mkvmerge.exe:
--------------------------------------------------------------------------------
1 | version https://git-lfs.github.com/spec/v1
2 | oid sha256:850373a68c1189a9345a2312b02acfdd574265f1bcc43d31ac855f6e35255c0f
3 | size 17450504
4 |
--------------------------------------------------------------------------------
/resources/mkvtoolnix/source.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/resources/mkvtoolnix/source.zip
--------------------------------------------------------------------------------
/scripts/build.js:
--------------------------------------------------------------------------------
1 | const { spawnSync } = require('child_process');
2 |
3 | const spawnOptions = { detached: false, shell: true, stdio: 'inherit' };
4 |
5 | /**
6 | * @namespace Builder
7 | * @description - Builds React & Python builds of project so Electron can be used.
8 | */
9 |
10 | class Builder {
11 |
12 | /**
13 | * @description - Creates React and Python production builds.
14 | * @memberof Builder
15 | */
16 | buildAll = () => {
17 | const { buildPython, buildReact } = this;
18 |
19 | buildPython();
20 | buildReact();
21 | }
22 |
23 | /**
24 | * @description - Creates production build of Python back end.
25 | * @memberof Builder
26 | */
27 | buildPython = () => {
28 | // eslint-disable-next-line no-console
29 | console.log('Creating Python distribution files...');
30 |
31 | const app = 'app.py';
32 | const icon = './public/favicon.ico';
33 |
34 | // PyInstaller default options
35 | const pyInstallerOptions = [
36 | '--noconfirm', // Don't confirm overwrite
37 | '--distpath=./resources', // Output path
38 | `--icon=${icon}`, // Icon to use for app
39 | '--collect-datas=langdetect' // modules
40 | ];
41 |
42 | // Options for app file with hidden console
43 | const productionOptions = [
44 | ...pyInstallerOptions,
45 | '--noconsole' // Hides console output
46 | ];
47 |
48 | // Options for app file with console shown
49 | const debugOptions = [
50 | ...pyInstallerOptions,
51 | '--name=app.debug' // Custom name for debug app
52 | ];
53 |
54 | // Create production and debug versions of app
55 | spawnSync('pyinstaller', [...productionOptions, app], spawnOptions);
56 | spawnSync('pyinstaller', [...debugOptions, app], spawnOptions);
57 | }
58 |
59 | /**
60 | * @description - Creates production build of React front end.
61 | * @memberof Builder
62 | */
63 | buildReact = () => {
64 | // eslint-disable-next-line no-console
65 | console.log('Creating React distribution files...');
66 |
67 | // Set the GENERATE_SOURCEMAP environment variable to false
68 | process.env.GENERATE_SOURCEMAP = 'false';
69 |
70 | spawnSync('react-scripts build', spawnOptions);
71 | }
72 | }
73 |
74 | module.exports.Builder = Builder;
75 |
--------------------------------------------------------------------------------
/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 the following files and folders:
12 | * docs, node_modules, yarn.lock, and package-lock.json.
13 | */
14 | class Cleaner {
15 |
16 | removePath = (pathToRemove) => {
17 | if (existsSync(pathToRemove)) {
18 | // eslint-disable-next-line no-console
19 | console.log(`Removing: ${pathToRemove}`);
20 | if (statSync(pathToRemove).isFile()) unlinkSync(pathToRemove);
21 |
22 | else {
23 | const files = readdirSync(pathToRemove);
24 |
25 | files.forEach((file) => {
26 | const filePath = `${pathToRemove}/${file}`;
27 |
28 | if (statSync(filePath).isDirectory()) this.removePath(filePath);
29 | else unlinkSync(filePath);
30 | });
31 | rmdirSync(pathToRemove);
32 | }
33 | }
34 | };
35 | }
36 |
37 | module.exports.Cleaner = Cleaner;
38 |
--------------------------------------------------------------------------------
/scripts/dispatch.js:
--------------------------------------------------------------------------------
1 | const [ , , script, command ] = process.argv;
2 | const { Builder } = require('./build');
3 | const { Cleaner } = require('./clean');
4 | const { Packager } = require('./package');
5 | const { Starter } = require('./start');
6 |
7 |
8 |
9 | /**
10 | * @namespace Dispatcher
11 | * @description - Dispatches script commands to various scripts.
12 | * @argument script - Script manager to use (e.g., build or package).
13 | * @argument command - Command argument describing exact script to run.
14 | */
15 |
16 | switch (script) {
17 | case 'build':
18 | return buildApp();
19 |
20 | case 'clean':
21 | return cleanProject();
22 |
23 | case 'package':
24 | return packageApp();
25 |
26 | case 'start':
27 | return startDeveloperMode();
28 |
29 | // no default
30 | }
31 |
32 | /**
33 | * @description - Builds various production builds (e.g., Python, React).
34 | * @memberof Dispatcher
35 | */
36 | function buildApp() {
37 | const builder = new Builder();
38 |
39 | switch (command) {
40 | case 'react':
41 | return builder.buildReact();
42 |
43 | case 'python':
44 | return builder.buildPython();
45 |
46 | case 'all':
47 | return builder.buildAll();
48 |
49 | // no default
50 | }
51 | }
52 |
53 | /**
54 | * @description - Cleans project by removing various files and folders.
55 | * @memberof Dispatcher
56 | */
57 | function cleanProject() {
58 | const cleaner = new Cleaner();
59 | const getPath = (...path) => path.join(__dirname, '..', ...path);
60 |
61 | // Files to remove during cleaning
62 | [
63 | // Cache
64 | getPath('app.pyc'),
65 | getPath('app.spec'),
66 | getPath('app.debug.spec'),
67 | getPath('__pycache__'),
68 |
69 | // Debug
70 | getPath('npm-debug.log'),
71 | getPath('yarn-debug.log'),
72 | getPath('yarn-error.log'),
73 |
74 | // Dependencies
75 | getPath('.pnp'),
76 | getPath('.pnp.js'),
77 | getPath('node_modules'),
78 | getPath('package-lock.json'),
79 | getPath('yarn.lock'),
80 |
81 | // Testing
82 | getPath('coverage'),
83 |
84 | // Production
85 | getPath('build'),
86 | getPath('dist'),
87 | getPath('docs'),
88 |
89 | // Misc
90 | getPath('.DS_Store')
91 | ]
92 | // Iterate and remove process
93 | .forEach(cleaner.removePath);
94 | // eslint-disable-next-line no-console
95 | console.log('Project is clean.');
96 | }
97 |
98 | /**
99 | * @description - Builds various installers (e.g., DMG, MSI).
100 | * @memberof Dispatcher
101 | */
102 | function packageApp() {
103 | const packager = new Packager();
104 |
105 | switch (command) {
106 | case 'windows':
107 | return packager.packageWindows();
108 |
109 | case 'mac':
110 | return packager.packageMacOS();
111 |
112 | // no default
113 | }
114 | }
115 |
116 | /**
117 | * @description - Starts developer mode of app.
118 | * Including; React, Electron, and Python/Flask.
119 | * @memberof Dispatcher
120 | */
121 | function startDeveloperMode() {
122 | const start = new Starter();
123 | start.developerMode();
124 | }
125 |
--------------------------------------------------------------------------------
/scripts/package.js:
--------------------------------------------------------------------------------
1 | const { spawnSync } = require('child_process');
2 | const { Builder } = require('./build');
3 |
4 | const builder = new Builder();
5 | const spawnOptions = { detached: false, shell: true, stdio: 'inherit' };
6 |
7 | // Define input and output directories
8 | const path = (directory) => {
9 | return require('path').resolve(__dirname, directory);
10 | };
11 |
12 | /**
13 | * @namespace Packager
14 | * @description - Packages app for various operating systems.
15 | */
16 | class Packager {
17 |
18 | /**
19 | * @description - Creates DMG installer for macOS.
20 | * @memberof Packager
21 | */
22 | packageMacOS = () => {
23 |
24 | // Build Python & React distribution files
25 | builder.buildAll();
26 |
27 | const options = {
28 | build: [
29 | 'app',
30 | '--asar',
31 | '--extra-resource=./resources/app',
32 | '--extra-resource=./resources/app.debug',
33 | '--icon ./public/favicon.ico',
34 | '--darwin',
35 | '--out',
36 | './dist/mac',
37 | '--overwrite'
38 | ].join(' '),
39 |
40 | package: [
41 | path('../dist/mac/app-darwin-x64/app.app'),
42 | 'Example',
43 | `--out=${path('../dist/mac/setup')}`,
44 | `--icon=${path('../utilities/dmg/images/icon.icns')}`,
45 | // `--background=${path('../utilities/dmg/images/background.png')}`,
46 | '--title="Example App"',
47 | '--overwrite'
48 | ].join(' '),
49 |
50 | spawn: spawnOptions
51 | };
52 |
53 | spawnSync(`electron-packager . ${options.build}`, options.spawn);
54 | spawnSync(`electron-installer-dmg ${options.package}`, options.spawn);
55 | };
56 |
57 |
58 | /**
59 | * @description - Creates MSI installer for Windows.
60 | * @memberof Packager
61 | */
62 | packageWindows = () => {
63 | // eslint-disable-next-line no-console
64 | console.log('Building windows package...');
65 |
66 | // Build Python & React distribution files
67 | builder.buildAll();
68 |
69 | const options = {
70 | app: [
71 | 'app',
72 | '--asar',
73 | '--extra-resource=./resources/app',
74 | '--extra-resource=./resources/app.debug',
75 | '--extra-resource=./resources/mkvtoolnix/mkvmerge.exe',
76 | '--extra-resource=./resources/ffmpeg/ffmpeg.exe',
77 | '--extra-resource=./resources/ffmpeg/ffprobe.exe',
78 | '--extra-resource=./resources/modules',
79 | '--extra-resource=./resources/__init__.py',
80 | '--icon ./public/favicon.ico',
81 | '--win32',
82 | '--out',
83 | './dist/windows',
84 | '--overwrite',
85 | '--debug'
86 | ].join(' '),
87 |
88 | spawn: spawnOptions
89 | };
90 |
91 | spawnSync(`electron-packager . ${options.app}`, options.spawn);
92 |
93 | const { MSICreator } = require('electron-wix-msi');
94 |
95 | const msiCreator = new MSICreator({
96 | appDirectory: path('../dist/windows/app-win32-x64'),
97 | appIconPath: path('../utilities/msi/images/icon.ico'),
98 | outputDirectory: path('../dist/windows/setup'),
99 | description: 'MKVToolNix batch processing tool',
100 | exe: 'app',
101 | manufacturer: 'MKVToolNix Batch Tool',
102 | name: 'MKVToolNix Batch Tool',
103 | ui: {
104 | chooseDirectory: true,
105 | images: {
106 | background: path('../utilities/msi/images/background.png'),
107 | banner: path('../utilities/msi/images/banner.png')
108 | }
109 | },
110 | version: '2.5.4'
111 | });
112 |
113 | // Customized MSI template
114 | msiCreator.wixTemplate = msiCreator.wixTemplate
115 | .replace(/ \(Machine - MSI\)/gi, '')
116 | .replace(/ \(Machine\)/gi, '');
117 |
118 | // Create .wxs template and compile MSI
119 | msiCreator.create().then(() => msiCreator.compile());
120 | };
121 |
122 | }
123 |
124 | module.exports.Packager = Packager;
125 |
--------------------------------------------------------------------------------
/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 | /**
12 | * @description - Starts developer mode.
13 | * @memberof Starter
14 | */
15 | developerMode = async () => {
16 |
17 | // Child spawn options for console
18 | const spawnOptions = {
19 | hideLogs: { detached: false, shell: true, stdio: 'pipe' },
20 | showLogs: { detached: false, shell: true, stdio: 'inherit' }
21 | };
22 |
23 | /**
24 | * Method to get first port in range of 3001-3999,
25 | * Remains unused here so will be the same as the
26 | * port used in main.js
27 | */
28 | const port = await getPort({
29 | port: getPort.makeRange(3001, 3999)
30 | });
31 |
32 | // Kill anything that might using required React port
33 | spawnSync('npx kill-port 3000', spawnOptions.hideLogs);
34 |
35 | // Start & identify React & Electron processes
36 | spawn('cross-env BROWSER=none react-scripts start', spawnOptions.showLogs);
37 | spawn('electron .', spawnOptions.showLogs);
38 |
39 | // Kill processes on exit
40 | const exitOnEvent = (event) => {
41 | process.once(event, () => {
42 | try {
43 |
44 | // These errors are expected since the connection is closing
45 | const expectedErrors = ['ECONNRESET', 'ECONNREFUSED'];
46 |
47 | // Send command to Flask server to quit and close
48 | get(`http://localhost:${port}/quit`)
49 | // eslint-disable-next-line no-console
50 | .catch((error) => !expectedErrors.includes(error.code) && console.log(error));
51 |
52 | } catch (error) {
53 |
54 | // This errors is expected since the process is closing
55 | if (error.code !== 'ESRCH') console.error(error);
56 | }
57 | });
58 | };
59 |
60 | const exitEvents = ['exit', 'SIGINT', 'SIGUSR1', 'SIGUSR2', 'uncaughtException', 'SIGTERM'];
61 | exitEvents.forEach(exitOnEvent);
62 | };
63 |
64 | }
65 |
66 | module.exports = { Starter };
67 |
--------------------------------------------------------------------------------
/src/components/App.js:
--------------------------------------------------------------------------------
1 | import React, { Component, Fragment } from 'react';
2 | import { darkTheme, lightTheme, togglePalette } from 'theme/palettes';
3 |
4 | import MainPage from 'components/pages/main/MainPage';
5 | import Navigation from 'components/navigation/Navigation';
6 | import SettingsPage from 'components/pages/settings/SettingsPage';
7 | import Titlebar from 'components/titlebar/Titlebar';
8 | import { loadTheme } from 'office-ui-fabric-react';
9 | import { settings } from 'utils/settings';
10 |
11 | import styles from 'components/App.module.scss';
12 |
13 | /**
14 | * @namespace App
15 | * @description - Controls global state and page navigation
16 | */
17 | class App extends Component {
18 | state = {
19 | input: '',
20 | output: '',
21 | page: 'main',
22 | settings: {}
23 | };
24 |
25 | // Initialize settings on load
26 | componentDidMount() {
27 | loadTheme({ palette: darkTheme }); // default theme
28 | const settingDefaults = settings.getSettings();
29 |
30 | // Always default debug mode to false
31 | settingDefaults.isDebugMode = false;
32 | settings.setItem('isDebugMode', false);
33 |
34 | this.setState({
35 | output: settings.getItem('outputDir') || '',
36 | settings: settingDefaults
37 | });
38 | }
39 |
40 | componentDidUpdate(_prevProps, prevState) {
41 | const {
42 | state: {
43 | settings: { theme }
44 | }
45 | } = this;
46 | const {
47 | settings: { theme: prevTheme }
48 | } = prevState;
49 |
50 | if (theme !== prevTheme) {
51 | togglePalette(theme);
52 |
53 | if (theme === 'light') loadTheme({ palette: lightTheme });
54 | else loadTheme({ palette: darkTheme });
55 | }
56 | }
57 |
58 | // Method to set global app state
59 | setAppState = (state, callback) => this.setState(state, callback);
60 |
61 | // Method to update settings (including state)
62 | updateSetting = (item, value, callback) => {
63 | settings.setItem(item, value);
64 | this.setState({ settings: settings.getSettings() }, callback);
65 | };
66 |
67 | // Method to update multiple settings (including state)
68 | updateMultipleSettings = (newSettings, callback) => {
69 | const currentSettings = settings.getSettings();
70 | const updatedSettings = { ...currentSettings, ...newSettings };
71 |
72 | settings.saveSettings(updatedSettings);
73 | this.setState({ settings: updatedSettings }, callback);
74 | };
75 |
76 | render() {
77 | const {
78 | setAppState,
79 | state: { input, output, page, settings: stateSettings, theme },
80 | updateMultipleSettings,
81 | updateSetting
82 | } = this;
83 |
84 | const componentProps = {
85 | appState: { input, output, theme },
86 | setAppState,
87 | settings: stateSettings,
88 | updateMultipleSettings,
89 | updateSetting
90 | };
91 |
92 | return (
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 | );
101 | }
102 | }
103 |
104 | /**
105 | * @description - Page navigation controller.
106 | * @property {Component} page - Component to render.
107 | */
108 | function PageController(props) {
109 | const { page, ...componentProps } = props;
110 |
111 | switch (page) {
112 | case 'settings':
113 | return ;
114 |
115 | case 'main':
116 | default:
117 | return ;
118 | }
119 | }
120 |
121 | export default App;
122 |
--------------------------------------------------------------------------------
/src/components/App.module.scss:
--------------------------------------------------------------------------------
1 | .main {
2 | display: grid;
3 | grid-template-columns: 1fr 8fr;
4 | height: 330px;
5 | }
--------------------------------------------------------------------------------
/src/components/dialog/Notice.js:
--------------------------------------------------------------------------------
1 | import React, { useMemo } from 'react';
2 | import {
3 | Dialog,
4 | DialogFooter,
5 | DialogType
6 | } from 'office-ui-fabric-react/lib/Dialog';
7 |
8 | import { PrimaryButton } from 'office-ui-fabric-react/lib/Button';
9 | import { useId } from '@uifabric/react-hooks';
10 |
11 | import PropTypes from 'prop-types';
12 |
13 | /**
14 | * @namespace Notice
15 | * @description - Generic notice component to display messages to the end user.
16 | *
17 | * @property {boolean} hideDialog - Boolean to determine if the dialog should be shown.
18 | * @property {string} messageText - Text to show as the main message.
19 | * @property {string} messageTitle - Text to show as the title of the notice.
20 | * @property {function} setHideDialog - Function used to set the `hideDialog` boolean.
21 | * @tutorial - https://developer.microsoft.com/en-us/fluentui#/controls/web/dialog
22 | */
23 |
24 | const Notice = (props) => {
25 | const { hideDialog, messageText, messageTitle, setHideDialog } = props;
26 |
27 | const dialogContentProps = {
28 | type: DialogType.normal,
29 | title: messageTitle,
30 | closeButtonAriaLabel: 'Close',
31 | subText: messageText
32 | };
33 |
34 | // Ensure unique IDs
35 | const labelId = useId('dialogLabel');
36 | const subTextId = useId('subTextLabel');
37 |
38 | const modalProps = useMemo(
39 | () => ({
40 | titleAriaId: labelId,
41 | subtitleAriaId: subTextId,
42 | isBlocking: false,
43 | styles: { main: { maxWidth: 450 } }
44 | }),
45 | [labelId, subTextId]
46 | );
47 |
48 | const toggleHideDialog = () => setHideDialog(!hideDialog);
49 |
50 | return (
51 |
61 | );
62 | };
63 |
64 | Notice.propTypes = {
65 | hideDialog: PropTypes.bool.isRequired,
66 | messageText: PropTypes.string.isRequired,
67 | setHideDialog: PropTypes.func.isRequired,
68 | messageTitle: PropTypes.string.isRequired
69 | };
70 |
71 | export default Notice;
72 |
--------------------------------------------------------------------------------
/src/components/footer/Footer.js:
--------------------------------------------------------------------------------
1 | import { PrimaryButton } from 'office-ui-fabric-react';
2 | import PropTypes from 'prop-types';
3 | import React from 'react';
4 | import styles from 'components/footer/assets/styles/Footer.module.scss';
5 |
6 | /**
7 | * @namespace Footer
8 | * @property {string|null} [buttonClassName=null] - Optional class name for button.
9 | * @property {function} buttonOnClick - On click handler for button.
10 | * @property {string|null} [buttonIcon=null] - Footer button icon.
11 | * @property {string} buttonText - Footer button text.
12 | * @property {string} buttonTitle - Title for button element.
13 | * @property {boolean} [disabled=false] - Boolean determining if button is disabled.
14 | */
15 | const Footer = (props) => {
16 | const {
17 | buttonClassName = null,
18 | buttonOnClick,
19 | buttonIcon = null,
20 | buttonText,
21 | buttonTitle,
22 | disabled = false
23 | } = props;
24 |
25 | const className = buttonClassName
26 | ? `${styles['continue-button']} ${styles[buttonClassName]}`
27 | : styles['continue-button'];
28 |
29 | return (
30 |
40 | );
41 | };
42 |
43 | Footer.propTypes = {
44 | buttonClassName: PropTypes.string,
45 | buttonOnClick: PropTypes.func.isRequired,
46 | buttonIcon: PropTypes.string,
47 | buttonText: PropTypes.string.isRequired,
48 | disabled: PropTypes.bool
49 | };
50 |
51 | Footer.defaultProps = {
52 | buttonClassName: null,
53 | buttonIcon: null,
54 | disabled: false
55 | };
56 |
57 | export default Footer;
58 |
--------------------------------------------------------------------------------
/src/components/footer/assets/styles/Footer.module.scss:
--------------------------------------------------------------------------------
1 | @import 'theme/variables.scss';
2 |
3 | .footer {
4 | display: flex;
5 | flex-direction: row-reverse;
6 | justify-content: flex-start;
7 | align-items: center;
8 | width: 100%;
9 | margin-top: 15px;
10 | }
11 |
12 | .continue-button {
13 | width: 117px;
14 | height: 30px;
15 | margin: 25px 15px;
16 | &[disabled] {
17 | cursor: not-allowed;
18 | pointer-events: auto;
19 | opacity: .75;
20 |
21 | &:hover {
22 | &::before {
23 | content: "You must first select a source and output folder";
24 | position: fixed;
25 | left: 180px;
26 | padding-top: 6px;
27 | color: var(--primary);
28 | }
29 | }
30 | }
31 | }
32 |
33 | .reset-button {
34 | margin: 49px 0 0;
35 | }
36 |
37 | .tooltip {
38 | margin-top: 10px;
39 | }
--------------------------------------------------------------------------------
/src/components/navigation/Navigation.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 |
3 | import FoldersIcon from 'components/navigation/assets/icons/FoldersIcon';
4 | import PropTypes from 'prop-types';
5 | import SettingsIcon from 'components/navigation/assets/icons/SettingsIcon';
6 | import ThemeIcon from 'components/navigation/assets/icons/ThemeIcon';
7 | import styles from 'components/navigation/assets/styles/Navigation.module.scss';
8 |
9 | /**
10 | * @namespace Navigation
11 | * @description - Settings page of the app where settings are updated.
12 | *
13 | * @property {object} appState - Global app state.
14 | * @property {function} setAppState - Function to set global app state.
15 | * @property {object} settings - User defined, persistent settings.
16 | * @property {function} updateMultipleSettings - Function to update multiple user defined settings at once.
17 | * @property {function} updateSetting - Function to update a single setting at a time.
18 | */
19 | const Navigation = (props) => {
20 | const [active, setActive] = useState('folders');
21 |
22 | const setFoldersActive = () => {
23 | props.setAppState({ page: 'home' }, setActive('folders'));
24 | };
25 |
26 | const setSettingsActive = () => {
27 | props.setAppState({ page: 'settings' }, setActive('settings'));
28 | };
29 |
30 | const setClassName = (type) =>
31 | active === type ? `${styles.active} ${styles.svg}` : styles.svg;
32 |
33 | const toggleAppTheme = () => {
34 | const {
35 | settings: { theme }
36 | } = props;
37 | const otherTheme = theme === 'dark' ? 'light' : 'dark';
38 |
39 | props.updateSetting('theme', otherTheme);
40 | };
41 |
42 | return (
43 |
68 | );
69 | };
70 |
71 | Navigation.propTypes = {
72 | appState: PropTypes.object.isRequired,
73 | setAppState: PropTypes.func.isRequired,
74 | settings: PropTypes.object.isRequired,
75 | updateMultipleSettings: PropTypes.func,
76 | updateSetting: PropTypes.func
77 | };
78 |
79 | export default Navigation;
80 |
--------------------------------------------------------------------------------
/src/components/navigation/assets/icons/FoldersIcon.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const FoldersIcon = (props) => {
4 | return (
5 |
6 | );
7 | };
8 |
9 | export default FoldersIcon;
--------------------------------------------------------------------------------
/src/components/navigation/assets/icons/SettingsIcon.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const SettingsIcon = (props) => {
4 | return (
5 |
8 | );
9 | };
10 |
11 | export default SettingsIcon;
--------------------------------------------------------------------------------
/src/components/navigation/assets/icons/ThemeIcon.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const ThemeIcon = (props) => {
4 | return (
5 |
6 | );
7 | };
8 |
9 | export default ThemeIcon;
--------------------------------------------------------------------------------
/src/components/navigation/assets/styles/Navigation.module.scss:
--------------------------------------------------------------------------------
1 | @import 'theme/variables.scss';
2 |
3 | .aside {
4 | display: flex;
5 | flex-direction: column;
6 | border-right: var(--border);
7 | margin-top: -8px;
8 | width: 80px;
9 | }
10 |
11 | .svg {
12 | display: flex;
13 | align-items: center;
14 | justify-content: center;
15 | height: 80px;
16 |
17 | svg {
18 | color: var(--white);
19 | width: 40px;
20 | }
21 |
22 | &:hover {
23 | cursor: pointer;
24 |
25 | &:not(.active) {
26 | background-color: var(--hover-state);
27 | }
28 | }
29 |
30 | &.active{
31 | background-color: var(--active-state);
32 | }
33 | }
34 |
35 | .theme {
36 | svg {
37 | width: 40px;
38 | color: var(--primary);
39 | transform: scale(-1, 1);
40 | position: fixed;
41 | bottom: 25px;
42 | left: 20px;
43 | cursor: pointer;
44 | }
45 | }
--------------------------------------------------------------------------------
/src/components/pages/main/InputField.js:
--------------------------------------------------------------------------------
1 | import { DefaultButton } from 'office-ui-fabric-react';
2 | import PropTypes from 'prop-types';
3 | import React from 'react';
4 | import { TextField } from 'office-ui-fabric-react/lib/TextField';
5 | import styles from 'components/pages/main/assets/styles/InputField.module.scss';
6 |
7 | /**
8 | * @description - Input section component
9 | * @property {boolean} disabled - Determines whether input field is disabled or not.
10 | * @property {string} label - Input label.
11 | * @property {string} placeholder - Input placeholder.
12 | * @property {function} setValue - Function set input value.
13 | * @property {string} type - Type of input field (e.g., input or output directory).
14 | * @property {string} value - Current value of input field.
15 | *
16 | * @memberof Home
17 | */
18 |
19 | const InputField = (props) => {
20 | const { disabled, label, placeholder, setValue, value } = props;
21 |
22 | const onDrop = (event) => {
23 | const path = event.dataTransfer.files[0].path;
24 | setValue(path);
25 | };
26 |
27 | return (
28 |
29 |
40 |
41 |
48 |
49 | );
50 | };
51 |
52 | InputField.propTypes = {
53 | disabled: PropTypes.bool,
54 | label: PropTypes.string.isRequired,
55 | placeholder: PropTypes.string.isRequired,
56 | setValue: PropTypes.func.isRequired,
57 | value: PropTypes.string.isRequired
58 | };
59 |
60 | export default InputField;
61 |
--------------------------------------------------------------------------------
/src/components/pages/main/LoadingScreen.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 |
3 | import { Label } from 'office-ui-fabric-react/lib/Label';
4 | import Spinner from 'components/pages/main/assets/icons/Spinner';
5 | import { socket } from 'utils/requests';
6 | import styles from 'components/pages/main/assets/styles/LoadingScreen.module.scss';
7 |
8 | /**
9 | * @description - Loading screen for when data is processing
10 | * @memberof MainPage
11 | */
12 | class LoadingScreen extends Component {
13 | state = {
14 | batchSize: 0,
15 | currentCount: 0
16 | };
17 |
18 | setBatchSize = (batchSize) => {
19 | this.setState({ batchSize });
20 | };
21 |
22 | processDirectory = () => {
23 | this.setState({ currentCount: this.state.currentCount + 1 });
24 | };
25 |
26 | componentDidMount() {
27 | // Configure socket communication
28 | socket.on('batch_size', this.setBatchSize);
29 | socket.on('processing_subdirectory', this.processDirectory);
30 | }
31 |
32 | componentWillUnmount() {
33 | // Disconnect socket on unmount
34 | socket.off('batch_size', this.setBatchSize);
35 | socket.off('processing_subdirectory', this.processDirectory);
36 | }
37 |
38 | render() {
39 | const {
40 | state: { batchSize, currentCount }
41 | } = this;
42 |
43 | return (
44 |
45 |
46 |
49 |
50 | );
51 | }
52 | }
53 |
54 | export default LoadingScreen;
55 |
--------------------------------------------------------------------------------
/src/components/pages/main/assets/icons/Spinner.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const Spinner = (props) => {
4 | return (
5 |
61 | );
62 | };
63 |
64 | export default Spinner;
65 |
--------------------------------------------------------------------------------
/src/components/pages/main/assets/styles/InputField.module.scss:
--------------------------------------------------------------------------------
1 | .browse-button {
2 | margin-top: 29px;
3 | margin-left: 4px;
4 | }
5 |
6 | .input-block {
7 | display: flex;
8 | margin: 15px 15px 0;
9 | }
10 |
11 | .input-field {
12 | width: 100%;
13 | max-width: 800px;
14 | }
--------------------------------------------------------------------------------
/src/components/pages/main/assets/styles/LoadingScreen.module.scss:
--------------------------------------------------------------------------------
1 | .label {
2 | color: var(--white-constant);
3 | }
4 |
5 | .spinner {
6 | position: fixed;
7 | top: 32px;
8 | right: 0;
9 | bottom: 0;
10 | left: 0;
11 | display: flex;
12 | justify-content: center;
13 | align-items: center;
14 | flex-direction: column;
15 | background: var(--loading-background-color);
16 | z-index: 1;
17 | cursor: not-allowed;
18 |
19 | * {
20 | cursor: not-allowed;
21 | }
22 | }
23 |
24 | .spinner-icon {
25 | height: 100px;
26 | width: 100px;
27 | margin-top: -16px;
28 | }
--------------------------------------------------------------------------------
/src/components/pages/main/assets/styles/MainPage.module.scss:
--------------------------------------------------------------------------------
1 | @import 'theme/variables.scss';
2 |
3 | .home {
4 | padding: 0 15px;
5 | }
6 |
7 | .checkbox {
8 | margin: 12px 20px;
9 | width: fit-content;
10 | }
11 |
12 | .mode-settings {
13 | display: flex;
14 | flex-direction: column;
15 | margin: 23px 12px -33px;
16 |
17 | button:first-child {
18 | margin-right: 7px;
19 | }
20 | }
21 |
22 | :global(.ms-Callout.ms-Dropdown-callout) {
23 | height: 110px !important;
24 | }
25 |
--------------------------------------------------------------------------------
/src/components/pages/settings/LanguageSettings.js:
--------------------------------------------------------------------------------
1 | import { Dropdown, DropdownMenuItemType } from 'office-ui-fabric-react/lib/Dropdown';
2 | import React, { useEffect, useMemo, useState } from 'react';
3 |
4 | import { Icon } from 'office-ui-fabric-react/lib/Icon';
5 | import { Label } from 'office-ui-fabric-react/lib/Label';
6 | import PropTypes from 'prop-types';
7 | import { Stack } from 'office-ui-fabric-react/lib/Stack';
8 | import { get } from 'utils/requests';
9 |
10 | const onRenderLabel = (props) => (
11 |
12 |
17 |
22 |
23 | );
24 |
25 | /**
26 | * @description - Language setting dropdown for settings page
27 | * @property {object} language - Selected language object with `key` and `text` keys.
28 | * @property {function} setLanguageSetting - Callback handler to return language data to the parent.
29 | *
30 | * @memberof SettingsPage
31 | */
32 | const LanguageSettings = (props) => {
33 | const {
34 | language: { text, key },
35 | setLanguageSetting
36 | } = props;
37 |
38 | // Primary languages to select from
39 | const primaryLanguageOptions = useMemo(() => ([
40 | { key: 'unset', text: 'None' },
41 | { key: 'chi', text: 'Chinese' },
42 | { key: 'dut', text: 'Dutch' },
43 | { key: 'eng', text: 'English' },
44 | { key: 'spa', text: 'Spanish' },
45 | { key: 'fre', text: 'French' },
46 | { key: 'ger', text: 'German' },
47 | { key: 'ita', text: 'Italian' },
48 | { key: 'jpn', text: 'Japanese' },
49 | { key: 'por', text: 'Portuguese' },
50 | { key: 'rus', text: 'Russian' },
51 | { key: 'swe', text: 'Swedish' }
52 | ]), []);
53 |
54 | const [languageOptions, setLanguageOptions] = useState(primaryLanguageOptions);
55 |
56 | // Additional supported languages (from MKVToolNix)
57 | useEffect(() => {
58 |
59 | // Create hashmap of existing keys for reference
60 | const existingKeys = primaryLanguageOptions.reduce((acc, languageOption) => {
61 | acc[languageOption.key] = true;
62 | return acc;
63 | }, {});
64 |
65 | get('supported_languages', (languages) => {
66 | const additionalLanguageOptions = [
67 | {
68 | key: 'additional-languages',
69 | text: 'Full Language List',
70 | itemType: DropdownMenuItemType.Header
71 | },
72 |
73 | // Don't include existing (primary) languages
74 | ...Object.values(languages).filter((option) => {
75 | return !(option.key in existingKeys);
76 | })
77 | ];
78 |
79 | // Combine primary and additional language options
80 | setLanguageOptions([
81 | ...primaryLanguageOptions,
82 | ...additionalLanguageOptions
83 | ]);
84 | });
85 | }, [primaryLanguageOptions]);
86 |
87 | const onKeyDown = (event) => {
88 | const option = languageOptions.find((language) => {
89 | return language.key[0] === event.key;
90 | });
91 |
92 | if (option) {
93 | setLanguageSetting(event, option);
94 | }
95 | };
96 |
97 | return (
98 |
108 | );
109 | };
110 |
111 | LanguageSettings.propTypes = {
112 | language: PropTypes.object.isRequired,
113 | setLanguageSetting: PropTypes.func.isRequired
114 | };
115 |
116 |
117 | export default LanguageSettings;
118 |
--------------------------------------------------------------------------------
/src/components/pages/settings/SettingsPage.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Checkbox } from 'office-ui-fabric-react/lib/Checkbox';
3 | import LanguageSettings from 'components/pages/settings/LanguageSettings';
4 | import Notice from 'components/dialog/Notice';
5 | import PropTypes from 'prop-types';
6 | import styles from 'components/pages/settings/assets/styles/SettingsPage.module.scss';
7 | import { app } from 'utils/services';
8 |
9 | /**
10 | * @namespace SettingsPage
11 | * @description - Settings page of the app where settings are updated.
12 | *
13 | * @property {object} appState - Global app state.
14 | * @property {function} setAppState - Function to set global app state (unused).
15 | * @property {object} settings - User defined, persistent settings.
16 | * @property {function} updateMultipleSettings - Function to update multiple user defined settings at once.
17 | * @property {function} updateSetting - Function to update a single setting at a time.
18 | *
19 | * @memberof Pages
20 | */
21 | class SettingsPage extends Component {
22 | state = {
23 | isDebugMode: true,
24 | isRememberOutputDir: false,
25 | isRemoveAds: false,
26 | isRemoveExistingSubtitles: false,
27 | isRemoveOld: false,
28 | language: { key: 'unset', text: 'None' },
29 | noticeData: {
30 | hideDialog: true,
31 | messageText: 'Manually closing the console may cause the application to misbehave. If this happens, restart the application.',
32 | messageTitle: 'Notice'
33 | }
34 | };
35 |
36 | // Keep component up-to-date w/latest props
37 | static getDerivedStateFromProps(nextProps) {
38 | return {
39 | isDebugMode: nextProps.settings.isDebugMode,
40 | isRememberOutputDir: nextProps.settings.isRememberOutputDir,
41 | isRemoveAds: nextProps.settings.isRemoveAds,
42 | isRemoveExistingSubtitles: nextProps.settings.isRemoveExistingSubtitles,
43 | isRemoveOld: nextProps.settings.isRemoveOld,
44 | language: nextProps.settings.language
45 | };
46 | }
47 |
48 | setHideDialog = (hideDialog) => {
49 | this.setState({ noticeData: { ...this.state.noticeData, hideDialog } });
50 | }
51 |
52 | // Method to toggle "subtitle language" setting
53 | setLanguageSetting = (event, language) => {
54 | this.props.updateSetting('language', language);
55 | };
56 |
57 | // Generic method to toggle or update a setting
58 | toggleSetting = (option) => {
59 | this.props.updateSetting(option, !this.props.settings[option]);
60 | };
61 |
62 | // Method to update the remember output directory and related settings
63 | updateRememberOutputDir = () => {
64 | const { isRememberOutputDir, isSameAsSource } = this.props.settings;
65 | const outputIfNotSameAsSource = !isSameAsSource && this.props.appState.output;
66 |
67 | if (isRememberOutputDir) {
68 | this.props.updateMultipleSettings({
69 | isRememberOutputDir: false,
70 | outputDir: null
71 | });
72 | } else {
73 | this.props.updateMultipleSettings({
74 | isRememberOutputDir: true,
75 | outputDir: outputIfNotSameAsSource || null
76 | });
77 | }
78 | };
79 |
80 | toggleDetached = () => {
81 | this.toggleSetting('isDebugMode');
82 |
83 | /**
84 | * Spamming checkbox would otherwise cause
85 | * issues w/async calls from socket.io
86 | */
87 | const debounceOption = (fn) => {
88 | const timeoutId = 'enable-dev-console-timeout';
89 | let timeout = this.props.settings[timeoutId];
90 |
91 | return () => {
92 | if (timeout) {
93 | clearTimeout(Number(timeout));
94 | this.props.updateSetting(timeoutId, 0);
95 | }
96 | timeout = setTimeout(fn, app.reconnectionDelay);
97 | this.props.updateSetting(timeoutId, timeout);
98 | };
99 | };
100 |
101 | // Debounced function to restart app
102 | const debouncedRestart = debounceOption(() => {
103 | const { isDebugMode } = this.state;
104 | if (isDebugMode) {
105 | this.setHideDialog(false);
106 | }
107 |
108 | app.restart({
109 | detached: isDebugMode,
110 | shell: true,
111 | stdio: isDebugMode ? 'inherit' : 'pipe'
112 | });
113 | });
114 |
115 | // Invoke debounced restart
116 | debouncedRestart();
117 | };
118 |
119 | render() {
120 | const {
121 | setHideDialog,
122 | setLanguageSetting,
123 | state: {
124 | isRememberOutputDir,
125 | isRemoveAds,
126 | isRemoveExistingSubtitles,
127 | isRemoveOld,
128 | language,
129 | isDebugMode,
130 | noticeData
131 | },
132 | toggleDetached,
133 | toggleSetting,
134 | updateRememberOutputDir
135 | } = this;
136 |
137 | return (
138 |
139 |
140 |
144 | toggleSetting('isRemoveExistingSubtitles') }
149 | />
150 |
151 | toggleSetting('isRemoveOld') }
156 | />
157 |
158 | toggleSetting('isRemoveAds') }
163 | />
164 |
165 |
171 |
172 |
178 |
179 | );
180 | }
181 | }
182 |
183 |
184 | SettingsPage.defaultProps = {
185 | updateMultipleSettings: undefined,
186 | updateSetting: undefined
187 | };
188 |
189 | SettingsPage.propTypes = {
190 | appState: PropTypes.object.isRequired,
191 | settings: PropTypes.shape({
192 | isSameAsSource: PropTypes.bool.isRequired,
193 | isDebugMode: PropTypes.bool.isRequired,
194 | isRememberOutputDir: PropTypes.bool.isRequired,
195 | isRemoveAds: PropTypes.bool.isRequired,
196 | isRemoveExistingSubtitles: PropTypes.bool.isRequired,
197 | isRemoveOld: PropTypes.bool.isRequired,
198 | language: PropTypes.shape({
199 | key: PropTypes.string.isRequired,
200 | text: PropTypes.string.isRequired
201 | }).isRequired
202 | }).isRequired,
203 | updateMultipleSettings: PropTypes.func,
204 | updateSetting: PropTypes.func
205 | };
206 |
207 | export default SettingsPage;
208 |
--------------------------------------------------------------------------------
/src/components/pages/settings/assets/styles/SettingsPage.module.scss:
--------------------------------------------------------------------------------
1 | .settings {
2 | padding: 15px 30px;
3 |
4 | .checkbox {
5 | margin: 24px 5px 0;
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/components/titlebar/Favicon.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | /**
4 | * @description - Favicon for titlebar of app.
5 | * @property {*} props - Optional props drilled down from parent component (e.g., className).
6 | *
7 | * @memberof Titlebar
8 | */
9 | const Favicon = (props) => {
10 | return (
11 |
35 | );
36 | };
37 |
38 | export default Favicon;
39 |
--------------------------------------------------------------------------------
/src/components/titlebar/Titlebar.js:
--------------------------------------------------------------------------------
1 | import {
2 | CloseButton,
3 | MinimizeButton
4 | } from 'components/titlebar/TitlebarButtons';
5 |
6 | import Favicon from 'components/titlebar/Favicon';
7 | import React from 'react';
8 | import { app } from 'utils/services';
9 | import { initializeIcons } from 'office-ui-fabric-react/lib/Icons';
10 | import styles from 'components/titlebar/scss/Titlebar.module.scss';
11 |
12 | initializeIcons();
13 |
14 | /**
15 | * @namespace Titlebar
16 | * @description Title Component to use as an Electron customized titlebar.
17 | *
18 | * @property {id} electron-window-title-text used in main.js to set opacity on/off focus.
19 | * @property {id} electron-window-title-buttons used in main.js to set opacity on/off focus.
20 | */
21 |
22 | const Titlebar = () => {
23 | return (
24 |
25 |
26 |
27 | {document.title}
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | );
36 | };
37 |
38 | export default Titlebar;
39 |
--------------------------------------------------------------------------------
/src/components/titlebar/TitlebarButtons.js:
--------------------------------------------------------------------------------
1 | import { IconButton } from '@fluentui/react/lib/Button';
2 | import React from 'react';
3 | import styles from 'components/titlebar/scss/TitlebarButtons.module.scss';
4 |
5 | /**
6 | * @description Titlebar minimize button.
7 | * @property {*} props - Optional props drilled down from parent component (e.g., className).
8 | *
9 | * @memberof Titlebar
10 | */
11 |
12 | export const MinimizeButton = (props) => (
13 |
20 | );
21 |
22 | /**
23 | * @description Titlebar close button.
24 | * @property {*} props - Optional props drilled down from parent component (e.g., className).
25 | *
26 | * @memberof Titlebar
27 | */
28 | export const CloseButton = (props) => (
29 |
36 | );
37 |
--------------------------------------------------------------------------------
/src/components/titlebar/scss/Titlebar.module.scss:
--------------------------------------------------------------------------------
1 | @import 'theme/variables.scss';
2 |
3 | body section.titlebar {
4 | display: flex;
5 | justify-content: space-between;
6 | align-items: center;
7 | height: 32px;
8 | padding: 0;
9 | position: fixed;
10 | top: 0;
11 | left: 0;
12 | width: 100vw;
13 | max-width: 100vw;
14 | -webkit-user-select: none;
15 | -webkit-app-region: drag;
16 | background-color: var(--primary);
17 |
18 | div {
19 | display: flex;
20 | align-items: center;
21 |
22 | span {
23 | font-size: 14px;
24 | font-weight: bold;
25 | font-family: "Segoe UI", "Segoe UI Web (West European)", "Segoe UI", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
26 | color: var(--black);
27 | }
28 |
29 | svg {
30 | color: var(--black);
31 | width: 20px;
32 | padding: 5px 6px 5px 8px;
33 | }
34 |
35 | }
36 | }
--------------------------------------------------------------------------------
/src/components/titlebar/scss/TitlebarButtons.module.scss:
--------------------------------------------------------------------------------
1 | @import 'theme/variables.scss';
2 |
3 | .button {
4 | padding: 0 25px;
5 | -webkit-app-region: no-drag;
6 | color: var(--black);
7 | border-radius: 0;
8 |
9 | &:hover {
10 | background-color: var(--background-color);
11 | color: var(--black);
12 | }
13 |
14 | &:last-child {
15 | &:hover {
16 | background-color: var(--red-exit);
17 | span {
18 | color: var(--white-constant);
19 | }
20 | }
21 | }
22 |
23 | span i {
24 | font-size: 12px;
25 | }
26 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import 'index.scss';
2 |
3 | import * as serviceWorker from 'serviceWorker';
4 |
5 | import App from 'components/App';
6 | import React from 'react';
7 | import ReactDOM from 'react-dom';
8 |
9 | ReactDOM.render(, document.getElementById('root'));
10 |
11 | // If you want your app to work offline and load faster, you can change
12 | // unregister() to register() below. Note this comes with some pitfalls.
13 | // Learn more about service workers: https://bit.ly/CRA-PWA
14 | serviceWorker.unregister();
15 |
--------------------------------------------------------------------------------
/src/index.scss:
--------------------------------------------------------------------------------
1 | @import 'theme/variables.scss';
2 | @import 'theme/overrides.scss';
3 |
4 | body {
5 | background: var(--black);
6 | margin: 0;
7 | margin-top: 40px;
8 | overflow: hidden;
9 | -webkit-font-smoothing: antialiased;
10 | -moz-osx-font-smoothing: grayscale;
11 |
12 | div[role="tooltip"] {
13 | color: var(--black);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/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 | // eslint-disable-next-line no-console
45 | console.log(
46 | 'This web app is being served cache-first by a service '
47 | + 'worker. To learn more, visit https://bit.ly/CRA-PWA'
48 | );
49 | });
50 | } else {
51 | // Is not localhost. Just register service worker
52 | registerValidSW(swUrl, config);
53 | }
54 | });
55 | }
56 | }
57 |
58 | function registerValidSW(swUrl, config) {
59 | navigator.serviceWorker
60 | .register(swUrl)
61 | .then((registration) => {
62 | registration.onupdatefound = () => {
63 | const installingWorker = registration.installing;
64 | if (installingWorker == null) {
65 | return;
66 | }
67 | installingWorker.onstatechange = () => {
68 | if (installingWorker.state === 'installed') {
69 | if (navigator.serviceWorker.controller) {
70 | // At this point, the updated precached content has been fetched,
71 | // but the previous service worker will still serve the older
72 | // content until all client tabs are closed.
73 | // eslint-disable-next-line no-console
74 | console.log(
75 | 'New content is available and will be used when all '
76 | + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
77 | );
78 |
79 | // Execute callback
80 | if (config && config.onUpdate) {
81 | config.onUpdate(registration);
82 | }
83 | } else {
84 | // At this point, everything has been precached.
85 | // It's the perfect time to display a
86 | // "Content is cached for offline use." message.
87 | // eslint-disable-next-line no-console
88 | console.log('Content is cached for offline use.');
89 |
90 | // Execute callback
91 | if (config && config.onSuccess) {
92 | config.onSuccess(registration);
93 | }
94 | }
95 | }
96 | };
97 | };
98 | })
99 | .catch((error) => {
100 | console.error('Error during service worker registration:', error);
101 | });
102 | }
103 |
104 | function checkValidServiceWorker(swUrl, config) {
105 | // Check if the service worker can be found. If it can't reload the page.
106 | fetch(swUrl, {
107 | headers: { 'Service-Worker': 'script' }
108 | })
109 | .then((response) => {
110 | // Ensure service worker exists, and that we really are getting a JS file.
111 | const contentType = response.headers.get('content-type');
112 | if (
113 | response.status === 404
114 | || (contentType != null && contentType.indexOf('javascript') === -1)
115 | ) {
116 | // No service worker found. Probably a different app. Reload the page.
117 | navigator.serviceWorker.ready.then((registration) => {
118 | registration.unregister().then(() => {
119 | window.location.reload();
120 | });
121 | });
122 | } else {
123 | // Service worker found. Proceed as normal.
124 | registerValidSW(swUrl, config);
125 | }
126 | })
127 | .catch(() => {
128 | // eslint-disable-next-line no-console
129 | console.log(
130 | 'No internet connection found. App is running in offline mode.'
131 | );
132 | });
133 | }
134 |
135 | export function unregister() {
136 | if ('serviceWorker' in navigator) {
137 | navigator.serviceWorker.ready.then((registration) => {
138 | registration.unregister();
139 | });
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/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/overrides.scss:
--------------------------------------------------------------------------------
1 | /* MS Fluent Overrides */
2 |
3 | body {
4 | .ms-Callout.ms-Dropdown-callout {
5 | margin-top: 5px;
6 | border: solid 1px;
7 | height: 158px;
8 | overflow-x: auto;
9 | }
10 |
11 | .ms-Callout-main {
12 |
13 | // `!important` to override inline styles
14 | max-height: unset !important;
15 | overflow: hidden !important;
16 | }
17 |
18 | .ms-Dropdown-container i {
19 | color: var(--primary);
20 |
21 | &[data-icon-name="LocaleLanguage"] {
22 | margin-left: 8px;
23 | }
24 | }
25 |
26 | span.ms-layer {
27 | position: absolute;
28 | }
29 |
30 | div.ms-Layer {
31 | top: 32px;
32 | }
33 |
34 | div.ms-Dialog-main {
35 | margin-top: -32px;
36 | }
37 | }
--------------------------------------------------------------------------------
/src/theme/palettes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @namespace Themes
3 | * @description - Themes for Microsoft Fluent UI, which is built into the project.
4 | *
5 | * @tutorial - https://www.aka.ms/themedesigner
6 | */
7 |
8 | export const darkTheme = {
9 | themePrimary: '#bf7e45',
10 | themeLighterAlt: '#080503',
11 | themeLighter: '#1f140b',
12 | themeLight: '#392615',
13 | themeTertiary: '#734c29',
14 | themeSecondary: '#a86f3d',
15 | themeDarkAlt: '#c68954',
16 | themeDark: '#cf996a',
17 | themeDarker: '#dbb18d',
18 | neutralLighterAlt: '#303030',
19 | neutralLighter: '#383838',
20 | neutralLight: '#464646',
21 | neutralQuaternaryAlt: '#4e4e4e',
22 | neutralQuaternary: '#555555',
23 | neutralTertiaryAlt: '#727272',
24 | neutralTertiary: '#f8f8f8',
25 | neutralSecondary: '#f9f9f9',
26 | neutralPrimaryAlt: '#fafafa',
27 | neutralPrimary: '#f5f5f5',
28 | neutralDark: '#fdfdfd',
29 | black: '#fefefe',
30 | white: '#252525',
31 | };
32 |
33 | export const lightTheme = {
34 | themePrimary: '#0078d4',
35 | themeLighterAlt: '#eff6fc',
36 | themeLighter: '#deecf9',
37 | themeLight: '#c7e0f4',
38 | themeTertiary: '#71afe5',
39 | themeSecondary: '#2b88d8',
40 | themeDarkAlt: '#106ebe',
41 | themeDark: '#005a9e',
42 | themeDarker: '#004578',
43 | neutralLighterAlt: '#faf9f8',
44 | neutralLighter: '#f3f2f1',
45 | neutralLight: '#edebe9',
46 | neutralQuaternaryAlt: '#e1dfdd',
47 | neutralQuaternary: '#d0d0d0',
48 | neutralTertiaryAlt: '#c8c6c4',
49 | neutralTertiary: '#a19f9d',
50 | neutralSecondary: '#605e5c',
51 | neutralPrimaryAlt: '#3b3a39',
52 | neutralPrimary: '#323130',
53 | neutralDark: '#201f1e',
54 | black: '#252525',
55 | white: '#fefefe',
56 | };
57 |
58 | /**
59 | * @description - Function to toggle theme pallet
60 | */
61 | export const togglePalette = (theme) => {
62 | const setProperty = (item, value) => {
63 | const root = window.document.documentElement;
64 | root.style.setProperty(item, value);
65 | };
66 |
67 | const setDark = () => {
68 | setProperty('--active-state', 'rgba(254, 254, 254, .2)');
69 | setProperty('--background-color', 'rgba(254, 254, 254, .5)');
70 | setProperty('--black', '#252525');
71 | setProperty('--border', 'solid 1px rgba(254, 254, 254, .1)');
72 | setProperty('--hover-state', 'rgba(254, 254, 254, .1)');
73 | setProperty('--loading-background-color', 'rgba(0, 0, 0, .6)');
74 | setProperty('--primary', '#bf7e45');
75 | setProperty('--white', '#fefefe');
76 | };
77 |
78 | const setLight = () => {
79 | setProperty('--active-state', 'rgba(37, 37, 37, .2)');
80 | setProperty('--background-color', 'rgba(37, 37, 37, .5)');
81 | setProperty('--black', '#fefefe');
82 | setProperty('--border', 'solid 1px rgba(37, 37, 37, .25)');
83 | setProperty('--hover-state', 'rgba(37, 37, 37, .1)');
84 | setProperty('--loading-background-color', 'rgba(0, 0, 0, .75)');
85 | setProperty('--primary', '#0078d4');
86 | setProperty('--white', '#252525');
87 | };
88 |
89 | if(theme === 'light') setLight();
90 | else setDark();
91 | };
--------------------------------------------------------------------------------
/src/theme/variables.scss:
--------------------------------------------------------------------------------
1 | // CSS custom properties which are changed
2 | // when theme is updated.
3 | :root {
4 | --active-state: rgba(254, 254, 254, .2);
5 | --background-color: rgba(254, 254, 254, .5);
6 | --black: #252525;
7 | --border: solid 1px rgba(254, 254, 254, .1);
8 | --hover-state: rgba(254, 254, 254, .1);
9 | --loading-background-color: rgba(0, 0, 0, .6);
10 | --primary: #bf7e45;
11 | --red-exit: #ff0000;
12 | --white: #fefefe;
13 | --white-constant: #fefefe;
14 | }
--------------------------------------------------------------------------------
/src/utils/requests.js:
--------------------------------------------------------------------------------
1 | import socketIOClient from 'socket.io-client';
2 |
3 | // Electron Inter Process Communication and dialog
4 | const { ipcRenderer } = window.require('electron');
5 |
6 | // Dynamically generated TCP (open) port between 3000-3999
7 | const port = ipcRenderer.sendSync('get-port-number');
8 |
9 | /**
10 | * @namespace Requests
11 | * @description - Helper functions for network requests (e.g., get, post, put, delete, etc..)
12 | */
13 |
14 | /**
15 | * @description - Helper GET method for sending requests to and from the Python/Flask services.
16 | * @param {string} url - URL route of the Python/Flask service you want to use.
17 | * @param {function} callback - Callback function which uses the returned data as an argument.
18 | * @param {function} errorCallback - Callback function to use if there's an error.
19 | * @return response data from Python/Flask service.
20 | * @memberof Requests
21 | */
22 | export const get = (route, callback, errorCallback = console.error) => {
23 | fetch(`http://localhost:${port}/${route}`)
24 | .then((response) => response.json())
25 | .then(callback)
26 | .catch(errorCallback);
27 | };
28 |
29 | /**
30 | * @description - Helper POST method for sending requests to and from the Python/Flask services.
31 | * @param {string} body - JSON.stringified request body of data that you want to pass.
32 | * @param {string} route - URL route of the Python/Flask service you want to use.
33 | * @param {function} callback - optional callback function to be invoked if provided.
34 | * @param {function} errorCallback - Callback function to use if there's an error.
35 | * @return response data from Python/Flask service.
36 | * @memberof Requests
37 | */
38 | export const post = (body, route, callback, errorCallback = console.error) => {
39 | fetch(`http://localhost:${port}/${route}`, {
40 | body,
41 | method: 'POST',
42 | headers: { 'Content-type': 'application/json' }
43 | })
44 | .then((response) => response.json())
45 | .then(callback)
46 | .catch(errorCallback);
47 | };
48 |
49 | /**
50 | * @description - SocketIO client interface configuration.
51 | */
52 | export const socket = socketIOClient(`http://localhost:${port}/`);
53 |
--------------------------------------------------------------------------------
/src/utils/services.js:
--------------------------------------------------------------------------------
1 | import { socket } from 'utils/requests';
2 |
3 | // Electron Inter Process Communication and dialog
4 | const { ipcRenderer, remote } = window.require('electron');
5 | const { dialog } = remote;
6 |
7 | /**
8 | * @namespace Services
9 | * @description - Methods from Electron Inter Process Communication.
10 | * @property {function} maximize - Function to maximize the screen size of the program.
11 | * @property {function} minimize - Function to minimize the screen size of the program.
12 | * @property {function} quit - Function to close and exit the program.
13 | * @property {function} unmaximize - Function to contract (unmaximize) the screen size of the program.
14 | * @property {function} restart - Function to restart the app with the given spawn options.
15 | */
16 | export const app = {
17 | maximize: () => ipcRenderer.send('app-maximize'),
18 | minimize: () => ipcRenderer.send('app-minimize'),
19 | quit: () => ipcRenderer.send('app-quit'),
20 | reconnectionDelay: socket.io.reconnectionDelay(),
21 | restart: (options) => {
22 | socket.once('disconnect', () => {
23 | setTimeout(() => {
24 | ipcRenderer.send('app-restart', options);
25 | setTimeout(() => {
26 | socket.connect();
27 | }, app.reconnectionDelay);
28 | }, app.reconnectionDelay);
29 | });
30 |
31 | socket.disconnect();
32 | },
33 | unmaximize: () => ipcRenderer.send('app-unmaximize')
34 | };
35 |
36 | /**
37 | * @description - Function to get a list of files that a user wants to have renamed, this
38 | * also returns the folder path and name the user has selected.
39 | * @return - User selected folder path.
40 | * @memberof Services
41 | */
42 | export const getDirectory = async (callback) => {
43 | dialog
44 | .showOpenDialog({ properties: ['openDirectory'] })
45 | .then((response) => {
46 | return response.canceled
47 | ? null
48 | : callback(String.raw`${response.filePaths[0]}`);
49 | })
50 | .catch(console.error);
51 | };
52 |
--------------------------------------------------------------------------------
/src/utils/settings.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @namespace Settings
3 | * @description - Class to manage user settings in localStorage so they persist after
4 | * the application has closed.
5 | */
6 | class Settings {
7 | // Check if item exists in settings
8 | hasItem = (item) => this.getSettings()[item] !== null;
9 |
10 | // Get a specific item in settings (or `undefined`)
11 | getItem = (item) => this.getSettings()[item];
12 |
13 | // Get all settings and return as a JavaScript object literal
14 | getSettings = () => {
15 | const settings = window.localStorage.getItem(this.settingsId)
16 | ?? this.loadDefaultSettings();
17 |
18 | // Parse settings into JSON object
19 | const settingsJSON = JSON.parse(settings);
20 |
21 | // Return object literal of settings
22 | return settingsJSON;
23 | };
24 |
25 | // Load default settings
26 | loadDefaultSettings = () => {
27 | const settings = JSON.stringify({
28 | isDebugMode: false,
29 | isExtractSubtitles: false,
30 | isRemoveAds: false,
31 | isRememberOutputDir: false,
32 | isRemoveExistingSubtitles: false,
33 | isRemoveOld: false,
34 | isRemoveSubtitles: false,
35 | isSameAsSource: false,
36 | language: { key: 'eng', text: 'English' },
37 | outputDir: null,
38 | theme: 'dark'
39 | });
40 |
41 | window.localStorage.setItem(this.settingsId, settings);
42 |
43 | return settings;
44 | };
45 |
46 | // Delete an item if it exists, otherwise does nothing
47 | removeItem = (item) => {
48 | const settings = this.getSettings();
49 | delete settings[item];
50 |
51 | this.saveSettings(settings);
52 | };
53 |
54 | // Update settings object with new settings
55 | saveSettings = (settings) => {
56 | window.localStorage.setItem(this.settingsId, JSON.stringify(settings));
57 | };
58 |
59 | // Set item in settings
60 | setItem = (item, setting) =>
61 | this.saveSettings({
62 | ...this.getSettings(),
63 | [item]: setting
64 | });
65 |
66 | // ID used for various instances
67 | settingsId = 'mkvtoolnix-batch-tool-settings';
68 | }
69 |
70 | // Export instantiated version of settings
71 | export const settings = new Settings();
72 |
--------------------------------------------------------------------------------
/utilities/dmg/images/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/utilities/dmg/images/background.png
--------------------------------------------------------------------------------
/utilities/dmg/images/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/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 | [](https://www.npmjs.com/package/daybrush-jsdoc-template) [](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/binder.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | /**
3 | * @fileOverview allows you to bind a change watcher that looks for get and set operations on an arbitrary
4 | * property of an object at at any depth. This allows you to look for changes or intercept values asynchronously or otherwise.
5 | * @module documents/binder
6 | * @requires async
7 | * @requires documents/probe
8 | * @requires lodash
9 | * @requires promise
10 | */
11 | var Promise = require( 'promise' );
12 | var async = require( "async" );
13 | var probe = require( "./probe" );
14 | var sys = require( "lodash" );
15 |
16 | /**
17 | * Identifies the properties that the binder expects
18 | * @type {{getter: null, getterAsync: boolean, setter: null, validator: null, validatorAsync: boolean, setterAsync: boolean}}
19 | * @private
20 | */
21 | var dataBinderOptions = exports.dataBinderOptions = {
22 | getter : null,
23 | getterAsync : false,
24 | setter : null,
25 | validator : null,
26 | validatorAsync : false,
27 | setterAsync : false
28 | };
29 |
30 | /**
31 | * You can unbind previously bound objects from here.
32 | *
33 | * @param {string} path The path that was bound using {@link module:documents/binder.bind}
34 | * @param {*} record The object that was bound
35 | */
36 | exports.unbind = function ( path, record ) {
37 | var context = record;
38 | var lastParent = context;
39 | var parts = path.split( probe.delimiter );
40 | var lastPartName = path;
41 | var lastParentName;
42 | sys.each( parts, function ( part ) {
43 | lastParentName = part;
44 | lastParent = context;
45 | context = context[part];
46 | lastPartName = part;
47 | if ( sys.isNull( context ) || sys.isUndefined( context ) ) {
48 | context = {};
49 | }
50 | } );
51 |
52 | if ( lastParent === context ) {
53 | deleteBindings( record, lastPartName );
54 | } else {
55 | deleteBindings( lastParent, lastPartName );
56 | }
57 |
58 | function deleteBindings( mountPoint, mountName ) {
59 | mountPoint[mountName] = mountPoint["__" + mountName + "__"];
60 | delete mountPoint["__" + mountName + "__"];
61 | }
62 | };
63 |
64 | /**
65 | * Bind to a property somewhere in an object. The property is found using dot notation and can be arbitrarily deep.
66 | * @param {string} path The path into the object to locate the property. For instance this could be `"_id"`, `"name.last"`.
67 | * or `"some.really.really.long.path.including.an.array.2.name"`
68 | * @param {object} record Anything you can hang a property off of
69 | * @param {options} options What you wanna do with the doohicky when yoyu bind it.
70 | * @param {function(*):Promise|*=} options.getter This is the method to run when getting the value. When it runs, you will receive
71 | * a single parameter which is the current value as the object understands it. You can return the value directly, just raise an event or
72 | * whatever your little heart demands. However, if you are asynchronous, this will turn your return value into a promise, one of the
73 | * few places this system will embrace promises over node-like error passing and that is mainly because this is a getter so a return value
74 | * is particularly important. *
75 | * @param {*} options.getter.value The current value of the record
76 | * @param {function(err, value)=} options.getter.callback When asynchronous, return you value through this method using node style
77 | * error passing (the promise is handled for you by this method).
78 | * @param {boolean=} options.getterAsync When true (not truthy) the getter is treated asynchronously and returns a promise with your value.
79 | * @param {function(*, *, *)=} options.setter A setter method
80 | * @param {*} options.setter.newVal The new value
81 | * @param {*} options.setter.oldVal The old value
82 | * @param {*} options.setter.record The record hosting the change
83 | * @param {function(*, *, *, function=)=} options.validator If you want a validator to run before settings values, pass this guy in
84 | * @param {*} options.validator.newVal The new value
85 | * @param {*} options.validator.oldVal The old value
86 | * @param {*} options.validator.record The record hosting the change
87 | * @param {function(err)=} options.validator.callback If the validator is asynchronous, then pass your value back here, otherwise pass it back as a return value.
88 | * When you use an asynchronous instance, pass the error in the first value and then the rest of the parameters are yours to play with
89 | * @param {boolean=} options.validatorAsync When true (not truthy) the validator is treated asynchornously and returns a promise with your value.
90 | * @returns {*}
91 | */
92 | exports.bind = function ( path, record, options ) {
93 | options = sys.extend( {}, dataBinderOptions, options );
94 | var context = record;
95 | var lastParent = context;
96 | var parts = path.split( probe.delimiter );
97 | var lastPartName = path;
98 | var lastParentName;
99 |
100 | sys.each( parts, function ( part ) {
101 | lastParentName = part;
102 | lastParent = context;
103 | context = context[part];
104 | lastPartName = part;
105 | if ( sys.isNull( context ) || sys.isUndefined( context ) ) {
106 | context = {};
107 | }
108 | } );
109 |
110 | if ( lastParent === context ) {
111 | setUpBindings( record, lastPartName );
112 | } else {
113 | setUpBindings( lastParent, lastPartName );
114 | }
115 |
116 | function setUpBindings( mountPoint, mountName ) {
117 | mountPoint["__" + mountName + "__"] = mountPoint[mountName];
118 | Object.defineProperty( mountPoint, mountName, {
119 | get : function () {
120 | if ( sys.isFunction( options.getter ) ) {
121 | var promise;
122 | if ( options.getterAsync === true ) {
123 | promise = Promise.denodeify( options.getter );
124 | }
125 |
126 | if ( promise ) {
127 | return promise( mountPoint["__" + mountName + "__"] ).then( function ( val ) {
128 | mountPoint["__" + mountName + "__"] = val;
129 | } );
130 | } else {
131 | mountPoint["__" + mountName + "__"] = options.getter( mountPoint["__" + mountName + "__"] );
132 | return mountPoint["__" + mountName + "__"];
133 | }
134 |
135 | } else {
136 | return mountPoint["__" + mountName + "__"];
137 | }
138 | },
139 | set : function ( val ) {
140 | async.waterfall( [
141 | function ( done ) {
142 | if ( sys.isFunction( options.validator ) ) {
143 | if ( options.validatorAsync ) {
144 | options.validator( val, mountPoint["__" + mountName + "__"], record, done );
145 | } else {
146 | var res = options.validator( val, mountPoint["__" + mountName + "__"], record );
147 | if ( res === true ) {
148 | done();
149 | } else {
150 | done( res );
151 | }
152 | }
153 | } else {
154 | done();
155 | }
156 | },
157 | function ( done ) {
158 | if ( sys.isFunction( options.setter ) ) {
159 | if ( options.setterAsync === true ) {
160 | options.setter( val, mountPoint["__" + mountName + "__"], record, done );
161 | } else {
162 | done( null, options.setter( val, mountPoint["__" + mountName + "__"], record ) );
163 | }
164 | } else {
165 | done( null, val );
166 | }
167 | }
168 | ], function ( err, newVal ) {
169 | if ( err ) { throw new Error( err ); }
170 | mountPoint["__" + mountName + "__"] = newVal;
171 | } );
172 |
173 | }
174 | } );
175 | }
176 |
177 | return context;
178 | };
179 |
--------------------------------------------------------------------------------
/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/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/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 |
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 |
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 |
24 |
25 |
26 |
27 | - Version:
28 |
29 |
30 |
31 |
32 | - Since:
33 |
34 |
35 |
36 |
37 | - Inherited From:
38 |
41 |
42 |
43 |
44 | - Overrides:
45 |
48 |
49 |
50 |
51 | - Implementations:
52 |
57 |
58 |
59 |
60 | - Implements:
61 |
66 |
67 |
68 |
69 | - Mixes In:
70 |
71 |
76 |
77 |
78 |
79 | - Deprecated:
83 |
84 |
85 |
86 | - Author:
87 | -
88 |
91 |
92 |
93 |
94 |
95 | - Copyright:
96 |
97 |
98 |
99 |
100 | - License:
101 |
102 |
103 |
104 |
105 | - Default Value:
106 |
109 |
110 |
111 |
112 | - Tutorials:
113 | -
114 |
117 |
118 |
119 |
120 |
121 | - See:
122 | -
123 |
126 |
127 |
128 |
129 |
130 | - To Do:
131 | -
132 |
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 | - 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 |
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 |
26 |
27 |
28 |
29 | Fires:
30 |
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 |
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 |
79 |
80 |
81 |
82 | Fires:
83 |
86 |
87 |
88 |
89 | Listens to Events:
90 |
93 |
94 |
95 |
96 | Listeners of This Event:
97 |
100 |
101 |
102 |
103 | Throws:
104 | 1) { ?>
110 |
111 |
113 |
114 |
115 | Returns:
116 | 1) { ?>
122 |
123 |
125 |
126 |
--------------------------------------------------------------------------------
/utilities/jsdoc/tmpl/params.tmpl:
--------------------------------------------------------------------------------
1 |
52 |
53 |
54 |
55 |
56 |
57 | Name |
58 |
59 |
60 | Type |
61 |
62 |
63 | Attributes |
64 |
65 |
66 |
67 | Default |
68 |
69 |
70 | Description |
71 |
72 |
73 |
74 |
75 |
80 |
81 |
82 |
83 | ? |
84 |
85 |
86 |
87 |
88 |
89 |
90 | |
91 |
92 |
93 |
94 |
95 |
96 | <nullable>
97 |
98 |
99 |
100 | <repeatable>
101 |
102 | |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | |
111 |
112 |
113 |
114 | Properties
115 |
116 | |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/utilities/jsdoc/tmpl/properties.tmpl:
--------------------------------------------------------------------------------
1 |
41 |
42 |
43 |
44 |
45 |
46 | Name |
47 |
48 |
49 | Type |
50 |
51 |
52 | Attributes |
53 |
54 |
55 |
56 | Default |
57 |
58 |
59 | Description |
60 |
61 |
62 |
63 |
64 |
69 |
70 |
71 |
72 | ? |
73 |
74 |
75 |
76 |
77 |
78 |
79 | |
80 |
81 |
82 |
83 |
84 | <nullable>
85 |
86 | |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | |
95 |
96 |
97 |
98 | Properties
99 | |
100 |
101 |
102 |
103 |
104 |
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 |
--------------------------------------------------------------------------------
/utilities/jsdoc/tmpl/tutorial.tmpl:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 0) { ?>
5 |
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 |
--------------------------------------------------------------------------------
/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 |
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 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/utilities/msi/images/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/utilities/msi/images/background.png
--------------------------------------------------------------------------------
/utilities/msi/images/banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/utilities/msi/images/banner.png
--------------------------------------------------------------------------------
/utilities/msi/images/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/iPzard/mkvtoolnix-batch-tool/33821381e38cf89a0702cd8276f86ccf0dd3189f/utilities/msi/images/icon.ico
--------------------------------------------------------------------------------