mirror of
https://github.com/microsoft/monaco-editor.git
synced 2025-12-22 07:00:11 +01:00
Implements #2383 Add syntax modes for FreeMarker template language
This commit is contained in:
parent
3e433551a9
commit
94f81dc4ae
16 changed files with 24866 additions and 0 deletions
3099
src/basic-languages/freemarker2/freemarker2-angle-bracket.test.ts
Normal file
3099
src/basic-languages/freemarker2/freemarker2-angle-bracket.test.ts
Normal file
File diff suppressed because it is too large
Load diff
3099
src/basic-languages/freemarker2/freemarker2-angle-dollar.test.ts
Normal file
3099
src/basic-languages/freemarker2/freemarker2-angle-dollar.test.ts
Normal file
File diff suppressed because it is too large
Load diff
5358
src/basic-languages/freemarker2/freemarker2-auto-bracket.test.ts
Normal file
5358
src/basic-languages/freemarker2/freemarker2-auto-bracket.test.ts
Normal file
File diff suppressed because it is too large
Load diff
5361
src/basic-languages/freemarker2/freemarker2-auto-dollar.test.ts
Normal file
5361
src/basic-languages/freemarker2/freemarker2-auto-dollar.test.ts
Normal file
File diff suppressed because it is too large
Load diff
3086
src/basic-languages/freemarker2/freemarker2-bracket-bracket.test.ts
Normal file
3086
src/basic-languages/freemarker2/freemarker2-bracket-bracket.test.ts
Normal file
File diff suppressed because it is too large
Load diff
3086
src/basic-languages/freemarker2/freemarker2-bracket-dollar.test.ts
Normal file
3086
src/basic-languages/freemarker2/freemarker2-bracket-dollar.test.ts
Normal file
File diff suppressed because it is too large
Load diff
111
src/basic-languages/freemarker2/freemarker2.contribution.ts
Normal file
111
src/basic-languages/freemarker2/freemarker2.contribution.ts
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { registerLanguage } from '../_.contribution';
|
||||
|
||||
declare var AMD: any;
|
||||
declare var require: any;
|
||||
|
||||
// freemarker.tag-square.interpolation-dollar is the default
|
||||
// According the docs tag-auto will be the default for version 2.4+, but that
|
||||
// hasn't event been released yet.
|
||||
registerLanguage({
|
||||
id: 'freemarker2',
|
||||
extensions: ['.ftl', '.ftlh', '.ftlx'],
|
||||
aliases: ['FreeMarker2', 'Apache FreeMarker2'],
|
||||
loader: () => {
|
||||
if (AMD) {
|
||||
return new Promise<typeof import('./freemarker2')>((resolve, reject) => {
|
||||
require(['vs/basic-languages/freemarker2/freemarker2'], resolve, reject);
|
||||
}).then((m) => m.TagAngleInterpolationDollar);
|
||||
} else {
|
||||
return import('./freemarker2').then((m) => m.TagAutoInterpolationDollar);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerLanguage({
|
||||
id: 'freemarker2.tag-angle.interpolation-dollar',
|
||||
aliases: ['FreeMarker2 (Angle/Dollar)', 'Apache FreeMarker2 (Angle/Dollar)'],
|
||||
loader: () => {
|
||||
if (AMD) {
|
||||
return new Promise<typeof import('./freemarker2')>((resolve, reject) => {
|
||||
require(['vs/basic-languages/freemarker2/freemarker2'], resolve, reject);
|
||||
}).then((m) => m.TagAngleInterpolationDollar);
|
||||
} else {
|
||||
return import('./freemarker2').then((m) => m.TagAngleInterpolationDollar);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerLanguage({
|
||||
id: 'freemarker2.tag-bracket.interpolation-dollar',
|
||||
aliases: ['FreeMarker2 (Bracket/Dollar)', 'Apache FreeMarker2 (Bracket/Dollar)'],
|
||||
loader: () => {
|
||||
if (AMD) {
|
||||
return new Promise<typeof import('./freemarker2')>((resolve, reject) => {
|
||||
require(['vs/basic-languages/freemarker2/freemarker2'], resolve, reject);
|
||||
}).then((m) => m.TagBracketInterpolationDollar);
|
||||
} else {
|
||||
return import('./freemarker2').then((m) => m.TagBracketInterpolationDollar);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerLanguage({
|
||||
id: 'freemarker2.tag-angle.interpolation-bracket',
|
||||
aliases: ['FreeMarker2 (Angle/Bracket)', 'Apache FreeMarker2 (Angle/Bracket)'],
|
||||
loader: () => {
|
||||
if (AMD) {
|
||||
return new Promise<typeof import('./freemarker2')>((resolve, reject) => {
|
||||
require(['vs/basic-languages/freemarker2/freemarker2'], resolve, reject);
|
||||
}).then((m) => m.TagAngleInterpolationBracket);
|
||||
} else {
|
||||
return import('./freemarker2').then((m) => m.TagAngleInterpolationBracket);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerLanguage({
|
||||
id: 'freemarker2.tag-bracket.interpolation-bracket',
|
||||
aliases: ['FreeMarker2 (Bracket/Bracket)', 'Apache FreeMarker2 (Bracket/Bracket)'],
|
||||
loader: () => {
|
||||
if (AMD) {
|
||||
return new Promise<typeof import('./freemarker2')>((resolve, reject) => {
|
||||
require(['vs/basic-languages/freemarker2/freemarker2'], resolve, reject);
|
||||
}).then((m) => m.TagBracketInterpolationBracket);
|
||||
} else {
|
||||
return import('./freemarker2').then((m) => m.TagBracketInterpolationBracket);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerLanguage({
|
||||
id: 'freemarker2.tag-auto.interpolation-dollar',
|
||||
aliases: ['FreeMarker2 (Auto/Dollar)', 'Apache FreeMarker2 (Auto/Dollar)'],
|
||||
loader: () => {
|
||||
if (AMD) {
|
||||
return new Promise<typeof import('./freemarker2')>((resolve, reject) => {
|
||||
require(['vs/basic-languages/freemarker2/freemarker2'], resolve, reject);
|
||||
}).then((m) => m.TagAutoInterpolationDollar);
|
||||
} else {
|
||||
return import('./freemarker2').then((m) => m.TagAutoInterpolationDollar);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
registerLanguage({
|
||||
id: 'freemarker2.tag-auto.interpolation-bracket',
|
||||
aliases: ['FreeMarker2 (Auto/Bracket)', 'Apache FreeMarker2 (Auto/Bracket)'],
|
||||
loader: () => {
|
||||
if (AMD) {
|
||||
return new Promise<typeof import('./freemarker2')>((resolve, reject) => {
|
||||
require(['vs/basic-languages/freemarker2/freemarker2'], resolve, reject);
|
||||
}).then((m) => m.TagAutoInterpolationBracket);
|
||||
} else {
|
||||
return import('./freemarker2').then((m) => m.TagAutoInterpolationBracket);
|
||||
}
|
||||
}
|
||||
});
|
||||
1230
src/basic-languages/freemarker2/freemarker2.ts
Normal file
1230
src/basic-languages/freemarker2/freemarker2.ts
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -21,6 +21,7 @@ import './ecl/ecl.contribution';
|
|||
import './elixir/elixir.contribution';
|
||||
import './flow9/flow9.contribution';
|
||||
import './fsharp/fsharp.contribution';
|
||||
import './freemarker2/freemarker2.contribution';
|
||||
import './go/go.contribution';
|
||||
import './graphql/graphql.contribution';
|
||||
import './handlebars/handlebars.contribution';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
<#ftl stripText=false>
|
||||
|
||||
<#-- Free marker demo -->
|
||||
|
||||
<#comment>
|
||||
This demonstrates the FreeMarker language. The default theme is not very
|
||||
colorful and displays many different token types in the same color, but keep in
|
||||
mind that you can define your own theme (or extend an existing one).
|
||||
|
||||
Note that free marker actually defines 6 similar but different syntax modes:
|
||||
|
||||
- 3 tag syntax modes: Angle (<#if>), Bracket ([#if]), and Auto.
|
||||
- 2 interpolation modes: Dollar (${...}) and Bracket ([=...])
|
||||
|
||||
In auto mode, the first tag determines the tag syntax. You can use the language
|
||||
IDs "freemarker.tag-bracket.interpolation-dollar" etc. to force a specific mode.
|
||||
|
||||
The default FreeMarker mode is Angle/Dollar.
|
||||
</#comment>
|
||||
|
||||
<#macro greet name>
|
||||
<font size="+2">Hello [=name]!</font>
|
||||
</#macro>
|
||||
|
||||
<#macro border>
|
||||
<table border=4 cellspacing=0 cellpadding=4><tr><td>
|
||||
<#nested>
|
||||
</tr></td></table>
|
||||
</#macro>
|
||||
|
||||
<#function avg x y>
|
||||
<#return (x + y) / 2>
|
||||
</#function>
|
||||
|
||||
<#assign user = "Juila Smith">
|
||||
<#assign animals = [{"name": "Tanuki", "price": 200}, {"name": "Phoenix", "price": 1111}]>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome!</title>
|
||||
</head>
|
||||
<body>
|
||||
<#-- Greet the user with his/her name -->
|
||||
<h1>
|
||||
<@greet user />
|
||||
</h1>
|
||||
|
||||
<p>We have these animals:
|
||||
|
||||
<ul>
|
||||
<#list animals as animal>
|
||||
<li>[=animal.name] for [=animal.price] Euros
|
||||
</#list>
|
||||
</ul>
|
||||
|
||||
<@border>The bordered text</@border>
|
||||
|
||||
The average of 35 and 49 is [=avg(35, 49)].
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
<#ftl stripText=false>
|
||||
|
||||
<#-- Free marker demo -->
|
||||
|
||||
<#comment>
|
||||
This demonstrates the FreeMarker language. The default theme is not very
|
||||
colorful and displays many different token types in the same color, but keep in
|
||||
mind that you can define your own theme (or extend an existing one).
|
||||
|
||||
Note that free marker actually defines 6 similar but different syntax modes:
|
||||
|
||||
- 3 tag syntax modes: Angle (<#if>), Bracket ([#if]), and Auto.
|
||||
- 2 interpolation modes: Dollar (${...}) and Bracket ([=...])
|
||||
|
||||
In auto mode, the first tag determines the tag syntax. You can use the language
|
||||
IDs "freemarker.tag-bracket.interpolation-dollar" etc. to force a specific mode.
|
||||
|
||||
The default FreeMarker mode is Angle/Dollar.
|
||||
</#comment>
|
||||
|
||||
<#macro greet name>
|
||||
<font size="+2">Hello ${name}!</font>
|
||||
</#macro>
|
||||
|
||||
<#macro border>
|
||||
<table border=4 cellspacing=0 cellpadding=4><tr><td>
|
||||
<#nested>
|
||||
</tr></td></table>
|
||||
</#macro>
|
||||
|
||||
<#function avg x y>
|
||||
<#return (x + y) / 2>
|
||||
</#function>
|
||||
|
||||
<#assign user = "Juila Smith">
|
||||
<#assign animals = [{"name": "Tanuki", "price": 200}, {"name": "Phoenix", "price": 1111}]>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome!</title>
|
||||
</head>
|
||||
<body>
|
||||
<#-- Greet the user with his/her name -->
|
||||
<h1>
|
||||
<@greet user />
|
||||
</h1>
|
||||
|
||||
<p>We have these animals:
|
||||
|
||||
<ul>
|
||||
<#list animals as animal>
|
||||
<li>${animal.name} for ${animal.price} Euros
|
||||
</#list>
|
||||
</ul>
|
||||
|
||||
<@border>The bordered text</@border>
|
||||
|
||||
The average of 35 and 49 is ${avg(35, 49)}.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
Auto mode detect the tag syntax mode automatically.
|
||||
Try exchanging the order of the next two lines and see what happens!
|
||||
|
||||
[#ftl stripText=false]
|
||||
<#ftl stripText=false>
|
||||
|
||||
<#-- Free marker demo -->
|
||||
|
||||
<#comment>
|
||||
This demonstrates the FreeMarker language. The default theme is not very
|
||||
colorful and displays many different token types in the same color, but keep in
|
||||
mind that you can define your own theme (or extend an existing one).
|
||||
|
||||
Note that free marker actually defines 6 similar but different syntax modes:
|
||||
|
||||
- 3 tag syntax modes: Angle (<#if>), Bracket ([#if]), and Auto.
|
||||
- 2 interpolation modes: Dollar (${...}) and Bracket ([=...])
|
||||
|
||||
In auto mode, the first tag determines the tag syntax. You can use the language
|
||||
IDs "freemarker.tag-bracket.interpolation-dollar" etc. to force a specific mode.
|
||||
|
||||
The default FreeMarker mode is Angle/Dollar.
|
||||
</#comment>
|
||||
|
||||
<#macro greet name>
|
||||
<font size="+2">Hello [=name]!</font>
|
||||
</#macro>
|
||||
|
||||
<#macro border>
|
||||
<table border=4 cellspacing=0 cellpadding=4><tr><td>
|
||||
<#nested>
|
||||
</tr></td></table>
|
||||
</#macro>
|
||||
|
||||
<#function avg x y>
|
||||
<#return (x + y) / 2>
|
||||
</#function>
|
||||
|
||||
<#assign user = "Juila Smith">
|
||||
<#assign animals = [{"name": "Tanuki", "price": 200}, {"name": "Phoenix", "price": 1111}]>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome!</title>
|
||||
</head>
|
||||
<body>
|
||||
<#-- Greet the user with his/her name -->
|
||||
<h1>
|
||||
<@greet user />
|
||||
</h1>
|
||||
|
||||
<p>We have these animals:
|
||||
|
||||
<ul>
|
||||
<#list animals as animal>
|
||||
<li>[=animal.name] for [=animal.price] Euros
|
||||
</#list>
|
||||
</ul>
|
||||
|
||||
<@border>The bordered text</@border>
|
||||
|
||||
The average of 35 and 49 is [=avg(35, 49)].
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
Auto mode detect the tag syntax mode automatically.
|
||||
Try exchanging the order of the next two lines and see what happens!
|
||||
|
||||
<#ftl stripText=false>
|
||||
[#ftl stripText=false]
|
||||
|
||||
<#-- Free marker demo -->
|
||||
|
||||
<#comment>
|
||||
This demonstrates the FreeMarker language. The default theme is not very
|
||||
colorful and displays many different token types in the same color, but keep in
|
||||
mind that you can define your own theme (or extend an existing one).
|
||||
|
||||
Note that free marker actually defines 6 similar but different syntax modes:
|
||||
|
||||
- 3 tag syntax modes: Angle (<#if>), Bracket ([#if]), and Auto.
|
||||
- 2 interpolation modes: Dollar (${...}) and Bracket ([=...])
|
||||
|
||||
In auto mode, the first tag determines the tag syntax. You can use the language
|
||||
IDs "freemarker.tag-bracket.interpolation-dollar" etc. to force a specific mode.
|
||||
|
||||
The default FreeMarker mode is Angle/Dollar.
|
||||
</#comment>
|
||||
|
||||
<#macro greet name>
|
||||
<font size="+2">Hello ${name}!</font>
|
||||
</#macro>
|
||||
|
||||
<#macro border>
|
||||
<table border=4 cellspacing=0 cellpadding=4><tr><td>
|
||||
<#nested>
|
||||
</tr></td></table>
|
||||
</#macro>
|
||||
|
||||
<#function avg x y>
|
||||
<#return (x + y) / 2>
|
||||
</#function>
|
||||
|
||||
<#assign user = "Juila Smith">
|
||||
<#assign animals = [{"name": "Tanuki", "price": 200}, {"name": "Phoenix", "price": 1111}]>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome!</title>
|
||||
</head>
|
||||
<body>
|
||||
<#-- Greet the user with his/her name -->
|
||||
<h1>
|
||||
<@greet user />
|
||||
</h1>
|
||||
|
||||
<p>We have these animals:
|
||||
|
||||
<ul>
|
||||
<#list animals as animal>
|
||||
<li>${animal.name} for ${animal.price} Euros
|
||||
</#list>
|
||||
</ul>
|
||||
|
||||
<@border>The bordered text</@border>
|
||||
|
||||
The average of 35 and 49 is ${avg(35, 49)}.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
[#ftl stripText=false]
|
||||
|
||||
[#-- Free marker demo --]
|
||||
|
||||
[#comment]
|
||||
This demonstrates the FreeMarker language. The default theme is not very
|
||||
colorful and displays many different token types in the same color, but keep in
|
||||
mind that you can define your own theme (or extend an existing one).
|
||||
|
||||
Note that free marker actually defines 6 similar but different syntax modes:
|
||||
|
||||
- 3 tag syntax modes: Angle (<#if>), Bracket ([#if]), and Auto.
|
||||
- 2 interpolation modes: Dollar (${...}) and Bracket ([=...])
|
||||
|
||||
In auto mode, the first tag determines the tag syntax. You can use the language
|
||||
IDs "freemarker.tag-bracket.interpolation-dollar" etc. to force a specific mode.
|
||||
|
||||
The default FreeMarker mode is Angle/Dollar.
|
||||
[/#comment]
|
||||
|
||||
[#macro greet name]
|
||||
<font size="+2">Hello [=name]!</font>
|
||||
[/#macro[
|
||||
|
||||
[#macro border]
|
||||
<table border=4 cellspacing=0 cellpadding=4><tr><td>
|
||||
[#nested]
|
||||
</tr></td></table>
|
||||
[/#macro]
|
||||
|
||||
[#function avg x y]
|
||||
[#return (x + y) / 2]
|
||||
[/#function]
|
||||
|
||||
[#assign user = "Juila Smith"]
|
||||
[#assign animals = [{"name": "Tanuki", "price": 200}, {"name": "Phoenix", "price": 1111}]]
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome!</title>
|
||||
</head>
|
||||
<body>
|
||||
[#-- Greet the user with his/her name --]
|
||||
<h1>
|
||||
<@greet user />
|
||||
</h1>
|
||||
|
||||
<p>We have these animals:
|
||||
|
||||
<ul>
|
||||
[#list animals as animal]
|
||||
<li>[=animal.name] for [=animal.price] Euros
|
||||
[/#list][
|
||||
</ul>
|
||||
|
||||
<@border>The bordered text</@border>
|
||||
|
||||
The average of 35 and 49 is [=avg(35, 49]}.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
[#ftl stripText=false]
|
||||
|
||||
[#-- Free marker demo --]
|
||||
|
||||
[#comment]
|
||||
This demonstrates the FreeMarker language. The default theme is not very
|
||||
colorful and displays many different token types in the same color, but keep in
|
||||
mind that you can define your own theme (or extend an existing one).
|
||||
|
||||
Note that free marker actually defines 6 similar but different syntax modes:
|
||||
|
||||
- 3 tag syntax modes: Angle (<#if>), Bracket ([#if]), and Auto.
|
||||
- 2 interpolation modes: Dollar (${...}) and Bracket ([=...])
|
||||
|
||||
In auto mode, the first tag determines the tag syntax. You can use the language
|
||||
IDs "freemarker.tag-bracket.interpolation-dollar" etc. to force a specific mode.
|
||||
|
||||
The default FreeMarker mode is Angle/Dollar.
|
||||
[/#comment]
|
||||
|
||||
[#macro greet name]
|
||||
<font size="+2">Hello ${name}!</font>
|
||||
[/#macro[
|
||||
|
||||
[#macro border]
|
||||
<table border=4 cellspacing=0 cellpadding=4><tr><td>
|
||||
[#nested]
|
||||
</tr></td></table>
|
||||
[/#macro]
|
||||
|
||||
[#function avg x y]
|
||||
[#return (x + y) / 2]
|
||||
[/#function]
|
||||
|
||||
[#assign user = "Juila Smith"]
|
||||
[#assign animals = [{"name": "Tanuki", "price": 200}, {"name": "Phoenix", "price": 1111}]]
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome!</title>
|
||||
</head>
|
||||
<body>
|
||||
[#-- Greet the user with his/her name --]
|
||||
<h1>
|
||||
<@greet user />
|
||||
</h1>
|
||||
|
||||
<p>We have these animals:
|
||||
|
||||
<ul>
|
||||
[#list animals as animal]
|
||||
<li>${animal.name} for ${animal.price} Euros
|
||||
[/#list][
|
||||
</ul>
|
||||
|
||||
<@border>The bordered text</@border>
|
||||
|
||||
The average of 35 and 49 is ${avg(35, 49)}.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
61
website/index/samples/sample.freemarker2.txt
Normal file
61
website/index/samples/sample.freemarker2.txt
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<#ftl stripText=false>
|
||||
|
||||
<#-- Free marker demo -->
|
||||
|
||||
<#comment>
|
||||
This demonstrates the FreeMarker language. The default theme is not very
|
||||
colorful and displays many different token types in the same color, but keep in
|
||||
mind that you can define your own theme (or extend an existing one).
|
||||
|
||||
Note that free marker actually defines 6 similar but different syntax modes:
|
||||
|
||||
- 3 tag syntax modes: Angle (<#if>), Bracket ([#if]), and Auto.
|
||||
- 2 interpolation modes: Dollar (${...}) and Bracket ([=...])
|
||||
|
||||
In auto mode, the first tag determines the tag syntax. You can use the language
|
||||
IDs "freemarker.tag-bracket.interpolation-dollar" etc. to force a specific mode.
|
||||
|
||||
The default FreeMarker mode is Angle/Dollar.
|
||||
</#comment>
|
||||
|
||||
<#macro greet name>
|
||||
<font size="+2">Hello ${name}!</font>
|
||||
</#macro>
|
||||
|
||||
<#macro border>
|
||||
<table border=4 cellspacing=0 cellpadding=4><tr><td>
|
||||
<#nested>
|
||||
</tr></td></table>
|
||||
</#macro>
|
||||
|
||||
<#function avg x y>
|
||||
<#return (x + y) / 2>
|
||||
</#function>
|
||||
|
||||
<#assign user = "Juila Smith">
|
||||
<#assign animals = [{"name": "Tanuki", "price": 200}, {"name": "Phoenix", "price": 1111}]>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome!</title>
|
||||
</head>
|
||||
<body>
|
||||
<#-- Greet the user with his/her name -->
|
||||
<h1>
|
||||
<@greet user />
|
||||
</h1>
|
||||
|
||||
<p>We have these animals:
|
||||
|
||||
<ul>
|
||||
<#list animals as animal>
|
||||
<li>${animal.name} for ${animal.price} Euros
|
||||
</#list>
|
||||
</ul>
|
||||
|
||||
<@border>The bordered text</@border>
|
||||
|
||||
The average of 35 and 49 is ${avg(35, 49)}.
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue