Skip to content

Commit 47dd0d8

Browse files
committed
Automation script to download assets
1 parent f79bdcf commit 47dd0d8

File tree

10 files changed

+157
-13
lines changed

10 files changed

+157
-13
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ We first introduce you to the basic development paradigms like *Model-View-Contr
3939

4040
The tutorial consists of the following steps. To start, just open the first link - you`ll be guided from there.
4141

42-
- **[Step 1: Hello World!](steps/01/README.md "As you know OpenUI5 is all about HTML5. Let’s get started with building a first \“Hello World\” with only HTML.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/01/index.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-01.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-01-js.zip))
42+
- **[Step 1: Hello World!](steps/01/README.md "As you know OpenUI5 is all about HTML5. Let’s get started with building a first "Hello World\” with only HTML.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/01/index.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-01.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-01-js.zip))
4343
- **[Step 2: Bootstrap](steps/02/README.md "Before we can do something with OpenUI5, we need to load and initialize it. This process of loading and initializing OpenUI5 is called bootstrapping. Once this bootstrapping is finished, we simply display an alert.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/02/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-02.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-02-js.zip))
44-
- **[Step 3: Controls](steps/03/README.md "Now it is time to build our first little UI by replacing the \“Hello World\” text in the HTML body by the OpenUI5 control sap/m/Text. In the beginning, we will use the JavaScript control interface to set up the UI, the control instance is then placed into the HTML body. ")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/03/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-03.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-03-js.zip))
44+
- **[Step 3: Controls](steps/03/README.md "Now it is time to build our first little UI by replacing the "Hello World\” text in the HTML body by the OpenUI5 control sap/m/Text. In the beginning, we will use the JavaScript control interface to set up the UI, the control instance is then placed into the HTML body. ")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/03/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-03.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-03-js.zip))
4545
- **[Step 4: XML Views](steps/04/README.md "Putting all our UI into the index.ts file will very soon result in a messy setup, and there is quite a bit of work ahead of us. So let’s do a first modularization by putting the sap/m/Text control into a dedicated view.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/04/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-04.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-04-js.zip))
46-
- **[Step 5: Controllers](steps/05/README.md "In this step, we replace the text with a button and show the \“Hello World\” message when the button is pressed. The handling of the button's press event is implemented in the controller of the view.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/05/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-05.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-05-js.zip))
46+
- **[Step 5: Controllers](steps/05/README.md "In this step, we replace the text with a button and show the "Hello World\” message when the button is pressed. The handling of the button's press event is implemented in the controller of the view.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/05/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-05.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-05-js.zip))
4747
- **[Step 6: Modules](steps/06/README.md "In OpenUI5, resources are often referred to as modules. In this step, we replace the alert from the last exercise with a proper Message Toast from the sap.m library.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/06/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-06.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-06-js.zip))
4848
- **[Step 7: JSON Model](steps/07/README.md "Now that we have set up the view and controller, it’s about time to think about the M in MVC.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/07/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-07.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-07-js.zip))
4949
- **[Step 8: Translatable Texts](steps/08/README.md "In this step we move the texts of our UI to a separate resource file.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/08/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-08.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-08-js.zip))

package-lock.json

Lines changed: 69 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"@octokit/rest": "^21.1.1",
1212
"anchor-js": "^5.0.0",
1313
"archiver": "^7.0.1",
14+
"axios": "^1.8.4",
1415
"browser-sync": "^3.0.3",
1516
"concurrently": "^9.1.2",
1617
"express": "^4.21.2",

steps/16/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ We will now add a dialog to our app. Dialogs are special, because they open on t
1414

1515
### Preview
1616

17-
![](https://sdk.openui5.org/docs/topics/loio0916080895e144ed8b31963bfb18e17f_LowRes.png "A dialog opens when the new \“Say Hello With Dialog\” button is clicked")
17+
![](https://sdk.openui5.org/docs/topics/loio0916080895e144ed8b31963bfb18e17f_LowRes.png "A dialog opens when the new "Say Hello With Dialog\” button is clicked")
1818

1919
<sup>*A dialog opens when the new “Say Hello With Dialog” button is clicked*</sup>
2020

steps/26/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ This system is the so-called back-end system that we will now simulate with anOp
1111
### Preview
1212

1313

14-
![](https://sdk.openui5.org/docs/topics/_LowRes.png "Folder Structure for this Step")
14+
![](https://sdk.openui5.org/docs/topics/loiofe1403346ce9499f8bb102beaa4986d5_LowRes.png "Folder Structure for this Step")
1515

1616
<sup>*The list of invoices is now served by the Mock Server*</sup>
1717

@@ -27,7 +27,7 @@ The folder structure of our app project is clearly separating test and productiv
2727

2828
The new `localService` folder contains a `metadata.xml` service description file for OData, the `mockserver.js` file that simulates a real service with local data, and the `mockdata` subfolder that contains the local test data \(`Invoices.json`\).
2929

30-
![](https://sdk.openui5.org/docs/topics/_LowRes.png "Folder Structure for this Step")
30+
![](https://sdk.openui5.org/docs/topics/loiofe1403346ce9499f8bb102beaa4986d5_LowRes.png "Folder Structure for this Step")
3131

3232
<sup>*Folder Structure for this Step*</sup>
3333

steps/28/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ We haven’t thought about testing our interaction with the app yet, so in this
1313

1414
### Preview
1515

16-
![](https://sdk.openui5.org/docs/topics/loio250d5b92921d44a4b432cc0fade88cc9_LowRes.png "An OPA test opens the "Hello" dialog from step 16")
16+
![](https://sdk.openui5.org/docs/topics/loio250d5b92921d44a4b432cc0fade88cc9_LowRes.png "An OPA test opens the &quot;Hello&quot; dialog from step 16")
1717

1818
<sup>*An OPA test opens the "Hello" dialog from step 16*</sup>
1919

@@ -28,7 +28,7 @@ Download solution for step 28 in [📥 TypeScript](https://sap-samples.github.io
2828
We add a new folder `integration` below the `test` folder, where we put our new test cases. Page objects that help structuring such integration tests are put in the `pages` subfolder that we also create now.
2929

3030

31-
![](https://sdk.openui5.org/docs/topics/_LowRes.png "Folder Structure for this Step")
31+
![](https://sdk.openui5.org/docs/topics/loio27e84d5bd72a485498564b92894869b5_LowRes.png "Folder Structure for this Step")
3232
<sup>*Folder Structure for this Step*</sup>
3333

3434

steps/37/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ To achieve this, we will add ARIA attributes. ARIA attributes are used by screen
1313

1414
### Preview
1515

16-
![](https://sdk.openui5.org/docs/topics/loiod9c6cd32743d40629bec7d77590e2c58_HiRes.png "Landmarks in our app")
16+
![](https://sdk.openui5.org/docs/topics/loiob35deda1ebe1433fbf0ff066f6e3fc4b_LowRes.png "Landmarks in our app")
1717

1818
<sup>*Landmarks in our app*</sup>
1919

tools/dev-server.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ async function getTemplate() {
3838
return templateFn;
3939
}
4040

41-
app.use("/assets", express.static(join(__dirname, "..", "assets")));
42-
4341
app.use("/node_modules", express.static(join(__dirname, "..", "node_modules")));
4442

4543
app.use(async (req, res, next) => {
@@ -60,12 +58,14 @@ app.use(async (req, res, next) => {
6058
file = undefined;
6159
}
6260
}
63-
if (file) {
61+
if (file && file.endsWith(".md")) {
6462
const md = readFileSync(file, { encoding: "utf-8" });
6563
const bodyContent = await convertMarkdown(md);
6664
const templateFn = await getTemplate();
6765
const html = templateFn({ title: req.url, bodyContent });
6866
res.send(html);
67+
} else if (file) {
68+
res.sendFile(file);
6969
} else {
7070
next();
7171
}

tools/download-assets.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const axios = require('axios');
4+
5+
const findMarkdownFiles = (dir) => {
6+
let results = [];
7+
const files = fs.readdirSync(dir, { withFileTypes: true });
8+
9+
for (const file of files) {
10+
const fullPath = path.join(dir, file.name);
11+
if (file.isDirectory() && file.name !== "node_modules" && file.name !== "dist") {
12+
results = results.concat(findMarkdownFiles(fullPath));
13+
} else if (file.isFile() && file.name.toLowerCase() === 'readme.md') {
14+
results.push(fullPath);
15+
}
16+
}
17+
return results;
18+
};
19+
20+
const markdownFiles = [path.join(process.cwd(), "README.md"), findMarkdownFiles(path.join(process.cwd(), 'steps'))].flat();
21+
22+
const downloadImage = async (url, outputPath) => {
23+
const response = await axios({
24+
method: 'GET',
25+
url,
26+
responseType: 'stream',
27+
});
28+
29+
const writer = fs.createWriteStream(outputPath);
30+
response.data.pipe(writer);
31+
32+
return new Promise((resolve, reject) => {
33+
writer.on('finish', resolve);
34+
writer.on('error', reject);
35+
});
36+
};
37+
38+
(async () => {
39+
40+
for await (const markdownFile of markdownFiles) {
41+
let markdownContent = fs.readFileSync(markdownFile, 'utf8');
42+
const imageUrls = [...markdownContent.matchAll(/!\[.*?\]\((\S+?)(?:\s+".*?")?\)/g)].map(match => match[1]);
43+
44+
const markdownDir = path.dirname(markdownFile);
45+
const assetsDir = path.join(markdownDir, 'assets');
46+
47+
if (!fs.existsSync(assetsDir)) {
48+
fs.mkdirSync(assetsDir, { recursive: true });
49+
}
50+
51+
let updated = false;
52+
53+
for await (const url of imageUrls) {
54+
if (url.startsWith('http') && url.endsWith('.png')) {
55+
try {
56+
const filename = path.basename(new URL(url).pathname);
57+
const outputPath = path.join(assetsDir, filename);
58+
await downloadImage(url, outputPath, filename);
59+
// Update markdown content
60+
markdownContent = markdownContent.replace(url, `assets/${filename}`);
61+
updated = true;
62+
} catch (error) {
63+
console.error(`Invalid URL: ${url} found in ${markdownFile}`, error.message);
64+
}
65+
}
66+
}
67+
68+
// Save updated markdown file
69+
if (updated) {
70+
fs.writeFileSync(markdownFile, markdownContent, 'utf8');
71+
}
72+
}
73+
74+
})();

tools/prepare-gh-pages.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ function zipDirectory(sourceDir, outPath) {
9999
console.error("No JS file found for", source);
100100
}
101101
}
102-
} else {
102+
} else if (file !== "tsconfig.json") {
103103
mkdirSync(dirname(target), { recursive: true });
104104
copyFileSync(source, target);
105105
}

0 commit comments

Comments
 (0)