├── .eslintignore
├── .eslintrc.json
├── .github
├── FUNDING.yml
└── workflows
│ └── docs.yml
├── .gitignore
├── .npmignore
├── .prettierrc.json
├── .vscode
└── settings.json
├── CHANGELOG.md
├── LICENSE
├── README.md
├── docs
├── config.toml
├── content
│ ├── _index.md
│ ├── getting-started
│ │ ├── _index.md
│ │ ├── overview.md
│ │ └── userchrome.md
│ └── guides
│ │ ├── _index.md
│ │ ├── includingAddons.md
│ │ └── removingPocket.md
├── sass
│ ├── _search.scss
│ ├── _variables.scss
│ ├── fabric-icons-inline.scss
│ └── main.scss
├── static
│ ├── images
│ │ └── userchrome
│ │ │ ├── browser-toolbox.png
│ │ │ ├── css-basic.png
│ │ │ ├── css-final.png
│ │ │ └── css-square-tabs.png
│ ├── js.js
│ └── logo.svg
├── templates
│ ├── anchor-link.html
│ ├── index.html
│ └── page.html
└── theme.toml
├── package.json
├── src
├── cmds.ts
├── commands
│ ├── bootstrap.ts
│ ├── bootstrap
│ │ ├── arch.ts
│ │ ├── debian.ts
│ │ └── macos.ts
│ ├── build.ts
│ ├── discard.ts
│ ├── download-artifacts.ts
│ ├── download.ts
│ ├── execute.ts
│ ├── export-file.ts
│ ├── fix-le.ts
│ ├── import-patches.ts
│ ├── index.ts
│ ├── init.ts
│ ├── license-check.ts
│ ├── linus.d.ts
│ ├── package.ts
│ ├── reset.ts
│ ├── run.ts
│ ├── set-branch.ts
│ ├── setupProject.ts
│ ├── status.ts
│ └── test.ts
├── constants
│ └── index.ts
├── controllers
│ ├── brandingPatch.ts
│ └── patch.ts
├── index.ts
├── interfaces
│ └── patch.ts
├── log.ts
├── manual-patches.ts
├── middleware
│ ├── patch-check.ts
│ ├── registerCommand.ts
│ ├── sha-check.ts
│ └── update-check.ts
├── types.d.ts
└── utils
│ ├── config.ts
│ ├── delay.ts
│ ├── dispatch.ts
│ ├── download.ts
│ ├── error-handler.ts
│ ├── fs.ts
│ ├── import.ts
│ ├── index.ts
│ ├── stringTemplate.ts
│ ├── version.ts
│ └── write-metadata.ts
├── template
├── .vscode
│ └── settings.json
├── branding.optional
│ ├── brand.dtd
│ ├── brand.ftl
│ └── brand.properties
├── configs
│ ├── common
│ │ └── mozconfig
│ ├── linux
│ │ ├── build_linux.sh
│ │ ├── linux.dockerfile
│ │ ├── mozconfig
│ │ └── mozconfig-i686
│ ├── macos
│ │ ├── build_macos.sh
│ │ ├── macos.dockerfile
│ │ ├── mozconfig
│ │ └── mozconfig-i686
│ └── windows
│ │ ├── mozconfig
│ │ └── mozconfig-i686
└── src
│ ├── README.md
│ ├── browser
│ ├── confvars-sh.patch.optional
│ └── themes.optional
│ │ ├── custom
│ │ ├── linux
│ │ │ └── linux.inc.css
│ │ ├── macos
│ │ │ └── macos.inc.css
│ │ ├── shared
│ │ │ └── shared.inc.css
│ │ └── windows
│ │ │ └── windows.inc.css
│ │ ├── linux
│ │ └── browser-css.patch
│ │ ├── osx
│ │ └── browser-css.patch
│ │ ├── shared
│ │ └── browser-inc-css.patch
│ │ └── windows
│ │ └── browser-css.patch
│ ├── customui.optional
│ ├── browser.html
│ ├── css
│ │ └── browser.css
│ ├── jar.mn
│ ├── moz.build
│ └── scripts
│ │ ├── browser.js
│ │ └── devtools.js
│ └── toolkit
│ └── toolkit-mozbuild.patch.optional
├── tsconfig.json
└── yarn.lock
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/
2 | node_modules/
3 | template/
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es2021": true,
4 | "node": true
5 | },
6 | "extends": [
7 | "eslint:recommended",
8 | "plugin:@typescript-eslint/recommended",
9 | "eslint-config-prettier"
10 | ],
11 | "parser": "@typescript-eslint/parser",
12 | "parserOptions": {
13 | "ecmaVersion": 12,
14 | "sourceType": "module"
15 | },
16 | "plugins": ["@typescript-eslint"],
17 | "rules": {}
18 | }
19 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: trickypr
4 | liberapay: dothq
5 | patreon: dothq
6 | custom: https://store.dothq.co
7 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Build docs
2 |
3 | on:
4 | push:
5 | paths:
6 | - 'docs/**'
7 | - '.github/**'
8 | workflow_dispatch:
9 |
10 | jobs:
11 | docs:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout 🛎️
15 | uses: actions/checkout@v2.3.1
16 |
17 | - name: Deploy docs
18 | uses: shalzz/zola-deploy-action@v0.13.0
19 | env:
20 | # Target branch
21 | PAGES_BRANCH: gh-pages
22 | BUILD_DIR: docs/
23 | # Provide personal access token
24 | TOKEN: ${{ secrets.TOKEN }}
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 |
12 | # Runtime data
13 | pids
14 | *.pid
15 | *.seed
16 | *.pid.lock
17 |
18 | # Directory for instrumented libs generated by jscoverage/JSCover
19 | lib-cov
20 |
21 | # Coverage directory used by tools like istanbul
22 | coverage
23 | *.lcov
24 |
25 | # nyc test coverage
26 | .nyc_output
27 |
28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29 | .grunt
30 |
31 | # Bower dependency directory (https://bower.io/)
32 | bower_components
33 |
34 | # node-waf configuration
35 | .lock-wscript
36 |
37 | # Compiled binary addons (https://nodejs.org/api/addons.html)
38 | build/Release
39 |
40 | # Dependency directories
41 | node_modules/
42 | jspm_packages/
43 |
44 | # TypeScript v1 declaration files
45 | typings/
46 |
47 | # TypeScript cache
48 | *.tsbuildinfo
49 |
50 | # Optional npm cache directory
51 | .npm
52 |
53 | # Optional eslint cache
54 | .eslintcache
55 |
56 | # Microbundle cache
57 | .rpt2_cache/
58 | .rts2_cache_cjs/
59 | .rts2_cache_es/
60 | .rts2_cache_umd/
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # Next.js build output
79 | .next
80 |
81 | # Nuxt.js build / generate output
82 | .nuxt
83 | dist
84 |
85 | # Gatsby files
86 | .cache/
87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
88 | # https://nextjs.org/blog/next-9-1#public-directory-support
89 | # public
90 |
91 | # vuepress build output
92 | .vuepress/dist
93 |
94 | # Serverless directories
95 | .serverless/
96 |
97 | # FuseBox cache
98 | .fusebox/
99 |
100 | # DynamoDB Local files
101 | .dynamodb/
102 |
103 | # TernJS port file
104 | .tern-port
105 |
106 | testing/
107 |
108 | site/
109 |
110 | docs/public/
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | testing/
2 | node_modules/
3 | src/
4 | !template/src/
5 | docs/
6 | site/
7 |
8 | .prettierrc.json
9 | melon.json
10 | tsconfig.json
11 | yarn.lock
12 | .eslintignore
13 | .eslintrc.json
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "tabWidth": 2,
3 | "useTabs": false,
4 | "semi": false,
5 | "singleQuote": true,
6 | "trailingComma": "es5"
7 | }
8 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "gitmoji.additionalEmojis": [
3 | {
4 | "emoji": "🔄",
5 | "code": ":arrows_counterclockwise:",
6 | "description": "Update changelog"
7 | }
8 | ]
9 | }
10 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | All notable changes to this project will be documented in this file.
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 |
8 | ## [Unreleased]
9 |
10 | ## [1.0.0-a.11]
11 |
12 | ### Fixed
13 |
14 | - Put the copy inputs around the right way
15 |
16 | ## [1.0.0-a.9]
17 |
18 | ### Fixed
19 |
20 | - Work around windows users not having the permissions to create symbolic links
21 |
22 | ## [1.0.0-a.8]
23 |
24 | ### Fixed
25 |
26 | - Windows tar compatibility
27 | - Make the progress bar be less flickery
28 | - `fs-extra` is being used for symlinks for cross-platform compatibility
29 |
30 | ### Changed
31 |
32 | - Windows now uses the same init script as everyone else
33 |
34 | ## [1.0.0-a.7]
35 |
36 | ### Fixed
37 |
38 | - Stop updates from crashing melon
39 | - Correct the api backend for updates
40 | - Stop crashes when symlinks don't exist
41 | - Error outputs are cleaner
42 | - Branding generators do not crash as much
43 | - Partly inited engine folders will not trigger unusual errors
44 | - Better error output when `bsdtar` causes errors
45 |
46 | ### Changed
47 |
48 | - The status command is now mildly more helpful
49 | - Removed unnecessary delays, improving performance
50 | - `export` is now an alias for `export-file`
51 | - Discard command now uses git instead of trying to download from firefox's source
52 | - Add the possibility of multiple branding types
53 | - Branding generator will regenerate locale files if the correct options are specified
54 | - Branding generator creates custom color for about page
55 |
56 | ### Added
57 |
58 | - Debian bootstrap
59 | - Verbose logging mode
60 | - Addons can be included
61 |
62 | ### Removed
63 |
64 | - `fs-extra` is no longer a depenancy
65 |
66 | ## [1.0.0-a.6]
67 |
68 | ### Fixed
69 |
70 | - Builds do not double count `#!/bin/node`
71 | - Run branding generator as a patch
72 |
73 | ## [1.0.0-a.5]
74 |
75 | ### Added
76 |
77 | - Userchrome docs
78 | - Basic branding generator
79 |
80 | ## [1.0.0-a.4]
81 |
82 | ### Added
83 |
84 | - Open devtools and reload button for custom UI
85 |
86 | ### Fixed
87 |
88 | - Theming patches don't cause errors now
89 | - Custom UI template compiles and runs
90 |
91 | ### Removed
92 |
93 | - Remove the melon executable from the template
94 |
95 | ## [1.0.0-a.3]
96 |
97 | ### Fixed
98 |
99 | - Include `template/src/`
100 |
101 | ## [1.0.0-a.2]
102 |
103 | ### Added
104 |
105 | - Initial beta release
106 |
107 | [unreleased]: https://github.com/dothq/melon/compare/v1.0.0-a.9...HEAD
108 | [1.0.0-a.9]: https://github.com/dothq/melon/compare/v1.0.0-a.8...v1.0.0-a.9
109 | [1.0.0-a.8]: https://github.com/dothq/melon/compare/v1.0.0-a.7...v1.0.0-a.8
110 | [1.0.0-a.7]: https://github.com/dothq/melon/compare/v1.0.0-a.6...v1.0.0-a.7
111 | [1.0.0-a.6]: https://github.com/dothq/melon/compare/v1.0.0-a.5...v1.0.0-a.6
112 | [1.0.0-a.5]: https://github.com/dothq/melon/compare/v1.0.0-a.4...v1.0.0-a.5
113 | [1.0.0-a.4]: https://github.com/dothq/melon/compare/v1.0.0-a.3...v1.0.0-a.4
114 | [1.0.0-a.3]: https://github.com/dothq/melon/compare/v1.0.0-a.2...v1.0.0-a.3
115 | [1.0.0-a.2]: https://github.com/dothq/melon/compare/v1.0.0-a.1...v1.0.0-a.2
116 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Mozilla Public License Version 2.0
2 | ==================================
3 |
4 | 1. Definitions
5 | --------------
6 |
7 | 1.1. "Contributor"
8 | means each individual or legal entity that creates, contributes to
9 | the creation of, or owns Covered Software.
10 |
11 | 1.2. "Contributor Version"
12 | means the combination of the Contributions of others (if any) used
13 | by a Contributor and that particular Contributor's Contribution.
14 |
15 | 1.3. "Contribution"
16 | means Covered Software of a particular Contributor.
17 |
18 | 1.4. "Covered Software"
19 | means Source Code Form to which the initial Contributor has attached
20 | the notice in Exhibit A, the Executable Form of such Source Code
21 | Form, and Modifications of such Source Code Form, in each case
22 | including portions thereof.
23 |
24 | 1.5. "Incompatible With Secondary Licenses"
25 | means
26 |
27 | (a) that the initial Contributor has attached the notice described
28 | in Exhibit B to the Covered Software; or
29 |
30 | (b) that the Covered Software was made available under the terms of
31 | version 1.1 or earlier of the License, but not also under the
32 | terms of a Secondary License.
33 |
34 | 1.6. "Executable Form"
35 | means any form of the work other than Source Code Form.
36 |
37 | 1.7. "Larger Work"
38 | means a work that combines Covered Software with other material, in
39 | a separate file or files, that is not Covered Software.
40 |
41 | 1.8. "License"
42 | means this document.
43 |
44 | 1.9. "Licensable"
45 | means having the right to grant, to the maximum extent possible,
46 | whether at the time of the initial grant or subsequently, any and
47 | all of the rights conveyed by this License.
48 |
49 | 1.10. "Modifications"
50 | means any of the following:
51 |
52 | (a) any file in Source Code Form that results from an addition to,
53 | deletion from, or modification of the contents of Covered
54 | Software; or
55 |
56 | (b) any new file in Source Code Form that contains any Covered
57 | Software.
58 |
59 | 1.11. "Patent Claims" of a Contributor
60 | means any patent claim(s), including without limitation, method,
61 | process, and apparatus claims, in any patent Licensable by such
62 | Contributor that would be infringed, but for the grant of the
63 | License, by the making, using, selling, offering for sale, having
64 | made, import, or transfer of either its Contributions or its
65 | Contributor Version.
66 |
67 | 1.12. "Secondary License"
68 | means either the GNU General Public License, Version 2.0, the GNU
69 | Lesser General Public License, Version 2.1, the GNU Affero General
70 | Public License, Version 3.0, or any later versions of those
71 | licenses.
72 |
73 | 1.13. "Source Code Form"
74 | means the form of the work preferred for making modifications.
75 |
76 | 1.14. "You" (or "Your")
77 | means an individual or a legal entity exercising rights under this
78 | License. For legal entities, "You" includes any entity that
79 | controls, is controlled by, or is under common control with You. For
80 | purposes of this definition, "control" means (a) the power, direct
81 | or indirect, to cause the direction or management of such entity,
82 | whether by contract or otherwise, or (b) ownership of more than
83 | fifty percent (50%) of the outstanding shares or beneficial
84 | ownership of such entity.
85 |
86 | 2. License Grants and Conditions
87 | --------------------------------
88 |
89 | 2.1. Grants
90 |
91 | Each Contributor hereby grants You a world-wide, royalty-free,
92 | non-exclusive license:
93 |
94 | (a) under intellectual property rights (other than patent or trademark)
95 | Licensable by such Contributor to use, reproduce, make available,
96 | modify, display, perform, distribute, and otherwise exploit its
97 | Contributions, either on an unmodified basis, with Modifications, or
98 | as part of a Larger Work; and
99 |
100 | (b) under Patent Claims of such Contributor to make, use, sell, offer
101 | for sale, have made, import, and otherwise transfer either its
102 | Contributions or its Contributor Version.
103 |
104 | 2.2. Effective Date
105 |
106 | The licenses granted in Section 2.1 with respect to any Contribution
107 | become effective for each Contribution on the date the Contributor first
108 | distributes such Contribution.
109 |
110 | 2.3. Limitations on Grant Scope
111 |
112 | The licenses granted in this Section 2 are the only rights granted under
113 | this License. No additional rights or licenses will be implied from the
114 | distribution or licensing of Covered Software under this License.
115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a
116 | Contributor:
117 |
118 | (a) for any code that a Contributor has removed from Covered Software;
119 | or
120 |
121 | (b) for infringements caused by: (i) Your and any other third party's
122 | modifications of Covered Software, or (ii) the combination of its
123 | Contributions with other software (except as part of its Contributor
124 | Version); or
125 |
126 | (c) under Patent Claims infringed by Covered Software in the absence of
127 | its Contributions.
128 |
129 | This License does not grant any rights in the trademarks, service marks,
130 | or logos of any Contributor (except as may be necessary to comply with
131 | the notice requirements in Section 3.4).
132 |
133 | 2.4. Subsequent Licenses
134 |
135 | No Contributor makes additional grants as a result of Your choice to
136 | distribute the Covered Software under a subsequent version of this
137 | License (see Section 10.2) or under the terms of a Secondary License (if
138 | permitted under the terms of Section 3.3).
139 |
140 | 2.5. Representation
141 |
142 | Each Contributor represents that the Contributor believes its
143 | Contributions are its original creation(s) or it has sufficient rights
144 | to grant the rights to its Contributions conveyed by this License.
145 |
146 | 2.6. Fair Use
147 |
148 | This License is not intended to limit any rights You have under
149 | applicable copyright doctrines of fair use, fair dealing, or other
150 | equivalents.
151 |
152 | 2.7. Conditions
153 |
154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
155 | in Section 2.1.
156 |
157 | 3. Responsibilities
158 | -------------------
159 |
160 | 3.1. Distribution of Source Form
161 |
162 | All distribution of Covered Software in Source Code Form, including any
163 | Modifications that You create or to which You contribute, must be under
164 | the terms of this License. You must inform recipients that the Source
165 | Code Form of the Covered Software is governed by the terms of this
166 | License, and how they can obtain a copy of this License. You may not
167 | attempt to alter or restrict the recipients' rights in the Source Code
168 | Form.
169 |
170 | 3.2. Distribution of Executable Form
171 |
172 | If You distribute Covered Software in Executable Form then:
173 |
174 | (a) such Covered Software must also be made available in Source Code
175 | Form, as described in Section 3.1, and You must inform recipients of
176 | the Executable Form how they can obtain a copy of such Source Code
177 | Form by reasonable means in a timely manner, at a charge no more
178 | than the cost of distribution to the recipient; and
179 |
180 | (b) You may distribute such Executable Form under the terms of this
181 | License, or sublicense it under different terms, provided that the
182 | license for the Executable Form does not attempt to limit or alter
183 | the recipients' rights in the Source Code Form under this License.
184 |
185 | 3.3. Distribution of a Larger Work
186 |
187 | You may create and distribute a Larger Work under terms of Your choice,
188 | provided that You also comply with the requirements of this License for
189 | the Covered Software. If the Larger Work is a combination of Covered
190 | Software with a work governed by one or more Secondary Licenses, and the
191 | Covered Software is not Incompatible With Secondary Licenses, this
192 | License permits You to additionally distribute such Covered Software
193 | under the terms of such Secondary License(s), so that the recipient of
194 | the Larger Work may, at their option, further distribute the Covered
195 | Software under the terms of either this License or such Secondary
196 | License(s).
197 |
198 | 3.4. Notices
199 |
200 | You may not remove or alter the substance of any license notices
201 | (including copyright notices, patent notices, disclaimers of warranty,
202 | or limitations of liability) contained within the Source Code Form of
203 | the Covered Software, except that You may alter any license notices to
204 | the extent required to remedy known factual inaccuracies.
205 |
206 | 3.5. Application of Additional Terms
207 |
208 | You may choose to offer, and to charge a fee for, warranty, support,
209 | indemnity or liability obligations to one or more recipients of Covered
210 | Software. However, You may do so only on Your own behalf, and not on
211 | behalf of any Contributor. You must make it absolutely clear that any
212 | such warranty, support, indemnity, or liability obligation is offered by
213 | You alone, and You hereby agree to indemnify every Contributor for any
214 | liability incurred by such Contributor as a result of warranty, support,
215 | indemnity or liability terms You offer. You may include additional
216 | disclaimers of warranty and limitations of liability specific to any
217 | jurisdiction.
218 |
219 | 4. Inability to Comply Due to Statute or Regulation
220 | ---------------------------------------------------
221 |
222 | If it is impossible for You to comply with any of the terms of this
223 | License with respect to some or all of the Covered Software due to
224 | statute, judicial order, or regulation then You must: (a) comply with
225 | the terms of this License to the maximum extent possible; and (b)
226 | describe the limitations and the code they affect. Such description must
227 | be placed in a text file included with all distributions of the Covered
228 | Software under this License. Except to the extent prohibited by statute
229 | or regulation, such description must be sufficiently detailed for a
230 | recipient of ordinary skill to be able to understand it.
231 |
232 | 5. Termination
233 | --------------
234 |
235 | 5.1. The rights granted under this License will terminate automatically
236 | if You fail to comply with any of its terms. However, if You become
237 | compliant, then the rights granted under this License from a particular
238 | Contributor are reinstated (a) provisionally, unless and until such
239 | Contributor explicitly and finally terminates Your grants, and (b) on an
240 | ongoing basis, if such Contributor fails to notify You of the
241 | non-compliance by some reasonable means prior to 60 days after You have
242 | come back into compliance. Moreover, Your grants from a particular
243 | Contributor are reinstated on an ongoing basis if such Contributor
244 | notifies You of the non-compliance by some reasonable means, this is the
245 | first time You have received notice of non-compliance with this License
246 | from such Contributor, and You become compliant prior to 30 days after
247 | Your receipt of the notice.
248 |
249 | 5.2. If You initiate litigation against any entity by asserting a patent
250 | infringement claim (excluding declaratory judgment actions,
251 | counter-claims, and cross-claims) alleging that a Contributor Version
252 | directly or indirectly infringes any patent, then the rights granted to
253 | You by any and all Contributors for the Covered Software under Section
254 | 2.1 of this License shall terminate.
255 |
256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all
257 | end user license agreements (excluding distributors and resellers) which
258 | have been validly granted by You or Your distributors under this License
259 | prior to termination shall survive termination.
260 |
261 | ************************************************************************
262 | * *
263 | * 6. Disclaimer of Warranty *
264 | * ------------------------- *
265 | * *
266 | * Covered Software is provided under this License on an "as is" *
267 | * basis, without warranty of any kind, either expressed, implied, or *
268 | * statutory, including, without limitation, warranties that the *
269 | * Covered Software is free of defects, merchantable, fit for a *
270 | * particular purpose or non-infringing. The entire risk as to the *
271 | * quality and performance of the Covered Software is with You. *
272 | * Should any Covered Software prove defective in any respect, You *
273 | * (not any Contributor) assume the cost of any necessary servicing, *
274 | * repair, or correction. This disclaimer of warranty constitutes an *
275 | * essential part of this License. No use of any Covered Software is *
276 | * authorized under this License except under this disclaimer. *
277 | * *
278 | ************************************************************************
279 |
280 | ************************************************************************
281 | * *
282 | * 7. Limitation of Liability *
283 | * -------------------------- *
284 | * *
285 | * Under no circumstances and under no legal theory, whether tort *
286 | * (including negligence), contract, or otherwise, shall any *
287 | * Contributor, or anyone who distributes Covered Software as *
288 | * permitted above, be liable to You for any direct, indirect, *
289 | * special, incidental, or consequential damages of any character *
290 | * including, without limitation, damages for lost profits, loss of *
291 | * goodwill, work stoppage, computer failure or malfunction, or any *
292 | * and all other commercial damages or losses, even if such party *
293 | * shall have been informed of the possibility of such damages. This *
294 | * limitation of liability shall not apply to liability for death or *
295 | * personal injury resulting from such party's negligence to the *
296 | * extent applicable law prohibits such limitation. Some *
297 | * jurisdictions do not allow the exclusion or limitation of *
298 | * incidental or consequential damages, so this exclusion and *
299 | * limitation may not apply to You. *
300 | * *
301 | ************************************************************************
302 |
303 | 8. Litigation
304 | -------------
305 |
306 | Any litigation relating to this License may be brought only in the
307 | courts of a jurisdiction where the defendant maintains its principal
308 | place of business and such litigation shall be governed by laws of that
309 | jurisdiction, without reference to its conflict-of-law provisions.
310 | Nothing in this Section shall prevent a party's ability to bring
311 | cross-claims or counter-claims.
312 |
313 | 9. Miscellaneous
314 | ----------------
315 |
316 | This License represents the complete agreement concerning the subject
317 | matter hereof. If any provision of this License is held to be
318 | unenforceable, such provision shall be reformed only to the extent
319 | necessary to make it enforceable. Any law or regulation which provides
320 | that the language of a contract shall be construed against the drafter
321 | shall not be used to construe this License against a Contributor.
322 |
323 | 10. Versions of the License
324 | ---------------------------
325 |
326 | 10.1. New Versions
327 |
328 | Mozilla Foundation is the license steward. Except as provided in Section
329 | 10.3, no one other than the license steward has the right to modify or
330 | publish new versions of this License. Each version will be given a
331 | distinguishing version number.
332 |
333 | 10.2. Effect of New Versions
334 |
335 | You may distribute the Covered Software under the terms of the version
336 | of the License under which You originally received the Covered Software,
337 | or under the terms of any subsequent version published by the license
338 | steward.
339 |
340 | 10.3. Modified Versions
341 |
342 | If you create software not governed by this License, and you want to
343 | create a new license for such software, you may create and use a
344 | modified version of this License if you rename the license and remove
345 | any references to the name of the license steward (except to note that
346 | such modified license differs from this License).
347 |
348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary
349 | Licenses
350 |
351 | If You choose to distribute Source Code Form that is Incompatible With
352 | Secondary Licenses under the terms of this version of the License, the
353 | notice described in Exhibit B of this License must be attached.
354 |
355 | Exhibit A - Source Code Form License Notice
356 | -------------------------------------------
357 |
358 | This Source Code Form is subject to the terms of the Mozilla Public
359 | License, v. 2.0. If a copy of the MPL was not distributed with this
360 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
361 |
362 | If it is not possible or desirable to put the notice in a particular
363 | file, then You may include the notice in a location (such as a LICENSE
364 | file in a relevant directory) where a recipient would be likely to look
365 | for such a notice.
366 |
367 | You may add additional accurate notices of copyright ownership.
368 |
369 | Exhibit B - "Incompatible With Secondary Licenses" Notice
370 | ---------------------------------------------------------
371 |
372 | This Source Code Form is "Incompatible With Secondary Licenses", as
373 | defined by the Mozilla Public License, v. 2.0.
374 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Depreciation
2 |
3 | This project is no longer used or maintained by Dot HQ. The [Pulse Browser](https://pulsebrowser.app/) developers [maintain and support a fork](https://github.com/pulse-browser/gluon).
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | # Melon
12 |
13 | Build Firefox-based browsers with ease
14 |
15 | **This is still in a prerelease / prototype phase. Changes will be made, things will be broken**
16 |
17 |
18 |
19 | ## Installation
20 |
21 | Per project (recommended):
22 |
23 | ```sh
24 | npm install melon-build
25 | # or
26 | yarn add melon-build
27 | ```
28 |
29 | Globally:
30 |
31 | ```sh
32 | npm install -g melon-build
33 | # or
34 | yarn global add melon-build
35 |
36 | # Note: Linux and mac users may have to run the above command with sudo
37 | ```
38 |
39 | ## Documentation
40 |
41 | Documentation is available on [Github pages](https://dothq.github.io/melon/) or in the docs folder of this repository.
42 |
43 | ## Licencing notes
44 |
45 | The following is included in good faith. The writer is not a lawyer, and this is not legal advice.
46 |
47 | ### Melon
48 |
49 | Melon has been extracted from the [desktop version of Dot Browser](https://github.com/dothq/browser-desktop) under MPL v2.0.
50 |
51 | This Source Code Form is subject to the terms of the Mozilla Public
52 | License, v. 2.0. If a copy of the MPL was not distributed with this
53 | file, You can obtain one at http://mozilla.org/MPL/2.0/.
54 |
55 | ### Firefox
56 |
57 | This program downloads and modifies Firefox. [Follow their license](https://hg.mozilla.org/mozilla-central/file/tip/LICENSE) when distributing your program.
58 |
59 | ### Tweemoji
60 |
61 | The melon icon is from tweemoji.
62 |
63 | Copyright 2020 Twitter, Inc and other contributors
64 | Code licensed under the MIT License: http://opensource.org/licenses/MIT
65 | Graphics licensed under CC-BY 4.0: https://creativecommons.org/licenses/by/4.0/
66 |
--------------------------------------------------------------------------------
/docs/config.toml:
--------------------------------------------------------------------------------
1 | base_url = "/melon/"
2 | title = "Melon docs"
3 | compile_sass = true
4 | build_search_index = true
5 |
6 | [markdown]
7 | highlight_code = true
8 | highlight_theme = "base16-ocean-dark"
9 |
10 | [extra]
11 | logo = "https://camo.githubusercontent.com/d8b2046aa769e171cb4c89d0f86dfb52c7f677ff287c2b5ac9451ae3d45b2ef3/68747470733a2f2f7477656d6f6a692e6d617863646e2e636f6d2f762f31332e302e312f7376672f31663334392e737667"
12 | release = "https://api.github.com/repos/dothq/melon/releases/latest"
13 | favicon = "https://www.dothq.co/favicon.png"
14 |
--------------------------------------------------------------------------------
/docs/content/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "index"
3 | insert_anchor_links = "right"
4 | +++
5 |
6 | ## Welcome to the melon docs
7 |
8 | If you are new here, you should read the [Getting Started](./getting-started/overview/) guide.
9 |
--------------------------------------------------------------------------------
/docs/content/getting-started/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Getting Started"
3 | weight = 1
4 | sort_by = "weight"
5 | +++
6 |
--------------------------------------------------------------------------------
/docs/content/getting-started/overview.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Overview"
3 | weight = 5
4 | +++
5 |
6 | ## Getting started with melon
7 |
8 | ### What is melon
9 |
10 | Melon is a build tool and documentation for creating firefox-based browsers. Its goal is to simplify the process of creating web browsers to encourage competition and development within the space.
11 |
12 | ### Getting help
13 |
14 | If you are having problems with following these instructions, or with melon in general, please contact us. You can [create a discussion on github](https://github.com/dothq/melon/discussions/new), ping @trickypr on the [Dot HQ discord](https://dothq.link/dsc), or [join our Matrix chat](https://dothq.link/matrix).
15 |
16 | ### System requirements
17 |
18 | - **OS**: Linux, Windows, MacOS (We only have active contributors on linux, so other platforms might be a touch buggy)
19 | - **Melon dependencies**: NodeJS and npm
20 | - **Browser dependencies**: TODO: find out what firefox's build dependencies are
21 |
22 | ### Getting started
23 |
24 | The first thing you are going to need to do is to install melon. As it is a nodejs program it can be installed through npm or yarn.
25 |
26 | ```sh
27 | npm install -g melon-build
28 | # or
29 | yarn global add melon-build
30 |
31 | # Note: Linux and mac users may have to run the above command with sudo
32 | ```
33 |
34 | Now create a git repo and clone it to your local machine. Then run `melon setup-project` inside of that repo. This will ask you a variety of questions in relation to your project setup. Firstly, the release of the browser you want to bind to.
35 |
36 | - `Firefox nightly`: Updates every 12 hours, making it almost impossible to keep up to date **(not recommended)**
37 | - `Firefox beta`: Updates every 4 weeks. It will have unresolved bugs **(not recommended)**
38 | - `Firefox developer edition`: Tracks firefox beta **(not recommended)**
39 | - `Firefox stable`: Releases around every 4 weeks, however has most of the bugs from beta fixed
40 | - `Firefox extended support release (newer)`: The latest extended support release. Releases around once every 8 stable cycles (mozilla isn't clear on this). Receives regular small security patches and bug fixes, but no large breaking changes (e.g. [proton](https://www.omgubuntu.co.uk/2021/02/try-firefox-proton-redesign-ubuntu)) between releases.
41 | - `Firefox extended support release (newer)`: The oldest supported extended support release. Maximum security and stability, but will lose support sooner than the newer extended support release.
42 |
43 | Dot browser currently uses the stable releases, and keeping up to date can be a struggle with a small development team.
44 |
45 | Then next is the version of the browser you want to use. By default melon will populate this with the latest version available, which we recommend using.
46 |
47 | Next it will ask for the name of your browser. Avoid references to firefox or other mozilla brands if you can.
48 |
49 | Vendor is the company (or solo developer) who is creating the browser.
50 |
51 | The appid follows reverse dns naming conventions. For example, DotHQ owns the domain `dothq.co`, so our browser is `co.dothq.browser`. If you do not have a domain, you can use your username / psudomim as the appid, e.g. `trickypr.watermelon`.
52 |
53 | Next you need to chose a starting template for your browser. You can go with userchrome, where you apply css changes to firefox or custom html, where you have to write everything (tabs, navigation, search boxes) yourself. We generally recommend userchrome for new users, as it has the lowest learning curve. Additionally, you can chose to use no template.
54 |
55 | Now you have created the directory structure for your project, you can build it for the first time. First, ask melon to download the firefox source.
56 |
57 | ```sh
58 | melon download
59 | ```
60 |
61 | After the source code has been downloaded, the changes to firefox described in the source code must be applied.
62 |
63 | ```sh
64 | melon import
65 | ```
66 |
67 | Finally, you can start building the firefox source code. This takes around an hour and a half on my computer, but the binary output will be cached, making later builds faster
68 |
69 | ```sh
70 | melon build
71 | ```
72 |
73 | Now you can finally start the browser!
74 |
75 | ```sh
76 | melon run
77 | ```
78 |
--------------------------------------------------------------------------------
/docs/content/getting-started/userchrome.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Userchrome"
3 | weight = 10
4 | +++
5 |
6 | This page will explain the process for applying custom css (or userchrome) to your new browser. I expect you to have already setup melon as described in the overview and have something that looks like the following on your screen.
7 |
8 | 
9 |
10 | The firefox window shown above is constructed from (x)html, styled with css and made dynamic with javascript. This means that the entire browser can be styled with custom css, called userchrome.
11 |
12 | If you selected the userchrome option when setting up the project, melon will have already created the theme files for you. `src/browser/themes/custom/shared/shared.inc.css` will be included on all platforms, whilst platform specific styles will be included from similar files in `src/browser/themes/custom`.
13 |
14 | Additionally, firefox has an equivalent to "inspect element", but for the browser. Click on the hamburger menu, select "More tools", then "Browser toolbox" to open it.
15 |
16 | 
17 |
18 | ## A touch of design
19 |
20 | This tutorial will attempt to replicate the design of [SimpleFox by Miguel R. Ávila](https://github.com/migueravila/SimpleFox), without copying its code. I would recommend creating your own visual identity for your browser.
21 |
22 | ## Squaring the tabs
23 |
24 | Firefox's proton made the tabs hover, with mixed reception. Let's reverse that.
25 |
26 | Using the select tool (top left of the browser toolbox) select the active tab and look for what element provides the background. In this case it is the `.tab-background` element.
27 |
28 | You can scroll down to find the code where the border radius is set. In firefox 91, this is:
29 |
30 | ```css
31 | .tab-background {
32 | border-radius: var(--tab-border-radius);
33 | margin-block: var(--tab-block-margin);
34 | }
35 | ```
36 |
37 | Firefox uses css variables for a lot of its properties, meaning we can make the tabs square by setting the border radius to 0. Here, the margin, which makes the tabs "float is set", so setting it to zero will cause them to stop floating. This can be done by adding the following line to `src/browser/themes/custom/shared/shared.inc.css`:
38 |
39 | ```css
40 | :root {
41 | --tab-border-radius: 0 !important;
42 | --tab-block-margin: 0 !important;
43 | }
44 | ```
45 |
46 | Rebuilding the browser, the tabs are now slightly closer to how we want them.
47 |
48 | 
49 |
50 | There is this weird padding to the left of the active tab. This is caused by the following css:
51 |
52 | ```css
53 | .tabbrowser-tab {
54 | min-height: var(--tab-min-height);
55 | padding-inline: 2px !important;
56 | }
57 | ```
58 |
59 | As mozilla are using `!important` here, we have to use [css priority](https://marksheet.io/css-priority.html) to override it, rather than simply creating our own style with `!important`.
60 |
61 | ```css
62 | #tabbrowser-arrowscrollbox .tabbrowser-tab {
63 | padding-inline: 0 !important;
64 | }
65 | ```
66 |
67 | Now, I want to remove the "Nightly" pill in the search bar, along with the background of it. Using the browser toolbox, we can figure out that we have to hide `#identity-icon-box`, remove the border on `#urlbar-background` and set `--toolbar-field-background-color` to the value of `--toolbar-bgcolor`.
68 |
69 | 
70 |
71 | I encourage you to experiment and customize your browser to fit what you want your browser to be.
72 |
73 | The source code for this tutorial can be found [here](https://github.com/trickypr/watermelon)
74 |
--------------------------------------------------------------------------------
/docs/content/guides/_index.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Guides"
3 | weight = 2
4 | sort_by = "weight"
5 | +++
6 |
--------------------------------------------------------------------------------
/docs/content/guides/includingAddons.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Including addons"
3 | weight = 10
4 | +++
5 |
6 | # Including addons
7 |
8 | Melon provides an automated system for including extensions in your project. The addons are downloaded and included during the `download` build step. Addons can be included in the project config (`melon.json`).
9 |
10 | ```json
11 | {
12 | // Your options here
13 | "addons": {
14 | "ublock": {
15 | "id": "uBlock0@raymondhill.net",
16 | "url": "https://github.com/gorhill/uBlock/releases/download/1.39.0/uBlock0_1.39.0.firefox.xpi"
17 | }
18 | }
19 | }
20 | ```
21 |
22 | Note that the `id` is the gecko application id specified in the `manifest.json`.
23 |
24 | ```json
25 | {
26 | // ...
27 |
28 | "browser_specific_settings": {
29 | "gecko": {
30 | "id": "uBlock0@raymondhill.net",
31 | "strict_min_version": "60.0"
32 | }
33 | }
34 |
35 | // ...
36 | }
37 | ```
38 |
39 | ## Specifying location in customizable ui
40 |
41 | By default, when an addon with a toolbar button, it will placed next to the hamburger menu. However, you may want to place it somewhere else. To do this, you must change the customizable ui in a similar way to how you would to remove pocket.
42 |
43 | You are going to want to open `engine/browser/components/customizableui/CustomizableUI.jsm`. At the top, you want to import the `ExtensionCommon` module.
44 |
45 | ```js
46 | const { makeWidgetId } = ChromeUtils.import(
47 | 'resource://gre/modules/ExtensionCommon.jsm'
48 | ).ExtensionCommon
49 | ```
50 |
51 | Then, at the top add a constant with the id of the addon at the top of the file, for example:
52 |
53 | ```js
54 | const kUBlockOriginID = 'uBlock0@raymondhill.net'
55 | ```
56 |
57 | Now, you can go down to the `navbarPlacements` array (around line 240) and add
58 |
59 | ```js
60 | `${makeWidgetId(kUBlockOriginID)}-browser-action`,
61 | ```
62 |
63 | To the array where you want the icon to appear, for example:
64 |
65 | ```js
66 | let navbarPlacements = [
67 | 'back-button',
68 | 'forward-button',
69 | 'stop-reload-button',
70 | Services.policies.isAllowed('removeHomeButtonByDefault')
71 | ? null
72 | : 'home-button',
73 | 'spring',
74 | `${makeWidgetId(kUBlockOriginID)}-browser-action`,
75 | 'urlbar-container',
76 | 'spring',
77 | 'save-to-pocket-button',
78 | 'downloads-button',
79 | AppConstants.MOZ_DEV_EDITION ? 'developer-button' : null,
80 | 'fxa-toolbar-menu-button',
81 | ].filter((name) => name)
82 | ```
83 |
84 | Finally, export the changes you have made:
85 |
86 | ```sh
87 | melon export-file browser/components/customizableui/CustomizableUI.jsm
88 | ```
89 |
--------------------------------------------------------------------------------
/docs/content/guides/removingPocket.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Removing pocket"
3 | weight = 5
4 | +++
5 |
6 | # Removing pocket
7 |
8 | **Note:** This expects you have melon setup.
9 |
10 | ## Disabling in firefox.js
11 |
12 | The goal of this guide is to disable pocket and remove its icon from the toolbar. The first changes we will need to make is to the firefox.js file located in `engine/browser/app/profile/firefox.js`. Scroll to the lines that include the following settings (around line 1980 in firefox 94):
13 |
14 | ```js
15 | pref('extensions.pocket.api', 'api.getpocket.com')
16 | pref('extensions.pocket.enabled', true)
17 | pref('extensions.pocket.oAuthConsumerKey', '40249-e88c401e1b1f2242d9e441c4')
18 | pref('extensions.pocket.site', 'getpocket.com')
19 | pref('extensions.pocket.onSaveRecs', true)
20 | pref('extensions.pocket.onSaveRecs.locales', 'en-US,en-GB,en-CA')
21 | ```
22 |
23 | Delete these lines and replace them with the following:
24 |
25 | ```js
26 | // Taken from BetterFox user.js
27 | user_pref('extensions.pocket.enabled', false)
28 | user_pref('extensions.pocket.api', ' ')
29 | user_pref('extensions.pocket.oAuthConsumerKey', ' ')
30 | user_pref('extensions.pocket.site', ' ')
31 | ```
32 |
33 | Next, you will need to remove pocket from the new tab page. You can do this by simply adding the following line to the bottom of `firefox.js`:
34 |
35 | ```js
36 | user_pref(
37 | 'browser.newtabpage.activity-stream.section.highlights.includePocket',
38 | false
39 | )
40 | ```
41 |
42 | Now you simply need to export the changes made to `firefox.js`:
43 |
44 | ```sh
45 | melon export-file browser/app/profile/firefox.js
46 | ```
47 |
48 | ## Removing pocket icon from toolbar
49 |
50 | Whilst the steps above will have disabled pocket. The pocket icon will still be visible in the toolbar. Instead you must remove it from the CustomizableUI layout. Open `engine/browser/components/customizableui/CustomizableUI.jsm` and find the array that looks like this (around line 240):
51 |
52 | ```js
53 | let navbarPlacements = [
54 | 'back-button',
55 | 'forward-button',
56 | 'stop-reload-button',
57 | Services.policies.isAllowed('removeHomeButtonByDefault')
58 | ? null
59 | : 'home-button',
60 | 'spring',
61 | 'urlbar-container',
62 | 'spring',
63 | 'save-to-pocket-button',
64 | 'downloads-button',
65 | AppConstants.MOZ_DEV_EDITION ? 'developer-button' : null,
66 | 'fxa-toolbar-menu-button',
67 | ].filter((name) => name)
68 | ```
69 |
70 | Remove the `save-to-pocket-button` item from the array and export the changes:
71 |
72 | ```sh
73 | melon export-file browser/components/customizableui/CustomizableUI.jsm
74 | ```
75 |
--------------------------------------------------------------------------------
/docs/sass/_search.scss:
--------------------------------------------------------------------------------
1 | .search-container {
2 | display: none;
3 |
4 | &--is-visible {
5 | display: block;
6 | width: 100%;
7 | }
8 |
9 | #search {
10 | width: 100%;
11 | display: block;
12 | border:none;
13 | border-left: 1px solid $color;
14 | padding:1px 0;
15 | text-align: left;
16 | line-height: $baseline;
17 | font-size: $font-size;
18 | font-family:$font-family;
19 | color:$color;
20 | background:transparent;
21 | }
22 |
23 | #search:focus {
24 | outline:none;
25 | border:none;
26 | }
27 |
28 | .search-results {
29 | &__header {
30 | font-weight: bold;
31 | padding: 1rem 0rem;
32 | }
33 |
34 | &__items {
35 | margin: 0 2vw;
36 | padding: 0;
37 | list-style: circle;
38 | }
39 |
40 | &__item {
41 | margin-bottom: 1rem;
42 | }
43 |
44 | &__teaser {
45 |
46 | }
47 | }
48 | }
49 |
50 | #on_right {
51 | display: block;
52 | text-align: right;
53 | margin-bottom: $baseline;
54 | }
55 |
56 | #search-ico {
57 | font-family: 'FabricMDL2Icons';
58 | cursor: pointer;
59 | font-size: $baseline;
60 | line-height: 1;
61 | }
--------------------------------------------------------------------------------
/docs/sass/_variables.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | --bg: #f9f9f9;
3 | --fg: #222;
4 |
5 | --links: #00f;
6 | --hover-links: #c00;
7 | --visited-links: #009;
8 | }
9 |
10 | @media (prefers-color-scheme: dark) {
11 | :root {
12 | --bg: #333;
13 | --fg: #f9f9f9;
14 |
15 | --links: rgb(142, 142, 255);
16 | --hover-links: rgb(204, 101, 101);
17 | --visited-links: rgb(86, 86, 151);
18 | }
19 | }
20 |
21 | $baseline: 1.5rem;
22 |
23 | $background: var(--bg);
24 | $color: var(--fg);
25 |
26 | $links: var(--links);
27 | $hover-links: var(--hover-links);
28 | $visited-links: var(--visited-links);
29 |
30 | $font-size: 1.125rem;
31 | $font-family: Segoe UI, system-ui, -apple-system, sans-serif;
32 | $line-height: 1.75;
33 | $code_font: 400 1.125rem/1.75 SFMono-Regular, Consolas, Liberation Mono, Menlo,
34 | monospace;
35 |
--------------------------------------------------------------------------------
/docs/sass/fabric-icons-inline.scss:
--------------------------------------------------------------------------------
1 | /*
2 | Your use of the content in the files referenced here is subject to the terms of the license at https://aka.ms/fabric-assets-license
3 | */
4 | @font-face {
5 | font-family: 'FabricMDL2Icons';
6 | src: url('data:application/octet-stream;base64,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') format('truetype');
7 | }
8 |
9 | .ms-Icon {
10 | -moz-osx-font-smoothing: grayscale;
11 | -webkit-font-smoothing: antialiased;
12 | display: inline-block;
13 | font-family: 'FabricMDL2Icons';
14 | font-style: normal;
15 | font-weight: normal;
16 | speak: none;
17 | }
18 |
19 | // Mixins
20 | @mixin ms-Icon--ChevronRightSmall { content: "\E970"; }
21 | @mixin ms-Icon--ChromeClose { content: "\E8BB"; }
22 | @mixin ms-Icon--Copy { content: "\E8C8"; }
23 | @mixin ms-Icon--GlobalNavButton { content: "\E700"; }
24 | @mixin ms-Icon--MiniLink { content: "\E732"; }
25 | @mixin ms-Icon--Page { content: "\E7C3"; }
26 | @mixin ms-Icon--ProductRelease { content: "\EE2E"; }
27 | @mixin ms-Icon--Save { content: "\E74E"; }
28 | @mixin ms-Icon--Search { content: "\E721"; }
29 |
30 |
31 | // Classes
32 | .ms-Icon--ChevronRightSmall:before { @include ms-Icon--ChevronRightSmall }
33 | .ms-Icon--ChromeClose:before { @include ms-Icon--ChromeClose }
34 | .ms-Icon--Copy:before { @include ms-Icon--Copy }
35 | .ms-Icon--GlobalNavButton:before { @include ms-Icon--GlobalNavButton }
36 | .ms-Icon--MiniLink:before { @include ms-Icon--MiniLink }
37 | .ms-Icon--Page:before { @include ms-Icon--Page }
38 | .ms-Icon--ProductRelease:before { @include ms-Icon--ProductRelease }
39 | .ms-Icon--Save:before { @include ms-Icon--Save }
40 | .ms-Icon--Search:before { @include ms-Icon--Search }
--------------------------------------------------------------------------------
/docs/sass/main.scss:
--------------------------------------------------------------------------------
1 | @import 'variables';
2 |
3 | html {
4 | font-kerning: normal;
5 | text-rendering: optimizeLegibility;
6 | scroll-behavior: smooth;
7 | }
8 |
9 | body {
10 | margin: $baseline 0;
11 | font-size: $font-size;
12 | font-family: $font-family;
13 | line-height: $line-height;
14 | background: $background;
15 | color: $color;
16 | }
17 |
18 | #wrap {
19 | max-width: 800px;
20 | }
21 |
22 | @keyframes fade-in {
23 | 0% {
24 | opacity: 0;
25 | }
26 |
27 | 50% {
28 | opacity: 0.8;
29 | }
30 |
31 | 100% {
32 | opacity: 1;
33 | }
34 | }
35 |
36 | a {
37 | &:link {
38 | color: $links;
39 | text-decoration: none;
40 | }
41 |
42 | &:hover {
43 | color: $hover-links;
44 | }
45 |
46 | &:visited {
47 | color: $visited-links;
48 | }
49 | }
50 |
51 | h1 {
52 | font-size: 3rem;
53 | }
54 |
55 | h2,
56 | h3,
57 | h4 {
58 | .anchor {
59 | visibility: hidden;
60 | text-decoration: none;
61 | cursor: pointer;
62 | line-height: 1;
63 | color: $color;
64 | }
65 |
66 | &:hover {
67 | .anchor {
68 | visibility: visible;
69 | animation: fade-in 0.3s ease-in-out;
70 | font-family: 'FabricMDL2Icons';
71 | }
72 | }
73 | }
74 |
75 | pre {
76 | margin: $baseline 0;
77 | border-radius: 4px;
78 | padding: $baseline;
79 | overflow: auto;
80 | position: relative;
81 |
82 | code {
83 | background: transparent;
84 |
85 | &::after {
86 | content: attr(data-lang);
87 | font-style: italic;
88 | line-height: 1;
89 | opacity: 0.3;
90 | position: absolute;
91 | bottom: $baseline;
92 | right: $baseline;
93 | z-index: 1;
94 | }
95 | }
96 | }
97 |
98 | code {
99 | font: $code_font;
100 | }
101 |
102 | .copy-code-button {
103 | font-family: 'FabricMDL2Icons';
104 | display: none;
105 | background: $background;
106 | border-radius: 4px;
107 | border: none;
108 | cursor: pointer;
109 | animation: fade-in 0.3s ease-in-out;
110 | font-size: $baseline;
111 | color: $color;
112 | z-index: 10;
113 | position: absolute;
114 | top: $baseline;
115 | right: $baseline;
116 | }
117 |
118 | pre:hover .copy-code-button {
119 | display: block;
120 | }
121 |
122 | nav {
123 | position: sticky;
124 | height: 92vh;
125 | top: $baseline;
126 | left: $baseline;
127 | bottom: $baseline;
128 | padding-right: $baseline;
129 | width: 20rem;
130 |
131 | img {
132 | width: 128px;
133 | }
134 |
135 | h1 {
136 | margin: 0;
137 | line-height: 1;
138 | }
139 | }
140 |
141 | #toc {
142 | margin-left: calc(#{$baseline} + #{$font-size});
143 | padding: 0;
144 | margin: 0 0 0 $baseline;
145 | font-size: 80%;
146 |
147 | li {
148 | color: $color;
149 | margin-left: $font-size;
150 |
151 | &::before {
152 | display: inline-block;
153 | content: '';
154 | }
155 |
156 | ul {
157 | padding: 0;
158 | }
159 | }
160 | }
161 |
162 | main {
163 | display: flex;
164 | flex-flow: row nowrap;
165 | animation: fade-in 0.4s ease-in-out;
166 | }
167 |
168 | #release {
169 | text-align: left;
170 | margin: $baseline 0;
171 |
172 | &::before {
173 | display: inline-block;
174 | content: '\EE2E';
175 | font-family: 'FabricMDL2Icons';
176 | margin-right: calc(#{$baseline} / 8);
177 | }
178 | }
179 |
180 | @keyframes slideIn {
181 | 0% {
182 | max-height: 0;
183 | opacity: 0;
184 | }
185 | 100% {
186 | max-height: 999px;
187 | opacity: 1;
188 | }
189 | }
190 | @keyframes slideOut {
191 | 0% {
192 | height: auto;
193 | opacity: 1;
194 | }
195 | 100% {
196 | height: 0;
197 | opacity: 0;
198 | }
199 | }
200 |
201 | nav label {
202 | display: block;
203 | }
204 |
205 | #trees {
206 | overflow-y: auto;
207 | height: 80%;
208 | }
209 |
210 | .subtree {
211 | overflow: hidden;
212 | margin: calc(#{$baseline} / 8) 0;
213 | transition: overflow 0.2s ease-in-out;
214 | padding: 0;
215 | }
216 |
217 | .tree-toggle-label {
218 | user-select: none;
219 | cursor: pointer;
220 | }
221 |
222 | .tree-toggle-label::before {
223 | display: inline-block;
224 | content: '\E970';
225 | font-family: 'FabricMDL2Icons';
226 | font-size: 0.75rem;
227 | transform: rotate(0deg);
228 | transform-origin: 50% 50% 0px;
229 | transition: transform 0.1s linear 0s;
230 | margin-right: 2px;
231 | }
232 |
233 | .tree-toggle {
234 | position: absolute;
235 | opacity: 0;
236 | z-index: -1;
237 | }
238 |
239 | .tree-toggle:checked + .tree-toggle-label::before {
240 | content: '\E970';
241 | font-family: 'FabricMDL2Icons';
242 | font-size: 0.75rem;
243 | transform: rotate(90deg);
244 | transform-origin: 50% 50% 0px;
245 | transition: transform 0.1s linear 0s;
246 | margin-right: 2px;
247 | }
248 |
249 | .tree-toggle:checked + .tree-toggle-label {
250 | font-weight: bold;
251 | }
252 |
253 | .tree-toggle + .tree-toggle-label + .subtree {
254 | animation-name: slideOut;
255 | animation-duration: 0.25s;
256 | animation-fill-mode: both;
257 | }
258 |
259 | .tree-toggle:checked + .tree-toggle-label + .subtree {
260 | animation-name: slideIn;
261 | animation-duration: 0.25s;
262 | animation-fill-mode: both;
263 | }
264 |
265 | .subtree li {
266 | list-style-type: none;
267 | margin-left: $baseline;
268 |
269 | a {
270 | color: $color;
271 | }
272 |
273 | &::before {
274 | content: '\E7C3';
275 | font-family: 'FabricMDL2Icons';
276 | font-size: 0.75rem;
277 | }
278 | }
279 |
280 | .active a {
281 | font-weight: bold;
282 | }
283 |
284 | article {
285 | width: calc(100% - (#{$baseline} * 4 + 20rem));
286 | margin-left: calc(#{$baseline} * 2);
287 |
288 | img {
289 | max-width: 100%;
290 | }
291 | }
292 |
293 | #mobile {
294 | display: none;
295 | }
296 |
297 | @media screen and (max-width: 1023px) {
298 | main {
299 | flex-flow: column nowrap;
300 | width: 100%;
301 | }
302 |
303 | nav {
304 | position: inherit;
305 | height: auto;
306 | margin: $baseline $baseline 0 $baseline;
307 | }
308 |
309 | article {
310 | width: calc(100% - (#{$baseline} * 2));
311 | margin: 0 $baseline;
312 | z-index: 1;
313 | }
314 |
315 | #mobile {
316 | font-family: 'FabricMDL2Icons';
317 | cursor: pointer;
318 | font-size: $baseline;
319 | margin: 0 $baseline 0 0;
320 | display: block;
321 | color: $color;
322 | }
323 |
324 | #trees {
325 | display: none;
326 | position: absolute;
327 | background: $background;
328 | height: auto;
329 | width: 100vw;
330 | z-index: 10;
331 | box-shadow: 0 2px 0 rgba(0, 0, 0, 0.1);
332 | }
333 |
334 | #on_right {
335 | margin-top: $baseline;
336 | }
337 | }
338 |
339 | @import 'fabric-icons-inline';
340 | @import 'search';
341 |
--------------------------------------------------------------------------------
/docs/static/images/userchrome/browser-toolbox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dothq/melon/775fa2cfe834ef437dc110bcc6b7a235dfe2f572/docs/static/images/userchrome/browser-toolbox.png
--------------------------------------------------------------------------------
/docs/static/images/userchrome/css-basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dothq/melon/775fa2cfe834ef437dc110bcc6b7a235dfe2f572/docs/static/images/userchrome/css-basic.png
--------------------------------------------------------------------------------
/docs/static/images/userchrome/css-final.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dothq/melon/775fa2cfe834ef437dc110bcc6b7a235dfe2f572/docs/static/images/userchrome/css-final.png
--------------------------------------------------------------------------------
/docs/static/images/userchrome/css-square-tabs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dothq/melon/775fa2cfe834ef437dc110bcc6b7a235dfe2f572/docs/static/images/userchrome/css-square-tabs.png
--------------------------------------------------------------------------------
/docs/static/js.js:
--------------------------------------------------------------------------------
1 | // search script, borrowed from book theme
2 |
3 | function debounce(func, wait) {
4 | let timeout;
5 |
6 | return function () {
7 | const context = this;
8 | const args = arguments;
9 | clearTimeout(timeout);
10 |
11 | timeout = setTimeout(() => {
12 | timeout = null;
13 | func.apply(context, args);
14 | }, wait);
15 | };
16 | }
17 |
18 | // Taken from mdbook
19 | // The strategy is as follows:
20 | // First, assign a value to each word in the document:
21 | // Words that correspond to search terms (stemmer aware): 40
22 | // Normal words: 2
23 | // First word in a sentence: 8
24 | // Then use a sliding window with a constant number of words and count the
25 | // sum of the values of the words within the window. Then use the window that got the
26 | // maximum sum. If there are multiple maximas, then get the last one.
27 | // Enclose the terms in .
28 | function makeTeaser(body, terms) {
29 | const TERM_WEIGHT = 40;
30 | const NORMAL_WORD_WEIGHT = 2;
31 | const FIRST_WORD_WEIGHT = 8;
32 | const TEASER_MAX_WORDS = 30;
33 |
34 | const stemmedTerms = terms.map((w) => elasticlunr.stemmer(w.toLowerCase()));
35 | let termFound = false;
36 | let index = 0;
37 | const weighted = []; // contains elements of ["word", weight, index_in_document]
38 |
39 | // split in sentences, then words
40 | const sentences = body.toLowerCase().split(". ");
41 |
42 | for (var i in sentences) {
43 | const words = sentences[i].split(" ");
44 | let value = FIRST_WORD_WEIGHT;
45 |
46 | for (const j in words) {
47 | var word = words[j];
48 |
49 | if (word.length > 0) {
50 | for (const k in stemmedTerms) {
51 | if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
52 | value = TERM_WEIGHT;
53 | termFound = true;
54 | }
55 | }
56 | weighted.push([word, value, index]);
57 | value = NORMAL_WORD_WEIGHT;
58 | }
59 |
60 | index += word.length;
61 | index += 1; // ' ' or '.' if last word in sentence
62 | }
63 |
64 | index += 1; // because we split at a two-char boundary '. '
65 | }
66 |
67 | if (weighted.length === 0) {
68 | return body;
69 | }
70 |
71 | const windowWeights = [];
72 | const windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
73 | // We add a window with all the weights first
74 | let curSum = 0;
75 | for (var i = 0; i < windowSize; i++) {
76 | curSum += weighted[i][1];
77 | }
78 | windowWeights.push(curSum);
79 |
80 | for (var i = 0; i < weighted.length - windowSize; i++) {
81 | curSum -= weighted[i][1];
82 | curSum += weighted[i + windowSize][1];
83 | windowWeights.push(curSum);
84 | }
85 |
86 | // If we didn't find the term, just pick the first window
87 | let maxSumIndex = 0;
88 | if (termFound) {
89 | let maxFound = 0;
90 | // backwards
91 | for (var i = windowWeights.length - 1; i >= 0; i--) {
92 | if (windowWeights[i] > maxFound) {
93 | maxFound = windowWeights[i];
94 | maxSumIndex = i;
95 | }
96 | }
97 | }
98 |
99 | const teaser = [];
100 | let startIndex = weighted[maxSumIndex][2];
101 | for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
102 | var word = weighted[i];
103 | if (startIndex < word[2]) {
104 | // missing text from index to start of `word`
105 | teaser.push(body.substring(startIndex, word[2]));
106 | startIndex = word[2];
107 | }
108 |
109 | // add around search terms
110 | if (word[1] === TERM_WEIGHT) {
111 | teaser.push("");
112 | }
113 | startIndex = word[2] + word[0].length;
114 | teaser.push(body.substring(word[2], startIndex));
115 |
116 | if (word[1] === TERM_WEIGHT) {
117 | teaser.push("");
118 | }
119 | }
120 | teaser.push("…");
121 | return teaser.join("");
122 | }
123 |
124 | function formatSearchResultItem(item, terms) {
125 | const li = document.createElement("li");
126 | li.classList.add("search-results__item");
127 | li.innerHTML = `${item.doc.title}`;
128 | li.innerHTML += `
You chose the option to customize the html of the browser. This means you inherit none of the UI or logic firefox has in relation to tabs, etc. I wish you the best of luck!
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/template/src/customui.optional/css/browser.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #333333;
3 | color: white;
4 | font-family: sans-serif;
5 | height: 100vh;
6 | margin: 0;
7 | }
8 |
9 | #grid {
10 | display: grid;
11 | grid-template-columns: 1fr 1fr;
12 | height: 100%;
13 | align-content: center;
14 | }
15 |
--------------------------------------------------------------------------------
/template/src/customui.optional/jar.mn:
--------------------------------------------------------------------------------
1 | browser.jar:
2 | % content customui %content/customui/ contentaccessible=yes
3 | content/customui/browser.html (browser.html)
4 | content/customui/css/ (css/**/**)
5 | content/customui/scripts/ (scripts/**/**)
--------------------------------------------------------------------------------
/template/src/customui.optional/moz.build:
--------------------------------------------------------------------------------
1 | JAR_MANIFESTS += ["jar.mn"]
--------------------------------------------------------------------------------
/template/src/customui.optional/scripts/browser.js:
--------------------------------------------------------------------------------
1 | import { launchDevTools } from './devtools.js'
2 |
3 | document.getElementById('launchDevTools').addEventListener('click', launchDevTools)
4 |
--------------------------------------------------------------------------------
/template/src/customui.optional/scripts/devtools.js:
--------------------------------------------------------------------------------
1 | const launcher = ChromeUtils.import(
2 | "resource://devtools/client/framework/browser-toolbox/Launcher.jsm"
3 | ).BrowserToolboxLauncher
4 |
5 | export function launchDevTools() {
6 | launcher.init()
7 | }
8 |
--------------------------------------------------------------------------------
/template/src/toolkit/toolkit-mozbuild.patch.optional:
--------------------------------------------------------------------------------
1 | diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild
2 | index fd9903bac5b07c655ee77c94f8f795b6773676ad..3127dc35fd8793b91ddd437f30b1917f6eff29ce 100644
3 | --- a/toolkit/toolkit.mozbuild
4 | +++ b/toolkit/toolkit.mozbuild
5 | @@ -202,3 +202,6 @@ if CONFIG['ENABLE_TESTS']:
6 |
7 | if CONFIG['FUZZING']:
8 | DIRS += ['/tools/fuzzing']
9 | +
10 | +# Custom UI toolkit
11 | +DIRS += ['/customui']
12 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */
4 | /* Basic Options */
5 | // "incremental": true, /* Enable incremental compilation */
6 | "target": "es2019" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
7 | "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
8 | // "lib": [], /* Specify library files to be included in the compilation. */
9 | // "allowJs": true, /* Allow javascript files to be compiled. */
10 | // "checkJs": true, /* Report errors in .js files. */
11 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
12 | // "declaration": true, /* Generates corresponding '.d.ts' file. */
13 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
14 | // "sourceMap": true, /* Generates corresponding '.map' file. */
15 | // "outFile": "./", /* Concatenate and emit output to single file. */
16 | "outDir": "./dist" /* Redirect output structure to the directory. */,
17 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
18 | // "composite": true, /* Enable project compilation */
19 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
20 | // "removeComments": true, /* Do not emit comments to output. */
21 | // "noEmit": true, /* Do not emit outputs. */
22 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */
23 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
24 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
25 | /* Strict Type-Checking Options */
26 | "strict": true /* Enable all strict type-checking options. */,
27 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
28 | // "strictNullChecks": true, /* Enable strict null checks. */
29 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */
30 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
31 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
32 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
33 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
34 | /* Additional Checks */
35 | // "noUnusedLocals": true, /* Report errors on unused locals. */
36 | // "noUnusedParameters": true, /* Report errors on unused parameters. */
37 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
38 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
39 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
40 | /* Module Resolution Options */
41 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
42 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
43 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
44 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
45 | // "typeRoots": [], /* List of folders to include type definitions from. */
46 | // "types": [], /* Type declaration files to be included in compilation. */,
47 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
48 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
49 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
50 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
51 | /* Source Map Options */
52 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
53 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
54 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
55 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
56 | /* Experimental Options */
57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
59 | /* Advanced Options */
60 | "skipLibCheck": true /* Skip type checking of declaration files. */,
61 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */,
62 |
63 | "resolveJsonModule": true
64 | },
65 | "exclude": [
66 | "node_modules/**/*",
67 | "**/firefox-*/**/*",
68 | "gecko",
69 | "**/engine/**/*"
70 | ]
71 | }
72 |
--------------------------------------------------------------------------------