├── .dockerignore ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .nvmrc ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.txt ├── Makefile ├── README.md ├── gulp ├── code-symbol-tags.js ├── enhance.js ├── extract.js ├── git.js ├── handlebars.js ├── links.js ├── math-formula.js ├── safeSymlink.js └── sidecarMetadata.js ├── gulpfile.babel.js ├── jenkins.bash ├── layouts ├── beyond-code.handlebars ├── guides.handlebars ├── reference.handlebars ├── software.handlebars └── tools.handlebars ├── package.json ├── partials ├── beyond-code │ └── sidebar.handlebars ├── contentWrapperEnd.handlebars ├── contentWrapperStart.handlebars ├── foot.handlebars ├── footer.handlebars ├── guides │ └── sidebar.handlebars ├── head.handlebars ├── header-full-with-sidebar.handlebars ├── mainNavMenu.handlebars ├── mainNavMenu │ └── item.handlebars ├── modules │ ├── dev-newsletter.handlebars │ └── friendbot4.handlebars ├── reference │ └── sidebar.handlebars ├── sidebarSubItems.handlebars ├── sidebarSubMenu.handlebars ├── siteLogo.handlebars ├── software │ └── sidebar.handlebars └── tools │ └── sidebar.handlebars ├── repos.json ├── src ├── .eslintrc ├── .gitkeep ├── go ├── guides ├── horizon ├── images │ ├── favicon │ │ ├── favicon.ico │ │ ├── icon-144x144.png │ │ ├── icon-152x152.png │ │ ├── icon-180x180.png │ │ └── icon-96x96.png │ ├── fonts │ │ ├── suisseintl-regular-webfont.woff │ │ ├── suisseintl-regular-webfont.woff2 │ │ ├── suisseintl-semibold-webfont.woff │ │ ├── suisseintl-semibold-webfont.woff2 │ │ ├── suisseintlmono-regular-webfont.woff │ │ └── suisseintlmono-regular-webfont.woff2 │ └── previews │ │ ├── landing-1.png │ │ └── landing-2.png ├── index.handlebars ├── interstellar ├── js-stellar-base ├── js-stellar-sdk ├── js │ ├── codeExamples.js │ ├── codeSymbolLinks.js │ ├── collapsibleListSet.js │ ├── endpointRef.js │ ├── footnotes.js │ ├── friendbot4.js │ ├── linkCheck.js │ └── syntaxHighlight.js ├── reference ├── software ├── stellar-core ├── styles │ ├── _anchorShortcut.scss │ ├── _backgrounds.scss │ ├── _codeExamples.scss │ ├── _collapsibleListSet.scss │ ├── _descriptionList.scss │ ├── _footnotes.scss │ ├── _friendbot4.scss │ ├── _graphics.scss │ ├── _header2016.scss │ ├── _icons.scss │ ├── _landing0616.scss │ ├── _mailSignup.scss │ ├── _mainNavMenu.scss │ ├── _mathFormula.scss │ ├── _popovers.scss │ ├── _reskinColors.scss │ ├── _siteFooter.scss │ ├── graphics │ │ ├── app-stack-bill.png │ │ ├── backArrow.svg │ │ ├── centaurus-120.png │ │ ├── check-id.png │ │ ├── circled-code-120.png │ │ ├── circled-folder-120.png │ │ ├── circled-horizon-120.png │ │ ├── codeWithOrbits.png │ │ ├── icon-create-account.svg │ │ ├── icon-guides.svg │ │ ├── icon-money.svg │ │ ├── icon-references.svg │ │ ├── icon-software.svg │ │ ├── icon-stellar-network.svg │ │ ├── ldark-github.png │ │ ├── ldark-keybase.png │ │ ├── ldark-paper.png │ │ ├── ldark-stackexchange.png │ │ ├── ldark-twitter.png │ │ ├── longDownArrow.png │ │ ├── nodeConnectedEarth.png │ │ ├── page-brick.png │ │ ├── page-code.png │ │ ├── page-writing.png │ │ ├── pencilOnEarth.png │ │ ├── prototype-gear.png │ │ ├── rocket.png │ │ ├── s-bigCogLittleCog.png │ │ ├── s-fileFolder.png │ │ ├── s-rectangularTree.png │ │ ├── s-stellarRocket.png │ │ ├── school-of-cash.png │ │ └── stars-texture.png │ ├── index.scss │ └── pages │ │ └── _landing.scss └── tools └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | repos 3 | Dockerfile 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | insert_final_newline = true 3 | 4 | [*.{js,md,handlebars,scss}] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | trim_trailing_whitespace = true 9 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | repos/**/* 2 | build/**/* 3 | src/js/vendor.js 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 6, 4 | "sourceType": "module" 5 | }, 6 | "env": { 7 | "node": true 8 | }, 9 | "extends": "eslint:recommended", 10 | "rules": { 11 | "semi": "error", 12 | "no-console": "off", 13 | "indent": ["error", 2, { 14 | "SwitchCase": 1 15 | }], 16 | "no-empty": "off", 17 | "no-unused-vars": ["error", { 18 | "args": "none" 19 | }] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bower_components 2 | /node_modules 3 | /build 4 | /repos 5 | /src/js/vendor.js 6 | /src/js/*-symbols.json 7 | 8 | ### 9 | # node.js and bower 10 | node_modules 11 | npm-debug.log 12 | bower_components/ 13 | 14 | ### 15 | # https://github.com/github/gitignore/blob/master/Global/OSX.gitignore (MIT License) 16 | .DS_Store 17 | .AppleDouble 18 | .LSOverride 19 | # Icon must end with two \r 20 | Icon 21 | # Thumbnails 22 | ._* 23 | # Files that might appear in the root of a volume 24 | .DocumentRevisions-V100 25 | .fseventsd 26 | .Spotlight-V100 27 | .TemporaryItems 28 | .Trashes 29 | .VolumeIcon.icns 30 | # Directories potentially created on remote AFP share 31 | .AppleDB 32 | .AppleDesktop 33 | Network Trash Folder 34 | Temporary Items 35 | .apdisk 36 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/carbon 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Please read the [Contribution Guide](https://github.com/stellar/docs/blob/master/CONTRIBUTING.md). 4 | 5 | Then please [sign the Contributor License Agreement](https://docs.google.com/forms/d/1g7EF6PERciwn7zfmfke5Sir2n10yddGGSXyZsq98tVY/viewform?usp=send_form). 6 | 7 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:22.04 as build 2 | 3 | MAINTAINER SDF Ops Team 4 | 5 | ADD . /app/src 6 | 7 | WORKDIR /app/src 8 | 9 | ENV DEBIAN_FRONTEND=noninteractive 10 | RUN apt-get update && apt-get install --no-install-recommends -y gpg curl git make ca-certificates gcc g++ apt-transport-https && \ 11 | curl -sSL https://deb.nodesource.com/gpgkey/nodesource.gpg.key|gpg --dearmor >/etc/apt/trusted.gpg.d/nodesource.gpg && \ 12 | echo "deb https://deb.nodesource.com/node_10.x focal main" | tee /etc/apt/sources.list.d/nodesource.list && \ 13 | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg |gpg --dearmor >/etc/apt/trusted.gpg.d/yarnpkg.gpg && \ 14 | echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \ 15 | apt-get update && apt-get install -y nodejs yarn 16 | 17 | 18 | RUN npm install -q -g gulp && yarn install && rm -rf ./repos/ && \ 19 | gulp --pathPrefix="/developers" 20 | 21 | FROM nginx:1.17 22 | 23 | COPY --from=build /app/src/build/ /usr/share/nginx/html/developers 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2015 Stellar Development Foundation 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Check if we need to prepend docker commands with sudo 2 | SUDO := $(shell docker version >/dev/null 2>&1 || echo "sudo") 3 | 4 | # If TAG is not provided set default value 5 | TAG ?= stellar/developers:$(shell git rev-parse --short HEAD)$(and $(shell git status -s),-dirty-$(shell id -u -n)) 6 | # https://github.com/opencontainers/image-spec/blob/master/annotations.md 7 | BUILD_DATE := $(shell date --utc --rfc-3339=seconds) 8 | 9 | docker-build: 10 | $(SUDO) docker build --pull --label org.opencontainers.image.created="$(BUILD_DATE)" -t $(TAG) . 11 | 12 | docker-push: 13 | $(SUDO) docker push $(TAG) 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Stellar Developers 2 | Stellar developer portal site generator. 3 | 4 | This uses gulp and metalsmith (plus a heap of plugins) to generate the site. 5 | 6 | ## Dependencies 7 | 8 | To build this project, you must have the following dependencies installed: 9 | 10 | - node 10.16.3 11 | - npm 12 | - yarn 13 | 14 | ## Installation 15 | ```bash 16 | git clone https://github.com/stellar/developers # or git@github.com:stellar/developers.git 17 | npm install --no-shrinkwrap 18 | yarn install 19 | ``` 20 | 21 | (Note the `no-shrinkwrap` option is because of an issue in `metalsmith-concat`: https://github.com/aymericbeaumet/metalsmith-concat/issues/22) 22 | 23 | ## Docs repository cloning 24 | The developers site tool generates content pulled in from other repos. These repositories are configured in `repos.json` and stored in `repos/`. To clone all the required repositories, run: 25 | ``` 26 | node_modules/.bin/gulp git:clone 27 | ``` 28 | 29 | Keeping these repositories up to date is the responsibility of the person using this tool. Here is a simple bash command you can use to do a `git pull` on all the repos. 30 | 31 | ``` 32 | for dir in ./repos/*; 33 | do 34 | if [[ -d $dir ]]; then 35 | ( echo; cd "$dir"; pwd; git pull ); 36 | fi; 37 | done 38 | ``` 39 | 40 | ## Development 41 | To generate the static site, run the following inside your repo containing this folder: 42 | 43 | ```bash 44 | node_modules/.bin/gulp # or just `gulp` if you have it installed globally or have path set up 45 | ``` 46 | 47 | To run a web server and view the site in a browser: 48 | 49 | ```bash 50 | node_modules/.bin/gulp watch serve 51 | ``` 52 | 53 | This will also automatically rebuild the site when edits are made. (To serve without rebuilding, drop the `watch` argument.) 54 | 55 | By default, the site is served under the developers/ subfolder. This is to reduce the amount of bugs when this site is deployed to https://www.stellar.org/developers/. This can be changed by passing a custom baseUrl to the gulp build task like so: `gulp --baseUrl="/"` or `gulp build --baseUrl="/"`. 56 | 57 | When working on the site, you can also use the `--debug` option to generate output that is easier to debug in the browser (it includes things like sourcemaps). 58 | 59 | 60 | ### Browser JavaScript 61 | Browser JavaScript files live in [`src/js`](/src/js/). `vendor.js` is generated from bower_components and not checked in to the repository. 62 | 63 | To add a new browser JS file, add it to [`src/js`](/src/js/) and update the metalsmith concat step by adding your new file to the list. The list of JS files is order sensitive. 64 | 65 | ## Development conventions 66 | - Use yaml especially for front matter since Github can nicely display markdown files with this 67 | - 2 spaces everywhere 68 | 69 | ### Writing Examples 70 | 71 | The developer portal for stellar includes a system for displaying code-samples alongside the documentation for horizon endpoints. To recognize and process these examples, you must write them in a particular way: 72 | 73 | 1. Any markdown (.md) file in a project that has a path prefix of `/docs/horizon-examples` will be considered to be an example file. 74 | 2. The example file must include a `language` attribute in it's front matter. Valid values for this attribute are `curl`, `ruby`, `javascript`, and `go` 75 | 3. The file's basename must match the basename of the horizon endpoint to which it is associated. For example `docs/horizon-examples/accounts-all.md` will be associated with the "accounts-all" horizon endpoint. 76 | 77 | By following the rules above, your example file should get recognized by the build pipeline and slotted into the appropriate output file. 78 | 79 | ## Client Data 80 | Sometimes, we may want to pass frontmatter data to js scripts on the page. Documents can specify "client data" in front matter. The term client refers to the browser. The `clientData` key in the front matter of a document will be converted to JSON and put in the web page as a js variable `window.clientData`. The `clientData` must be an object in order to successfully appear in the html. 81 | 82 | ## Troubleshooting 83 | 84 | ### No handlebars file 85 | 86 | ```sh 87 | [00:49:37] Error: ENOENT: no such file or directory, open '/app/layouts/plans.handlebars' 88 | ``` 89 | 90 | This happens when you add a new directory in a `docs` folder in one of the repos that `stellar/developers` processes. If you don't want any of the docs in the directory to be included in the developers site, you can add your directory to the `excluded_dirs` in `gulp/enhance.js:addSection`. 91 | 92 | ## Contributing 93 | Please read the [contributing guide](CONTRIBUTING.md) to learn more about how to contribute to the developer portal. For contributions to docs, please put contributions in their respective repositories. 94 | 95 | ## License 96 | This project is licensed under Apache License Version 2.0. For more information, refer to the [LICENSE.txt](LICENSE.txt) file. 97 | -------------------------------------------------------------------------------- /gulp/code-symbol-tags.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Generate JSON summaries of symbols from Stellar SDKs for use when syntax 3 | * highlighting code samples in documentation. 4 | * 5 | * TODO: other SDKs besides JS 6 | * TODO: does this belong as a CLI script in each SDK repo instead? 7 | * TODO: is there a JS API for JSDoc we can/should use instead? 8 | */ 9 | 10 | import child_process from 'child_process'; 11 | import cheerio from 'cheerio'; 12 | 13 | const DOCUMENTATION_URL = 'https://stellar.github.io/js-stellar-sdk/'; 14 | 15 | export function javascriptSymbols(callback) { 16 | let output = ''; 17 | let error = ''; 18 | 19 | // npm install in js-stellar-sdk 20 | child_process.spawnSync('yarn', ['install'], {cwd: './repos/js-stellar-sdk/'}); 21 | child_process.spawnSync('yarn', ['build:docs'], {cwd: './repos/js-stellar-sdk/'}); 22 | 23 | const jsDoc = child_process.spawn( 24 | // Executed in './repos/js-stellar-sdk/' 25 | './node_modules/.bin/jsdoc', 26 | [ 27 | '-c', '.jsdoc.json', 28 | '--explain' // output doclet JSON instead of templated web site 29 | ], 30 | { 31 | cwd: './repos/js-stellar-sdk/' 32 | }); 33 | 34 | jsDoc.stdout.on('data', data => output += data); 35 | jsDoc.stderr.on('data', data => error += data); 36 | jsDoc.on('exit', code => { 37 | if (code === 0) { 38 | const doc = parseDoclets(output); 39 | callback(null, doc.names); 40 | } 41 | else { 42 | callback(error, null); 43 | } 44 | }); 45 | } 46 | 47 | function parseDoclets (rawString) { 48 | const doclets = JSON.parse(rawString); 49 | 50 | const parsed = doclets.reduce((result, doclet) => { 51 | if ( 52 | doclet.name && 53 | !doclet.name.startsWith('_') && 54 | doclet.description && 55 | !(result.longnames[doclet.longname] && result.longnames[doclet.longname].description) && 56 | !doclet.undocumented) { 57 | 58 | const finalDoclet = simplifiedDoclet(doclet); 59 | result.longnames[doclet.longname] = finalDoclet; 60 | if (!result.names[doclet.name]) { 61 | result.names[doclet.name] = []; 62 | } 63 | result.names[doclet.name].push(finalDoclet); 64 | } 65 | return result; 66 | }, { 67 | longnames: {}, 68 | names: {} 69 | }); 70 | 71 | return parsed; 72 | } 73 | 74 | /** 75 | * Create a standardized, minimal doc object from a JSDoc doclet. 76 | * @param {JSDocDoclet} doclet 77 | * @return {{kind: String, name: String, longname: String, params: Array}} 78 | */ 79 | function simplifiedDoclet (doclet) { 80 | const result = { 81 | kind: doclet.kind, 82 | name: doclet.name, 83 | longName: doclet.longname, 84 | url: urlForSymbol(doclet.longname, DOCUMENTATION_URL), 85 | description: formatDescription(doclet.description, DOCUMENTATION_URL) 86 | }; 87 | if (doclet.memberof) { 88 | result.memberOf = doclet.memberof; 89 | } 90 | // Params take up a lot of space & we don't use them, but may want them later. 91 | // if (doclet.params) { 92 | // result.params = doclet.params; 93 | // } 94 | return result; 95 | } 96 | 97 | function formatDescription (text, baseUrl) { 98 | let formatted = convertLinksToHTML(text, baseUrl); 99 | const $ = cheerio.load(formatted); 100 | 101 | // remove example code 102 | $('.source').remove(); 103 | 104 | // TODO: clip at a certain number of words or characters? 105 | 106 | return $.html(); 107 | } 108 | 109 | // Find calls for links to other symbols in a description. Captures 1 is the 110 | // target of the link. 111 | const LINK_MATCHER = /\{\@link\s([^}]+)\}/g; 112 | 113 | // Break up a target into the owner and member being targeted. The member 114 | // includes the type specifier (e.g. '.') for all but instance members. 115 | const TARGET_PARTS = /^(\w+)\#?(.*)$/; 116 | 117 | function convertLinksToHTML (text, baseUrl) { 118 | return text.replace(LINK_MATCHER, (match, target) => { 119 | const url = urlForSymbol(target, baseUrl); 120 | return `${target}`; 121 | }); 122 | } 123 | 124 | function urlForSymbol (symbol, baseUrl) { 125 | const [_, owner, member] = symbol.match(TARGET_PARTS); 126 | return `${baseUrl}${owner}.html#${member}`; 127 | } 128 | -------------------------------------------------------------------------------- /gulp/enhance.js: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | import path from "path"; 3 | import minimatch from "minimatch"; 4 | 5 | let repos = require("../repos.json"); 6 | 7 | // The enhance middleware populates a bunch of metadata fields on the files. 8 | export default function enhance(files, metalsmith, done) { 9 | _.each(files, (file, filePath) => { 10 | addSrcInfo(file, filePath, metalsmith); 11 | addRepoInfo(file, filePath, metalsmith); 12 | addProject(file, filePath, metalsmith); 13 | addFullTitle(file, filePath, metalsmith); 14 | addSection(file, filePath, metalsmith); 15 | addLayout(file, filePath, metalsmith); 16 | addDefaultTitles(file, filePath, metalsmith); 17 | addExamples(file, filePath, metalsmith); 18 | addSequenceInfo(file, filePath, metalsmith, files); 19 | }); 20 | done(); 21 | } 22 | 23 | function addSrcInfo(file, filePath) { 24 | file.srcPath = filePath; 25 | } 26 | 27 | function addRepoInfo(file, filePath) { 28 | let parts = filePath.split(path.sep); 29 | 30 | switch (parts[0]) { 31 | case "guides": 32 | case "reference": 33 | case "software": 34 | case "tools": 35 | case "beyond-code": 36 | file.repo = "docs"; 37 | file.repoPath = filePath; 38 | break; 39 | case "horizon": 40 | file.repo = "go"; 41 | file.repoPath = 42 | "services/horizon/internal/docs/" + parts.slice(1).join("/"); 43 | break; 44 | default: 45 | // if parts[0] is the name of a repo, use it 46 | if (parts[0] in repos) { 47 | file.repo = parts[0]; 48 | let newParts = parts.slice(0); 49 | newParts[0] = "docs"; 50 | file.repoPath = newParts.join("/"); 51 | } else { 52 | // no repo for this case 53 | } 54 | break; 55 | } 56 | 57 | if (!file.repo) return; 58 | 59 | let repo = repos[file.repo]; 60 | file.repoURL = repo.githubURL; 61 | file.repoBlobURL = repo.githubURL + "/blob/master/" + file.repoPath; 62 | } 63 | 64 | function addProject(file, filePath) { 65 | if (!file.repo) return; 66 | if (file.repo === "docs") return; 67 | 68 | file.project = file.repo; 69 | file.projectTitle = repos[file.repo].projectTitle; 70 | } 71 | 72 | function addFullTitle(file, filePath) { 73 | let titleSuffix = " | Stellar Developers"; 74 | 75 | if (!file.projectTitle || file.repo === "docs") { 76 | file.fullTitle = file.title + titleSuffix; 77 | return; 78 | } 79 | 80 | file.fullTitle = file.title + " - " + file.projectTitle + titleSuffix; 81 | } 82 | 83 | function addSection(file, filePath) { 84 | if (path.extname(filePath) !== ".md") return; 85 | if (file.section) return; 86 | const excluded_dirs = ["plans"]; 87 | 88 | let parts = filePath.split(path.sep); 89 | switch (parts[0]) { 90 | case "guides": 91 | case "reference": 92 | case "software": 93 | case "tools": 94 | file.section = parts[0]; 95 | break; 96 | default: 97 | // if we're dealing with a document inside a project's /docs folder, don't assign a layout 98 | if (parts.length == 2) { 99 | return; 100 | } 101 | 102 | // directories that we shouldn't process / assign a layout to 103 | if (excluded_dirs.includes(parts[1])) { 104 | return; 105 | } 106 | 107 | // if not one of the above cases, then we are dealing with a project-specific 108 | // file (i.e. js-stellar-sdk). In this case, we determine layout 109 | // based upon the nesting undernearth the project name. 110 | file.section = parts[1]; 111 | break; 112 | } 113 | } 114 | 115 | function addLayout(file, filePath) { 116 | if ("section" in file) { 117 | file.layout = file.section + ".handlebars"; 118 | } 119 | } 120 | 121 | function addDefaultTitles(file, filePath) { 122 | if (minimatch(filePath, "**/!(*.md)")) return; 123 | if ("title" in file) return; 124 | 125 | console.log(`warn: ${filePath} has no title`); 126 | file.title = path.basename(filePath); 127 | } 128 | 129 | function addExamples(f, p, metalsmith) { 130 | if (!minimatch(p, "horizon/reference/*.*")) return; 131 | let examples = metalsmith.metadata()._examples; 132 | let ext = path.extname(p); 133 | let endpoint = path.basename(p).slice(0, -ext.length); 134 | 135 | if (!(endpoint in examples)) return; 136 | 137 | f.examples = examples[endpoint]; 138 | } 139 | 140 | /** 141 | * Replace `sequence` objects in file metadata with metadata about the 142 | * referenced sequence files. Sequence is used to describe navigation through a 143 | * multi-step guide. In the file metadata, you might have: 144 | * 145 | * sequence: 146 | * previous: first-step.md 147 | * next: third-step.md 148 | * 149 | * This method will update the sequence property to replace the referenced 150 | * file path with the metadata of the given file, plus a URL to link to: 151 | * 152 | * {sequnce: { 153 | * previous: {title: "Step 1", linkPath: "./first-step.html", ...} 154 | * next: {title: "Step 3", linkPath: "./third-step.html", ...} 155 | * }} 156 | * 157 | * @param {MetalsmithFile} file File metadata object from Metalsmith 158 | * @param {String} filePath Path of the file 159 | * @param {Metalsmith} metalsmith 160 | * @param {Object} allFiles Metalsmith file collection object 161 | * @returns 162 | */ 163 | function addSequenceInfo(file, filePath, metalsmith, allFiles) { 164 | const sequence = file.sequence; 165 | if (!sequence) return; 166 | 167 | if (sequence.previous) { 168 | sequence.previous = fileLinkInfo(sequence.previous, filePath, allFiles); 169 | } 170 | if (sequence.next) { 171 | sequence.next = fileLinkInfo(sequence.next, filePath, allFiles); 172 | } 173 | } 174 | 175 | /** 176 | * Get an object with a relative URL and title for the given file, as well as 177 | * any existing metadata for that file. 178 | * @private 179 | * @param {String} relativePath The relative path to the file 180 | * @param {String} fromPath The path that `relativePath` is relative to 181 | * @param {Object} allFiles A metalsmith file collection to get metadata from 182 | * @returns {{title: String, linkPath: String}} 183 | */ 184 | function fileLinkInfo(relativePath, fromPath, allFiles) { 185 | const filePath = path.join(path.dirname(fromPath), relativePath); 186 | const linkPath = filePath 187 | .replace(/(^|\/)readme\.md$/, "index.html") 188 | .replace(/\.md$/, ".html"); 189 | return Object.assign( 190 | { 191 | // this is just a fallback if a file doesn't have an explicit title set 192 | title: relativePath.replace(/\.md$/, ""), 193 | linkPath: linkPath 194 | }, 195 | allFiles[filePath] 196 | ); 197 | } 198 | -------------------------------------------------------------------------------- /gulp/extract.js: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | import minimatch from "minimatch"; 3 | import path from "path"; 4 | 5 | let languageMap = { 6 | ".js": "javascript", 7 | ".rb": "ruby", 8 | ".curl": "curl", 9 | ".go": "go", 10 | }; 11 | 12 | // Collects any files underneath a `horizon-examples` directory into 13 | // a central metadata field for use when rendering a horizon "endpoint" 14 | // page. 15 | // 16 | // Each example file is matched to the corresponding endpoint by file name. 17 | // The examples language is deduced via the file extension. 18 | module.exports.examples = function(files, metalsmith, done) { 19 | let metadata = metalsmith.metadata(); 20 | let exampleFiles = glob(files, "**/horizon-examples/*.*"); 21 | 22 | let results = {}; 23 | metadata._examples = results; 24 | 25 | _.each(exampleFiles, (f,p) => { 26 | delete files[p]; 27 | let ext = path.extname(p); 28 | let language = languageMap[ext]; 29 | let endpoint = path.basename(p).slice(0, -ext.length); 30 | if (!language) { 31 | console.log(`warn: no languageMap entry for ${ext}`); 32 | } 33 | 34 | results[endpoint] = results[endpoint] || {}; 35 | results[endpoint][language] = f; 36 | }); 37 | 38 | done(); 39 | }; 40 | 41 | function glob(files, pattern) { 42 | let results = {}; 43 | _.each(files, (f,p) => { 44 | if (!minimatch(p,pattern)) return; 45 | results[p] = f; 46 | }); 47 | return results; 48 | } 49 | -------------------------------------------------------------------------------- /gulp/git.js: -------------------------------------------------------------------------------- 1 | import {exec} from "child_process"; 2 | import _ from "lodash"; 3 | import fs from "fs"; 4 | import path from "path"; 5 | import Promise from 'bluebird'; 6 | import gulp from 'gulp'; 7 | 8 | let repos = require("../repos"); 9 | let execAsync = Promise.promisify(exec); 10 | 11 | gulp.task("git:clone", done => { 12 | let clones = _.map(repos, (data, name) => { 13 | let dest = path.join("repos", name); 14 | if (fs.existsSync(dest)) { 15 | console.log(`info: ${dest} already cloned`); 16 | return Promise.resolve(); 17 | } 18 | 19 | return execAsync(`git clone ${data.githubURL} ${dest}`) 20 | .then(() => console.log(`info: cloned ${dest}`)); 21 | }); 22 | 23 | Promise.all(clones).then( 24 | () => done(), 25 | err => done(err) 26 | ); 27 | }); 28 | -------------------------------------------------------------------------------- /gulp/handlebars.js: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import minimatch from "minimatch"; 3 | 4 | let allFiles = {}; 5 | 6 | module.exports.helpers = { 7 | equal(lvalue, rvalue, options) { 8 | if (arguments.length < 3) 9 | throw new Error("Handlebars Helper equal needs 2 parameters"); 10 | if( lvalue!=rvalue ) { 11 | return options.inverse(this); 12 | } else { 13 | return options.fn(this); 14 | } 15 | }, 16 | 17 | eachFile() { 18 | let args = Array.slice(arguments); 19 | let options = _.last(args); 20 | let globs = args 21 | .slice(0, args.length - 1) 22 | .map(glob => new minimatch.Minimatch(glob)); 23 | 24 | return _.chain(allFiles) 25 | .map((file, path) => path) 26 | .filter(path => _.some(globs, glob => glob.match(path))) 27 | .sortBy() 28 | .map(path => options.fn( 29 | // create a child context object for rendering 30 | _.extend({}, this, {path, file: allFiles[path]}))) 31 | .join('') 32 | .value(); 33 | }, 34 | 35 | sidebarSubMenu(title, options) { 36 | let c = options.hash.collapsible == true; 37 | const listTag = options.hash.numbered ? 'ol' : 'ul'; 38 | 39 | return ` 40 | 46 | `; 47 | }, 48 | 49 | // clientData is documented in the README.md 50 | frontmatterClientDataScript(options) { 51 | // If clientData is not specified, an empty object will appear at window.clientData. 52 | // This makes it easier since scripts can always know clientData exists. 53 | let clientDataJson = '{}'; 54 | if (typeof options.data.root.clientData === 'object') { 55 | clientDataJson = JSON.stringify(options.data.root.clientData); 56 | } 57 | if (typeof options.data.root.clientData === 'string') { 58 | console.log(`warn: clientData in "${options.data.root.title}" must be formatted as an object`); 59 | } 60 | return ``; 61 | }, 62 | 63 | // If available, return the fingerprinted version of a path, otherwise just 64 | // return the path as-is. 65 | fingerprint (path) { 66 | return this.fingerprint && this.fingerprint[path] || path; 67 | } 68 | }; 69 | 70 | 71 | module.exports.setFileList = function(files) { 72 | allFiles = files; 73 | }; 74 | -------------------------------------------------------------------------------- /gulp/links.js: -------------------------------------------------------------------------------- 1 | import url from 'url'; 2 | import cheerio from 'cheerio'; 3 | import minimatch from 'minimatch'; 4 | import _ from 'lodash'; 5 | 6 | module.exports.rewrite = function(files, metalsmith, done) { 7 | const pathPrefix = metalsmith.metadata().pathPrefix || ''; 8 | 9 | _.each(files, (f,p) => { 10 | if (!minimatch(p, "**/*.html")) return; 11 | 12 | let $ = cheerio.load(f.contents); 13 | 14 | 15 | $('[link-process-md] a').each(function(i, elem) { 16 | //re-write relative .md links to .html 17 | mdToHtml($, elem, f, p); 18 | rootRelativeToGithub($, elem, f, p); 19 | devportalToRelative($, elem, f, p, pathPrefix); 20 | }); 21 | 22 | decorateSequentialNavigation($, f, p); 23 | 24 | f.contents = $.html(); 25 | }); 26 | 27 | 28 | // link re-targeting 29 | // TODO: protocol relative links are left alone 30 | // TODO: root relative links are rewritten using the documents root. 31 | // TODO: relative links are maintainted 32 | // TODO: If relative or root-relative, re 33 | // 34 | done(); 35 | }; 36 | 37 | // All .md links that are relative should point to the rendered output 38 | function mdToHtml($, elem) { 39 | let href = $(elem).attr('href'); 40 | if (!href) return; 41 | 42 | let u = url.parse(href); 43 | if(!u.pathname) return; 44 | 45 | var isMarkdown = u.pathname.match(/\.md$/) !== null; 46 | var isRelative = u.pathname.charAt(0) !== '/'; 47 | 48 | if (!(isMarkdown && isRelative)) return; 49 | 50 | u.pathname = u.pathname.replace(/\.md$/, ".html"); 51 | $(elem).attr('href', url.format(u)); 52 | } 53 | 54 | // All root-relative links in content should link to github in the rendered output. 55 | function rootRelativeToGithub($, elem, f, p) { 56 | let href = $(elem).attr('href'); 57 | if (!href) return; 58 | if (!f.repoURL) return; 59 | 60 | var isRootRelative = href.charAt(0) === '/'; 61 | if (!isRootRelative) return; 62 | 63 | $(elem).attr('href', f.repoURL + "/blob/master" + href); 64 | } 65 | 66 | // Identifies a URL for a dev portal page and matches a group for the path 67 | const DEVPORTAL_URL = 68 | /^http(?:s)?:\/\/(?:www\.)?stellar.org\/developers\/?(.*)$/; 69 | 70 | /** 71 | * Convert links to dev portal pages (used when linking to a doc whose 72 | * canonical version lives in another repo, e.g. a Horizon reference page 73 | * linking to a Stellar-Core reference page) to be relative. 74 | * e.g. "https://stellar.org/developers/whatever" -> "/whatever" 75 | * @param {CheerioDocument} $ 76 | * @param {HTMLAnchorElement} element 77 | * @param {MetalsmithFile} file 78 | * @param {String} pathname 79 | * @param {String} pathPrefix 80 | */ 81 | function devportalToRelative($, element, file, pathname, pathPrefix) { 82 | let href = $(element).attr('href'); 83 | const urlMatch = DEVPORTAL_URL.exec(href); 84 | 85 | if (urlMatch) { 86 | const urlPath = urlMatch[1]; 87 | $(element).attr('href', `${pathPrefix}/${urlPath}`); 88 | } 89 | } 90 | 91 | /** 92 | * Ensure sequential navigation blocks (the previous/next links at the bottom 93 | * of multi-page guides) get the right markup and styles. 94 | * @param {Cheerio} $ 95 | * @param {MetalsmithFile} file 96 | * @param {String} filePath 97 | */ 98 | function decorateSequentialNavigation($, file, filePath) { 99 | $('.sequence-navigation') 100 | .children('[rel~="prev"]').addClass('button button--previous').end() 101 | .children('[rel~="next"]').addClass('button button--next').end(); 102 | } 103 | -------------------------------------------------------------------------------- /gulp/math-formula.js: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | import path from "path"; 3 | 4 | /** 5 | * Ultra-simple math formula formatting (as Metalsmith middleware). 6 | * A richer version might use Ascii2MathML (runarberg.github.io/ascii2mathml) or 7 | * MathJax (mathjax.org), but: 8 | * - MathML support is not so good (http://caniuse.com/#feat=mathml) 9 | * - MathJax can do a nice non-MathML render, but it is a little complex and 10 | * it (and AsciiMath) is very oriented towards traditional mathematical 11 | * formulae and doesn't some constructs we'd like well (e.g. multiplication 12 | * symbols, pretty variable names with spaces). 13 | * So, do something simpler here which suits our purposes for now. 14 | * 15 | * Finds "```math-formula" code blocks in Markdown and converts them to 16 | * `
` with some additional typography cleanup and 17 | * markup/classes around types of symbols (operators, parens, etc). 18 | * 19 | * Inline blocks are delimited by `$$` and are displayed without modified 20 | * font sizes and margins so as not to disrupt text flow. 21 | */ 22 | export default function mathFormula(files, metalsmith, done) { 23 | _.chain(files) 24 | .filter(isMarkdown) 25 | .each(file => { 26 | file.contents = file.contents.toString() 27 | .replace( 28 | /\n```math-formula\n((?:.|\n)*?)\n```\n/g, 29 | (token, content) => `\n${formatFormula(content)}\n`) 30 | .replace( 31 | /\$\$(.+?)\$\$/g, 32 | (token, content) => formatFormula(content, true)); 33 | }) 34 | .value(); 35 | done(); 36 | } 37 | 38 | function isMarkdown(file, filePath) { 39 | return /\.(md|markdown|mdown)$/.test(path.extname(filePath)); 40 | } 41 | 42 | function formatFormula(text, inline = false) { 43 | const formatted = 44 | prettyParentheses( 45 | prettyVariables( 46 | prettyNumbers( 47 | prettyExponents( 48 | prettyOperators(text))))); 49 | const tagName = inline ? 'code' : 'figure'; 50 | return `<${tagName} class="math-formula">${formatted}`; 51 | } 52 | 53 | function prettyOperators(text) { 54 | return text 55 | .replace(/\*/g, '×') 56 | .replace(/\//g, '÷') 57 | .replace(/\+-/g, '±') 58 | .replace(/\-/g, '−') 59 | .replace(/\!=/g, '≠') 60 | .replace(/<=/g, '≤') 61 | .replace(/>=/g, '≥') 62 | .replace( 63 | /([×÷=≠≤≥]|\s[+−]\s)/g, 64 | '$1'); 65 | } 66 | 67 | function prettyVariables(text) { 68 | return text.replace(/\[(.+?)\]/g, '$1'); 69 | } 70 | 71 | // NOTE: this won't handle [variables with spaces]; we'd need more rigorous 72 | // parsing than this simple pile of regexes for that. 73 | function prettyExponents(text) { 74 | return text 75 | .replace(/\^\(([^)]+)\)/g, '$1') 76 | .replace(/\^(\S+)/g, '$1'); 77 | } 78 | 79 | function prettyParentheses(text) { 80 | return text 81 | // NOTE: the parenthesis character in the replacement is a special paren 82 | .replace(/\(/g, '(') 83 | .replace(/\)/g, ')'); 84 | } 85 | 86 | function prettyNumbers(text) { 87 | return text 88 | .replace(/\d+(\.\d*)?/g, '$&'); 89 | } 90 | -------------------------------------------------------------------------------- /gulp/safeSymlink.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | 3 | // safeSymlink synchronously creates a symlink to src if there is no existing 4 | // file or symlink at dest 5 | module.exports = function(src, dest) { 6 | try { 7 | fs.lstatSync(dest); 8 | } catch(e) { 9 | fs.symlinkSync(src,dest); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /gulp/sidecarMetadata.js: -------------------------------------------------------------------------------- 1 | import _ from "lodash"; 2 | import minimatch from "minimatch"; 3 | 4 | export default function sidecarMetadata(allFiles, metalsmith, done) { 5 | _.each(allFiles, (f, p) => { 6 | if (!minimatch(p, '**/*.metadata')) { 7 | return; 8 | } 9 | 10 | delete f.contents; 11 | delete f.mode; 12 | delete f.stats; 13 | 14 | let mainPath = p.replace(/\.metadata$/, ''); 15 | 16 | if (mainPath in allFiles) { 17 | allFiles[mainPath] = _.extend(allFiles[mainPath], f); 18 | } 19 | delete allFiles[p]; 20 | }); 21 | 22 | done(); 23 | } 24 | -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import gulp from 'gulp'; 3 | import path from 'path'; 4 | import Metalsmith from 'metalsmith'; 5 | import _ from 'lodash'; 6 | import markdownItAnchor from 'markdown-it-anchor'; 7 | import markdownItImplicitFigures from 'markdown-it-implicit-figures'; 8 | import markdownItFootnote from 'markdown-it-footnote'; 9 | import hbars from './gulp/handlebars'; 10 | import extract from "./gulp/extract"; 11 | import links from "./gulp/links"; 12 | import minimatch from "minimatch"; 13 | import safeSymlink from './gulp/safeSymlink'; 14 | import runSequence from 'run-sequence'; 15 | import {javascriptSymbols} from './gulp/code-symbol-tags'; 16 | 17 | runSequence.use(gulp); 18 | 19 | let argv = require('minimist')(process.argv.slice(2)); 20 | let $g = require('gulp-load-plugins')(); 21 | let $m = require('load-metalsmith-plugins')(); 22 | 23 | if (argv.pathPrefix && argv.pathPrefix[0] !== '/') { 24 | throw new Error('The --pathPrefix argument must start with a "/"'); 25 | } 26 | const PATH_PREFIX = argv.pathPrefix || ''; 27 | 28 | // add the git related gulp tasks 29 | import "./gulp/git"; 30 | 31 | gulp.task("default", ["build"]); 32 | 33 | gulp.task("src", done => { 34 | runSequence( 35 | 'git:clone', 36 | 'src:symlink-repos', 37 | 'src:copy-stellar-base-to-js-sdk', 38 | 'generate-sdk-symbols', 39 | done 40 | ); 41 | }); 42 | 43 | gulp.task('src:symlink-repos', () => { 44 | // symlink the landing pages/custom content from the docs repo for each section 45 | safeSymlink("../repos/docs/guides", "src/guides"); 46 | safeSymlink("../repos/docs/reference", "src/reference"); 47 | safeSymlink("../repos/docs/software", "src/software"); 48 | safeSymlink("../repos/docs/tools", "src/tools"); 49 | 50 | // link up other repo's docs folder into the src structure 51 | return gulp.src("./repos/*/docs/") 52 | .pipe($g.sym(repoToSrc, {force: true, relative: true})); 53 | }); 54 | 55 | gulp.task('js:copy-vendor', function() { 56 | return gulp.src([ 57 | // TODO: optimize and only load which ones are necessary 58 | './node_modules/jquery/dist/jquery.min.js', 59 | './node_modules/codemirror/lib/codemirror.js', 60 | './node_modules/codemirror/addon/runmode/runmode.js', 61 | './node_modules/codemirror/mode/javascript/javascript.js', 62 | './node_modules/codemirror/mode/shell/shell.js', 63 | './node_modules/codemirror/mode/clike/clike.js', 64 | './node_modules/codemirror/mode/go/go.js', 65 | './node_modules/codemirror/mode/toml/toml.js', 66 | './node_modules/codemirror/mode/python/python.js', 67 | './node_modules/stellar-sdk/stellar-sdk.min.js', 68 | './node_modules/tether/dist/js/tether.min.js', 69 | './node_modules/tether-drop/dist/js/drop.min.js', 70 | ]) 71 | .pipe($g.concat('vendor.js')) 72 | .pipe(gulp.dest('./src/js')); 73 | }); 74 | 75 | gulp.task('build', ['js:copy-vendor', 'src'], done => { 76 | build({incremental: !!argv.incremental}, done); 77 | }); 78 | 79 | gulp.task('serve', () => { 80 | gulp.src('./build') 81 | .pipe($g.webserver({ 82 | livereload: true, 83 | open: "index.html", 84 | host: '0.0.0.0' 85 | })); 86 | }); 87 | 88 | gulp.task('watch', done => { 89 | gulp.watch('src/**/*', (event) => { 90 | build({incremental: true}, function() {}); 91 | }); 92 | }); 93 | 94 | // This is needed to generate the symbols for the js-stellar-sdk 95 | gulp.task('src:copy-stellar-base-to-js-sdk', done => { 96 | return gulp.src(['repos/js-stellar-base/**/*']).pipe(gulp.dest('repos/js-stellar-sdk/js-stellar-base')); 97 | }); 98 | 99 | gulp.task('generate-sdk-symbols', done => { 100 | javascriptSymbols((error, symbols) => { 101 | if (error) { 102 | console.error(error); 103 | return done(error); 104 | } 105 | fs.writeFile( 106 | './src/js/javascript-symbols.json', JSON.stringify(symbols), done); 107 | }); 108 | }); 109 | 110 | function repoToSrc(file) { 111 | let project = file.relative.split(path.sep)[0]; 112 | return path.join("src", project); 113 | } 114 | 115 | function renameReadme(files, metalsmith, done) { 116 | let toReplace = _(files).keys().filter(p => path.basename(p) === "readme.md").value(); 117 | _.each(toReplace, p => { 118 | let newPath = path.join(path.dirname(p), "index.md"); 119 | files[newPath] = files[p]; 120 | delete files[p]; 121 | }); 122 | done(); 123 | } 124 | 125 | function renameHandlebars (files, metalsmith, done) { 126 | let toReplace = _(files).keys().pickBy(key => minimatch(key, '*.handlebars')).value(); 127 | _.each(toReplace, key => { 128 | let newPath = path.basename(key, '.handlebars') + '.html'; 129 | files[newPath] = files[key]; 130 | delete files[key]; 131 | }); 132 | done(); 133 | } 134 | 135 | function build({clean = false, incremental = false, debug = !!argv.debug}, done) { 136 | 137 | let templateOptions = { 138 | engine: "handlebars", 139 | partials: "partials", 140 | helpers: hbars.helpers, 141 | preventIndent: true, 142 | }; 143 | 144 | const sassOptions = { 145 | outputStyle: "expanded", 146 | includePaths: ["./node_modules"] 147 | }; 148 | if (debug) { 149 | Object.assign(sassOptions, { 150 | sourceMap: true, 151 | sourceMapContents: true, 152 | sourceMapEmbed: true 153 | }); 154 | } 155 | 156 | const pipeline = Metalsmith(__dirname) 157 | .clean(!incremental) 158 | .metadata({ pathPrefix: PATH_PREFIX }) 159 | .use(extract.examples) 160 | .use(require("./gulp/sidecarMetadata")) 161 | .use(require("./gulp/enhance")) 162 | .use($m.sass(sassOptions)) 163 | .use($m.autoprefixer({ })) 164 | .use($m.concat({ 165 | files: [ 166 | "js/vendor.js", 167 | "js/syntaxHighlight.js", 168 | "js/codeExamples.js", 169 | "js/endpointRef.js", 170 | "js/friendbot4.js", 171 | "js/collapsibleListSet.js", 172 | "js/linkCheck.js", 173 | "js/footnotes.js", 174 | "js/codeSymbolLinks.js", 175 | ], 176 | output: "js/app.js", 177 | })); 178 | 179 | if (!incremental) { 180 | // fingerprinting can only be done for non-incremental builds, otherwise 181 | // we'd need to rebuild every file that references the fingerprinted assets 182 | pipeline.use($m.fingerprint({ 183 | pattern: [ 184 | "styles/index.css", 185 | "js/app.js", 186 | ] 187 | })); 188 | } 189 | 190 | pipeline 191 | .use(renameReadme) 192 | .use((files, metalsmith, done) => { 193 | // we both need to copy the file list (so it doesn't get truncated if we 194 | // limit to incremental building in the next step) and do the renaming of 195 | // .md -> .html (again in case we limit to incremental building) 196 | const renamedFiles = _.mapKeys( 197 | files, (file, name) => name.replace(/\.md$/, '.html')); 198 | hbars.setFileList(renamedFiles); 199 | done(); 200 | }) 201 | .use($m.changed({ 202 | forcePattern: '**/index*.css' 203 | })) 204 | .use(require("./gulp/math-formula.js")) 205 | .use( 206 | $m.markdownit({ 207 | html: true, 208 | linkify: true, 209 | typographer: true 210 | }) 211 | .use(markdownItAnchor, { 212 | permalink: true, 213 | permalinkClass: 'anchorShortcut', 214 | permalinkSymbol: '', 215 | permalinkBefore: true 216 | }) 217 | .use(markdownItFootnote) 218 | .use(markdownItImplicitFigures)) 219 | .use($m.inPlace(_.extend({}, templateOptions, { 220 | pattern: '*.handlebars' 221 | }))) 222 | .use(renameHandlebars) 223 | .use($m.layouts(templateOptions)) 224 | .use(links.rewrite) 225 | .build(done); 226 | } 227 | 228 | 229 | // TODO: 230 | // rewrite link engine 231 | // example system 232 | // concat vendor.js 233 | // concat app.js 234 | // fingerprint assets 235 | // copy graphics files from solar module 236 | // run tests for link processor 237 | // 238 | 239 | 240 | // Example design 241 | // 242 | // Each project that provides examples for horizon's endpoints will define a folder such as 243 | // js-stellar-sdk/docs/horizon-examples/all-accounts.js 244 | // 245 | // the filename will be used for determining an examples file type 246 | // metalsmith will be used to populate a metadata field with all examples, indexed by endpoint name 247 | // each endpoint file can extract its examples using its name, then render them directly 248 | // 249 | -------------------------------------------------------------------------------- /jenkins.bash: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | set -e 3 | 4 | cat <<-EOS > build-node.bash 5 | set -e 6 | cd "\$(dirname "\$0")" 7 | 8 | rollback() { 9 | echo "rolling back" 10 | set +e 11 | rm -rf node_modules 12 | rm -rf build 13 | rm -rf repos 14 | rm build-node.bash 15 | } 16 | 17 | trap rollback INT TERM EXIT ERR 18 | 19 | npm install -q -g gulp 20 | 21 | yarn install 22 | chown -R ${UID} ./node_modules 23 | 24 | rm -rf ./repos/ 25 | gulp --pathPrefix="/developers" 26 | chown -R ${UID} ./build 27 | 28 | rm build-node.bash 29 | 30 | trap - INT TERM EXIT ERR 31 | EOS 32 | 33 | docker run \ 34 | --rm \ 35 | -v $(pwd):/app \ 36 | node:10 /bin/bash /app/build-node.bash 37 | 38 | 39 | -------------------------------------------------------------------------------- /layouts/beyond-code.handlebars: -------------------------------------------------------------------------------- 1 | {{> head }} 2 | {{> header-full-with-sidebar }} 3 | 4 |
5 | {{> beyond-code/sidebar }} 6 | {{> contentWrapperStart }} 7 | {{> contentWrapperEnd }} 8 |
9 | 10 | {{> footer }} 11 | {{> foot }} 12 | -------------------------------------------------------------------------------- /layouts/guides.handlebars: -------------------------------------------------------------------------------- 1 | {{> head }} 2 | {{> header-full-with-sidebar }} 3 | 4 |
5 | {{> guides/sidebar }} 6 | {{> contentWrapperStart }} 7 | {{> contentWrapperEnd }} 8 |
9 | 10 | {{> footer }} 11 | {{> foot }} 12 | -------------------------------------------------------------------------------- /layouts/reference.handlebars: -------------------------------------------------------------------------------- 1 | {{> head }} 2 | {{> header-full-with-sidebar }} 3 | 4 |
5 | {{> reference/sidebar }} 6 | {{> contentWrapperStart }} 7 | 8 | 9 | 10 |
11 |
12 |
13 | {{> contentWrapperEnd }} 14 |
15 | 16 | {{> footer }} 17 | {{> foot }} 18 | -------------------------------------------------------------------------------- /layouts/software.handlebars: -------------------------------------------------------------------------------- 1 | {{> head }} 2 | {{> header-full-with-sidebar }} 3 | 4 |
5 | {{> software/sidebar }} 6 | {{> contentWrapperStart }} 7 | {{> contentWrapperEnd }} 8 |
9 | 10 | {{> footer }} 11 | {{> foot }} 12 | -------------------------------------------------------------------------------- /layouts/tools.handlebars: -------------------------------------------------------------------------------- 1 | {{> head }} 2 | {{> header-full-with-sidebar }} 3 | 4 |
5 | {{> tools/sidebar }} 6 | {{> contentWrapperStart }} 7 | {{> contentWrapperEnd }} 8 |
9 | 10 | {{> footer }} 11 | {{> foot }} 12 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "developers", 3 | "private": true, 4 | "version": "1.0.0", 5 | "description": "", 6 | "dependencies": { 7 | "array-to-table": "^1.0.1", 8 | "axios": "^0.18.0", 9 | "babel": "^5.8.23", 10 | "bluebird": "^2.10.1", 11 | "cheerio": "^0.19.0", 12 | "codemirror": "~5.6.0", 13 | "gulp": "^3.9.0", 14 | "gulp-concat": "^2.6.0", 15 | "gulp-load-plugins": "^0.10.0", 16 | "gulp-replace": "^1.0.0", 17 | "gulp-sym": "0.0.14", 18 | "gulp-webserver": "^0.9.1", 19 | "handlebars": "^4.0.2", 20 | "jquery": "~3.0.0", 21 | "load-metalsmith-plugins": "^0.1.1", 22 | "lodash": "^4.17.5", 23 | "markdown-it-anchor": "^2.5.0", 24 | "markdown-it-footnote": "^3.0.1", 25 | "markdown-it-implicit-figures": "^0.3.2", 26 | "metalsmith": "^2.3.0", 27 | "metalsmith-autoprefixer": "^1.1.0", 28 | "metalsmith-changed": "^2.0.0", 29 | "metalsmith-concat": "^3.0.3", 30 | "metalsmith-fingerprint": "^1.0.3", 31 | "metalsmith-in-place": "^1.3.1", 32 | "metalsmith-layouts": "^1.4.1", 33 | "metalsmith-markdownit": "^0.4.0", 34 | "metalsmith-metadata": "0.0.1", 35 | "metalsmith-sass": "^1.3.0", 36 | "minimatch": "^2.0.10", 37 | "minimist": "^1.2.0", 38 | "run-sequence": "^2.2.1", 39 | "solar-css": "git+https://github.com/stellar/solar#master", 40 | "solar-stellarorg": "git+https://github.com/stellar/solar-stellarorg#master", 41 | "solar-stellarorg-pages": "git+https://github.com/stellar/solar-stellarorg-pages#master", 42 | "stellar-sdk": "~0.9.1", 43 | "tether-drop": "1.4.2" 44 | }, 45 | "devDependencies": { 46 | "eslint": "^3.3.1", 47 | "gulp-debug": "^2.1.0" 48 | }, 49 | "scripts": { 50 | "test": "echo \"Error: no test specified\" && exit 1", 51 | "build": "$(npm bin)/gulp build" 52 | }, 53 | "author": "", 54 | "license": "Apache-2.0" 55 | } 56 | -------------------------------------------------------------------------------- /partials/beyond-code/sidebar.handlebars: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /partials/contentWrapperEnd.handlebars: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | -------------------------------------------------------------------------------- /partials/contentWrapperStart.handlebars: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 | {{ title }} 5 | {{#if projectTitle}} [{{ projectTitle }}]{{/if}} 6 |

7 |
8 |
9 |
10 |
11 | {{#if replacement}} 12 | Updated content is available in the new documentation. 13 | {{else}} 14 | This page is deprecated, and will be removed once the new documentation is stable. 15 | {{/if}} 16 |
17 |
18 |
19 |
20 | 25 | -------------------------------------------------------------------------------- /partials/foot.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /partials/footer.handlebars: -------------------------------------------------------------------------------- 1 |
2 |
3 | 18 |
19 |
20 | -------------------------------------------------------------------------------- /partials/guides/sidebar.handlebars: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /partials/head.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | {{ fullTitle }} 12 | 13 | 14 | 15 | 16 | 17 | 18 | {{#if previewImage}} 19 | 20 | 21 | {{/if}} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 58 | 59 | 67 | 68 | {{#frontmatterClientDataScript}}{{/frontmatterClientDataScript}} 69 | 70 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /partials/header-full-with-sidebar.handlebars: -------------------------------------------------------------------------------- 1 |
2 | 7 | 10 |
11 | -------------------------------------------------------------------------------- /partials/mainNavMenu.handlebars: -------------------------------------------------------------------------------- 1 | {{> mainNavMenu/item href="/guides/" text="Guides" sectionFilter="guides"}} 2 | {{> mainNavMenu/item href="/reference/" text="API Reference" sectionFilter="reference"}} 3 | {{> mainNavMenu/item href="/software/" text="Software" sectionFilter="software"}} 4 | {{> mainNavMenu/item href="/tools/" text="Tools" sectionFilter="tools"}} 5 | -------------------------------------------------------------------------------- /partials/mainNavMenu/item.handlebars: -------------------------------------------------------------------------------- 1 | {{text}} 2 | -------------------------------------------------------------------------------- /partials/modules/dev-newsletter.handlebars: -------------------------------------------------------------------------------- 1 |
2 | Get developer updates: 3 | 4 |
5 | 13 | 14 |
15 | -------------------------------------------------------------------------------- /partials/modules/friendbot4.handlebars: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | 7 |
8 | 9 |
10 |
11 |
12 |
13 |

1. Use js-stellar-sdk to generate the public and secret keys for your test account.

14 |
15 |
16 | 17 | Generate Stellar testnet keys 18 | 19 | 22 |
23 |
26 |
27 |
28 |
29 |

2. Using the public key you generated, ask Stroopy, our friendly robot, to send you some lumens.

30 |
31 |
32 | stroopy 33 |
34 |
35 | 36 | 37 |
38 |

39 |
40 |
41 |
42 | 43 |
44 |
45 |

3. Your account should contain 10,000 lumens. Run this command to view your account using the Horizon API. 46 |

47 |
48 |
49 | 50 |
51 | 54 |
55 |
58 |
59 |
60 |
61 |

Your test account is all set! Save your keys to make other API calls on the network.

62 |

63 | Public key: 64 |
65 | 66 |

67 |

68 | Secret key: 69 |
70 | 71 |

72 |

Explore more of the Stellar ecosystem.

73 |
74 |
75 | 80 |
81 |
82 | -------------------------------------------------------------------------------- /partials/reference/sidebar.handlebars: -------------------------------------------------------------------------------- 1 | 45 | -------------------------------------------------------------------------------- /partials/sidebarSubItems.handlebars: -------------------------------------------------------------------------------- 1 | {{#eachFile glob}} 2 | 3 | {{/eachFile}} 4 | -------------------------------------------------------------------------------- /partials/sidebarSubMenu.handlebars: -------------------------------------------------------------------------------- 1 | {{#sidebarSubMenu title collapsible=collapsible}} 2 | {{>sidebarSubItems glob=glob}} 3 | {{/sidebarSubMenu}} 4 | -------------------------------------------------------------------------------- /partials/siteLogo.handlebars: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /partials/software/sidebar.handlebars: -------------------------------------------------------------------------------- 1 | 17 | -------------------------------------------------------------------------------- /partials/tools/sidebar.handlebars: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /repos.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs" : { 3 | "githubURL": "https://github.com/stellar/docs" 4 | }, 5 | "stellar-core" : { 6 | "githubURL": "https://github.com/stellar/stellar-core", 7 | "projectTitle": "Stellar Core" 8 | }, 9 | "interstellar" : { 10 | "githubURL": "https://github.com/stellar/interstellar", 11 | "projectTitle": "Interstellar" 12 | }, 13 | "js-stellar-base" : { 14 | "githubURL": "https://github.com/stellar/js-stellar-base", 15 | "projectTitle": "JS Stellar Base" 16 | }, 17 | "js-stellar-sdk" : { 18 | "githubURL": "https://github.com/stellar/js-stellar-sdk", 19 | "projectTitle": "JS Stellar SDK" 20 | }, 21 | "go" : { 22 | "githubURL": "https://github.com/stellar/go", 23 | "projectTitle": "Go SDK" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "jquery": true 5 | }, 6 | "extends": "eslint:recommended", 7 | "rules": { 8 | "semi": "error", 9 | "no-console": "warn", 10 | "no-empty": "off" 11 | }, 12 | "globals": { 13 | "clientData": true, 14 | "CodeMirror": true, 15 | "StellarSdk": true, 16 | "syntaxHighlight": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/.gitkeep -------------------------------------------------------------------------------- /src/go: -------------------------------------------------------------------------------- 1 | ../repos/go/docs -------------------------------------------------------------------------------- /src/guides: -------------------------------------------------------------------------------- 1 | ../repos/docs/guides -------------------------------------------------------------------------------- /src/horizon: -------------------------------------------------------------------------------- 1 | ../repos/go/services/horizon/internal/docs -------------------------------------------------------------------------------- /src/images/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/favicon/favicon.ico -------------------------------------------------------------------------------- /src/images/favicon/icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/favicon/icon-144x144.png -------------------------------------------------------------------------------- /src/images/favicon/icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/favicon/icon-152x152.png -------------------------------------------------------------------------------- /src/images/favicon/icon-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/favicon/icon-180x180.png -------------------------------------------------------------------------------- /src/images/favicon/icon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/favicon/icon-96x96.png -------------------------------------------------------------------------------- /src/images/fonts/suisseintl-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/fonts/suisseintl-regular-webfont.woff -------------------------------------------------------------------------------- /src/images/fonts/suisseintl-regular-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/fonts/suisseintl-regular-webfont.woff2 -------------------------------------------------------------------------------- /src/images/fonts/suisseintl-semibold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/fonts/suisseintl-semibold-webfont.woff -------------------------------------------------------------------------------- /src/images/fonts/suisseintl-semibold-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/fonts/suisseintl-semibold-webfont.woff2 -------------------------------------------------------------------------------- /src/images/fonts/suisseintlmono-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/fonts/suisseintlmono-regular-webfont.woff -------------------------------------------------------------------------------- /src/images/fonts/suisseintlmono-regular-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/fonts/suisseintlmono-regular-webfont.woff2 -------------------------------------------------------------------------------- /src/images/previews/landing-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/previews/landing-1.png -------------------------------------------------------------------------------- /src/images/previews/landing-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/images/previews/landing-2.png -------------------------------------------------------------------------------- /src/index.handlebars: -------------------------------------------------------------------------------- 1 | --- 2 | title: Stellar Developers Documentation 3 | previewImage: landing-2.png 4 | --- 5 | {{> head}} 6 | {{> header-full-with-sidebar}} 7 | 8 |
9 |
10 |

Stellar Documentation

11 |

12 | Stellar is open-source, distributed payments infrastructure. Build affordable 13 | financial services. 14 |

15 |
16 | 17 |
18 | 42 |
43 | 44 |
45 |
46 | 47 |
48 |
49 |
50 | 56 | 62 | 65 | 76 |
77 | 78 |
79 | 85 | 93 |
94 | 95 |
96 | 102 | 113 |
114 |
115 |
116 |
117 | 118 | 131 |
132 |
133 |

Don't see what you're looking for?

134 |
135 |
136 |

Ask questions and get in touch with 1000+ developers.

137 | 147 |
148 |
149 |
150 |
151 |

Find more information and contact us in other Stellar channels.

152 | 166 |
167 |
168 |
169 |
170 | 171 |
172 |
173 | {{> modules/dev-newsletter}} 174 |
175 |
176 | 177 | {{> footer }} 178 | {{> foot}} 179 | -------------------------------------------------------------------------------- /src/interstellar: -------------------------------------------------------------------------------- 1 | ../repos/interstellar/docs -------------------------------------------------------------------------------- /src/js-stellar-base: -------------------------------------------------------------------------------- 1 | ../repos/js-stellar-base/docs -------------------------------------------------------------------------------- /src/js-stellar-sdk: -------------------------------------------------------------------------------- 1 | ../repos/js-stellar-sdk/docs -------------------------------------------------------------------------------- /src/js/codeExamples.js: -------------------------------------------------------------------------------- 1 | /** 2 | * For multi-language code samples, show only one language add a time and add 3 | * a language switching UI. 4 | */ 5 | (function($) { 6 | 'use strict'; 7 | 8 | var MATCH_LANGUAGE = /(?:lang|language)-([a-zA-Z]+)/; 9 | var LANGUAGE_NAMES = { 10 | sh: 'Bash', 11 | js: 'JavaScript', 12 | json: 'JSON', 13 | toml: 'TOML' 14 | }; 15 | var DEFAULT_LANGUAGE = 'js'; 16 | var STORAGE_KEY = 'code-examples'; 17 | 18 | var codeExamples = { 19 | getLanguage: function() { 20 | if (!this._language && window.localStorage) { 21 | try { 22 | var data = JSON.parse(window.localStorage.getItem(STORAGE_KEY)); 23 | this._language = data.language; 24 | } 25 | catch (error) {} 26 | } 27 | if (!this._language) { 28 | this._language = DEFAULT_LANGUAGE; 29 | } 30 | return this._language; 31 | }, 32 | setLanguage: function(language) { 33 | this._language = language; 34 | if (window.localStorage) { 35 | window.localStorage.setItem(STORAGE_KEY, JSON.stringify({ 36 | language: language 37 | })); 38 | } 39 | $(document).trigger('change-code-example-language', language); 40 | } 41 | }; 42 | 43 | function clickedLanguageButton(event) { 44 | var language = $(event.target).attr('data-language'); 45 | if (language) { 46 | codeExamples.setLanguage(language); 47 | } 48 | } 49 | 50 | function languageForElement(element) { 51 | var className = $(element).children('code').attr('class'); 52 | var match = className && className.match(MATCH_LANGUAGE); 53 | return match && match[1]; 54 | } 55 | 56 | function Switcher (element) { 57 | this.element = element; 58 | this.examples = this.findExamples(); 59 | this.addUi(); 60 | $(document).on('change-code-example-language', function(event, language) { 61 | this.setLanguage(language); 62 | }.bind(this)); 63 | this.setLanguage(codeExamples.getLanguage()); 64 | } 65 | 66 | Switcher.prototype.findExamples = function() { 67 | var examples = {}; 68 | var self = this; 69 | $('pre', this.element).each(function(index, pre) { 70 | var language = languageForElement(pre); 71 | if (language) { 72 | examples[language] = pre; 73 | self._baseLanguage = self._baseLanguage || language; 74 | } 75 | }); 76 | return examples; 77 | }; 78 | 79 | Switcher.prototype.addUi = function() { 80 | this.createUi().prependTo(this.element); 81 | }; 82 | 83 | Switcher.prototype.createUi = function() { 84 | var title = $(this.element).attr('name'); 85 | var container = $('
'); 86 | container.append($('').text(title)); 87 | for (var language in this.examples) { 88 | var languageName = LANGUAGE_NAMES[language] || capitalize(language); 89 | var button = $('') 90 | .text(languageName) 91 | .attr('data-language', language) 92 | .on('click', clickedLanguageButton); 93 | container.append(button); 94 | } 95 | return container; 96 | }; 97 | 98 | Switcher.prototype.setLanguage = function(value) { 99 | if (!(value in this.examples)) { 100 | // find the first available language and show it 101 | value = this._baseLanguage; 102 | } 103 | 104 | var scrollTop = document.body.scrollTop; 105 | var bounds = this.element.getBoundingClientRect(); 106 | 107 | for (var language in this.examples) { 108 | var visible = language === value; 109 | $(this.examples[language]).css('display', visible ? '' : 'none'); 110 | $('.language-switcher--setter[data-language="' + language + '"]', 111 | this.element) 112 | .toggleClass('selected', visible); 113 | } 114 | 115 | if (bounds.top < 0) { 116 | var newBounds = this.element.getBoundingClientRect(); 117 | window.scrollTo( 118 | document.body.scrollLeft, 119 | scrollTop + (newBounds.height - bounds.height)); 120 | } 121 | }; 122 | 123 | function capitalize(text) { 124 | return text.split(' ').map(function(word) { 125 | return word.charAt(0).toUpperCase() + word.slice(1); 126 | }).join(' '); 127 | } 128 | 129 | // ...and go! 130 | $('code-example').each(function(index, element) { 131 | new Switcher(element); 132 | }); 133 | 134 | })(jQuery); 135 | -------------------------------------------------------------------------------- /src/js/codeSymbolLinks.js: -------------------------------------------------------------------------------- 1 | /* global Drop */ 2 | 3 | (function($) { 4 | 'use strict'; 5 | 6 | var SUPPORTS_TOUCH = 'createTouch' in document; 7 | 8 | function loadSymbols() { 9 | return $.ajax({ 10 | // FIXME: need to grab a base url from somewhere 11 | url: 'https://www.stellar.org/developers/js/javascript-symbols.json', 12 | dataType: 'json' 13 | }); 14 | } 15 | 16 | function setupStyles() { 17 | var style = document.createElement('style'); 18 | style.type = 'text/css'; 19 | style.innerHTML = 'pre > code a[rel=documentation] { color: inherit; }'; 20 | document.head.appendChild(style); 21 | } 22 | 23 | function replaceWithLink(element, symbol) { 24 | var link = document.createElement('a'); 25 | link.appendChild(document.createTextNode(element.textContent)); 26 | link.rel = 'documentation'; 27 | link.href = symbol.url; 28 | link.target = '_blank'; 29 | 30 | if (symbol.description) { 31 | var dropContent = document.createElement('div'); 32 | var description = document.createElement('s-read-md'); 33 | description.className = 'symbol-description'; 34 | description.innerHTML = symbol.description; 35 | dropContent.appendChild(description); 36 | $(dropContent).find('a').each(function(index, link) { 37 | if (isOffsiteUrl(link.href)) { 38 | link.target = '_blank'; 39 | } 40 | }); 41 | 42 | var readMoreLink = document.createElement('a'); 43 | readMoreLink.href = symbol.url; 44 | readMoreLink.target = '_blank'; 45 | readMoreLink.textContent = 'Read Full Documentation'; 46 | dropContent.appendChild(readMoreLink); 47 | 48 | new Drop({ 49 | target: link, 50 | position: 'bottom center', 51 | classes: 'drop-theme-arrows api-reference-drop', 52 | openOn: SUPPORTS_TOUCH ? 'click' : 'hover', 53 | hoverOpenDelay: 1000, 54 | content: dropContent 55 | }); 56 | } 57 | 58 | $(element).empty().append(link); 59 | return link; 60 | } 61 | 62 | function linkSymbols(element, symbols) { 63 | $('.cm-variable:contains("StellarSdk") + .cm-property', element).each(function(index, propertyElement) { 64 | var symbolName = $.trim(propertyElement.textContent); 65 | var candidates = symbols[symbolName]; 66 | 67 | // TODO: handle >1 candidates? 68 | if (!candidates || candidates.length !== 1) return; 69 | 70 | var symbol = candidates[0]; 71 | replaceWithLink(propertyElement, symbol); 72 | 73 | // this is a little messy, but we want to link the next one, too, e.g: 74 | // StellarSdk.Keypair.fromSeed <- link both `Keypair` and `fromSeed` 75 | var nextProperty = $(propertyElement).next('.cm-property')[0]; 76 | if (!nextProperty) return; 77 | var nextName = $.trim(nextProperty.textContent); 78 | candidates = symbols[nextName]; 79 | if (!candidates) return; 80 | 81 | var nextSymbol; 82 | for (var i = 0, len = candidates.length; i < len; i++) { 83 | if (candidates[i].memberOf === symbol.name) { 84 | nextSymbol = candidates[i]; 85 | break; 86 | } 87 | } 88 | if (!nextSymbol) return; 89 | replaceWithLink(nextProperty, nextSymbol); 90 | }); 91 | 92 | // This approach could potentially have a lot of false positives, but if we 93 | // keep example code nicely written, it should be workable. 94 | $('.cm-property', element).each(function(index, propertyElement) { 95 | // don't re-link symbols we already found 96 | if (propertyElement.children.length) return; 97 | 98 | var propertyName = $.trim(propertyElement.textContent); 99 | // TODO: can we make any good inferences that allow us to handle multiple 100 | // types with the same members, e.g. Keypair#sign vs. Transaction#sign 101 | if ((symbols[propertyName] || []).length !== 1) return; 102 | var symbol = symbols[propertyName][0]; 103 | replaceWithLink(propertyElement, symbol); 104 | }); 105 | } 106 | 107 | var URL_EXPRESSION = /\b((?:[a-z][\w-]+:(?:\/{1,3}|[a-z0-9%])|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}\/)(?:[^\s()<>\[\]'"]+|\([^\s()<>\[\]'"]*\))+(?:\([^\s()<>\[\]'"]*\)|[^\s`!()\[\]{}:'".,<>?«»“”‘’]))/gi; 108 | 109 | function linkCommentUrls(element) { 110 | // if we highlighted anything, only set up links in comments 111 | if (element.children.length) { 112 | $('.cm-comment', element).each(function(index, comment) { 113 | autoLinkInElement(comment); 114 | }); 115 | } 116 | else { 117 | var fragment = document.createDocumentFragment(); 118 | var foundLinks = false; 119 | element.textContent.split('\n').forEach(function (line) { 120 | line += '\n'; 121 | if (line[0] === '#' || line.slice(0, 2) === '//') { 122 | var links = createLinksFromText(line); 123 | fragment.appendChild(links); 124 | if (links.nodeType !== document.TEXT_NODE) { 125 | foundLinks = true; 126 | } 127 | } 128 | else { 129 | fragment.appendChild(document.createTextNode(line)); 130 | } 131 | }); 132 | if (foundLinks) { 133 | element.innerHTML = ''; 134 | element.appendChild(fragment); 135 | } 136 | } 137 | } 138 | 139 | function autoLinkInElement(element) { 140 | // TODO: use a treewalker to just walk the text nodes so we don’t destroy 141 | // an existing element tree 142 | var links = createLinksFromText(element.textContent); 143 | if (links.nodeType !== document.TEXT_NODE) { 144 | element.innerHTML = ''; 145 | element.appendChild(links); 146 | } 147 | } 148 | 149 | function createLinksFromText(text) { 150 | var segments = text.split(URL_EXPRESSION); 151 | var length = segments.length; 152 | if (length === 1) { return document.createTextNode(text); } 153 | 154 | var fragment = document.createDocumentFragment(); 155 | for (var i = 0; i < length; i += 2) { 156 | fragment.appendChild(document.createTextNode(segments[i])); 157 | var url = segments[i + 1]; 158 | if (url) { 159 | var link = document.createElement('a'); 160 | link.href = url; 161 | link.appendChild(document.createTextNode(url)); 162 | if (isOffsiteUrl(url)) { 163 | link.target = '_blank'; 164 | } 165 | fragment.appendChild(link); 166 | } 167 | } 168 | return fragment; 169 | } 170 | 171 | function isOffsiteUrl(url) { 172 | var hostname = url && url.match(/^(?:\w+:\/\/(?:\/?))?([^\/]+)/); 173 | return hostname && hostname[1] !== window.location.hostname; 174 | } 175 | 176 | $(function() { 177 | $('pre > code').each(function(index, element) { 178 | linkCommentUrls(element); 179 | }); 180 | 181 | var highlightedCode = $('pre > code.language-js, pre > code.language-javascript, pre > code.language-node'); 182 | if (!highlightedCode.length) return; 183 | 184 | loadSymbols().then(function(symbols) { 185 | setupStyles(); 186 | highlightedCode.each(function(index, element) { 187 | linkSymbols(element, symbols); 188 | }); 189 | }); 190 | }); 191 | 192 | })(jQuery); 193 | -------------------------------------------------------------------------------- /src/js/collapsibleListSet.js: -------------------------------------------------------------------------------- 1 | // collapsibleListSet is a container that wraps two elements: label and list. 2 | // The label toggles the collapsed state of the list. 3 | 4 | // This also scans for any children that is the currentItem 5 | // ('.js-collapsibleListSet__list li.is-currentItem'). If any of these items 6 | // are present, then the collapsibleListSet's classes will be all removed. 7 | // The reason is for this is due to limitations on how we can style multi level 8 | // nested items that take up an absolute space relative to an item that is not 9 | // the collapsibleListSet. (see `.pageNavList__item.is-currentItem` and 10 | // `.pageNavListBounder`). 11 | 12 | // A collapsibleListSet's classes can also be removed if it is a child of another 13 | // collapsibleListSet. 14 | 15 | (function() { 16 | $('.js-collapsibleListSet').each(function(index, container) { 17 | var $container = $(container); 18 | var $label = $container.find('> .js-collapsibleListSet__label'); 19 | var $list = $container.find('> .js-collapsibleListSet__list'); 20 | 21 | if ($container.parents('.js-collapsibleListSet, .js-collapsibleListSet--nullified').length > 0 22 | || $list.find('.is-currentItem').length > 0) { 23 | $container.removeClass('collapsibleListSet js-collapsibleListSet'); 24 | $container.addClass('js-collapsibleListSet--nullified'); 25 | $container.find('> .js-collapsibleListSet__label').removeClass('collapsibleListSet__label is-collapsed js-collapsibleListSet__label'); 26 | $container.find('> .js-collapsibleListSet__list').removeClass('collapsibleListSet__list is-collapsed js-collapsibleListSet__list'); 27 | return; 28 | } 29 | 30 | $label.click(function() { 31 | // Set up the element to transition to a set max-height. This is necessary 32 | // because it is not possible to use pure css to animate height. 33 | $list.css('max-height', $list[0].scrollHeight); 34 | $([$label, $list]).toggleClass('is-collapsed'); 35 | }); 36 | }); 37 | })(); -------------------------------------------------------------------------------- /src/js/endpointRef.js: -------------------------------------------------------------------------------- 1 | // Skip .ready so that there is less FOUC 2 | // FOUC can be removed by moving the DOM manipulation into the post processing 3 | 4 | // Build step 5 | (function() { 6 | 'use strict'; 7 | 8 | // init 9 | var $endpointDocs = $('.mainContent'); 10 | var $endpointBar = $('.js-endpointRef-exampleBar'); 11 | if ($endpointDocs.length !== 1 && $endpointBar.length !== 1) { 12 | $endpointBar.remove(); 13 | return; 14 | } 15 | 16 | // language list is in order. first item is the default 17 | // This does not include the 'default' language which may exist in the store 18 | // Will be directly inserted into a classname, so if there is ever a language 19 | // with special characters, code below to escape it will need to be written 20 | var languageList = ['curl', 'JavaScript', 'Go', 'Ruby']; 21 | var languagesWithExamples = {}; // will contain case sensitive name of languages that have content 22 | var exampleStore = { // contains string representation of html 23 | request: {}, 24 | response: {}, 25 | }; 26 | 27 | // scrape relevant content and put it into our exampleStore 28 | var processExample = function(id, language, type) { 29 | var $id = $(id); 30 | var $example = $id.nextUntil('h3,h2'); 31 | if ($example.length !== 0) { 32 | languagesWithExamples[language] = true; 33 | exampleStore[type][language] = $('
').append($example.clone()).html(); 34 | } 35 | 36 | $id.remove(); 37 | $example.remove(); 38 | }; 39 | languageList.forEach(function(language) { 40 | var languageId = language.toLowerCase(); 41 | processExample('#' + languageId + '-example-request', language, 'request'); 42 | processExample('#' + languageId + '-example-response', language, 'response'); 43 | }); 44 | processExample('#example-request', '_default', 'request'); 45 | processExample('#example-response', '_default', 'response'); 46 | 47 | // initial render: since we don't have a library to manage our clicks, 48 | // this initial render only runs once so that the click handlers don't get 49 | // destroyed. This is also so that we don't have to re-initialize the content 50 | // that may be expensive to load (codemirror) 51 | var $menu = $endpointBar.find('.js-endpointRef-menu'); 52 | var $exampleRequest = $endpointBar.find('.js-endpointRef-exampleRequest'); 53 | var $exampleResponse = $endpointBar.find('.js-endpointRef-exampleResponse'); 54 | 55 | var examplesExist = false; 56 | 57 | if (languageList.length === 0) { 58 | $endpointBar.remove(); 59 | return $.html(); 60 | } 61 | 62 | var firstLanguage = true; 63 | languageList.forEach(function(language) { 64 | if (language in languagesWithExamples) { 65 | examplesExist = true; 66 | var activeClass = (firstLanguage) ? ' is-active' : ''; 67 | $menu.append(''); 68 | 69 | $exampleRequest.append('
'); 70 | $exampleResponse.append('
'); 71 | 72 | var $currentExampleReqBox = $('.js-endpointRef-exampleRequest .js-endpointRef-lang--' + language); 73 | var $currentExampleResBox = $('.js-endpointRef-exampleResponse .js-endpointRef-lang--' + language); 74 | 75 | if (language in exampleStore.request) { 76 | $currentExampleReqBox.html(exampleStore.request[language]); 77 | } else if ('_default' in exampleStore.request) { 78 | $currentExampleReqBox.html(exampleStore.request['_default']); 79 | } 80 | 81 | if (language in exampleStore.response) { 82 | $currentExampleResBox.html(exampleStore.response[language]); 83 | } else if ('_default' in exampleStore.response) { 84 | $currentExampleResBox.html(exampleStore.response['_default']); 85 | } 86 | 87 | // Default to only showing the first language available 88 | if (firstLanguage) { 89 | firstLanguage = false; 90 | } else { 91 | $currentExampleReqBox.css('display', 'none'); 92 | $currentExampleResBox.css('display', 'none'); 93 | } 94 | } 95 | }); 96 | 97 | // Try it out [in the laboratory] button 98 | if (typeof clientData.laboratoryUrl === 'string') { 99 | $menu.append('Try it out '); 101 | } 102 | 103 | if (!examplesExist) { 104 | $endpointBar.remove(); 105 | } else { 106 | $endpointBar.addClass('is-available'); 107 | } 108 | })() 109 | 110 | // Runtime controller for the endpointRef module (to show examples in a sidebar) 111 | ;(function endpointRef() { 112 | "use strict"; 113 | // init 114 | var $endpointBar = $('.js-endpointRef-exampleBar'); 115 | if ($endpointBar.length === 1) { 116 | // state definition 117 | var state = { 118 | language: $endpointBar.find('.js-endpointRef-menu .is-active').attr('endpoint-ref-lang') 119 | }; 120 | 121 | // get initial state 122 | var storedItem = localStorage.getItem('developers.endpointRef.language'); 123 | if (storedItem !== null && $endpointBar.find('.js-endpointRef-menu [endpoint-ref-lang=' + storedItem + ']').length == 1) { 124 | state.language = storedItem; 125 | } 126 | 127 | // render function. directly mutates the DOM already present in HTML 128 | var render = function() { 129 | $endpointBar.find('.js-endpointRef-menu').children().removeClass('is-active'); 130 | $endpointBar.find('.js-endpointRef-menu .js-endpointRef-menuLang--' + state.language).addClass('is-active'); 131 | $endpointBar.find('.js-endpointRef-lang').hide(); 132 | $endpointBar.find('.js-endpointRef-lang--' + state.language).show(); 133 | }; 134 | // runtime render for the first time 135 | render(); 136 | 137 | // component "mounted". now attach click handler to tab menu only on items 138 | // that are considered language examples (and not external links) 139 | $endpointBar.find('.js-endpointRef-menu__item--lang').on('click', function(el) { 140 | state.language = el.target.innerHTML; 141 | // component will update. save to localstorage the current param 142 | localStorage.setItem('developers.endpointRef.language', state.language); 143 | render(); 144 | }); 145 | } 146 | })(); 147 | -------------------------------------------------------------------------------- /src/js/footnotes.js: -------------------------------------------------------------------------------- 1 | /* global Drop */ 2 | 3 | /** 4 | * Display footnotes as popovers. 5 | */ 6 | (function($) { 7 | 'use strict'; 8 | 9 | var SUPPORTS_TOUCH = 'createTouch' in document; 10 | 11 | /** 12 | * Clone the footnote associated with a reference link and display it as a 13 | * popover so the user can see the footnote in context. 14 | * @param {Element} footnoteLink 15 | */ 16 | function createFootnoteDropdown(footnoteLink) { 17 | var content = $(footnoteLink.getAttribute('href')); 18 | if (!content.length) return; 19 | 20 | // Our text styles are scoped to , so wrap the footnote in one. 21 | var noteNode = document.createElement('s-read-md'); 22 | $(noteNode) 23 | .append(content.clone().children()) 24 | .find('.footnote-backref') 25 | .remove(); 26 | 27 | return new Drop({ 28 | target: footnoteLink.parentNode, 29 | position: 'bottom center', 30 | classes: 'drop-theme-arrows footnote-drop', 31 | openOn: SUPPORTS_TOUCH ? 'click' : 'hover', 32 | content: noteNode 33 | }); 34 | } 35 | 36 | $('.footnote-ref a').each(function(index, element) { 37 | createFootnoteDropdown(element); 38 | }); 39 | 40 | })(jQuery); 41 | -------------------------------------------------------------------------------- /src/js/friendbot4.js: -------------------------------------------------------------------------------- 1 | // Friendbot 4 2 | 3 | (function() { 4 | $('.js-friendbot4').each(function() { 5 | var $fb4 = $(this); 6 | var CONFIG = { 7 | horizonUri: 'https://horizon-testnet.stellar.org' // no trailing slash 8 | }; 9 | 10 | // initial state template 11 | var state = { 12 | currentStep: 0, 13 | maxStep: 1, // highest index of step we can go to 14 | endingStep: 4, 15 | keypair: { 16 | seed: '', 17 | address: '' 18 | }, 19 | step1: { 20 | result: '' 21 | }, 22 | step2: { 23 | friendbotStatus: '', 24 | friendbotError: '', 25 | customAddress: '', 26 | }, 27 | step3: { 28 | result: '', 29 | } 30 | }; 31 | 32 | // Navigation 33 | var canNavPrev = function() { 34 | return state.currentStep > 0; 35 | }; 36 | var canNavNext = function() { 37 | return state.currentStep !== state.maxStep; 38 | }; 39 | var ensureTopVisible = function() { 40 | if ($fb4[0].getBoundingClientRect().top < 0) { 41 | window.scrollTo(window.scrollX, $fb4.offset().top - 18); 42 | } 43 | }; 44 | $fb4.find('.js-friendbot4__nav__prev').on('click', function() { 45 | if (canNavPrev()) { 46 | state.currentStep = state.currentStep - 1; 47 | ensureTopVisible(); 48 | render(); 49 | } 50 | }); 51 | $fb4.find('.js-friendbot4__nav__next').on('click', function() { 52 | if (canNavNext()) { 53 | state.currentStep = state.currentStep + 1; 54 | ensureTopVisible(); 55 | render(); 56 | } 57 | }); 58 | $fb4.find('.js-friendbot4__nav__minimize').on('click', function() { 59 | state.currentStep = 1; 60 | render(); 61 | }); 62 | 63 | // Step 0 64 | $fb4.find('.js-friendbot4-step0__start').on('click', function() { 65 | $(this).blur(); 66 | state.currentStep = 1; 67 | render(); 68 | }); 69 | 70 | // Step 1 71 | $fb4.find('.js-friendbot4-step1-generate').on('click', function() { 72 | var keypair = StellarSdk.Keypair.random(); 73 | state.keypair.seed = keypair.seed(); 74 | state.keypair.address = keypair.address(); 75 | state.maxStep = 2; 76 | state.step1.result = '' + 77 | '{\n' + 78 | ' "public key": "' + state.keypair.address + '",\n' + 79 | ' "secret key": "' + state.keypair.seed + '"\n' + 80 | '}'; 81 | render(); 82 | }); 83 | 84 | // Step 2 85 | $fb4.find('.js-friendbot4__bot__button').on('click', function() { 86 | state.step2.friendbotStatus = 'Asking Stroopy...'; 87 | state.step2.friendbotError = ''; 88 | state.step2.friendbotDisabled = true; 89 | 90 | var requestAddress = state.keypair.address; 91 | var inputVal = $fb4.find('.js-friendbot4__bot__input').val(); 92 | if (inputVal !== state.keypair.address) { 93 | requestAddress = state.step2.customAddress = inputVal; 94 | } 95 | render(); 96 | 97 | $.ajax({ 98 | url: 'https://horizon-testnet.stellar.org/friendbot?addr=' + requestAddress, 99 | }) 100 | .fail(function (data) { 101 | if (typeof data === 'undefined') { 102 | state.step2.friendbotStatus = 'Network connection problem. Try again in a moment.'; 103 | state.step2.friendbotDisabled = false; 104 | } else { 105 | state.step2.friendbotStatus = 'We\'re having a server issue: '; 106 | state.step2.friendbotError = data.responseText; 107 | state.step2.friendbotDisabled = false; 108 | } 109 | render(); 110 | }) 111 | .done(function(data) { 112 | state.step2.friendbotStatus = 'Lumens have arrived!'; 113 | state.maxStep = 3; 114 | render(); 115 | }); 116 | }); 117 | 118 | // Step 3 119 | $fb4.find('.js-friendbot4-step3-run').on('click', function() { 120 | state.maxStep = 4; 121 | $.ajax({ 122 | type: 'GET', 123 | url: CONFIG.horizonUri + '/accounts/' + state.keypair.address, 124 | success: function (result) { 125 | state.step3.result = JSON.stringify(result, null, 2); 126 | render(); 127 | }, 128 | error: function() { 129 | state.step3.result = 'Couldn\'t find test account due to a server issue. Report in our public Keybase channel and try creating an account again later.'; 130 | render(); 131 | } 132 | }); 133 | }); 134 | 135 | var render = function() { 136 | // show the current step 137 | $fb4.find('[js-friendbot4-step]').hide() 138 | .filter('[js-friendbot4-step=' + state.currentStep + ']').show(); 139 | 140 | // helpers 141 | var setButtonDisabled = function(button, disabled) { 142 | if (disabled) { 143 | button.addClass('is-disabled').attr('disabled', 'disabled'); 144 | } else { 145 | button.removeClass('is-disabled').removeAttr('disabled'); 146 | } 147 | }; 148 | 149 | // navigation 150 | if (state.currentStep > 0) { 151 | $fb4.find('.js-friendbot4__navWrapper').show(); 152 | } else { 153 | $fb4.find('.js-friendbot4__navWrapper').hide(); 154 | } 155 | 156 | if (state.currentStep === state.endingStep) { 157 | $fb4.find('.js-friendbot4__nav__next').hide(); 158 | } else { 159 | $fb4.find('.js-friendbot4__nav__next').show(); 160 | } 161 | 162 | setButtonDisabled($('.js-friendbot4__nav__next'), !canNavNext()); 163 | setButtonDisabled($('.js-friendbot4__nav__prev'), !canNavPrev()); 164 | 165 | // step 1 166 | $fb4.find('.js-friendbot4-step1-result').text(state.step1.result); 167 | syntaxHighlight($fb4.find('.js-friendbot4-step1-result')); 168 | 169 | // step 2 170 | $fb4.find('.js-friendbot4__bot__button__status').text(state.step2.friendbotStatus); 171 | $fb4.find('.js-friendbot4__bot__button__error__code').text(state.step2.friendbotError); 172 | if (state.step2.friendbotError != '') { 173 | $fb4.find('.js-friendbot4__bot__button__error').addClass('is-populated'); 174 | } else { 175 | $fb4.find('.js-friendbot4__bot__button__error').removeClass('is-populated'); 176 | } 177 | 178 | syntaxHighlight($fb4.find('.js-friendbot4__bot__button__error__code')); 179 | 180 | if (state.step2.customAddress !== '') { 181 | $fb4.find('.friendbot4__bot__input').val(state.step2.customAddress); 182 | } else { 183 | $fb4.find('.friendbot4__bot__input').val(state.keypair.address); 184 | } 185 | 186 | setButtonDisabled($('.js-friendbot4__bot__button'), state.step2.friendbotDisabled); 187 | 188 | // step 3 189 | $fb4.find('.js-friendbot4-step3-request').text('curl -X GET \'' + CONFIG.horizonUri + '/accounts/' + state.keypair.address + '\''); 190 | $fb4.find('.js-friendbot4-step3-result').text(state.step3.result); 191 | syntaxHighlight($fb4.find('.js-friendbot4-step3-request')); 192 | syntaxHighlight($fb4.find('.js-friendbot4-step3-result')); 193 | 194 | // step 4 195 | $fb4.find('.js-friendbot4-step4-address').text(state.keypair.address); 196 | $fb4.find('.js-friendbot4-step4-seed').text(state.keypair.seed); 197 | }; 198 | render(); 199 | }); 200 | })(); 201 | -------------------------------------------------------------------------------- /src/js/linkCheck.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var linkcheck = function() { 3 | var links = document.getElementsByTagName('a'); 4 | for (var i = 0; i < links.length; i++) { 5 | if (links[i].href.match(/\/\#check$/) !== null) { 6 | links[i].className += ' linkCheck-emptyLink'; 7 | } 8 | } 9 | }; 10 | linkcheck(); 11 | })(); 12 | -------------------------------------------------------------------------------- /src/js/syntaxHighlight.js: -------------------------------------------------------------------------------- 1 | // Usage: 2 | // syntaxHighlight($('code.block')); 3 | // 4 | // Parent will be adorned with some extra classes 5 | 6 | window.syntaxHighlight = (function() { 7 | var languageMap = { 8 | 'js': 'javascript', 9 | 'javascript': 'javascript', 10 | 'json': 'javascript', 11 | 'node': 'javascript', 12 | 'sh': 'shell', 13 | 'shell': 'shell', 14 | 'bash': 'shell', 15 | 'java': 'text/x-java', 16 | 'go': 'text/x-go', 17 | 'toml': 'text/x-toml', 18 | 'python': 'text/x-python' 19 | }; 20 | 21 | var highlighter = function(code) { 22 | var $code = $(code); 23 | var $parent = $code.parent(); 24 | 25 | // see if this is a valid candidate for highlighting (has class starting with lang- or language-) 26 | if (typeof $code.attr('class') === 'undefined') { 27 | return; 28 | } 29 | var classMatch = $code.attr('class').match(/(lang|language)-([a-zA-Z]+)/); 30 | 31 | if (classMatch !== null && classMatch.length == 3 && classMatch[2] in languageMap) { 32 | CodeMirror.runMode($code.text(), languageMap[classMatch[2]], $code[0]); 33 | $parent.addClass('cm-s-monokai CodeMirror codeBlock codeBlock--syntaxHighlight'); 34 | } else { 35 | $parent.addClass('cm-s-monokai CodeMirror codeBlock codeBlock--plain'); 36 | } 37 | }; 38 | 39 | $('pre > code').each(function(k, code) { 40 | highlighter($(code)); 41 | }); 42 | 43 | return highlighter; 44 | })(); 45 | -------------------------------------------------------------------------------- /src/reference: -------------------------------------------------------------------------------- 1 | ../repos/docs/reference -------------------------------------------------------------------------------- /src/software: -------------------------------------------------------------------------------- 1 | ../repos/docs/software -------------------------------------------------------------------------------- /src/stellar-core: -------------------------------------------------------------------------------- 1 | ../repos/stellar-core/docs -------------------------------------------------------------------------------- /src/styles/_anchorShortcut.scss: -------------------------------------------------------------------------------- 1 | // Anchor shortcuts only apply on headings (h1, h2, h3, h4, h5, h6) 2 | .anchorShortcut { 3 | position: relative; 4 | } 5 | .anchorShortcut:before { 6 | display: inline-block; 7 | content: '#'; 8 | position: absolute; 9 | right: 0; 10 | 11 | padding: 0 .25em; 12 | opacity: 0; 13 | color: $s-color-neutral7; 14 | } 15 | .anchorShortcut:hover:before { 16 | color: $purple; 17 | } 18 | h1:hover > .anchorShortcut:before, 19 | h2:hover > .anchorShortcut:before, 20 | h3:hover > .anchorShortcut:before, 21 | h4:hover > .anchorShortcut:before, 22 | h5:hover > .anchorShortcut:before, 23 | h6:hover > .anchorShortcut:before { 24 | opacity: 1; 25 | } 26 | -------------------------------------------------------------------------------- /src/styles/_backgrounds.scss: -------------------------------------------------------------------------------- 1 | // These custom color backgrounds are done so that colors can more easily match 2 | // the mockups while we can still track which colors we have already used. 3 | .background-5B6A72 { 4 | background-color: #5B6A72; 5 | } 6 | .background-nightBlue { 7 | background-color: #1E3440; 8 | } 9 | .background-starsLayer { 10 | @include so-graphic('stars-texture.png', 1530, 1140); 11 | width: auto; 12 | height: auto; 13 | } 14 | -------------------------------------------------------------------------------- /src/styles/_codeExamples.scss: -------------------------------------------------------------------------------- 1 | code-example { 2 | display: block; 3 | margin-bottom: 1em; 4 | } 5 | 6 | code-example pre { 7 | border-top-left-radius: 0; 8 | border-top-right-radius: 0; 9 | } 10 | 11 | .language-switcher { 12 | border: 1px solid $s-color-neutral6; 13 | border-bottom: none; 14 | border-top-left-radius: 2px; 15 | border-top-right-radius: 2px; 16 | color: $s-color-neutral4; 17 | font-size: 0.75em; 18 | padding: 0.5em 1em 0 1em; 19 | 20 | .code-example-title { 21 | margin-right: 2em; 22 | } 23 | 24 | .language-switcher--setter { 25 | border: none; 26 | background: transparent; 27 | color: $s-color-neutral5; 28 | margin: 0 1em 0 0; 29 | padding: 0 0.65em 0.4em 0.65em; 30 | } 31 | 32 | .language-switcher--setter:not(.selected):hover { 33 | color: $s-color-neutral3; 34 | border-bottom: 3px solid $s-color-neutral3; 35 | } 36 | 37 | .language-switcher--setter.selected { 38 | border-bottom: 3px solid $purple; 39 | color: $purple; 40 | } 41 | } 42 | 43 | .drop-element .symbol-description { 44 | max-height: 10.5em; 45 | overflow: hidden; 46 | } 47 | -------------------------------------------------------------------------------- /src/styles/_collapsibleListSet.scss: -------------------------------------------------------------------------------- 1 | .collapsibleListSet { 2 | } 3 | .collapsibleListSet__label { 4 | cursor: pointer; 5 | } 6 | .collapsibleListSet__label:after { 7 | content: ''; 8 | display: inline-block; 9 | vertical-align: middle; 10 | margin-left: 6px; 11 | width: 9px; 12 | height: 6px; 13 | background-repeat: no-repeat; 14 | background-size: 9px 6px; 15 | background-image: url('data:image/svg+xml;utf8,'); 16 | } 17 | .collapsibleListSet__label.is-collapsed:after { 18 | background-image: url('data:image/svg+xml;utf8,'); 19 | } 20 | 21 | .collapsibleListSet__list { 22 | transition: 0.4s all; 23 | } 24 | .collapsibleListSet__list.is-collapsed { 25 | overflow: hidden; 26 | max-height: 0 !important; 27 | } 28 | -------------------------------------------------------------------------------- /src/styles/_descriptionList.scss: -------------------------------------------------------------------------------- 1 | s-read-md dl { 2 | & > * { 3 | margin: 0; 4 | padding: 0.2em 0; 5 | } 6 | 7 | dt { 8 | float: left; 9 | font-weight: bold; 10 | min-width: 8em; 11 | padding-right: 0.5em; 12 | } 13 | 14 | dt:after { 15 | content: ': '; 16 | } 17 | 18 | dd { 19 | border-bottom: 1px solid $s-color-neutral7; 20 | margin-bottom: 0.5em; 21 | text-align: right; 22 | } 23 | 24 | dd code:only-child { 25 | background: transparent; 26 | outline: none; 27 | } 28 | } 29 | 30 | @supports (display: grid) { 31 | s-read-md dl { 32 | display: grid; 33 | grid-template-columns: auto 1fr; 34 | 35 | dt, 36 | dd { 37 | border-bottom: 1px solid $s-color-neutral7; 38 | margin-bottom: 0.5em; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/styles/_footnotes.scss: -------------------------------------------------------------------------------- 1 | // Line separating footnotes from rest of document 2 | .footnotes-sep { 3 | border: none; 4 | border-top: 1px solid $s-color-neutral7; 5 | // like most text content, .footnotes-sep has a max-width. However, it is 6 | // normally centered. Remove the left margin so it lines up with content. 7 | margin-left: 0; 8 | } 9 | -------------------------------------------------------------------------------- /src/styles/_friendbot4.scss: -------------------------------------------------------------------------------- 1 | .friendbot4__console { 2 | background: $s-color-neutral1; 3 | } 4 | .friendbot4__console__input { 5 | @include S-flex-row; 6 | align-items: center; 7 | border-bottom: 1px solid $s-color-neutral4; 8 | padding: 1em; 9 | } 10 | .friendbot4__console__result { 11 | padding: 1em; 12 | margin: 0; 13 | } 14 | .friendbot4__console__input__text { 15 | @include S-flexItem-share; 16 | word-break: break-all; 17 | margin-right: 2em; 18 | } 19 | .friendbot4__console__input__button { 20 | @include S-flexItem-noFlex; 21 | } 22 | .friendbot4__nav { 23 | @include S-flex-row; 24 | justify-content: space-between; 25 | align-items: flex-end; 26 | padding: 1em; 27 | } 28 | .friendbot4__nav__minimize { 29 | font-size: $s-scale-5; 30 | } 31 | 32 | .friendbot4__bot__image { 33 | text-align: center; 34 | } 35 | .friendbot4__bot__input { 36 | margin-right: 0.5em; 37 | } 38 | 39 | .friendbot4__info { 40 | padding: 1em; 41 | } 42 | .friendbot4__bot__button__status { 43 | text-align: center; 44 | font-size: $s-scale-2; 45 | padding-top: 1em; 46 | } 47 | .friendbot4__bot__button__error.is-populated { 48 | padding: 1em; 49 | } 50 | .friendbot4-step0 { 51 | padding: 1em; 52 | } 53 | .friendbot4-step0__code { 54 | color: $s-color-neutral8; 55 | } 56 | .friendbot4-step4__key { 57 | text-align: center; 58 | } 59 | 60 | .friendbot4-stepIntro { 61 | padding: 1.5em 1em 0.5em 1em; 62 | } 63 | .friendbot4-stepOutro { 64 | padding-left: 1em; 65 | padding-right: 1em; 66 | } 67 | .friendbot4-stepIntro a, 68 | .friendbot4-stepOutro a { 69 | color: $purple; 70 | } 71 | .friendbot4-initialHide { 72 | display: none; 73 | } 74 | -------------------------------------------------------------------------------- /src/styles/_graphics.scss: -------------------------------------------------------------------------------- 1 | // the following is generated using solar-stellarorg/tools/graphicGenerator.js 2 | .so-graphic-codeWithOrbits { @include so-graphic("codeWithOrbits.png", 284, 284); @extend .so-graphic; } 3 | .so-graphic-nodeConnectedEarth { @include so-graphic("nodeConnectedEarth.png", 262, 264); @extend .so-graphic; } 4 | .so-graphic-pencilOnEarth { @include so-graphic("pencilOnEarth.png", 288, 250); @extend .so-graphic; } 5 | .so-graphic-s-bigCogLittleCog { @include so-graphic("s-bigCogLittleCog.png", 124, 124); @extend .so-graphic; } 6 | .so-graphic-s-fileFolder { @include so-graphic("s-fileFolder.png", 132, 120); @extend .so-graphic; } 7 | .so-graphic-s-rectangularTree { @include so-graphic("s-rectangularTree.png", 126, 120); @extend .so-graphic; } 8 | .so-graphic-s-stellarRocket { @include so-graphic("s-stellarRocket.png", 96, 120); @extend .so-graphic; } 9 | 10 | // New format since it was taken out of solar 11 | .graphic-circled-code-120 { @include so-graphic("circled-code-120.png", 240, 240); @extend .so-graphic; } 12 | .graphic-circled-folder-120 { @include so-graphic("circled-folder-120.png", 240, 240); @extend .so-graphic; } 13 | .graphic-circled-horizon-120 { @include so-graphic("circled-horizon-120.png", 240, 240); @extend .so-graphic; } 14 | 15 | .graphic-centaurus-120 { @include so-graphic("centaurus-120.png", 240, 240); @extend .so-graphic; } 16 | .graphic-app-stack-bill-140 { @include so-graphic("app-stack-bill.png", 280, 280); @extend .so-graphic; } 17 | .graphic-longDownArrow-88 { @include so-graphic("longDownArrow.png", 66, 176); @extend .so-graphic; } 18 | .graphic-backArrow-9 { @include so-graphic("backArrow.svg", 36, 18); @extend .so-graphic;} 19 | 20 | 21 | .graphic-centaurus-120 { @include so-graphic("centaurus-120.png", 240, 240); @extend .so-graphic; } 22 | .graphic-app-stack-bill-140 { @include so-graphic("app-stack-bill.png", 280, 280); @extend .so-graphic; } 23 | .graphic-longDownArrow-88 { @include so-graphic("longDownArrow.png", 66, 176); @extend .so-graphic; } 24 | .graphic-backArrow-9 { @include so-graphic("backArrow.svg", 36, 18); @extend .so-graphic;} 25 | 26 | // for landing0616 27 | .graphic-network { @include so-graphic("icon-stellar-network.svg", 96, 120); @extend .so-graphic;} 28 | .graphic-checkId { @include so-graphic("icon-create-account.svg", 164, 120); @extend .so-graphic;} 29 | .graphic-money { @include so-graphic("icon-money.svg", 186, 120); @extend .so-graphic;} 30 | .graphic-pageCode { @include so-graphic("icon-references.svg", 184, 162); @extend .so-graphic;} 31 | .graphic-pageWriting { @include so-graphic("icon-guides.svg", 180, 164); @extend .so-graphic;} 32 | .graphic-pageSoftware { @include so-graphic("icon-software.svg", 154, 164); @extend .so-graphic;} 33 | .graphic-prototypeGear { @include so-graphic("prototype-gear.png", 180, 180); @extend .so-graphic;} 34 | .graphic-ldarkKeybase { @include so-graphic("ldark-keybase.png", 100, 100); @extend .so-graphic;} 35 | .graphic-ldarkGithub { @include so-graphic("ldark-github.png", 100, 100); @extend .so-graphic;} 36 | .graphic-ldarkPaper { @include so-graphic("ldark-paper.png", 100, 100); @extend .so-graphic;} 37 | .graphic-ldarkTwitter { @include so-graphic("ldark-twitter.png", 100, 100); @extend .so-graphic;} 38 | .graphic-ldarkStackExchange { @include so-graphic("ldark-stackexchange.png", 100, 100); @extend .so-graphic;} 39 | -------------------------------------------------------------------------------- /src/styles/_header2016.scss: -------------------------------------------------------------------------------- 1 | .header2016, .header2016Back { 2 | border-bottom: 1px solid $lightestGray; 3 | background-color: $white; 4 | } 5 | .header2016 { 6 | @include S-flex-row; 7 | } 8 | .header2016--centered { 9 | border-bottom: 0; 10 | } 11 | .header2016__logo { 12 | @include S-flexItem-noFlex; 13 | @include S-flexItem-noFlex; 14 | } 15 | .header2016__logo--spaced { 16 | width: 288px; 17 | padding-left: 2em; 18 | } 19 | .header2016__nav { 20 | @include S-flexItem-share; 21 | } 22 | -------------------------------------------------------------------------------- /src/styles/_icons.scss: -------------------------------------------------------------------------------- 1 | // faSvg icons are Font Awesome icons in (minified/optimized) svg format. 2 | // Font Awesome by Dave Gandy - http://fontawesome.io 3 | // License: SIL OFL 1.1 http://scripts.sil.org/OFL 4 | // Some icons are color coded. We are using svg instead of fonts here to reduce 5 | // file size and complexity. We may consider switching to image fonts if it makes 6 | // more sense. 7 | .icon-faSvg { 8 | display: inline-block; 9 | width: 1em; 10 | height: 1em; 11 | vertical-align: baseline; 12 | background-size: 1em; 13 | background-repeat: no-repeat; 14 | } 15 | .icon-faSvg--small { 16 | width: 0.75em; 17 | height: 0.75em; 18 | background-size: 0.75em; 19 | } 20 | .icon-faSvg-external-neutral9 { 21 | background-image: url('data:image/svg+xml;utf8,'); 22 | } 23 | .icon-faSvg-external-neutral5 { 24 | background-image: url('data:image/svg+xml;utf8,'); 25 | } 26 | -------------------------------------------------------------------------------- /src/styles/_landing0616.scss: -------------------------------------------------------------------------------- 1 | .landing0616 { 2 | 3 | } 4 | .landing0616-cta { 5 | padding: 0.7em 2em 0.6333em 2em; 6 | } 7 | 8 | 9 | // Resources 10 | .landing0616-resTitle { 11 | font-weight: normal; 12 | text-align: center; 13 | border-bottom: 1px solid $gray; 14 | padding-bottom: 0.5em; 15 | padding-top: 0.5em; 16 | color: $darkestGray; 17 | 18 | &.sub { 19 | font-size: 20px; 20 | } 21 | } 22 | 23 | a.landing0616-resLink { 24 | color: $s-color-neutral4; 25 | text-decoration: none; 26 | } 27 | a.landing0616-resLink:hover { 28 | text-decoration: underline; 29 | } 30 | .landing0616-res { 31 | list-style: none; 32 | } 33 | .landing0616-res__item { 34 | padding: 0; 35 | border-bottom: 1px solid $gray; 36 | } 37 | .landing0616-res__item a { 38 | display: block; 39 | padding: 0.5em 0; 40 | text-decoration: none; 41 | color: $darkestGray; 42 | } 43 | .landing0616-res__item a:hover { 44 | text-decoration: underline; 45 | } 46 | 47 | 48 | .landing0616-buildApps, .landing0616-buildAppsSlant { 49 | background: #121D24; 50 | } 51 | .landing0616-buildApps__chunk { 52 | max-width: 47em; 53 | } 54 | .landing0616-buildApps__lead { 55 | } 56 | 57 | .landing0616-introMini { 58 | max-width: 600px; 59 | margin: 0 auto; 60 | text-align: center; 61 | display: block; 62 | } 63 | @include r-media(m) { 64 | .landing0616-introMini { 65 | display: flex; 66 | } 67 | } 68 | a.landing0616-introMini__item { 69 | text-decoration: none; 70 | text-align: center; 71 | } 72 | a.landing0616-introMini__item:hover { 73 | text-decoration: underline; 74 | } 75 | .landing0616-circleNum { 76 | display: inline-block; 77 | width: 36px; 78 | height: 36px; 79 | padding: 0.75em; 80 | border: 1px solid $lightPurple; 81 | color: #1E1E1E; 82 | margin-bottom: 18px; 83 | 84 | text-align: center; 85 | line-height: 9px; 86 | font-size: 16px; 87 | background: $lightPurple; 88 | border-radius: 100%; 89 | } 90 | 91 | // Don't see what you're looking for? 92 | .landing0616-lookMini { 93 | } 94 | a.landing0616-lookMini__item { 95 | display: block; 96 | max-width: 120px; 97 | text-decoration: none; 98 | } 99 | a.landing0616-lookMini__item:hover { 100 | text-decoration: underline; 101 | } 102 | .landing0616-lookMini__item__graphic { 103 | opacity: 0.6; 104 | } 105 | a.landing0616-lookMini__item:hover .landing0616-lookMini__item__graphic { 106 | opacity: 1; 107 | } 108 | -------------------------------------------------------------------------------- /src/styles/_mailSignup.scss: -------------------------------------------------------------------------------- 1 | .mailSignup { 2 | @include S-flex-rowWrap; 3 | } 4 | .mailSignup__title { 5 | @include S-flexItem-full; 6 | font-weight: bold; 7 | margin-bottom: 0.5em; 8 | } 9 | .mailSignup__input { 10 | @include S-flexItem-share; 11 | margin-right: 0.5em; 12 | } 13 | .mailSignup__submit { 14 | @include S-flexItem-noFlex; 15 | } 16 | 17 | @include r-media(l) { 18 | .mailSignup__title { 19 | @include S-flexItem-noFlex; 20 | margin: 0 1.5em 0 0; 21 | align-self: center; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/styles/_mainNavMenu.scss: -------------------------------------------------------------------------------- 1 | .mainNavMenu { 2 | @include S-flex-row; 3 | align-items: stretch; 4 | } 5 | .mainNavMenu__item { 6 | margin-right: 3em; 7 | margin-top: 26px; 8 | color: $darkestGray; 9 | text-decoration: none; 10 | } 11 | .mainNavMenu__item:hover { 12 | color: $darkerPurple; 13 | } 14 | .mainNavMenu__item.is-currentItem { 15 | color: $purple; 16 | font-weight: 500; 17 | border-bottom: 2px solid $purple; 18 | } 19 | -------------------------------------------------------------------------------- /src/styles/_mathFormula.scss: -------------------------------------------------------------------------------- 1 | .math-formula { 2 | .math-formula-paren { 3 | font-weight: lighter; 4 | opacity: 0.25; 5 | } 6 | 7 | .math-formula-operator { 8 | opacity: 0.8; 9 | } 10 | 11 | var { 12 | border-bottom: 1px solid $s-color-neutral7; 13 | line-height: 1; 14 | white-space: nowrap; 15 | } 16 | } 17 | 18 | figure.math-formula { 19 | display: block; 20 | font-size: 1.5em; 21 | margin: 1em; 22 | text-align: center; 23 | 24 | .math-formula-paren { 25 | font-size: 1.5em; 26 | 27 | &.open { 28 | margin-right: 0.25em; 29 | } 30 | &.close { 31 | margin-left: 0.25em; 32 | } 33 | } 34 | 35 | .math-formula-operator { 36 | margin: 0 0.2em; 37 | } 38 | } 39 | 40 | code.math-formula { 41 | margin: 0 0.1em; 42 | padding: 0em 0.1em 0.1em; 43 | } 44 | -------------------------------------------------------------------------------- /src/styles/_popovers.scss: -------------------------------------------------------------------------------- 1 | // Note Drop also provides SASS content we could use for more customization. 2 | @import '../../node_modules/tether-drop/dist/css/drop-theme-arrows.min'; 3 | 4 | // Customized version of Drop's built-in 'drop-theme-arrows' theme 5 | .drop-element.drop-theme-arrows { 6 | $background-color: whiten($s-color-neutral8, 50%); 7 | opacity: 0; 8 | 9 | &.drop-after-open { 10 | transition: opacity 0.25s; 11 | opacity: 1; 12 | } 13 | 14 | // Set the color of the "arrow" in the popover 15 | &.drop-element-attached-bottom.drop-element-attached-center .drop-content:before { 16 | border-top-color: $background-color; 17 | } 18 | &.drop-element-attached-top.drop-element-attached-center .drop-content:before { 19 | border-bottom-color: $background-color; 20 | } 21 | 22 | .drop-content { 23 | background: $background-color; 24 | max-width: 30em; 25 | filter: 26 | drop-shadow(0 0px 1px $s-color-neutral5) 27 | drop-shadow(0 1px 8px rgba(0, 0, 0, 0.2)); 28 | 29 | p:last-child { 30 | margin-bottom: 0; 31 | } 32 | 33 | s-read-md { 34 | display: block; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/styles/_reskinColors.scss: -------------------------------------------------------------------------------- 1 | $black: #1E1E1E; 2 | $lightestGray: #FAFAFA; 3 | $gray: #CCCCCC; 4 | $darkestGray: #4A4A49; 5 | $white: #FFFFFF; 6 | $darkerPurple: #6400cc; 7 | $purple: #7D00FF; 8 | $lightPurple: rgba(125, 0, 255, 0.32); 9 | $lightestPurple: rgba(125, 0, 255,0.16); 10 | 11 | .spu-color-neutral6.spu-color-neutral6 { 12 | color: $darkestGray; 13 | } 14 | -------------------------------------------------------------------------------- /src/styles/_siteFooter.scss: -------------------------------------------------------------------------------- 1 | .siteFooter { 2 | @include S-flex-col; 3 | justify-content: space-between; 4 | } 5 | .siteFooter__list { 6 | @include S-flex-rowWrap; 7 | margin-right: 1em; 8 | align-content: flex-start; 9 | } 10 | .siteFooter__list--aux { 11 | @include S-flex-row; 12 | justify-content: flex-end; 13 | margin-right: 0; 14 | margin-top: 1em; 15 | } 16 | .siteFooter__list__sep { 17 | color: $s-color-neutral4; 18 | margin-right: 1.25em; 19 | } 20 | .siteFooter__list__item { 21 | align-content: flex-start; 22 | margin-right: 1.5em; 23 | font-size: $s-scale-5; 24 | color: $s-color-neutral4; 25 | text-decoration: none; 26 | } 27 | .siteFooter__list__item:hover { 28 | color: $purple; 29 | } 30 | .siteFooter__list__item--aux { 31 | margin-left: 1.5em; 32 | margin-right: 0; 33 | color: $s-color-neutral4; 34 | } 35 | 36 | 37 | @include r-media(l) { 38 | .siteFooter { 39 | @include S-flex-row; 40 | } 41 | .siteFooter__list--aux { 42 | margin-top: 0; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/styles/graphics/app-stack-bill.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/app-stack-bill.png -------------------------------------------------------------------------------- /src/styles/graphics/backArrow.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/styles/graphics/centaurus-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/centaurus-120.png -------------------------------------------------------------------------------- /src/styles/graphics/check-id.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/check-id.png -------------------------------------------------------------------------------- /src/styles/graphics/circled-code-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/circled-code-120.png -------------------------------------------------------------------------------- /src/styles/graphics/circled-folder-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/circled-folder-120.png -------------------------------------------------------------------------------- /src/styles/graphics/circled-horizon-120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/circled-horizon-120.png -------------------------------------------------------------------------------- /src/styles/graphics/codeWithOrbits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/codeWithOrbits.png -------------------------------------------------------------------------------- /src/styles/graphics/icon-create-account.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/styles/graphics/icon-guides.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/styles/graphics/icon-money.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/styles/graphics/icon-references.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/styles/graphics/icon-software.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/styles/graphics/icon-stellar-network.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/styles/graphics/ldark-github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/ldark-github.png -------------------------------------------------------------------------------- /src/styles/graphics/ldark-keybase.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/ldark-keybase.png -------------------------------------------------------------------------------- /src/styles/graphics/ldark-paper.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/ldark-paper.png -------------------------------------------------------------------------------- /src/styles/graphics/ldark-stackexchange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/ldark-stackexchange.png -------------------------------------------------------------------------------- /src/styles/graphics/ldark-twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/ldark-twitter.png -------------------------------------------------------------------------------- /src/styles/graphics/longDownArrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/longDownArrow.png -------------------------------------------------------------------------------- /src/styles/graphics/nodeConnectedEarth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/nodeConnectedEarth.png -------------------------------------------------------------------------------- /src/styles/graphics/page-brick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/page-brick.png -------------------------------------------------------------------------------- /src/styles/graphics/page-code.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/page-code.png -------------------------------------------------------------------------------- /src/styles/graphics/page-writing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/page-writing.png -------------------------------------------------------------------------------- /src/styles/graphics/pencilOnEarth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/pencilOnEarth.png -------------------------------------------------------------------------------- /src/styles/graphics/prototype-gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/prototype-gear.png -------------------------------------------------------------------------------- /src/styles/graphics/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/rocket.png -------------------------------------------------------------------------------- /src/styles/graphics/s-bigCogLittleCog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/s-bigCogLittleCog.png -------------------------------------------------------------------------------- /src/styles/graphics/s-fileFolder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/s-fileFolder.png -------------------------------------------------------------------------------- /src/styles/graphics/s-rectangularTree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/s-rectangularTree.png -------------------------------------------------------------------------------- /src/styles/graphics/s-stellarRocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/s-stellarRocket.png -------------------------------------------------------------------------------- /src/styles/graphics/school-of-cash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/school-of-cash.png -------------------------------------------------------------------------------- /src/styles/graphics/stars-texture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stellar-deprecated/developers/f191bebdd7340e82d71dc95a70cda1086fe60443/src/styles/graphics/stars-texture.png -------------------------------------------------------------------------------- /src/styles/index.scss: -------------------------------------------------------------------------------- 1 | @import 'solar-css/lib/index'; 2 | @import 'solar-stellarorg/lib/index'; 3 | @import 'solar-stellarorg-pages/lib/index'; 4 | 5 | @import 'solar-css/styles/index'; 6 | @import 'solar-stellarorg/styles/index'; 7 | @import 'solar-stellarorg-pages/styles/index'; 8 | 9 | @import 'reskinColors'; 10 | 11 | @import 'popovers'; 12 | @import 'friendbot4'; 13 | @import 'mailSignup'; 14 | @import 'graphics'; 15 | @import 'icons'; 16 | @import 'backgrounds'; 17 | @import 'anchorShortcut'; 18 | @import 'footnotes'; 19 | @import 'codeExamples'; 20 | @import 'mathFormula'; 21 | @import 'descriptionList'; 22 | 23 | @import 'header2016'; 24 | @import 'mainNavMenu'; 25 | @import 'siteFooter'; 26 | @import 'collapsibleListSet'; 27 | 28 | @import 'pages/landing'; 29 | 30 | .S-flexItem-share { 31 | // this causes the boxes to actually create a layout context where their 32 | // width, as determined by the flexbox algorithm, is respected (otherwise 33 | // their content can force them wider (note this *doesn't* actually create 34 | // scrollbars. Just causes the flex width to actually be used as the width.) 35 | overflow: auto; 36 | } 37 | 38 | // site wide above the content, the title in the sidebar and above the body 39 | .mainSectionTitle { 40 | padding-top: 1em; 41 | padding-bottom: 1em; 42 | font-size: $s-scale-2; 43 | color: $s-color-neutral2; 44 | } 45 | .mainSidebar { 46 | padding-top: 1.5em; 47 | } 48 | .mainContent { 49 | max-width: 900px; 50 | 51 | & > figure { 52 | margin: 1em 0; 53 | } 54 | } 55 | 56 | s-read-md.mainContent { 57 | max-width: none; 58 | min-width: 500px; 59 | 60 | @include r-media(3xl) { 61 | min-width: 1000px; 62 | } 63 | 64 | & > * { 65 | max-width: 804px; 66 | max-width: calc(900px - 6em); 67 | } 68 | 69 | & > figure, 70 | & > code-example, 71 | & > table, 72 | & > .codeBlock { 73 | max-width: none; 74 | } 75 | } 76 | 77 | // gray sidebar on full width pages 78 | .siteSidebar { 79 | @include S-flexItem-noFlex; 80 | width: 288px; 81 | padding-left: 2em; 82 | background: $lightestGray; 83 | padding-bottom: 2em; 84 | } 85 | 86 | // syntaxHighlight (.codeBlock is added automatically by syntaxHighlight.js) 87 | @import 'codemirror/theme/monokai'; 88 | .cm-s-monokai.CodeMirror { 89 | background: $s-color-neutral1; 90 | } 91 | .codeBlock { 92 | font-size: $s-scale-5; 93 | font-family: 'suisse-mono', monospace; 94 | } 95 | 96 | // Note this intentially affects non-highlighted "code blocks" as well 97 | // (they don't get the `.codeBlock` class) 98 | s-read-md pre { 99 | margin-bottom: 1em; 100 | } 101 | 102 | 103 | // API reference sidebar 104 | // Due to a bug in sass, 1.5*$s-scale-4 does not work. Instead, we just do 18*1.5 + px = 27px 105 | .endpointRef-exampleBar { 106 | display: none; 107 | padding: 2em 27px 0 27px; 108 | } 109 | .endpointRef-exampleBar.is-available { 110 | display: block; 111 | @include S-flexItem-full; 112 | // FIXME: should this flex problem from the above include be fixed in solar? 113 | flex: 12 0 auto; 114 | } 115 | @include r-media(3xl) { 116 | .endpointRef-exampleBar.is-available { 117 | @include S-flexItem-share; 118 | } 119 | } 120 | .endpointRef-exampleBar .codeBlock { 121 | margin-left: -27px; 122 | margin-right: -27px; 123 | padding-left: 27px; 124 | padding-right: 27px; 125 | } 126 | .endpointRef-exampleRequest:before, .endpointRef-exampleResponse:before { 127 | display: block; 128 | color: $s-color-neutral7; 129 | font-size: $s-scale-5; 130 | } 131 | .endpointRef-exampleRequest:before { 132 | content: 'Example Request'; 133 | } 134 | .endpointRef-exampleResponse:before { 135 | content: 'Example Response'; 136 | } 137 | .endpointRef-exampleResponse pre:last-of-type { 138 | margin-bottom: 0; 139 | } 140 | 141 | .pageNavListBounder { 142 | position: relative; 143 | } 144 | .pageNavList { 145 | list-style: none; 146 | } 147 | .pageNavList ul { 148 | padding-left: 1em; 149 | list-style: none; 150 | margin-bottom: 0.5em; 151 | } 152 | .pageNavList ul ul { 153 | padding-left: 1em; 154 | } 155 | .pageNavList > ul:first-child { 156 | margin-top: 0; 157 | } 158 | .pageNavList__title { 159 | font-weight: 700; 160 | } 161 | .pageNavList__item { 162 | padding-right: 1.5em; 163 | font-size: .88888em; 164 | } 165 | .pageNavList__item.is-currentItem { 166 | color: $purple; 167 | position: relative; 168 | 169 | &:before { 170 | content: ''; 171 | position: absolute; 172 | top: 0; 173 | right: 0; 174 | bottom: 0; 175 | left: -5em; 176 | background-color: rgba(125, 0, 255,0.08); 177 | } 178 | } 179 | .pageNavList__item a { 180 | display: block; 181 | line-height: 1.75; 182 | text-decoration: none; 183 | } 184 | .pageNavList__item:not(.is-currentItem) a:hover { 185 | color: $s-color-neutral2; 186 | text-decoration: underline; 187 | } 188 | .pageNavList__subList { 189 | margin-top: 0.5em; 190 | } 191 | .pageNavList > .pageNavList__subList:first-child { 192 | margin-top: 0; 193 | } 194 | 195 | 196 | // variable size flexible columns with different responsive options 197 | .flexCols { 198 | @include S-flex-rowWrap; 199 | } 200 | .flexCols__col { 201 | @include S-flexItem-full; 202 | } 203 | // in theory, one is supposed to use utilities to style the color 204 | .flexCols__col--borderBetween { 205 | border-bottom: 1px solid transparent; 206 | } 207 | .flexCols__col--borderBetween:last-child { 208 | border-bottom: none; 209 | } 210 | 211 | @include r-media(l) { 212 | .flexCols--l { 213 | } 214 | .flexCols--l__col { 215 | @include S-flexItem-share; 216 | } 217 | .flexCols--l__col--borderBetween { 218 | border-bottom: none; 219 | border-right: 1px solid transparent; 220 | } 221 | .flexCols--l__col--borderBetween:last-child { 222 | border-right: none; 223 | } 224 | } 225 | 226 | 227 | .centerText { 228 | text-align: center; 229 | } 230 | 231 | .miniItems { 232 | @include S-flex-row; 233 | justify-content: space-around; 234 | } 235 | .miniItems__item { 236 | flex: 0 12 auto; 237 | width: 200px; 238 | } 239 | 240 | // Single row splitting into half 241 | .halfSplit { 242 | display: block; 243 | } 244 | .halfSplit__half { 245 | width: 100%; 246 | border-bottom: 1px solid $s-color-neutral4; 247 | padding: 1em; 248 | } 249 | .halfSplit__half:last-child { 250 | border-bottom: none; 251 | } 252 | .halfSplit__divider { 253 | display: none; 254 | } 255 | @include r-media(l) { 256 | .halfSplit { 257 | @include S-flex-row; 258 | align-items: center; 259 | justify-content: space-around; 260 | } 261 | .halfSplit__half { 262 | @include S-flexItem-noFlex; 263 | border: none; 264 | padding: 0 1em; 265 | width: 50%; 266 | max-width: 400px; 267 | } 268 | .halfSplit__divider { 269 | flex: 0 0 auto; 270 | display: block; 271 | width: 1px; 272 | background: $gray; 273 | align-self: stretch; 274 | } 275 | } 276 | 277 | // solar stuff incubated here. Will be moved into solar when needed 278 | .so-capTitle { 279 | text-transform: uppercase; 280 | font-size: $s-scale-5; 281 | margin-bottom: 0.5em; 282 | } 283 | 284 | // Testing 285 | .linkCheck-emptyLink:after { 286 | position: absolute; 287 | content: '*'; 288 | color: red; 289 | } 290 | 291 | // sequential navigation for multi-page docs (e.g. "get started") 292 | .sequence-navigation { 293 | overflow: hidden; 294 | margin: 2em 0; 295 | } 296 | 297 | .button--previous { 298 | float: left; 299 | } 300 | 301 | .button--next { 302 | float: right; 303 | } 304 | 305 | // Page specific comes after 306 | @import 'landing0616'; 307 | 308 | 309 | // Reskin 310 | body { 311 | font-family: "suisse", sans-serif; 312 | color: $darkestGray; 313 | } 314 | 315 | .so-logo { 316 | align-items: center; 317 | } 318 | .so-logo__main { 319 | margin: -12px 0 -7px; 320 | line-height: 0; 321 | } 322 | .so-logo__separator { 323 | height: 1em; 324 | border-color: $gray; 325 | } 326 | 327 | .hero { 328 | background-color: $lightestGray; 329 | color: $black; 330 | } 331 | 332 | .s-button.s-button { 333 | background-color: $purple; 334 | border-color: $purple; 335 | border-radius: 4rem; 336 | &:hover { 337 | background-color: $darkerPurple; 338 | border-color: $purple; 339 | } 340 | } 341 | 342 | .js-endpointRef-menu.js-endpointRef-menu .s-button:not(.is-active) { 343 | background-color: transparent; 344 | border-color: white; 345 | } 346 | 347 | s-read-md{ 348 | font-size: 16px; 349 | 350 | code{ 351 | background-color: $lightestPurple; 352 | outline-color: $lightestPurple; 353 | } 354 | 355 | a { 356 | color: $purple; 357 | text-decoration: none; 358 | 359 | &:hover { 360 | color: $darkerPurple; 361 | text-decoration: underline; 362 | } 363 | } 364 | } 365 | 366 | .replacement-banner { 367 | padding: .25rem .5rem .25rem .5rem; 368 | background-color: #3E1BDB; 369 | border-radius: .25rem; 370 | color: #FFF; 371 | } 372 | -------------------------------------------------------------------------------- /src/styles/pages/_landing.scss: -------------------------------------------------------------------------------- 1 | .landing-lead { 2 | max-width: 28em; 3 | } 4 | .landing-sectionTitle { 5 | margin-bottom: 1em; 6 | font-weight: 300; 7 | letter-spacing: 4px; 8 | text-align: center; 9 | text-transform: uppercase; 10 | } 11 | 12 | .landing-introItemDesc { 13 | max-width: 13em; 14 | } 15 | 16 | .landing-apps { 17 | @include S-flex-row; 18 | padding-bottom: 120px; 19 | } 20 | .landing-appItem { 21 | @include S-flex-row; 22 | text-decoration: none; 23 | margin: 0 1em 1em 1em; 24 | } 25 | .landing-appItem__media { 26 | position: relative; 27 | align-self: center; 28 | margin-right: 1em; 29 | } 30 | .landing-appItem__media__downArrow { 31 | position: absolute; 32 | bottom: -105px; 33 | left: 30px; 34 | } 35 | .landing-appItem__copy { 36 | @include S-flexItem-share; 37 | align-self: center; 38 | } 39 | .landing-appItem__copy__title { 40 | font-size: $s-scale-3; 41 | display: block; 42 | color: $purple; 43 | margin-bottom: 0.25em; 44 | text-decoration: none; 45 | } 46 | .landing-appItem__copy__description { 47 | font-size: $s-scale-4; 48 | color: $s-color-neutral3; 49 | } 50 | -------------------------------------------------------------------------------- /src/tools: -------------------------------------------------------------------------------- 1 | ../repos/docs/tools --------------------------------------------------------------------------------