Skip to content

Introduce dev-server for local testing of GH pages #116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ We first introduce you to the basic development paradigms like *Model-View-Contr

### Preview

![Preview of the OpenUI5 application that is going to be built in this tutorial. Contains a Hello World upper part with buttons and a text input. The lower part shows list of invoices with details, grouped by vendor names.](https://sdk.openui5.org/docs/topics/loiofb12cea5ac9b45bb9007aac5a1a8689f_LowRes.png)
![Preview of the OpenUI5 application that is going to be built in this tutorial. Contains a Hello World upper part with buttons and a text input. The lower part shows list of invoices with details, grouped by vendor names.](assets/loiofb12cea5ac9b45bb9007aac5a1a8689f_LowRes.png)

> 💡 **Tip:** <br>
> You don't have to do all tutorial steps sequentially, you can also jump directly to any step you want. Just download the code from the previous step and make sure that the application runs as intended.
Expand All @@ -39,11 +39,11 @@ We first introduce you to the basic development paradigms like *Model-View-Contr

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

- **[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))
- **[Step 1: Hello World!](steps/01/README.md "As you know OpenUI5 is all about HTML5. Let’s get started with building a first &quot;Hello World&quot; 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))
- **[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))
- **[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))
- **[Step 3: Controls](steps/03/README.md "Now it is time to build our first little UI by replacing the &quot;Hello World&quot; 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))
- **[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))
- **[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))
- **[Step 5: Controllers](steps/05/README.md "In this step, we replace the text with a button and show the &quot;Hello World&quot; 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))
- **[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))
- **[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))
- **[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))
Expand All @@ -54,7 +54,7 @@ The tutorial consists of the following steps. To start, just open the first link
- **[Step 13: Margins and Paddings](steps/13/README.md "Our app content is still glued to the corners of the letterbox. To fine-tune our layout, we can add margins and paddings to the controls that we added in the previous step. ")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/13/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-13.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-13-js.zip))
- **[Step 14: Custom CSS and Theme Colors](steps/14/README.md "Sometimes we need to define some more fine-granular layouts and this is when we can use the flexibility of CSS by adding custom style classes to controls and style them as we like. ")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/14/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-14.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-14-js.zip))
- **[Step 15: Nested Views](steps/15/README.md "Our panel content is getting more and more complex and now it is time to move the panel content to a separate view. With that approach, the application structure is much easier to understand, and the individual parts of the app can be reused.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/15/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-15.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-15-js.zip))
- **[Step 16: Dialogs and Fragments](1/steps/16/README.md "In this step, we will take a closer look at another element which can be used to assemble views: the fragment. ")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/16/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-16.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-16-js.zip))
- **[Step 16: Dialogs and Fragments](steps/16/README.md "In this step, we will take a closer look at another element which can be used to assemble views: the fragment. ")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/16/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-16.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-16-js.zip))
- **[Step 17: Fragment Callbacks](steps/17/README.md "Now that we have integrated the dialog, it's time to add some user interaction. The user will definitely want to close the dialog again at some point, so we add a button to close the dialog and assign an event handler.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/17/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-17.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-17-js.zip))
- **[Step 18: Icons](steps/18/README.md "Our dialog is still pretty much empty. Since OpenUI5 is shipped with a large icon font that contains more than 500 icons, we will add an icon to greet our users when the dialog is opened.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/18/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-18.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-18-js.zip))
- **[Step 19: Aggregation Binding](steps/19/README.md "Now that we have established a good structure for our app, it's time to add some more functionality. We start exploring more features of data binding by adding some invoice data in JSON format that we display in a list below the panel.")** ([🔗 Live Preview](https://sap-samples.github.io/ui5-typescript-walkthrough/build/19/index-cdn.html) \| [📥 Download Solution in TS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-19.zip) \| [📥 Download Solution in JS](https://sap-samples.github.io/ui5-typescript-walkthrough/ui5-typescript-walkthrough-step-19-js.zip))
Expand Down
147 changes: 147 additions & 0 deletions README_AUTHORS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
# Documentation for Tutorial Authors

# General

The setup of this project allows maintaining *one* tutorial text that covers both JavaScript and TypeScript with minimal overhead and without duplication of content.

Readers of the tutorial can freely switch the programming language of code snippets or the entire page, once deployed on GitHub Pages. For tutorial authors, an integrated dev server allows previewing the result with the same functionality locally and instantly.

Main features of the two-language support are:
1. Content meant only for *one* of the programming languages can be hidden in the other by enclosing it in a specific block.
2. Two adjacent code sections in different languages are automatically converted to a tab container which allows switching between languages.
3. File extensions writen as `.?s` appear automatically as `.js` or `.ts` depending on the current language.

## Limitations

The feature 3. above does not work inside code blocks (yet).


## Running the preview/dev server

To immediately preview the markdown document you are writing *including* the two-language magic, simply run

```sh
npm i
```

in the root folder of this project once for the setup, then to actually run the server, run

```sh
npm start
```

Then, open http://localhost:1337/README.md in your browser.

Alternatively, and even easier, run

```sh
npm run watch
```

And the browser will automatically open (on port 3000) and automatically reload on every saved change.


## Writing *one* document which covers both JavaScript and TypeScript without duplication

The following features help providing language-specific content without duplication of other content.

### 1. Language-specific Blocks of Content

When a certain part of the tutorial content (can be explanation and/or code) is only relevant for *one* of the languages (JavaScript *or* TypeScript), then enclose it within the following tags. The CSS class decides for which language it is meant!

TypeScript-only:

```html
<details class="ts-only" markdown="1"><summary>This section is relevant for TypeScript only</summary>
...here comes the TS-only text...
</details>
```

JavaScript-only:

```html
<details class="js-only" markdown="1"><summary>This section is relevant for JavaScript only</summary>
...here comes the JS-only text...
</details>
```

The `markdown="1"` part is required for markdown parsing within HTML and the `<summary>` is helpful for readers of the raw markdown view, so please use the tag structure as-is, with your actual content in between.

#### Resulting Appearance<span class="hidden"> in markdown view (not in the final page)</span>

<details class="ts-only" markdown="1"><summary>This section is relevant for TypeScript only</summary>
...here comes the TS-only text...
</details>

<details class="js-only" markdown="1"><summary>This section is relevant for JavaScript only</summary>
...here comes the JS-only text...
</details>


### 2. Switchable code blocks in both languages

When a piece of code should be displayed in either JS or TS, whatever is current, then simply create two adjacent markdown-fenced code blocks. They are automatically recognized as language-specific alternatives.

Example:
```md

```js
const i = 0;
```

```ts
const i: number = 0;
```
```
> Do not indent, this was only done to make the backticks within the code block visible.

> Some places where this occurs may not be properly recognized, so make sure to test it.

#### Resulting Appearance<span class="hidden"> in markdown view (here in markdown you still see BOTH and no tab container; the magic only happens in the dev server and in GitHub Pages)</span>

```js
const i = 0;
```

```ts
const i: number = 0;
```

### 3. File Extensions (`.js/.ts`)

When the text or a section heading mentions the name of a file that will be JavaScript or TypeScript, depending on the language, then use the file extension `.\?s`. It will automatically be switched to the current language.

Example:
```md
In this step you create the file `Example.controller.\?s`.
```

#### Resulting Appearance<span class="hidden"> in markdown view (here the extension is not replaced, the replacement only happens in the dev server and in GitHub Pages)</span>

In this step you create the file `Example.controller.?s`.

## Converting the JS Code to TypeScript

TODO: tool support for this functionality does not exist yet. It can, however, already be done manually.

General approach: develop the tutorial in TS and use the debug version of the transpilation result as JS code.

To clean up the transpilation result, search for and remove content containing the following in the transpiled JS code:

### `_interopRequireDefault`

Looks like this:

```js
sap.ui.define(["./BaseController"], function (__BaseController) {

function _interopRequireDefault(obj) {
return obj && obj.__esModule && typeof obj.default !== "undefined" ? obj.default : obj;
}
const BaseController = _interopRequireDefault(__BaseController);
```

Remove the function definition and the line calling the function. Rename the dependency in the `sap.ui.define` call from `__BaseController` to `BaseController`.


### TODO: Some more similar things, unless we do it in the transpiler
2 changes: 2 additions & 0 deletions _includes/head-custom.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
<link rel="stylesheet" href="{{ 'assets/css/custom.css' | relative_url }}">
<script src="{{ 'assets/js/custom.js' | relative_url }}"></script>
Loading