Skip to content

Commit

Permalink
Adjust Android Extension for Adobe Experience SDK v3 (#1170)
Browse files Browse the repository at this point in the history
  • Loading branch information
Sporiff authored Nov 21, 2024
2 parents 52aa8d3 + 0b9fdd4 commit 5144363
Show file tree
Hide file tree
Showing 27 changed files with 2,461 additions and 178 deletions.
8 changes: 5 additions & 3 deletions ec.config.mjs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { defineEcConfig } from 'astro-expressive-code'
import { defineEcConfig } from 'astro-expressive-code';
import { pluginCollapsibleSections } from "@expressive-code/plugin-collapsible-sections";
import { pluginLineNumbers } from "@expressive-code/plugin-line-numbers";

export default defineEcConfig({
defaultProps: {
wrap: true
wrap: true,
showLineNumbers: true,
},
// This is where you can pass your plugin options
plugins: [pluginCollapsibleSections()],
plugins: [pluginCollapsibleSections(), pluginLineNumbers()],
frames: {
extractFileNameFromCode: true
},
Expand Down
23 changes: 23 additions & 0 deletions markdoc.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,15 @@ export default defineMarkdocConfig({
type: Boolean,
required: false,
default: false
},
showLineNumbers: {
type: Boolean,
required: false,
default: true,
},
startLineNumber: {
type: Number,
required: false,
}
}
},
Expand Down Expand Up @@ -133,5 +142,19 @@ export default defineMarkdocConfig({
tabs: {
render: component("src/components/Tabs.astro"),
},
exampleapp: {
render: component("src/components/ExampleApp.astro"),
attributes: {
permalink: {
type: String,
required: true,
},
lang: {
type: String,
required: false,
default: "txt",
}
}
}
}
})
27 changes: 27 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@astrojs/sitemap": "^3.2.1",
"@astrojs/tailwind": "^5.1.2",
"@expressive-code/plugin-collapsible-sections": "^0.35.6",
"@expressive-code/plugin-line-numbers": "^0.38.3",
"@nanostores/persistent": "^0.10.2",
"@nanostores/react": "^0.8.0",
"@octokit/core": "^6.1.2",
Expand Down
73 changes: 29 additions & 44 deletions src/components/CodeBlock.astro
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ interface Props {
ins?: string;
del?: string;
useDiffSyntax?: boolean;
showLineNumbers?: boolean;
startLineNumber: Number;
}
const {
Expand All @@ -19,64 +21,47 @@ const {
del,
collapse,
useDiffSyntax = false,
showLineNumbers = false,
startLineNumber = undefined,
} = Astro.props as Props;
let content = "";
if (Astro.slots.has("default")) {
// Get the raw content of the slot without transformations
content = await Astro.slots.render("default");
}
const parseHighlight = (
highlight: string,
): MarkerDefinition | MarkerDefinition[] => {
const parseHighlight = (highlight: string): MarkerDefinition[] => {
return highlight.split(",").map((item) => {
const trimmedItem = item.trim();
if (trimmedItem.startsWith("{") && trimmedItem.endsWith("}")) {
if (/^\{.*\}$/.test(trimmedItem)) {
const innerContent = trimmedItem.slice(1, -1).trim();
// Check if the inner content contains a colon
if (innerContent.includes(":")) {
const [key, value] = innerContent.split(":").map((part) => part.trim());
return { [key]: value.replace(/"/g, "") } as MarkerDefinition;
return { [key]: value.replace(/['"]/g, "") } as MarkerDefinition;
}
// If no colon, treat it as a regular string token
return trimmedItem;
}
if (trimmedItem.startsWith("/") && trimmedItem.endsWith("/")) {
} else if (/^\/.*\/$/.test(trimmedItem)) {
return new RegExp(trimmedItem.slice(1, -1), "g") as MarkerDefinition;
}
return trimmedItem.replace(/'/g, "");
return trimmedItem.replace(/['"]/g, "") as MarkerDefinition;
}) as MarkerDefinition[];
};
const parseCollapse = (collapse?: string | string[]): string[] => {
if (typeof collapse === "string") {
return collapse.split(",").map((item) => item.trim());
}
const parseCollapse = (collapse?: string | string[]): string[] =>
typeof collapse === "string"
? collapse.split(",").map((item) => item.trim())
: collapse || [];
return Array.isArray(collapse) ? collapse : [];
};
const { code, lang } = await extractCodeFromHTML(
await Astro.slots.render("default"),
);
const { code, lang } = await extractCodeFromHTML(content);
const parsedHighlight = highlight ? parseHighlight(highlight) : undefined;
const parsedIns = ins ? parseHighlight(ins) : undefined;
const parsedDel = del ? parseHighlight(del) : undefined;
const parsedCollapse = collapse ? parseCollapse(collapse) : undefined;
const codeAttributes = {
title,
lang,
code,
collapse: collapse ? parseCollapse(collapse) : [],
mark: highlight ? parseHighlight(highlight) : [],
ins: ins ? parseHighlight(ins) : [],
del: del ? parseHighlight(del) : [],
useDiffSyntax,
showLineNumbers,
...(startLineNumber && { startLineNumber }),
};
---

<ExpressiveCode
title={title}
lang={lang}
collapse={parsedCollapse}
mark={parsedHighlight}
ins={parsedIns}
del={parsedDel}
code={code}
useDiffSyntax={useDiffSyntax}
/>
<ExpressiveCode {...codeAttributes} />
3 changes: 1 addition & 2 deletions src/components/DefList.astro
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
import { decode } from "tiny-decode";
import { parseDefList } from "@components/utils/parseDefList";
const content = decode(await Astro.slots.render("default"));
const content = await Astro.slots.render("default");
const parsedContent = await parseDefList(content);
---

Expand Down
19 changes: 19 additions & 0 deletions src/components/ExampleApp.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
import { fetchExampleApp } from "@components/utils/fetchExampleApp";
import { Code as ExpressiveCode } from "astro-expressive-code/components";
interface Props {
permalink: string;
lang: string;
}
const { permalink, lang } = Astro.props as Props;
const { code, title } = await fetchExampleApp(permalink);
const codeAttributes = {
code,
lang,
title,
};
---

<ExpressiveCode {...codeAttributes} />
10 changes: 7 additions & 3 deletions src/components/utils/extractCode.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
import { unified } from "unified";
import rehypeParse from "rehype-parse";
import { selectAll, select } from "hast-util-select";
import { select, selectAll } from "hast-util-select";
import { toString } from "hast-util-to-string";

interface CodeExtractionResult {
code: string;
lang?: string;
}

export const extractCodeFromHTML = async (htmlString: string): Promise<CodeExtractionResult> => {
export const extractCodeFromHTML = async (
htmlString: string,
): Promise<CodeExtractionResult> => {
const processor = unified().use(rehypeParse, { fragment: true });
const ast = processor.parse(htmlString);

const preElement = select("pre[data-language]", ast);
const lang = preElement ? preElement.properties["dataLanguage"] as string : "";
const lang = preElement
? preElement.properties["dataLanguage"] as string
: "";

const codeBlocks = selectAll(".ec-line .code", ast);

Expand Down
67 changes: 67 additions & 0 deletions src/components/utils/fetchExampleApp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { Octokit } from "@octokit/core";

const octokit = new Octokit({ auth: import.meta.env.VITE_GITHUB_TOKEN });

/**
* Parses a file URL and returns its component parts
* @param fileUrl
* @returns The component parts of the URL for use in a GraphQL query
*/
function parsePermalink(fileUrl: string) {
const regex =
/https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/blob\/([^\/]+)\/(.+)/;
const match = fileUrl.match(regex);
if (!match) {
throw new Error("Invalid file URL format.");
}

const [, owner, repo, branch, filePath] = match;

const filename = filePath.split("/").pop()!;

return { owner, repo, branch, filePath, filename };
}

/**
* Fetches the text content of a file from GitHub
* @param fileUrl
* @returns The file name and contents
*/
export async function fetchExampleApp(
fileUrl: string,
): Promise<{ code: string; title: string }> {
const { owner, repo, branch, filePath, filename } = parsePermalink(fileUrl);

const query = `
query($owner: String!, $repo: String!, $expression: String!) {
repository(owner: $owner, name: $repo) {
object(expression: $expression) {
... on Blob {
text
}
}
}
}
`;

const expression = `${branch}:${filePath}`;

const variables = { owner, repo, expression };

try {
const response = await octokit.graphql<
{ repository: { object: { text: string } } }
>(query, variables);

if (!response.repository.object) {
throw new Error("File not found in the repository.");
}

const { text: code } = response.repository.object;
return { code, title: filename };
} catch (error) {
throw new Error(
`Failed to fetch file content: ${(error as Error).message}`,
);
}
}
Loading

0 comments on commit 5144363

Please sign in to comment.