Skip to content
Draft
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ jobs:
- name: Build site
uses: borales/actions-yarn@v3
with:
cmd: build
cmd: build:deploy
env:
PREFIX_PATHS: true # equivalent to --prefix-paths flag for 'gatsby build'
PATH_PREFIX: ${{ needs.set-state.outputs.path_prefix }}
Expand All @@ -152,6 +152,12 @@ jobs:
GATSBY_FEDS_PRIVACY_ID: ${{ secrets.AIO_FEDS_PRIVACY_ID }}
GATSBY_SITE_DOMAIN_URL: https://developer-stage.adobe.com
NODE_OPTIONS: "--max_old_space_size=8192"
IMS_BASE_URL: "https://ims-na1-stg1.adobelogin.com"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why use stage environments?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Developer docs is deployed on stage. We are planning to hand over the task of adding try tags on relevant samples to devEx team. I feel uploading samples in stage environment will help them in testing the flow.

FFC_BASE_URL: "https://ffc-addon-stage.adobe.io/"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the product instance only.

PLAYGROUND_CLIENT_ID: ${{ secrets.PLAYGROUND_CLIENT_ID }}
PLAYGROUND_CLIENT_SECRET: ${{ secrets.PLAYGROUND_CLIENT_SECRET }}
PLAYGROUND_AUTH_CODE: ${{ secrets.PLAYGROUND_AUTH_CODE }}
PLAYGROUND_API_KEY: ${{ secrets.PLAYGROUND_API_KEY }}
- name: Deploy
uses: AdobeDocs/static-website-deploy@master
with:
Expand Down Expand Up @@ -229,7 +235,7 @@ jobs:
- name: Build site
uses: borales/actions-yarn@v3
with:
cmd: build
cmd: build:deploy
env:
PREFIX_PATHS: true # equivalent to --prefix-paths flag for 'gatsby build'
PATH_PREFIX: ${{ needs.set-state.outputs.path_prefix }}
Expand Down Expand Up @@ -259,6 +265,13 @@ jobs:
GATSBY_FEDS_PRIVACY_ID: ${{ secrets.AIO_FEDS_PRIVACY_ID }}
GATSBY_SITE_DOMAIN_URL: https://developer.adobe.com
NODE_OPTIONS: "--max_old_space_size=8192"
IMS_BASE_URL: "https://ims-na1.adobelogin.com"
FFC_BASE_URL: "https://ffc-addon.adobe.io/"
# TODO: Replace with prod credentials
PLAYGROUND_CLIENT_ID: ${{ secrets.PLAYGROUND_CLIENT_ID }}
PLAYGROUND_CLIENT_SECRET: ${{ secrets.PLAYGROUND_CLIENT_SECRET }}
PLAYGROUND_AUTH_CODE: ${{ secrets.PLAYGROUND_AUTH_CODE }}
PLAYGROUND_API_KEY: ${{ secrets.PLAYGROUND_API_KEY }}
- name: Deploy
uses: AdobeDocs/static-website-deploy@master
with:
Expand Down
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
},
"dependencies": {
"@adobe/gatsby-theme-aio": "^4.15.1",
"dotenv": "17.2.2",
"fs-extra": "11.3.2",
"gatsby": "4.22.0",
"jszip": "3.10.1",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
Expand All @@ -27,12 +30,14 @@
"dev": "gatsby develop",
"dev:https": "gatsby develop --https --host localhost.corp.adobe.com --port 9000",
"build": "gatsby build",
"build:deploy": "gatsby build && yarn run postbuild",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Generally when you name a script as postbuild, it runs on its own after the build.

Copy link
Collaborator Author

@varshini-adiga varshini-adiga Oct 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure but I guess yarn doesn't run postbuild after build because the post build script is not automatically run after build.
Renamed this command now.

"serve": "gatsby serve",
"clean": "gatsby clean",
"test:links": "remark src/pages --quiet --frail",
"test:lint": "./node_modules/.bin/markdownlint --config .github/linters/.markdownlint.yml src",
"fix:lint": "./node_modules/.bin/markdownlint --config .github/linters/.markdownlint.yml src --fix",
"lint": "docker run --rm -e RUN_LOCAL=true --env-file '.github/super-linter.env' -v \"$PWD\":/tmp/lint github/super-linter:slim-v4.10.1"
"lint": "docker run --rm -e RUN_LOCAL=true --env-file '.github/super-linter.env' -v \"$PWD\":/tmp/lint github/super-linter:slim-v4.10.1",
"postbuild": "node upload-playground-samples.mjs"
},
"remarkConfig": {
"plugins": [
Expand Down
227 changes: 227 additions & 0 deletions src/@adobe/gatsby-theme-aio/components/Code/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
/*
* Copyright 2025 Adobe. All rights reserved.
* This file is licensed to you 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 REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

import "@spectrum-css/typography";
import "@spectrum-css/tooltip";
import "@adobe/prism-adobe";
import { ActionButton } from "@adobe/gatsby-theme-aio/src/components/ActionButton";

import React, { useState } from "react";
import nextId from "react-id-generator";
import classNames from "classnames";
import Highlight, { defaultProps } from "prism-react-renderer";
import PropTypes from "prop-types";
import Prism from "prism-react-renderer/prism";

import "./styles.css";

const EXPRESS_PROD_URL = "https://express.adobe.com/new";
const CODE_PLAYGROUND_MODE = "playground";
const CODE_PLAYGROUND_SESSION = "new";

(typeof global !== "undefined" ? global : window).Prism = Prism;

const getLoader = require("prismjs/dependencies");
const components = require("prismjs/components");

const componentsToLoad = [
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these copied from some template? Do we need all these here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed unwanted components.

"java",
"php",
"csharp",
"kotlin",
"swift",
"bash",
"sql",
"typescript",
"objectivec",
"yaml",
"json",
];
const loadedComponents = ["clike", "javascript"];

// dynamically load all the prism language components
const loader = getLoader(components, componentsToLoad, loadedComponents);
try {
loader.load((id) => {
require(`prismjs/components/prism-${id}.min.js`);
});
} catch (error) {
console.warn(error);
}

// show/hide copy tooltip
const showCopyTooltip = (setShouldShowCopyTooltip) => {
setShouldShowCopyTooltip(true);
setTimeout(() => {
setShouldShowCopyTooltip(false);
}, 3000);
};

// copy to clipboard
const copyToClipboard = async (codeContent, setIsTooltipOpen) => {
await navigator.clipboard.writeText(codeContent);
showCopyTooltip(setIsTooltipOpen);
};

// open code playground
const openCodePlayground = (codeContent, sampleId) => {
const url = new URL(EXPRESS_PROD_URL);
url.searchParams.set("mode", CODE_PLAYGROUND_MODE);
url.searchParams.set("session", CODE_PLAYGROUND_SESSION);
url.searchParams.set("sessionId", sampleId);
url.searchParams.set("executionMode", "script");
window.open(url.toString(), "_blank");
};

// parse language, try option and id.
// usage: ```js{try id=createRectangle}
function parseAttributes(className, metastring) {
const cls = String(className || "");
const meta = String(metastring || "");

// Extract language
const langMatch = cls.match(/language-([^\s{]+)/);
const language = langMatch ? langMatch[1].trim() : "";

// Check if "try" is present in the class string
const shouldShowTry = /\btry\b/.test(`${cls} ${meta}`);

// Extract id if present
const idMatch =
meta.match(/\bid\s*=\s*([^}\s]+)/) || cls.match(/\bid\s*=\s*([^}\s]+)/);
const sampleId = idMatch ? idMatch[1].trim() : "";

return { language, shouldShowTry, sampleId };
}

const Code = ({ children, className = "", theme, metastring = "" }) => {
const [tooltipId] = useState(nextId);
const [shouldShowCopyTooltip, setShouldShowCopyTooltip] = useState(false);

const { language, shouldShowTry, sampleId } = parseAttributes(
className,
metastring
);

return (
<Highlight
{...defaultProps}
code={children}
language={language}
theme={undefined}
>
{({ className, tokens, getLineProps, getTokenProps }) => {
const isEmptyItem = (token) =>
token && token.length === 1 && token[0].empty;
const lines = isEmptyItem(tokens[tokens.length - 1])
? tokens.slice(0, -1)
: tokens;
const isMultiLine = lines.length > 1;

return (
<div className={`spectrum--${theme} code-container`}>
{/* Copy Button */}
<ActionButton
className={classNames(
"spectrum-ActionButton",
"code-action-button",
"code-copy-button",
{ "with-try": shouldShowTry }
)}
aria-describedby={tooltipId}
onClick={() =>
copyToClipboard(children, setShouldShowCopyTooltip)
}
>
Copy
</ActionButton>

{/* Try Button */}
{shouldShowTry && (
<ActionButton
className="spectrum-ActionButton code-action-button code-try-button"
onClick={() => openCodePlayground(children, sampleId)}
>
Try
</ActionButton>
)}

<div
className={classNames("code-tooltip-container", {
"with-try": shouldShowTry,
})}
>
<span
role="tooltip"
id={tooltipId}
className={classNames(
"spectrum-Tooltip spectrum-Tooltip--left code-tooltip",
{ "is-open": shouldShowCopyTooltip }
)}
>
<span className="spectrum-Tooltip-label">
Copied to your clipboard
</span>
<span className="spectrum-Tooltip-tip" />
</span>
</div>

<pre
className={classNames(
className,
"spectrum-Code spectrum-Code--sizeM code-pre"
)}
>
{lines.map((line, i) => {
const { style: lineStyle, ...lineProps } = getLineProps({
line,
key: i,
});

return (
<div key={i} className="code-line">
{isMultiLine && (
<span
data-pseudo-content={i + 1}
className="code-line-number"
/>
)}
<span
{...lineProps}
style={lineStyle}
className="code-line-content"
>
{/* styling the tokens in the line */}
{line.map((token, key) => {
const { style: tokenStyle, ...tokenProps } =
getTokenProps({ token, key });
return (
<span key={key} {...tokenProps} style={tokenStyle} />
);
})}
</span>
</div>
);
})}
</pre>
</div>
);
}}
</Highlight>
);
};

Code.propTypes = {
theme: PropTypes.oneOf(["light", "dark"]),
};

export { Code };
72 changes: 72 additions & 0 deletions src/@adobe/gatsby-theme-aio/components/Code/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
.code-container {
position: relative;
max-width: calc(100vw - var(--spectrum-global-dimension-size-800));
}

.code-pre {
padding-top: var(--spectrum-global-dimension-size-400) !important;
}

.code-line {
display: table-row;
}

.code-line-number {
display: table-cell;
color: var(--spectrum-global-color-gray-500);
text-align: left;
padding-right: var(--spectrum-global-dimension-size-200);
user-select: none;
}

.code-line-number::before {
content: attr(data-pseudo-content);
}

.code-line-content {
margin-right: var(--spectrum-global-dimension-size-1000);
}

.code-action-button {
position: absolute;
inset-block-start: 0;
border-color: var(--spectrum-actionbutton-m-border-color, var(--spectrum-alias-border-color)) !important;
color: var(--spectrum-actionbutton-m-text-color, var(--spectrum-alias-text-color)) !important;
padding: var(--spectrum-global-dimension-size-65);
}

.code-copy-button {
inset-inline-end: var(--spectrum-global-dimension-size-125);
}

.code-copy-button.with-try {
inset-inline-end: var(--spectrum-global-dimension-size-700);
}

.code-try-button {
inset-inline-end: var(--spectrum-global-dimension-size-125);
}

.code-tooltip-container {
position: absolute;
inset-block-start: var(--spectrum-global-dimension-size-65);
height: var(--spectrum-global-dimension-size-300);
display: flex;
align-items: center;
pointer-events: none;
}

.code-tooltip-container:not(.with-try) {
inset-inline-end: calc(var(--spectrum-global-dimension-size-125) + var(--spectrum-global-dimension-size-600) + var(--spectrum-global-dimension-size-125));
}

.code-tooltip-container.with-try {
inset-inline-end: calc(var(--spectrum-global-dimension-size-700) + var(--spectrum-global-dimension-size-600) + var(--spectrum-global-dimension-size-125));
}

.code-tooltip {
display: block;
position: relative;
white-space: nowrap;
font-family: var(--spectrum-alias-body-text-font-family, var(--spectrum-global-font-family-base));
}
4 changes: 1 addition & 3 deletions src/pages/references/document-sandbox/document-apis/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ See the example below for further usage details.

The following code snippet illustrates how to use the [Express Document APIs](./classes/Editor.md) from the document sandbox code running in your `code.js` for instance, to access the current document, create a rectangle, set some properties and a fill for the rectangle, and finally, add it to the document:

```js
import { editor, colorUtils } from "express-document-sdk";

```js{try id=createRectangle}
const insertionParent = editor.context.insertionParent; // get node to insert content into

const rectangle = editor.createRectangle();
Expand Down
Loading