diff --git a/airbyte-webapp/build.gradle b/airbyte-webapp/build.gradle index 0c67957231b30..55bcc38d9fe56 100644 --- a/airbyte-webapp/build.gradle +++ b/airbyte-webapp/build.gradle @@ -49,6 +49,15 @@ task copyDocs(type: Copy) { duplicatesStrategy DuplicatesStrategy.INCLUDE } +// Copy images that are used in .md integration documentation docs +task copyAssets(type: Copy) { + dependsOn copyDocker + + from "${project.rootProject.projectDir}/docs/.gitbook" + into "build/docker/bin/docs/.gitbook" + duplicatesStrategy DuplicatesStrategy.INCLUDE +} + task copyNginx(type: Copy) { dependsOn copyDocker @@ -59,6 +68,7 @@ task copyNginx(type: Copy) { copyBuild.dependsOn npm_run_build copyNginx.dependsOn npm_run_build copyDocs.dependsOn npm_run_build +copyAssets.dependsOn npm_run_build assemble.dependsOn copyDocs copyDocker.dependsOn(npm_run_build) @@ -66,4 +76,5 @@ Task dockerBuildTask = getDockerBuildTask("webapp", "$project.projectDir") dockerBuildTask.dependsOn(copyBuild) dockerBuildTask.dependsOn(copyNginx) dockerBuildTask.dependsOn(copyDocs) -assemble.dependsOn(dockerBuildTask) +dockerBuildTask.dependsOn(copyAssets) +assemble.dependsOn(dockerBuildTask) \ No newline at end of file diff --git a/airbyte-webapp/package-lock.json b/airbyte-webapp/package-lock.json index 57b6ac718b7fe..58f8b31642c76 100644 --- a/airbyte-webapp/package-lock.json +++ b/airbyte-webapp/package-lock.json @@ -39,6 +39,7 @@ "react-use-intercom": "^1.4.0", "react-widgets": "^4.6.1", "recharts": "^2.1.3", + "rehype-urls": "^1.1.1", "remark-gfm": "^3.0.0", "rest-hooks": "^5.0.20", "sanitize-html": "^2.3.3", @@ -26184,6 +26185,15 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/hast-util-has-property": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-1.0.4.tgz", + "integrity": "sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-parse-selector": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", @@ -39410,6 +39420,37 @@ "jsesc": "bin/jsesc" } }, + "node_modules/rehype-urls": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rehype-urls/-/rehype-urls-1.1.1.tgz", + "integrity": "sha512-ct9Kb/nAL6oe/O5fDc0xjiqm8Z9xgXdorOdDhZAWx7awucyiuYXU7Dax+23Gu24nnGwtdaCW6zslKAYzlEW1lw==", + "dependencies": { + "hast-util-has-property": "^1.0.2", + "stdopt": "^2.0.0", + "unist-util-visit": "^1.4.0" + } + }, + "node_modules/rehype-urls/node_modules/unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + }, + "node_modules/rehype-urls/node_modules/unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "dependencies": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "node_modules/rehype-urls/node_modules/unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "dependencies": { + "unist-util-is": "^3.0.0" + } + }, "node_modules/relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -42408,6 +42449,19 @@ "node": ">= 0.6" } }, + "node_modules/stdopt": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stdopt/-/stdopt-2.2.0.tgz", + "integrity": "sha512-D/p41NgXOkcj1SeGhfXOwv9z1K6EV3sjAUY5aeepVbgEHv7DpKWLTjhjScyzMWAQCAgUQys1mjH0eArm4cjRGw==", + "dependencies": { + "is-arrayish": "^0.3.2" + } + }, + "node_modules/stdopt/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", @@ -67563,6 +67617,11 @@ "web-namespaces": "^1.0.0" } }, + "hast-util-has-property": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-1.0.4.tgz", + "integrity": "sha512-ghHup2voGfgFoHMGnaLHOjbYFACKrRh9KFttdCzMCbFoBMJXiNi2+XTrPP8+q6cDJM/RSqlCfVWrjp1H201rZg==" + }, "hast-util-parse-selector": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", @@ -77871,6 +77930,39 @@ } } }, + "rehype-urls": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rehype-urls/-/rehype-urls-1.1.1.tgz", + "integrity": "sha512-ct9Kb/nAL6oe/O5fDc0xjiqm8Z9xgXdorOdDhZAWx7awucyiuYXU7Dax+23Gu24nnGwtdaCW6zslKAYzlEW1lw==", + "requires": { + "hast-util-has-property": "^1.0.2", + "stdopt": "^2.0.0", + "unist-util-visit": "^1.4.0" + }, + "dependencies": { + "unist-util-is": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-3.0.0.tgz", + "integrity": "sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A==" + }, + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "requires": { + "unist-util-is": "^3.0.0" + } + } + } + }, "relateurl": { "version": "0.2.7", "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", @@ -80212,6 +80304,21 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", "dev": true }, + "stdopt": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/stdopt/-/stdopt-2.2.0.tgz", + "integrity": "sha512-D/p41NgXOkcj1SeGhfXOwv9z1K6EV3sjAUY5aeepVbgEHv7DpKWLTjhjScyzMWAQCAgUQys1mjH0eArm4cjRGw==", + "requires": { + "is-arrayish": "^0.3.2" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, "stealthy-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", diff --git a/airbyte-webapp/package.json b/airbyte-webapp/package.json index 715d3c9edb798..f12a90b26862e 100644 --- a/airbyte-webapp/package.json +++ b/airbyte-webapp/package.json @@ -45,6 +45,7 @@ "react-use-intercom": "^1.4.0", "react-widgets": "^4.6.1", "recharts": "^2.1.3", + "rehype-urls": "^1.1.1", "remark-gfm": "^3.0.0", "rest-hooks": "^5.0.20", "sanitize-html": "^2.3.3", diff --git a/airbyte-webapp/src/components/Markdown/Markdown.tsx b/airbyte-webapp/src/components/Markdown/Markdown.tsx index c2fd0fac944bd..64d5e2dd8aad0 100644 --- a/airbyte-webapp/src/components/Markdown/Markdown.tsx +++ b/airbyte-webapp/src/components/Markdown/Markdown.tsx @@ -2,18 +2,22 @@ import React from "react"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; import styled from "styled-components"; +import type { PluggableList } from "react-markdown/lib/react-markdown"; type Props = { content?: string; className?: string; + rehypePlugins?: PluggableList; }; -const Markdown: React.FC = ({ content, className }) => { +const Markdown: React.FC = ({ content, className, rehypePlugins }) => { return ( ); @@ -21,18 +25,30 @@ const Markdown: React.FC = ({ content, className }) => { const StyledMarkdown = styled(Markdown)` * { - color: rgba(59, 69, 78, 1); - line-height: 20px; + color: ${({ theme }) => theme.textColor}; + line-height: 24px; + font-size: 16px; font-weight: 400; } h1 { font-size: 48px; line-height: 56px; + font-weight: bold; + } + + h2 { + font-size: 24px; + line-height: 36px; + font-weight: bold; + } + + h3 { + font-weight: bold; } a { - color: rgb(26, 25, 117); + color: ${({ theme }) => theme.primaryColor}; text-decoration: none; line-height: 24px; @@ -40,6 +56,46 @@ const StyledMarkdown = styled(Markdown)` text-decoration: underline; } } + + table { + border-collapse: collapse; + } + + th, + td { + border: 1px solid ${({ theme }) => theme.borderTableColor}; + margin: 0; + padding: 8px 16px; + } + + th { + background: ${({ theme }) => theme.lightTableColor}; + } + + blockquote { + border-left: 4px solid ${({ theme }) => theme.borderTableColor}; + padding-left: 16px; + margin-left: 25px; + } + + strong { + font-weight: bold; + } + + code { + background: ${({ theme }) => theme.lightTableColor}; + + &.language-sql, + &.language-text { + display: block; + padding: 15px; + overflow: auto; + } + } + + img { + max-width: 100%; + } `; export default StyledMarkdown; diff --git a/airbyte-webapp/src/components/SideView/styled.ts b/airbyte-webapp/src/components/SideView/styled.ts index e10b528c9d28b..a2a7c12e6a370 100644 --- a/airbyte-webapp/src/components/SideView/styled.ts +++ b/airbyte-webapp/src/components/SideView/styled.ts @@ -20,7 +20,7 @@ export const Actions = styled.div` export const Body = styled.div` display: flex; flex-direction: column; - padding: 70px 25px 0; + padding: 70px 35px 20px; `; export const Close = styled.div` diff --git a/airbyte-webapp/src/theme.ts b/airbyte-webapp/src/theme.ts index 5ad8bac147351..a3f930cbe3c38 100644 --- a/airbyte-webapp/src/theme.ts +++ b/airbyte-webapp/src/theme.ts @@ -38,6 +38,8 @@ export const theme = { whiteColor: "#FFFFFF", beigeColor: "#FEF9F4", darkBeigeColor: "#FFEBD7", + borderTableColor: "#D3DCE4", + lightTableColor: "#F5F7F9", darkGreyColor: "#8B8BA0", redColor: "#FF6A4D", lightRedColor: "#FF8870", diff --git a/airbyte-webapp/src/types/rehype-urls.d.ts b/airbyte-webapp/src/types/rehype-urls.d.ts new file mode 100644 index 0000000000000..fdb16590f8b9d --- /dev/null +++ b/airbyte-webapp/src/types/rehype-urls.d.ts @@ -0,0 +1,2 @@ +/// +declare module "rehype-urls"; diff --git a/airbyte-webapp/src/views/Connector/ServiceForm/components/Controls/Instruction.tsx b/airbyte-webapp/src/views/Connector/ServiceForm/components/Controls/Instruction.tsx index 714ba81eb0c1d..e038127aef90f 100644 --- a/airbyte-webapp/src/views/Connector/ServiceForm/components/Controls/Instruction.tsx +++ b/airbyte-webapp/src/views/Connector/ServiceForm/components/Controls/Instruction.tsx @@ -2,12 +2,15 @@ import React from "react"; import { FormattedMessage } from "react-intl"; import styled from "styled-components"; import { useToggle } from "react-use"; +import urls from "rehype-urls"; +import type { PluggableList } from "react-markdown/lib/react-markdown"; import useDocumentation from "hooks/services/useDocumentation"; import { LoadingPage } from "components"; import { SideView } from "components/SideView"; import { Markdown } from "components/Markdown"; import { DestinationDefinition, SourceDefinition } from "core/domain/connector"; +import { useConfig } from "config"; type IProps = { selectedService: SourceDefinition | DestinationDefinition; @@ -47,8 +50,18 @@ const Instruction: React.FC = ({ documentationUrl, }) => { const [isSideViewOpen, setIsSideViewOpen] = useToggle(false); + const config = useConfig(); const { data: docs, isLoading } = useDocumentation(documentationUrl); + const removeBaseUrl = (url: { path: string }) => { + if (url.path.startsWith("../../")) { + return url.path.replace("../../", `${config.integrationUrl}/`); + } + return url.path; + }; + + const urlReplacerPlugin: PluggableList = [[urls, removeBaseUrl]]; + return ( <> {isSideViewOpen && ( @@ -70,7 +83,7 @@ const Instruction: React.FC = ({ {isLoading ? ( ) : docs ? ( - + ) : ( )}