Merge branch 'master' into scaffold

This commit is contained in:
Fabian Chong
2020-09-11 14:49:39 +08:00
56 changed files with 6181 additions and 118 deletions
+19
View File
@@ -0,0 +1,19 @@
# Owners
- See [CONTRIBUTING.md](CONTRIBUTING.md) for general contribution guidelines.
## Maintainers 🏓
- Patrik Oldsberg (@Rugvip, Spotify)
- Fredrik Adelöw (@freben, Spotify)
- Raghunandan Balachandran (@soapraj, Spotify)
- Ben Lambert (@benjdlambert, Spotify)
- Marcus Eide (@marcuseide, Spotify)
- Niklas Ek (@nikek, Spotify)
- Stefan Ålund (@stefanalund, Spotify)
- Kat Zhou (@katz95, Spotify)
## Hall of Fame 👏
- Andrew Thauer (@andrewthauer, Wealthsimple)
- Oliver Sand (@Fox32, SDA-SE)
+2 -2
View File
@@ -12,8 +12,8 @@ to? Edit this file
## Technology
- [What static site generator is TechDocs using?](./#what-static-site-generator-is-techdocs-using)
- [What is the mkdocs-techdocs-core plugin?](./#what-is-the-mkdocs-techdocs-core-plugin)
- [What static site generator is TechDocs using?](#what-static-site-generator-is-techdocs-using)
- [What is the mkdocs-techdocs-core plugin?](#what-is-the-mkdocs-techdocs-core-plugin)
#### What static site generator is TechDocs using?
+6 -6
View File
@@ -26,12 +26,12 @@ Spotifys developer experience offering with 2,400+ documentation sites and
## Project roadmap
| Version | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| [TechDocs V.0 ✅][v0] | Read docs in Backstage - Enable anyone to get a reader experience working in Backstage. [See V.0 Use Cases.](./#techdocs-v0) |
| [TechDocs V.1 🚧][v1] | TechDocs end to end (alpha) - Alpha of TechDocs that you can use end to end - and contribute to. [See V.1 Use Cases.](./#techdocs-v1) |
| [TechDocs V.2 🔮⌛][v2] | Platform stability and compatibility improvements. [See V.2 Use Cases.](./#techdocs-v2) |
| TechDocs V.3 🔮⌛ | Widget Architecture - TechDocs widget architecture available, so the community can create their own customized features. |
| Version | Description |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| [TechDocs V.0 ✅][v0] | Read docs in Backstage - Enable anyone to get a reader experience working in Backstage. [See V.0 Use Cases.](#techdocs-v0) |
| [TechDocs V.1 🚧][v1] | TechDocs end to end (alpha) - Alpha of TechDocs that you can use end to end - and contribute to. [See V.1 Use Cases.](#techdocs-v1) |
| [TechDocs V.2 🔮⌛][v2] | Platform stability and compatibility improvements. [See V.2 Use Cases.](#techdocs-v2) |
| TechDocs V.3 🔮⌛ | Widget Architecture - TechDocs widget architecture available, so the community can create their own customized features. |
[v0]: https://github.com/spotify/backstage/milestone/15
[v1]: https://github.com/spotify/backstage/milestone/16
+41
View File
@@ -0,0 +1,41 @@
---
id: logos
title: Logos
sidebar_label: Logo assets
---
Guidelines for how to use the Backstage logo and icon can be found
[here](/logo_assets/Backstage_Identity_Assets_Overview.pdf). The assets below
are all in `.svg` format. Other formats are available in the
[repository](https://github.com/spotify/backstage/tree/master/microsite/static/logo_assets).
## Backstage logo
<a href="/logo_assets/svg/Logo_White.svg">
<img src="/logo_assets/svg/Logo_White.svg" width="600" />
</a>
<a href="/logo_assets/svg/Logo_Teal.svg">
<img src="/logo_assets/svg/Logo_Teal.svg" width="600" />
</a>
<a href="/logo_assets/svg/Logo_Black.svg">
<img src="/logo_assets/svg/Logo_Black.svg" width="600" style="background-color:white" />
</a>
## Backstage icon
<div>
<a href="/logo_assets/svg/Icon_White.svg">
<img src="/logo_assets/svg/Icon_White.svg" width="180" height="180" />
</a>
<a href="/logo_assets/svg/Icon_Teal.svg">
<img src="/logo_assets/svg/Icon_Teal.svg" width="180" height="180" />
</a>
<a href="/logo_assets/svg/Icon_Gradient.svg">
<img src="/logo_assets/svg/Icon_Gradient.svg" width="180" height="180" />
</a>
<a href="/logo_assets/svg/Icon_Black.svg">
<img src="/logo_assets/svg/Icon_Black.svg" width="180" height="180" style="background-color:white" />
</a>
</div>
+8 -1
View File
@@ -53,6 +53,11 @@ async function verifyUrl(basePath, url) {
return { url, basePath, problem: 'not-relative' };
}
const staticPath = resolvePath(projectRoot, 'microsite/static', `.${url}`);
if (await fs.pathExists(staticPath)) {
return;
}
path = resolvePath(projectRoot, `.${url}`);
} else {
path = resolvePath(dirname(resolvePath(projectRoot, basePath)), url);
@@ -103,7 +108,9 @@ async function main() {
console.log(`Found ${badUrls.length} bad links within repo`);
for (const { url, basePath, problem } of badUrls) {
if (problem === 'missing') {
console.error(`Unable to reach ${url}, linked from ${basePath}`);
console.error(
`Unable to reach ${url} from root or microsite/static/, linked from ${basePath}`,
);
} else if (problem === 'not-relative') {
console.error('Links to /docs/ must be relative');
console.error(` From: ${basePath}`);
+2 -1
View File
@@ -7,7 +7,8 @@
"overview/roadmap",
"overview/vision",
"overview/background",
"overview/adopting"
"overview/adopting",
"overview/logos"
],
"Getting Started": [
"getting-started/index",
+4 -2
View File
@@ -93,8 +93,10 @@ const siteConfig = {
cleanUrl: true,
// Open Graph and Twitter card images.
ogImage: 'img/logo-gradient-on-dark.svg',
twitterImage: 'img/logo-gradient-on-dark.svg',
ogImage:
'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png',
twitterImage:
'logo_assets/png/Backstage_Identity_Assets_Artwork_RGB_04_Icon_Teal.png',
// For sites with a sizable amount of content, set collapsible to true.
// Expand/collapse the links and subcategories under categories.
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 299 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

@@ -0,0 +1 @@
<svg id="Assets" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 337.46 428.5"><defs><style>.cls-1{fill:#121212;}</style></defs><title>06 Icon_Black</title><path class="cls-1" d="M303,166.05a80.69,80.69,0,0,0,13.45-10.37c.79-.77,1.55-1.53,2.3-2.3a83.12,83.12,0,0,0,7.93-9.38A63.69,63.69,0,0,0,333,133.23a48.58,48.58,0,0,0,4.35-16.4c1.49-19.39-10-38.67-35.62-54.22L198.56,0,78.3,115.23,0,190.25l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.22,49.22,0,0,0-6.8-8.87A89.17,89.17,0,0,0,259,178.29h.15a85.08,85.08,0,0,0,31-5.79A80.88,80.88,0,0,0,303,166.05ZM202.45,225.86c-19.32,18.51-50.4,21.23-75.7,5.9L51.61,186.15l67.45-64.64,76.41,46.38C223,184.58,221.49,207.61,202.45,225.86Zm8.93-82.22-70.65-42.89L205.14,39,274.51,81.1c25.94,15.72,29.31,37,10.55,55A60.69,60.69,0,0,1,211.38,143.64Zm29.86,190c-19.57,18.75-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,282.52v24.67L108.6,373.1a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.27,87.27,0,0,1,241.24,333.68Zm0-39c-19.57,18.75-46.17,29.08-74.88,29.08a123.81,123.81,0,0,1-64.1-18.19L0,243.53v24.68l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.5v-1.78A87.27,87.27,0,0,1,241.24,294.7Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.81,123.81,0,0,1-64.1-18.19L0,204.55v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.82A86.09,86.09,0,0,1,241.24,255.71Zm83.7,25.74a94.15,94.15,0,0,1-60.2,25.86h0V334a81.6,81.6,0,0,0,51.74-22.37c14-13.38,21.14-28.11,21-42.64v-2.19A94.92,94.92,0,0,1,324.94,281.45Zm-83.7,91.21c-19.57,18.76-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,321.5v24.68l108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A86.29,86.29,0,0,1,241.24,372.66ZM327,162.45c-.68.69-1.35,1.38-2.05,2.06a94.37,94.37,0,0,1-10.64,8.65,91.35,91.35,0,0,1-11.6,7,94.53,94.53,0,0,1-26.24,8.71,97.69,97.69,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a53.27,53.27,0,0,1,1.14,12V217h.05a84.41,84.41,0,0,0,25.35-5.55,81,81,0,0,0,26.39-16.82c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,172.17a48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7V150q-1.08,1.54-2.25,3.09A96.73,96.73,0,0,1,327,162.45Zm0,77.92c-.69.7-1.31,1.41-2,2.1a94.2,94.2,0,0,1-60.2,25.86h0l0,26.67h0a81.6,81.6,0,0,0,51.74-22.37A73.51,73.51,0,0,0,333,250.13a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.47.19-3.71v-2.19c-.74,1.07-1.46,2.15-2.27,3.21A95.68,95.68,0,0,1,327,240.37Zm0-39c-.69.7-1.31,1.41-2,2.1a93.18,93.18,0,0,1-10.63,8.65,91.63,91.63,0,0,1-11.63,7,95.47,95.47,0,0,1-37.94,10.18h0V256h0a81.65,81.65,0,0,0,51.74-22.37c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,211.15a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.46,2.16-2.27,3.22A95.68,95.68,0,0,1,327,201.39Z"/></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -0,0 +1 @@
<svg id="Assets" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 982.38 1247.39"><defs><style>.cls-1{fill:url(#linear-gradient);}</style><linearGradient id="linear-gradient" x1="392.22" y1="1235.97" x2="609.18" y2="5.5" gradientUnits="userSpaceOnUse"><stop offset="0.07" stop-color="#36baa2"/><stop offset="0.34" stop-color="#61ddc8"/><stop offset="0.53" stop-color="#7df3e1"/></linearGradient></defs><title>07 Large Icon_Gradient</title><path class="cls-1" d="M702.28,857.87c-57,54.61-134.4,84.68-218,84.68-64.94,0-129.45-18.31-186.61-53L0,708.94v71.84L316.14,972.65c53.11,32.19,111.56,47.78,168.15,47.78,72.55,0,142.06-25.62,193.35-74.77,37.49-35.93,58.2-79,57.29-120.8v-5.2A253.66,253.66,0,0,1,702.28,857.87Zm0-113.47c-57,54.6-134.4,84.68-218,84.68-64.94,0-129.45-18.32-186.61-53L0,595.47V667.3L316.14,859.16C369.25,891.36,427.7,907,484.29,907c72.55,0,142.06-25.62,193.35-74.77,37.49-35.93,58.2-79,57.29-120.79v-5.31A252.11,252.11,0,0,1,702.28,744.4Zm0,227c-57,54.6-134.4,84.68-218,84.68-64.94,0-129.45-18.32-186.61-53L0,822.42v71.84l316.14,191.86c53.11,32.2,111.56,47.79,168.15,47.79,72.55,0,142.06-25.63,193.35-74.78,37.49-35.92,58.2-79,57.29-120.78v-5.22A253.79,253.79,0,0,1,702.28,971.36Zm0,113.48c-57,54.6-134.4,84.68-218,84.68-64.94,0-129.45-18.32-186.61-53L0,935.9v71.84L316.14,1199.6c53.11,32.2,111.56,47.79,168.15,47.79,72.55,0,142.06-25.62,193.35-74.78,37.49-35.92,58.2-79,57.29-120.78v-5.21A253.73,253.73,0,0,1,702.28,1084.84ZM951.79,586.27c-2,2-3.79,4.1-5.88,6.09A283.08,283.08,0,0,1,881.13,638a278.45,278.45,0,0,1-110.44,29.63h-.15l0,77.63h.11C825,741.78,878.61,721,921.28,680.14c2.33-2.24,4.38-4.54,6.59-6.8A239.4,239.4,0,0,0,951,646a185,185,0,0,0,18.29-31.37,141.27,141.27,0,0,0,12.57-47.87c.27-3.6.6-7.2.56-10.79v-6.38c-2.17,3.12-4.26,6.26-6.61,9.36A284.07,284.07,0,0,1,951.79,586.27Zm.1-113.36c-2,2-3.92,4-6,6a288.89,288.89,0,0,1-64.72,45.66,276.05,276.05,0,0,1-76.4,25.37,287,287,0,0,1-41.23,4.55c1.48,4.7,2.63,9.47,3.64,14.27a155,155,0,0,1,3.32,34.94v28.1h.16a245.44,245.44,0,0,0,73.78-16.15,235.88,235.88,0,0,0,76.81-49c2.33-2.24,4.38-4.53,6.59-6.8A237.77,237.77,0,0,0,951,532.55a184.13,184.13,0,0,0,18.29-31.36,141.22,141.22,0,0,0,12.57-47.86c.27-3.6.6-7.2.56-10.8v-6c-2.09,3-4.29,6-6.56,9A285.06,285.06,0,0,1,951.89,472.91Zm-.1,226.84c-2,2-3.8,4.09-5.88,6.09C898.8,751,837.08,777.38,770.69,781.11h-.09l0,77.63h.06c54.26-3.48,107.92-24.23,150.59-65.12,21.84-20.92,37.77-43,48-65.47a141.28,141.28,0,0,0,12.57-47.86c.27-3.61.6-7.21.56-10.8V663.1c-2.17,3.13-4.26,6.27-6.61,9.36A283,283,0,0,1,951.79,699.75ZM770.69,894.59h0l0,77.63C825,968.74,878.61,948,921.28,907.1c40.67-39,61.55-81.83,61.09-124.13v-6.4a276.79,276.79,0,0,1-36.46,42.76C898.79,864.47,837.08,890.86,770.69,894.59ZM878.3,182.25,578,0,227.93,335.43,0,553.82,316.14,745.68c53.11,32.2,111.56,47.79,168.15,47.79,72.55,0,142.06-25.62,193.35-74.77,55.78-53.45,74.29-122.64,39.87-180.11a142.23,142.23,0,0,0-19.79-25.82A260,260,0,0,0,753.87,519h.43a247.6,247.6,0,0,0,90.17-16.86,235.71,235.71,0,0,0,76.81-49c2.32-2.21,4.52-4.45,6.7-6.69a238.54,238.54,0,0,0,23.08-27.3,184.08,184.08,0,0,0,18.25-31.34A141.52,141.52,0,0,0,982,340.11C986.32,283.66,953,227.53,878.3,182.25Zm-289,475.23C533.09,711.36,442.61,719.3,369,674.66L150.25,541.89,346.58,353.71,569,488.74C649.19,537.34,644.77,604.36,589.33,657.48Zm240.5-261.25C776,447.8,689,462.79,615.33,418.14L409.67,293.29l187.5-179.81L799.11,236.07C874.62,281.85,884.43,343.9,829.83,396.23Z"/></svg>

After

Width:  |  Height:  |  Size: 3.4 KiB

@@ -0,0 +1 @@
<svg id="Assets" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 337.46 428.5"><defs><style>.cls-1{fill:#7df3e1;}</style></defs><title>04 Icon_Teal</title><path class="cls-1" d="M303,166.05a80.69,80.69,0,0,0,13.45-10.37c.79-.77,1.55-1.53,2.3-2.3a83.12,83.12,0,0,0,7.93-9.38A63.69,63.69,0,0,0,333,133.23a48.58,48.58,0,0,0,4.35-16.4c1.49-19.39-10-38.67-35.62-54.22L198.56,0,78.3,115.23,0,190.25l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.22,49.22,0,0,0-6.8-8.87A89.17,89.17,0,0,0,259,178.29h.15a85.08,85.08,0,0,0,31-5.79A80.88,80.88,0,0,0,303,166.05ZM202.45,225.86c-19.32,18.51-50.4,21.23-75.7,5.9L51.61,186.15l67.45-64.64,76.41,46.38C223,184.58,221.49,207.61,202.45,225.86Zm8.93-82.22-70.65-42.89L205.14,39,274.51,81.1c25.94,15.72,29.31,37,10.55,55A60.69,60.69,0,0,1,211.38,143.64Zm29.86,190c-19.57,18.75-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,282.52v24.67L108.6,373.1a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.27,87.27,0,0,1,241.24,333.68Zm0-39c-19.57,18.75-46.17,29.08-74.88,29.08a123.81,123.81,0,0,1-64.1-18.19L0,243.53v24.68l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.5v-1.78A87.27,87.27,0,0,1,241.24,294.7Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.81,123.81,0,0,1-64.1-18.19L0,204.55v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.82A86.09,86.09,0,0,1,241.24,255.71Zm83.7,25.74a94.15,94.15,0,0,1-60.2,25.86h0V334a81.6,81.6,0,0,0,51.74-22.37c14-13.38,21.14-28.11,21-42.64v-2.19A94.92,94.92,0,0,1,324.94,281.45Zm-83.7,91.21c-19.57,18.76-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,321.5v24.68l108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A86.29,86.29,0,0,1,241.24,372.66ZM327,162.45c-.68.69-1.35,1.38-2.05,2.06a94.37,94.37,0,0,1-10.64,8.65,91.35,91.35,0,0,1-11.6,7,94.53,94.53,0,0,1-26.24,8.71,97.69,97.69,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a53.27,53.27,0,0,1,1.14,12V217h.05a84.41,84.41,0,0,0,25.35-5.55,81,81,0,0,0,26.39-16.82c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,172.17a48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7V150q-1.08,1.54-2.25,3.09A96.73,96.73,0,0,1,327,162.45Zm0,77.92c-.69.7-1.31,1.41-2,2.1a94.2,94.2,0,0,1-60.2,25.86h0l0,26.67h0a81.6,81.6,0,0,0,51.74-22.37A73.51,73.51,0,0,0,333,250.13a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.47.19-3.71v-2.19c-.74,1.07-1.46,2.15-2.27,3.21A95.68,95.68,0,0,1,327,240.37Zm0-39c-.69.7-1.31,1.41-2,2.1a93.18,93.18,0,0,1-10.63,8.65,91.63,91.63,0,0,1-11.63,7,95.47,95.47,0,0,1-37.94,10.18h0V256h0a81.65,81.65,0,0,0,51.74-22.37c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,211.15a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.46,2.16-2.27,3.22A95.68,95.68,0,0,1,327,201.39Z"/></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@@ -0,0 +1 @@
<svg id="Assets" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 337.46 428.5"><defs><style>.cls-1{fill:#fff;}</style></defs><title>02 Icon_White</title><path class="cls-1" d="M303,166.05a80.69,80.69,0,0,0,13.45-10.37c.79-.77,1.55-1.53,2.3-2.3a83.12,83.12,0,0,0,7.93-9.38A63.69,63.69,0,0,0,333,133.23a48.58,48.58,0,0,0,4.35-16.4c1.49-19.39-10-38.67-35.62-54.22L198.56,0,78.3,115.23,0,190.25l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.69,19.16-18.36,25.52-42.12,13.7-61.87a49.22,49.22,0,0,0-6.8-8.87A89.17,89.17,0,0,0,259,178.29h.15a85.08,85.08,0,0,0,31-5.79A80.88,80.88,0,0,0,303,166.05ZM202.45,225.86c-19.32,18.51-50.4,21.23-75.7,5.9L51.61,186.15l67.45-64.64,76.41,46.38C223,184.58,221.49,207.61,202.45,225.86Zm8.93-82.22-70.65-42.89L205.14,39,274.51,81.1c25.94,15.72,29.31,37,10.55,55A60.69,60.69,0,0,1,211.38,143.64Zm29.86,190c-19.57,18.75-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,282.52v24.67L108.6,373.1a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A87.27,87.27,0,0,1,241.24,333.68Zm0-39c-19.57,18.75-46.17,29.08-74.88,29.08a123.81,123.81,0,0,1-64.1-18.19L0,243.53v24.68l108.6,65.91a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.81,66.42-25.69,12.88-12.34,20-27.13,19.68-41.5v-1.78A87.27,87.27,0,0,1,241.24,294.7Zm0-39c-19.57,18.76-46.17,29.09-74.88,29.09a123.81,123.81,0,0,1-64.1-18.19L0,204.55v24.68l108.6,65.91a111.59,111.59,0,0,0,57.76,16.41c24.92,0,48.8-8.8,66.42-25.68,12.88-12.35,20-27.13,19.68-41.5v-1.82A86.09,86.09,0,0,1,241.24,255.71Zm83.7,25.74a94.15,94.15,0,0,1-60.2,25.86h0V334a81.6,81.6,0,0,0,51.74-22.37c14-13.38,21.14-28.11,21-42.64v-2.19A94.92,94.92,0,0,1,324.94,281.45Zm-83.7,91.21c-19.57,18.76-46.17,29.09-74.88,29.09a123.73,123.73,0,0,1-64.1-18.2L0,321.5v24.68l108.6,65.9a111.6,111.6,0,0,0,57.76,16.42c24.92,0,48.8-8.8,66.42-25.69,12.88-12.34,20-27.13,19.68-41.49v-1.79A86.29,86.29,0,0,1,241.24,372.66ZM327,162.45c-.68.69-1.35,1.38-2.05,2.06a94.37,94.37,0,0,1-10.64,8.65,91.35,91.35,0,0,1-11.6,7,94.53,94.53,0,0,1-26.24,8.71,97.69,97.69,0,0,1-14.16,1.57c.5,1.61.9,3.25,1.25,4.9a53.27,53.27,0,0,1,1.14,12V217h.05a84.41,84.41,0,0,0,25.35-5.55,81,81,0,0,0,26.39-16.82c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,172.17a48.55,48.55,0,0,0,4.32-16.45c.09-1.23.2-2.47.19-3.7V150q-1.08,1.54-2.25,3.09A96.73,96.73,0,0,1,327,162.45Zm0,77.92c-.69.7-1.31,1.41-2,2.1a94.2,94.2,0,0,1-60.2,25.86h0l0,26.67h0a81.6,81.6,0,0,0,51.74-22.37A73.51,73.51,0,0,0,333,250.13a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.47.19-3.71v-2.19c-.74,1.07-1.46,2.15-2.27,3.21A95.68,95.68,0,0,1,327,240.37Zm0-39c-.69.7-1.31,1.41-2,2.1a93.18,93.18,0,0,1-10.63,8.65,91.63,91.63,0,0,1-11.63,7,95.47,95.47,0,0,1-37.94,10.18h0V256h0a81.65,81.65,0,0,0,51.74-22.37c.8-.77,1.5-1.56,2.26-2.34a82.08,82.08,0,0,0,7.93-9.38A63.76,63.76,0,0,0,333,211.15a48.56,48.56,0,0,0,4.32-16.44c.09-1.24.2-2.48.19-3.71v-2.2c-.74,1.08-1.46,2.16-2.27,3.22A95.68,95.68,0,0,1,327,201.39Z"/></svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

+1
View File
@@ -10,6 +10,7 @@ nav:
- Vision: 'overview/vision.md'
- The Spotify story: 'overview/background.md'
- Strategies for adopting: 'overview/adopting.md'
- Logo assets: 'overview/logos.md'
- Getting started:
- Running Backstage locally: 'getting-started/index.md'
- Installation: 'getting-started/installation.md'
+1 -1
View File
@@ -41,7 +41,7 @@
"@spotify/eslint-config": "^7.0.1",
"@sucrase/webpack-loader": "^2.0.0",
"@svgr/plugin-jsx": "5.4.x",
"@svgr/plugin-svgo": "4.3.x",
"@svgr/plugin-svgo": "5.4.x",
"@svgr/rollup": "5.4.x",
"@svgr/webpack": "5.4.x",
"@types/start-server-webpack-plugin": "^2.2.0",
@@ -86,3 +86,9 @@ export const Languages = () => (
<CodeSnippet text={PYTHON} language="python" showLineNumbers />
</InfoCard>
);
export const CopyCode = () => (
<InfoCard title="Copy Code">
<CodeSnippet text={JAVASCRIPT} language="javascript" showCopyCodeButton />
</InfoCard>
);
@@ -15,7 +15,7 @@
*/
import React from 'react';
import { render } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import { CodeSnippet } from './CodeSnippet';
@@ -55,4 +55,14 @@ describe('<CodeSnippet />', () => {
expect(queryByText(/2/)).toBeInTheDocument();
expect(queryByText(/3/)).toBeInTheDocument();
});
it('copy code using button', async () => {
document.execCommand = jest.fn();
const rendered = render(
wrapInTestApp(<CodeSnippet {...minProps} showCopyCodeButton />),
);
const button = rendered.getByTitle('Text copied to clipboard');
fireEvent.click(button);
expect(document.execCommand).toHaveBeenCalled();
});
});
@@ -20,19 +20,22 @@ import SyntaxHighlighter from 'react-syntax-highlighter';
import { docco, dark } from 'react-syntax-highlighter/dist/cjs/styles/hljs';
import { useTheme } from '@material-ui/core';
import { BackstageTheme } from '@backstage/theme';
import { CopyTextButton } from '../CopyTextButton';
type Props = {
text: string;
language: string;
showLineNumbers?: boolean;
showCopyCodeButton?: boolean;
};
const defaultProps = {
showLineNumbers: false,
showCopyCodeButton: false,
};
export const CodeSnippet: FC<Props> = props => {
const { text, language, showLineNumbers } = {
const { text, language, showLineNumbers, showCopyCodeButton } = {
...defaultProps,
...props,
};
@@ -41,13 +44,20 @@ export const CodeSnippet: FC<Props> = props => {
const mode = theme.palette.type === 'dark' ? dark : docco;
return (
<SyntaxHighlighter
language={language}
style={mode}
showLineNumbers={showLineNumbers}
>
{text}
</SyntaxHighlighter>
<div style={{ position: 'relative' }}>
<SyntaxHighlighter
language={language}
style={mode}
showLineNumbers={showLineNumbers}
>
{text}
</SyntaxHighlighter>
{showCopyCodeButton && (
<div style={{ position: 'absolute', top: 0, right: 0 }}>
<CopyTextButton text={text} />
</div>
)}
</div>
);
};
@@ -56,4 +66,5 @@ CodeSnippet.propTypes = {
text: PropTypes.string.isRequired,
language: PropTypes.string.isRequired,
showLineNumbers: PropTypes.bool,
showCopyCodeButton: PropTypes.bool,
};
@@ -15,7 +15,7 @@
*/
import React from 'react';
import { render } from '@testing-library/react';
import { render, fireEvent } from '@testing-library/react';
import { wrapInTestApp } from '@backstage/test-utils';
import { CopyTextButton } from './CopyTextButton';
import {
@@ -76,7 +76,7 @@ describe('<CopyTextButton />', () => {
),
);
const button = rendered.getByTitle('mockTooltip');
button.click();
fireEvent.click(button);
expect(document.execCommand).toHaveBeenCalled();
rendered.getByText('mockTooltip');
});
@@ -63,7 +63,7 @@ export const CopyTextButton: FC<Props> = props => {
};
const classes = useStyles(props);
const errorApi = useApi(errorApiRef);
const inputRef = useRef<HTMLInputElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null);
const [open, setOpen] = useState(false);
const handleCopyClick: MouseEventHandler = e => {
@@ -82,9 +82,8 @@ export const CopyTextButton: FC<Props> = props => {
return (
<>
<input
<textarea
ref={inputRef}
type="text"
style={{ position: 'absolute', top: -9999, left: 9999 }}
defaultValue={text}
/>
@@ -2,8 +2,15 @@ FROM node:12
WORKDIR /usr/src/app
COPY . .
# Copy repo skeleton first, to avoid unnecessary docker cache invalidation.
# The skeleton contains the package.json of each package in the monorepo,
# and along with yarn.lock and the root package.json, that's enough to run yarn install.
ADD yarn.lock package.json skeleton.tar ./
RUN yarn install --frozen-lockfile --production
# This will copy the contents of the dist-workspace when running the build-image command.
# Do not use this Dockerfile outside of that command, as it will copy in the source code instead.
COPY . .
CMD ["node", "packages/backend"]
+2 -1
View File
@@ -31,6 +31,7 @@ import {
AnyApiFactory,
} from '@backstage/core';
import SentimentDissatisfiedIcon from '@material-ui/icons/SentimentDissatisfied';
import { Routes } from 'react-router';
// TODO(rugvip): export proper plugin type from core that isn't the plugin class
type BackstagePlugin = ReturnType<typeof createPlugin>;
@@ -97,7 +98,7 @@ class DevAppBuilder {
<AppRouter>
<SidebarPage>
{sidebar}
{deprecatedAppRoutes}
<Routes>{deprecatedAppRoutes}</Routes>
</SidebarPage>
</AppRouter>
</AppProvider>
@@ -39,7 +39,7 @@ export const EntityPageApi: FC<{ entity: Entity }> = ({ entity }) => {
<Grid container spacing={3}>
{apiNames.map(api => (
<Grid item xs={12} key={api}>
<ApiDefinitionCard title={api} apiEntity={apiEntities!.get(api)} />
<ApiDefinitionCard apiEntity={apiEntities!.get(api)} />
</Grid>
))}
</Grid>
@@ -15,31 +15,92 @@
*/
import { ApiEntity } from '@backstage/catalog-model';
import { InfoCard } from '@backstage/core';
import { TabbedCard, CardTab } from '@backstage/core';
import React from 'react';
import { ApiDefinitionWidget } from '../ApiDefinitionWidget';
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
import { Alert } from '@material-ui/lab';
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget';
type Props = {
title?: string;
apiEntity?: ApiEntity;
type ApiDefinitionWidget = {
type: string;
title: string;
component: (definition: string) => React.ReactElement;
rawLanguage?: string;
};
export const ApiDefinitionCard = ({ title, apiEntity }: Props) => {
export function defaultDefinitionWidgets(): ApiDefinitionWidget[] {
return [
{
type: 'openapi',
title: 'OpenAPI',
rawLanguage: 'yaml',
component: definition => (
<OpenApiDefinitionWidget definition={definition} />
),
},
{
type: 'asyncapi',
title: 'AsyncAPI',
rawLanguage: 'yaml',
component: definition => (
<AsyncApiDefinitionWidget definition={definition} />
),
},
];
}
type Props = {
apiEntity?: ApiEntity;
definitionWidgets?: ApiDefinitionWidget[];
};
const defaultProps = {
definitionWidgets: defaultDefinitionWidgets(),
};
export const ApiDefinitionCard = (props: Props) => {
const { apiEntity, definitionWidgets } = {
...defaultProps,
...props,
};
if (!apiEntity) {
return <Alert severity="error">Could not fetch the API</Alert>;
}
const definitionWidget = definitionWidgets.find(
d => d.type === apiEntity.spec.type,
);
if (definitionWidget) {
return (
<InfoCard title={title}>
<Alert severity="error">Could not fetch the API</Alert>
</InfoCard>
<TabbedCard title={apiEntity.metadata.name}>
<CardTab label={definitionWidget.title}>
{definitionWidget.component(apiEntity.spec.definition)}
</CardTab>
<CardTab label="Raw">
<PlainApiDefinitionWidget
definition={apiEntity.spec.definition}
language={definitionWidget.rawLanguage || apiEntity.spec.type}
/>
</CardTab>
</TabbedCard>
);
}
return (
<InfoCard title={title} subheader={apiEntity.spec.type}>
<ApiDefinitionWidget
type={apiEntity.spec.type}
definition={apiEntity.spec.definition}
/>
</InfoCard>
<TabbedCard
title={apiEntity.metadata.name}
children={[
// Has to be an array, otherwise typescript doesn't like that this has only a single child
<CardTab label={apiEntity.spec.type}>
<PlainApiDefinitionWidget
definition={apiEntity.spec.definition}
language={apiEntity.spec.type}
/>
</CardTab>,
]}
/>
);
};
@@ -1,40 +0,0 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import { AsyncApiDefinitionWidget } from '../AsyncApiDefinitionWidget';
import { OpenApiDefinitionWidget } from '../OpenApiDefinitionWidget';
import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget';
type Props = {
type: string;
definition: string;
};
export const ApiDefinitionWidget = ({ type, definition }: Props) => {
switch (type) {
case 'openapi':
return <OpenApiDefinitionWidget definition={definition} />;
case 'asyncapi':
return <AsyncApiDefinitionWidget definition={definition} />;
default:
return (
<PlainApiDefinitionWidget definition={definition} language={type} />
);
}
};
@@ -1,17 +0,0 @@
/*
* Copyright 2020 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { ApiDefinitionWidget } from './ApiDefinitionWidget';
@@ -136,7 +136,7 @@ const useStyles = makeStyles(theme => ({
}));
type Props = {
definition: any;
definition: string;
};
export const AsyncApiDefinitionWidget = ({ definition }: Props) => {
@@ -66,7 +66,7 @@ const useStyles = makeStyles(theme => ({
}));
type Props = {
definition: any;
definition: string;
};
export const OpenApiDefinitionWidget = ({ definition }: Props) => {
@@ -23,5 +23,7 @@ type Props = {
};
export const PlainApiDefinitionWidget = ({ definition, language }: Props) => {
return <CodeSnippet text={definition} language={language} />;
return (
<CodeSnippet text={definition} language={language} showCopyCodeButton />
);
};
+3
View File
@@ -15,5 +15,8 @@
*/
export { ApiDefinitionCard } from './ApiDefinitionCard';
export { AsyncApiDefinitionWidget } from './AsyncApiDefinitionWidget';
export { OpenApiDefinitionWidget } from './OpenApiDefinitionWidget';
export { PlainApiDefinitionWidget } from './PlainApiDefinitionWidget';
export { useComponentApiNames } from './useComponentApiNames';
export { useComponentApiEntities } from './useComponentApiEntities';
+1
View File
@@ -32,6 +32,7 @@
"@material-ui/core": "^4.11.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.45",
"classnames": "^2.2.6",
"moment": "^2.26.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
@@ -102,6 +102,9 @@ export function AboutCard({ entity }: AboutCardProps) {
<nav className={classes.links}>
<IconLinkVertical label="View Source" {...codeLink} />
<IconLinkVertical
disabled={
!entity.metadata.annotations?.['backstage.io/techdocs-ref']
}
label="View Techdocs"
icon={<DocsIcon />}
href={`/docs/${entity.kind}:${entity.metadata.namespace ?? ''}:${
@@ -14,12 +14,14 @@
* limitations under the License.
*/
import * as React from 'react';
import classnames from 'classnames';
import { makeStyles, Link } from '@material-ui/core';
import LinkIcon from '@material-ui/icons/Link';
export type IconLinkVerticalProps = {
icon?: React.ReactNode;
href?: string;
disabled?: boolean;
label: string;
};
@@ -30,6 +32,9 @@ const useIconStyles = makeStyles({
gridGap: 4,
textAlign: 'center',
},
disabled: {
color: 'gray',
},
label: {
fontSize: '0.7rem',
textTransform: 'uppercase',
@@ -41,9 +46,24 @@ const useIconStyles = makeStyles({
export function IconLinkVertical({
icon = <LinkIcon />,
href = '#',
disabled = false,
...props
}: IconLinkVerticalProps) {
const classes = useIconStyles();
if (disabled) {
return (
<Link
className={classnames(classes.link, classes.disabled)}
underline="none"
{...props}
>
{icon}
<span className={classes.label}>{props.label}</span>
</Link>
);
}
return (
<Link className={classes.link} href={href} {...props}>
{icon}
@@ -26,9 +26,11 @@ export const addLinkClickListener = ({
return dom => {
Array.from(dom.getElementsByTagName('a')).forEach(elem => {
elem.addEventListener('click', (e: MouseEvent) => {
e.preventDefault();
const target = e.target as HTMLAnchorElement;
if (target?.getAttribute('href')) {
const href = target?.getAttribute('href');
if (!href) return;
if (!href.match(/^https?:\/\//i)) {
e.preventDefault();
onClick(e, target.getAttribute('href')!);
}
});
@@ -27,6 +27,10 @@ export const rewriteDocLinks = (): Transformer => {
.forEach((elem: T) => {
const elemAttribute = elem.getAttribute(attributeName);
if (elemAttribute) {
// if link is external, add target to open in a new window or tab
if (elemAttribute.match(/^https?:\/\//i)) {
elem.setAttribute('target', '_blank');
}
const normalizedWindowLocation = window.location.href.endsWith('/')
? window.location.href
: `${window.location.href}/`;
+2 -11
View File
@@ -3693,16 +3693,7 @@
"@svgr/hast-util-to-babel-ast" "^5.4.0"
svg-parser "^2.0.2"
"@svgr/plugin-svgo@4.3.x":
version "4.3.1"
resolved "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-4.3.1.tgz#daac0a3d872e3f55935c6588dd370336865e9e32"
integrity sha512-PrMtEDUWjX3Ea65JsVCwTIXuSqa3CG9px+DluF1/eo9mlDrgrtFE7NE/DjdhjJgSM9wenlVBzkzneSIUgfUI/w==
dependencies:
cosmiconfig "^5.2.1"
merge-deep "^3.0.2"
svgo "^1.2.2"
"@svgr/plugin-svgo@^5.4.0":
"@svgr/plugin-svgo@5.4.x", "@svgr/plugin-svgo@^5.4.0":
version "5.4.0"
resolved "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-5.4.0.tgz#45d9800b7099a6f7b4d85ebac89ab9abe8592f64"
integrity sha512-3Cgv3aYi1l6SHyzArV9C36yo4kgwVdF3zPQUC6/aCDUeXAofDYwE5kk3e3oT5ZO2a0N3lB+lLGvipBG6lnG8EA==
@@ -7863,7 +7854,7 @@ cosmiconfig@6.0.0, cosmiconfig@^6.0.0:
path-type "^4.0.0"
yaml "^1.7.2"
cosmiconfig@^5.0.0, cosmiconfig@^5.1.0, cosmiconfig@^5.2.1:
cosmiconfig@^5.0.0, cosmiconfig@^5.1.0:
version "5.2.1"
resolved "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==