Add ToC to generated pages
This commit is contained in:
parent
b4529e4f63
commit
752538ec14
18 changed files with 346 additions and 243 deletions
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
1. [Special and other useful layers](#Special_and_other_useful_layers)
|
1. [Special and other useful layers](#special-and-other-useful-layers)
|
||||||
1. [Priviliged layers](#Priviliged_layers)
|
1. [Priviliged layers](#priviliged-layers)
|
||||||
+ [gps_location](#gps_location)
|
+ [gps_location](#gps_location)
|
||||||
+ [gps_location_history](#gps_location_history)
|
+ [gps_location_history](#gps_location_history)
|
||||||
+ [home_location](#home_location)
|
+ [home_location](#home_location)
|
||||||
|
@ -14,17 +14,17 @@
|
||||||
+ [type_node](#type_node)
|
+ [type_node](#type_node)
|
||||||
+ [conflation](#conflation)
|
+ [conflation](#conflation)
|
||||||
+ [left_right_style](#left_right_style)
|
+ [left_right_style](#left_right_style)
|
||||||
1. [Frequently reused layers](#Frequently_reused_layers)
|
1. [Frequently reused layers](#frequently-reused-layers)
|
||||||
+ [bicycle_library](#bicycle_library)
|
+ [bicycle_library](#bicycle_library)
|
||||||
* [Themes using this layer](#Themes_using_this_layer)
|
* [Themes using this layer](#themes-using-this-layer)
|
||||||
+ [drinking_water](#drinking_water)
|
+ [drinking_water](#drinking_water)
|
||||||
* [Themes using this layer](#Themes_using_this_layer)
|
* [Themes using this layer](#themes-using-this-layer)
|
||||||
+ [food](#food)
|
+ [food](#food)
|
||||||
* [Themes using this layer](#Themes_using_this_layer)
|
* [Themes using this layer](#themes-using-this-layer)
|
||||||
+ [map](#map)
|
+ [map](#map)
|
||||||
* [Themes using this layer](#Themes_using_this_layer)
|
* [Themes using this layer](#themes-using-this-layer)
|
||||||
+ [all_streets](#all_streets)
|
+ [all_streets](#all_streets)
|
||||||
* [Themes using this layer](#Themes_using_this_layer)
|
* [Themes using this layer](#themes-using-this-layer)
|
||||||
|
|
||||||
MapComplete has a few data layers available in the theme which have special properties through builtin-hooks. Furthermore, there are some normal layers (which are built from normal Theme-config files) but are so general that they get a mention here.
|
MapComplete has a few data layers available in the theme which have special properties through builtin-hooks. Furthermore, there are some normal layers (which are built from normal Theme-config files) but are so general that they get a mention here.
|
||||||
|
|
||||||
|
|
|
@ -5,21 +5,21 @@
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
1. [Metatags](#Metatags)
|
1. [Metatags](#metatags)
|
||||||
- [Metatags calculated by MapComplete](#Metatags_calculated_by_MapComplete)
|
- [Metatags calculated by MapComplete](#metatags-calculated-by-mapcomplete)
|
||||||
+ [_lat, _lon](#_lat,__lon)
|
+ [_lat, _lon](#_lat,-_lon)
|
||||||
+ [_layer](#_layer)
|
+ [_layer](#_layer)
|
||||||
+ [_surface, _surface:ha](#_surface,__surface:ha)
|
+ [_surface, _surface:ha](#_surface,-_surfaceha)
|
||||||
+ [_length, _length:km](#_length,__length:km)
|
+ [_length, _length:km](#_length,-_lengthkm)
|
||||||
+ [Theme-defined keys](#Theme-defined_keys)
|
+ [Theme-defined keys](#theme-defined-keys)
|
||||||
+ [_country](#_country)
|
+ [_country](#_country)
|
||||||
+ [_isOpen, _isOpen:description](#_isOpen,__isOpen:description)
|
+ [_isOpen, _isOpen:description](#_isopen,-_isopendescription)
|
||||||
+ [_direction:numerical, _direction:leftright](#_direction:numerical,__direction:leftright)
|
+ [_direction:numerical, _direction:leftright](#_directionnumerical,-_direction:leftright)
|
||||||
+ [_now:date, _now:datetime, _loaded:date, _loaded:_datetime](#_now:date,__now:datetime,__loaded:date,__loaded:_datetime)
|
+ [_now:date, _now:datetime, _loaded:date, _loaded:_datetime](#_nowdate,-_now:datetime,-_loaded:date,-_loaded:_datetime)
|
||||||
+ [_last_edit:contributor, _last_edit:contributor:uid, _last_edit:changeset, _last_edit:timestamp, _version_number, _backend](#_last_edit:contributor,__last_edit:contributor:uid,__last_edit:changeset,__last_edit:timestamp,__version_number,__backend)
|
+ [_last_edit:contributor, _last_edit:contributor:uid, _last_edit:changeset, _last_edit:timestamp, _version_number, _backend](#_last_editcontributor,-_last_edit:contributor:uid,-_last_edit:changeset,-_last_edit:timestamp,-_version_number,-_backend)
|
||||||
+ [sidewalk:left, sidewalk:right, generic_key:left:property, generic_key:right:property](#sidewalk:left,_sidewalk:right,_generic_key:left:property,_generic_key:right:property)
|
+ [sidewalk:left, sidewalk:right, generic_key:left:property, generic_key:right:property](#sidewalkleft,-sidewalk:right,-generic_key:left:property,-generic_key:right:property)
|
||||||
+ [distanceTo](#distanceTo)
|
+ [distanceTo](#distanceto)
|
||||||
+ [overlapWith](#overlapWith)
|
+ [overlapWith](#overlapwith)
|
||||||
+ [closest](#closest)
|
+ [closest](#closest)
|
||||||
+ [closestn](#closestn)
|
+ [closestn](#closestn)
|
||||||
+ [memberships](#memberships)
|
+ [memberships](#memberships)
|
||||||
|
|
|
@ -5,29 +5,59 @@
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
1. [Available types for text fields](#Available_types_for_text_fields)
|
1. [Available types for text fields](#available-types-for-text-fields)
|
||||||
|
+ [string](#string)
|
||||||
|
+ [text](#text)
|
||||||
|
+ [date](#date)
|
||||||
|
+ [direction](#direction)
|
||||||
|
+ [length](#length)
|
||||||
|
+ [wikidata](#wikidata)
|
||||||
|
+ [int](#int)
|
||||||
|
+ [nat](#nat)
|
||||||
|
+ [pnat](#pnat)
|
||||||
|
+ [float](#float)
|
||||||
|
+ [pfloat](#pfloat)
|
||||||
|
+ [email](#email)
|
||||||
|
+ [url](#url)
|
||||||
|
+ [phone](#phone)
|
||||||
|
+ [opening_hours](#opening_hours)
|
||||||
|
+ [color](#color)
|
||||||
|
|
||||||
The listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them ## string
|
The listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them
|
||||||
|
|
||||||
A basic string
|
### string
|
||||||
|
|
||||||
## text
|
|
||||||
|
|
||||||
A string, but allows input of longer strings more comfortably and supports newlines (a text area)
|
|
||||||
|
|
||||||
## date
|
A basic string
|
||||||
|
|
||||||
A date
|
### text
|
||||||
|
|
||||||
## direction
|
|
||||||
|
|
||||||
A geographical direction, in degrees. 0° is north, 90° is east, ... Will return a value between 0 (incl) and 360 (excl)
|
|
||||||
|
|
||||||
## length
|
A string, but allows input of longer strings more comfortably and supports newlines (a text area)
|
||||||
|
|
||||||
|
### date
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A date
|
||||||
|
|
||||||
|
### direction
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A geographical direction, in degrees. 0° is north, 90° is east, ... Will return a value between 0 (incl) and 360 (excl)
|
||||||
|
|
||||||
|
### length
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A geographical length in meters (rounded at two points). Will give an extra minimap with a measurement tool. Arguments: [ zoomlevel, preferredBackgroundMapType (comma separated) ], e.g. `["21", "map,photo"]
|
||||||
|
|
||||||
|
### wikidata
|
||||||
|
|
||||||
A geographical length in meters (rounded at two points). Will give an extra minimap with a measurement tool. Arguments: [ zoomlevel, preferredBackgroundMapType (comma separated) ], e.g. `["21", "map,photo"]
|
|
||||||
|
|
||||||
## wikidata
|
|
||||||
|
|
||||||
A wikidata identifier, e.g. Q42.
|
A wikidata identifier, e.g. Q42.
|
||||||
|
|
||||||
|
@ -68,41 +98,59 @@ removePostfixes | remove these snippets of text from the end of the passed strin
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## int
|
### int
|
||||||
|
|
||||||
A number
|
|
||||||
|
|
||||||
## nat
|
|
||||||
|
|
||||||
A positive number or zero
|
A number
|
||||||
|
|
||||||
## pnat
|
### nat
|
||||||
|
|
||||||
A strict positive number
|
|
||||||
|
|
||||||
## float
|
|
||||||
|
|
||||||
A decimal
|
A positive number or zero
|
||||||
|
|
||||||
## pfloat
|
### pnat
|
||||||
|
|
||||||
A positive decimal (incl zero)
|
|
||||||
|
|
||||||
## email
|
|
||||||
|
|
||||||
An email adress
|
A strict positive number
|
||||||
|
|
||||||
## url
|
### float
|
||||||
|
|
||||||
A url
|
|
||||||
|
|
||||||
## phone
|
|
||||||
|
|
||||||
A phone number
|
A decimal
|
||||||
|
|
||||||
|
### pfloat
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A positive decimal (incl zero)
|
||||||
|
|
||||||
|
### email
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
An email adress
|
||||||
|
|
||||||
|
### url
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A url
|
||||||
|
|
||||||
|
### phone
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A phone number
|
||||||
|
|
||||||
|
### opening_hours
|
||||||
|
|
||||||
|
|
||||||
## opening_hours
|
|
||||||
|
|
||||||
Has extra elements to easily input when a POI is opened.
|
Has extra elements to easily input when a POI is opened.
|
||||||
|
|
||||||
|
@ -139,9 +187,11 @@ postfix | Piece of text that will always be added to the end of the generated op
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
*Don't forget to pass the prefix and postfix in the rendering as well*: `{opening_hours_table(opening_hours,yes @ &LPARENS, &RPARENS )`
|
*Don't forget to pass the prefix and postfix in the rendering as well*: `{opening_hours_table(opening_hours,yes @ &LPARENS, &RPARENS )`
|
||||||
|
|
||||||
|
### color
|
||||||
|
|
||||||
|
|
||||||
## color
|
|
||||||
|
|
||||||
Shows a color picker
|
Shows a color picker
|
||||||
|
|
||||||
|
|
|
@ -5,41 +5,41 @@
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
1. [Special tag renderings](#Special_tag_renderings)
|
1. [Special tag renderings](#special-tag-renderings)
|
||||||
+ [all_tags](#all_tags)
|
+ [all_tags](#all_tags)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [image_carousel](#image_carousel)
|
+ [image_carousel](#image_carousel)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [image_upload](#image_upload)
|
+ [image_upload](#image_upload)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [wikipedia](#wikipedia)
|
+ [wikipedia](#wikipedia)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [minimap](#minimap)
|
+ [minimap](#minimap)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [sided_minimap](#sided_minimap)
|
+ [sided_minimap](#sided_minimap)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [reviews](#reviews)
|
+ [reviews](#reviews)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [opening_hours_table](#opening_hours_table)
|
+ [opening_hours_table](#opening_hours_table)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [live](#live)
|
+ [live](#live)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [histogram](#histogram)
|
+ [histogram](#histogram)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [share_link](#share_link)
|
+ [share_link](#share_link)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [canonical](#canonical)
|
+ [canonical](#canonical)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [import_button](#import_button)
|
+ [import_button](#import_button)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [multi_apply](#multi_apply)
|
+ [multi_apply](#multi_apply)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [tag_apply](#tag_apply)
|
+ [tag_apply](#tag_apply)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [export_as_gpx](#export_as_gpx)
|
+ [export_as_gpx](#export_as_gpx)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
+ [clear_location_history](#clear_location_history)
|
+ [clear_location_history](#clear_location_history)
|
||||||
* [Example usage](#Example_usage)
|
* [Example usage](#example-usage)
|
||||||
|
|
||||||
In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's. General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args
|
In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's. General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
|
|
||||||
## Table of contents
|
## Table of contents
|
||||||
|
|
||||||
1. [URL-parameters and URL-hash](#URL-parameters_and_URL-hash)
|
1. [URL-parameters and URL-hash](#url-parameters-and-url-hash)
|
||||||
- [What is a URL parameter?](#what_is_a_url_parameter)
|
- [What is a URL parameter?](#what-is-a-url-parameter)
|
||||||
- [fs-userbadge](#fs-userbadge)
|
- [fs-userbadge](#fs-userbadge)
|
||||||
- [fs-search](#fs-search)
|
- [fs-search](#fs-search)
|
||||||
- [fs-background](#fs-background)
|
- [fs-background](#fs-background)
|
||||||
|
@ -24,10 +24,10 @@
|
||||||
- [test](#test)
|
- [test](#test)
|
||||||
- [debug](#debug)
|
- [debug](#debug)
|
||||||
- [fake-user](#fake-user)
|
- [fake-user](#fake-user)
|
||||||
- [overpassUrl](#overpassUrl)
|
- [overpassUrl](#overpassurl)
|
||||||
- [overpassTimeout](#overpassTimeout)
|
- [overpassTimeout](#overpasstimeout)
|
||||||
- [overpassMaxZoom](#overpassMaxZoom)
|
- [overpassMaxZoom](#overpassmaxzoom)
|
||||||
- [osmApiTileSize](#osmApiTileSize)
|
- [osmApiTileSize](#osmapitilesize)
|
||||||
- [background](#background)
|
- [background](#background)
|
||||||
- [layer-<layer-id>](#layer-<layer-id>)
|
- [layer-<layer-id>](#layer-<layer-id>)
|
||||||
|
|
||||||
|
|
|
@ -485,7 +485,6 @@ export default class SimpleMetaTagger {
|
||||||
public static HelpText(): BaseUIElement {
|
public static HelpText(): BaseUIElement {
|
||||||
const subElements: (string | BaseUIElement)[] = [
|
const subElements: (string | BaseUIElement)[] = [
|
||||||
new Combine([
|
new Combine([
|
||||||
new Title("Metatags", 1),
|
|
||||||
"Metatags are extra tags available, in order to display more data or to give better questions.",
|
"Metatags are extra tags available, in order to display more data or to give better questions.",
|
||||||
"The are calculated automatically on every feature when the data arrives in the webbrowser. This document gives an overview of the available metatags.",
|
"The are calculated automatically on every feature when the data arrives in the webbrowser. This document gives an overview of the available metatags.",
|
||||||
"**Hint:** when using metatags, add the [query parameter](URL_Parameters.md) `debug=true` to the URL. This will include a box in the popup for features which shows all the properties of the object"
|
"**Hint:** when using metatags, add the [query parameter](URL_Parameters.md) `debug=true` to the URL. This will include a box in the popup for features which shows all the properties of the object"
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
import {UIEventSource} from "../UIEventSource";
|
import {UIEventSource} from "../UIEventSource";
|
||||||
import Hash from "./Hash";
|
import Hash from "./Hash";
|
||||||
import {Utils} from "../../Utils";
|
import {Utils} from "../../Utils";
|
||||||
import Title from "../../UI/Base/Title";
|
|
||||||
import Combine from "../../UI/Base/Combine";
|
|
||||||
|
|
||||||
export class QueryParameters {
|
export class QueryParameters {
|
||||||
|
|
||||||
|
@ -13,29 +11,11 @@ export class QueryParameters {
|
||||||
private static _wasInitialized: Set<string> = new Set()
|
private static _wasInitialized: Set<string> = new Set()
|
||||||
private static knownSources = {};
|
private static knownSources = {};
|
||||||
private static initialized = false;
|
private static initialized = false;
|
||||||
private static defaults = {}
|
static defaults = {}
|
||||||
|
|
||||||
|
static documentation = {}
|
||||||
|
|
||||||
|
|
||||||
private static documentation = {}
|
|
||||||
private static QueryParamDocsIntro = "\n" +
|
|
||||||
"URL-parameters and URL-hash\n" +
|
|
||||||
"============================\n" +
|
|
||||||
"\n" +
|
|
||||||
"This document gives an overview of which URL-parameters can be used to influence MapComplete.\n" +
|
|
||||||
"\n" +
|
|
||||||
"What is a URL parameter?\n" +
|
|
||||||
"------------------------\n" +
|
|
||||||
"\n" +
|
|
||||||
"URL-parameters are extra parts of the URL used to set the state.\n" +
|
|
||||||
"\n" +
|
|
||||||
"For example, if the url is `https://mapcomplete.osm.be/cyclofix?lat=51.0&lon=4.3&z=5&test=true#node/1234`,\n" +
|
|
||||||
"the URL-parameters are stated in the part between the `?` and the `#`. There are multiple, all separated by `&`, namely:\n" +
|
|
||||||
"\n" +
|
|
||||||
"- The url-parameter `lat` is `51.0` in this instance\n" +
|
|
||||||
"- The url-parameter `lon` is `4.3` in this instance\n" +
|
|
||||||
"- The url-parameter `z` is `5` in this instance\n" +
|
|
||||||
"- The url-parameter `test` is `true` in this instance\n" +
|
|
||||||
"\n" +
|
|
||||||
"Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case."
|
|
||||||
|
|
||||||
public static GetQueryParameter(key: string, deflt: string, documentation?: string): UIEventSource<string> {
|
public static GetQueryParameter(key: string, deflt: string, documentation?: string): UIEventSource<string> {
|
||||||
if (!this.initialized) {
|
if (!this.initialized) {
|
||||||
|
@ -59,19 +39,7 @@ export class QueryParameters {
|
||||||
return QueryParameters.GetQueryParameter(key, deflt, documentation).map(str => str === "true", [], b => "" + b)
|
return QueryParameters.GetQueryParameter(key, deflt, documentation).map(str => str === "true", [], b => "" + b)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static GenerateQueryParameterDocs(): string {
|
|
||||||
const docs = [QueryParameters.QueryParamDocsIntro];
|
|
||||||
for (const key in QueryParameters.documentation) {
|
|
||||||
const c = new Combine([
|
|
||||||
new Title(key, 2),
|
|
||||||
QueryParameters.documentation[key],
|
|
||||||
QueryParameters.defaults[key] === undefined ? "No default value set" : `The default value is _${QueryParameters.defaults[key]}_`
|
|
||||||
|
|
||||||
])
|
|
||||||
docs.push(c.AsMarkdown())
|
|
||||||
}
|
|
||||||
return docs.join("\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static wasInitialized(key: string): boolean {
|
public static wasInitialized(key: string): boolean {
|
||||||
return QueryParameters._wasInitialized.has(key)
|
return QueryParameters._wasInitialized.has(key)
|
||||||
|
@ -108,9 +76,6 @@ export class QueryParameters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window["mapcomplete_query_parameter_overview"] = () => {
|
|
||||||
console.log(QueryParameters.GenerateQueryParameterDocs())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Serialize() {
|
private static Serialize() {
|
||||||
|
|
|
@ -47,18 +47,10 @@ export default class Combine extends BaseUIElement {
|
||||||
return el;
|
return el;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getToC(): Title[]{
|
public getElements(): BaseUIElement[]{
|
||||||
const titles = []
|
return this.uiElements
|
||||||
for (const uiElement of this.uiElements) {
|
|
||||||
if(uiElement instanceof Combine){
|
|
||||||
titles.push(...uiElement.getToC())
|
|
||||||
}else if(uiElement instanceof Title){
|
|
||||||
titles.push(uiElement)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return titles
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,25 +1,26 @@
|
||||||
import BaseUIElement from "../BaseUIElement";
|
import BaseUIElement from "../BaseUIElement";
|
||||||
|
|
||||||
export class FixedUiElement extends BaseUIElement {
|
export class FixedUiElement extends BaseUIElement {
|
||||||
private _html: string;
|
public readonly content: string;
|
||||||
|
|
||||||
constructor(html: string) {
|
constructor(html: string) {
|
||||||
super();
|
super();
|
||||||
this._html = html ?? "";
|
this.content = html ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
InnerRender(): string {
|
InnerRender(): string {
|
||||||
return this._html;
|
return this.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsMarkdown(): string {
|
AsMarkdown(): string {
|
||||||
return this._html;
|
return this.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected InnerConstructElement(): HTMLElement {
|
protected InnerConstructElement(): HTMLElement {
|
||||||
const e = document.createElement("span")
|
const e = document.createElement("span")
|
||||||
e.innerHTML = this._html
|
e.innerHTML = this.content
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
|
@ -10,7 +10,7 @@ export default class List extends BaseUIElement {
|
||||||
super();
|
super();
|
||||||
this._ordered = ordered;
|
this._ordered = ordered;
|
||||||
this.uiElements = Utils.NoNull(uiElements)
|
this.uiElements = Utils.NoNull(uiElements)
|
||||||
.map(Translations.W);
|
.map(s => Translations.W(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
AsMarkdown(): string {
|
AsMarkdown(): string {
|
||||||
|
|
123
UI/Base/TableOfContents.ts
Normal file
123
UI/Base/TableOfContents.ts
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
import Combine from "./Combine";
|
||||||
|
import BaseUIElement from "../BaseUIElement";
|
||||||
|
import {Translation} from "../i18n/Translation";
|
||||||
|
import {FixedUiElement} from "./FixedUiElement";
|
||||||
|
import Title from "./Title";
|
||||||
|
import List from "./List";
|
||||||
|
import Hash from "../../Logic/Web/Hash";
|
||||||
|
import Link from "./Link";
|
||||||
|
import {Utils} from "../../Utils";
|
||||||
|
|
||||||
|
export default class TableOfContents extends Combine {
|
||||||
|
|
||||||
|
private readonly titles: Title[]
|
||||||
|
|
||||||
|
constructor(elements: Combine | Title[], options?: {
|
||||||
|
noTopLevel: false | boolean,
|
||||||
|
maxDepth?: number
|
||||||
|
}) {
|
||||||
|
let titles: Title[]
|
||||||
|
if (elements instanceof Combine) {
|
||||||
|
titles = TableOfContents.getTitles(elements.getElements())
|
||||||
|
} else {
|
||||||
|
titles = elements
|
||||||
|
}
|
||||||
|
|
||||||
|
let els: { level: number, content: BaseUIElement }[] = []
|
||||||
|
for (const title of titles) {
|
||||||
|
let content: BaseUIElement
|
||||||
|
if (title.title instanceof Translation) {
|
||||||
|
content = title.title.Clone()
|
||||||
|
}else if(title.title instanceof FixedUiElement){
|
||||||
|
content = title.title
|
||||||
|
}else if(Utils.runningFromConsole){
|
||||||
|
content = new FixedUiElement(title.AsMarkdown())
|
||||||
|
} else {
|
||||||
|
content = new FixedUiElement(title.title.ConstructElement().innerText)
|
||||||
|
}
|
||||||
|
|
||||||
|
const vis = new Link(content, "#" + title.id)
|
||||||
|
|
||||||
|
Hash.hash.addCallbackAndRun(h => {
|
||||||
|
if (h === title.id) {
|
||||||
|
vis.SetClass("font-bold")
|
||||||
|
} else {
|
||||||
|
vis.RemoveClass("font-bold")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
els.push({level: title.level, content: vis})
|
||||||
|
|
||||||
|
}
|
||||||
|
const minLevel = Math.min(...els.map(e => e.level))
|
||||||
|
if (options?.noTopLevel) {
|
||||||
|
els = els.filter(e => e.level !== minLevel )
|
||||||
|
}
|
||||||
|
|
||||||
|
if(options?.maxDepth){
|
||||||
|
els = els.filter(e => e.level <= (options.maxDepth + minLevel))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
super(TableOfContents.mergeLevel(els).map(el => el.SetClass("mt-2")));
|
||||||
|
this.SetClass("flex flex-col")
|
||||||
|
this.titles = titles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static getTitles(elements: BaseUIElement[]): Title[]{
|
||||||
|
const titles = []
|
||||||
|
for (const uiElement of elements){
|
||||||
|
if(uiElement instanceof Combine){
|
||||||
|
titles.push(...TableOfContents.getTitles(uiElement.getElements()))
|
||||||
|
}else if(uiElement instanceof Title){
|
||||||
|
titles.push(uiElement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return titles
|
||||||
|
}
|
||||||
|
|
||||||
|
private static mergeLevel(elements: { level: number, content: BaseUIElement }[]): BaseUIElement[] {
|
||||||
|
const maxLevel = Math.max(...elements.map(e => e.level))
|
||||||
|
const minLevel = Math.min(...elements.map(e => e.level))
|
||||||
|
if (maxLevel === minLevel) {
|
||||||
|
return elements.map(e => e.content)
|
||||||
|
}
|
||||||
|
const result: { level: number, content: BaseUIElement } [] = []
|
||||||
|
let running: BaseUIElement[] = []
|
||||||
|
for (const element of elements) {
|
||||||
|
if (element.level === maxLevel) {
|
||||||
|
running.push(element.content)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (running.length !== undefined) {
|
||||||
|
result.push({
|
||||||
|
content: new List(running),
|
||||||
|
level: maxLevel - 1
|
||||||
|
})
|
||||||
|
running = []
|
||||||
|
}
|
||||||
|
result.push(element)
|
||||||
|
}
|
||||||
|
if (running.length !== undefined) {
|
||||||
|
result.push({
|
||||||
|
content: new List(running),
|
||||||
|
level: maxLevel - 1
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return TableOfContents.mergeLevel(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
AsMarkdown(): string {
|
||||||
|
const depthIcons = ["1."," -"," +"," *"]
|
||||||
|
const lines = ["## Table of contents\n"];
|
||||||
|
const minLevel = Math.min(...this.titles.map(t => t.level))
|
||||||
|
for (const title of this.titles) {
|
||||||
|
const prefix = depthIcons[title.level - minLevel] ?? " ~"
|
||||||
|
const text = title.title.AsMarkdown().replace("\n","")
|
||||||
|
const link = title.id
|
||||||
|
lines.push(prefix + " ["+text+"](#"+link+")")
|
||||||
|
}
|
||||||
|
|
||||||
|
return lines.join("\n")+"\n\n"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,5 @@
|
||||||
import BaseUIElement from "../BaseUIElement";
|
import BaseUIElement from "../BaseUIElement";
|
||||||
import {FixedUiElement} from "./FixedUiElement";
|
import {FixedUiElement} from "./FixedUiElement";
|
||||||
import Hash from "../../Logic/Web/Hash";
|
|
||||||
|
|
||||||
export default class Title extends BaseUIElement {
|
export default class Title extends BaseUIElement {
|
||||||
public readonly title: BaseUIElement;
|
public readonly title: BaseUIElement;
|
||||||
|
@ -17,7 +16,19 @@ export default class Title extends BaseUIElement {
|
||||||
this.title = embedded
|
this.title = embedded
|
||||||
}
|
}
|
||||||
this.level = level;
|
this.level = level;
|
||||||
this.id = this.title.ConstructElement()?.innerText?.replace(/ /g, '_') ?? ""
|
|
||||||
|
let innerText : string = undefined;
|
||||||
|
if(typeof embedded === "string" ) {
|
||||||
|
innerText = embedded
|
||||||
|
}else if(embedded instanceof FixedUiElement){
|
||||||
|
innerText = embedded.content
|
||||||
|
}else{
|
||||||
|
this.title.ConstructElement()?.innerText
|
||||||
|
}
|
||||||
|
|
||||||
|
this.id = innerText?.replace(/ /g, '-')
|
||||||
|
?.replace(/[?#.;:/]/, "")
|
||||||
|
?.toLowerCase() ?? ""
|
||||||
this.SetClass(Title.defaultClassesPerLevel[level] ?? "")
|
this.SetClass(Title.defaultClassesPerLevel[level] ?? "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -553,13 +553,15 @@ export default class ValidatedTextField {
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static HelpText(): string {
|
public static HelpText(): BaseUIElement {
|
||||||
const explanations = ValidatedTextField.tpList.map(type => ["## " + type.name, "", type.explanation].join("\n")).join("\n\n")
|
const explanations : BaseUIElement[]=
|
||||||
|
ValidatedTextField.tpList.map(type =>
|
||||||
|
new Combine([new Title(type.name,3), type.explanation]).SetClass("flex flex-col"))
|
||||||
return new Combine([
|
return new Combine([
|
||||||
new Title("Available types for text fields", 1),
|
new Title("Available types for text fields", 1),
|
||||||
"The listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them",
|
"The listed types here trigger a special input element. Use them in `tagrendering.freeform.type` of your tagrendering to activate them",
|
||||||
explanations
|
...explanations
|
||||||
]).SetClass("flex flex-col").AsMarkdown()
|
]).SetClass("flex flex-col")
|
||||||
}
|
}
|
||||||
|
|
||||||
private static tp(name: string,
|
private static tp(name: string,
|
||||||
|
|
|
@ -5,97 +5,10 @@ import Title from "./Base/Title";
|
||||||
import Toggleable, {Accordeon} from "./Base/Toggleable";
|
import Toggleable, {Accordeon} from "./Base/Toggleable";
|
||||||
import List from "./Base/List";
|
import List from "./Base/List";
|
||||||
import BaseUIElement from "./BaseUIElement";
|
import BaseUIElement from "./BaseUIElement";
|
||||||
import Link from "./Base/Link";
|
|
||||||
import LanguagePicker from "./LanguagePicker";
|
import LanguagePicker from "./LanguagePicker";
|
||||||
import Hash from "../Logic/Web/Hash";
|
|
||||||
import {Translation} from "./i18n/Translation";
|
|
||||||
import {SubtleButton} from "./Base/SubtleButton";
|
import {SubtleButton} from "./Base/SubtleButton";
|
||||||
import Svg from "../Svg";
|
import Svg from "../Svg";
|
||||||
|
import TableOfContents from "./Base/TableOfContents";
|
||||||
class TableOfContents extends Combine {
|
|
||||||
|
|
||||||
private readonly titles: Title[]
|
|
||||||
|
|
||||||
constructor(elements: Combine | Title[], options: {
|
|
||||||
noTopLevel: false | boolean,
|
|
||||||
maxDepth?: number
|
|
||||||
}) {
|
|
||||||
let titles: Title[]
|
|
||||||
if (elements instanceof Combine) {
|
|
||||||
titles = elements.getToC()
|
|
||||||
} else {
|
|
||||||
titles = elements
|
|
||||||
}
|
|
||||||
|
|
||||||
let els: { level: number, content: BaseUIElement }[] = []
|
|
||||||
for (const title of titles) {
|
|
||||||
let content: BaseUIElement
|
|
||||||
if (title.title instanceof Translation) {
|
|
||||||
content = title.title.Clone()
|
|
||||||
} else {
|
|
||||||
content = new FixedUiElement(title.title.ConstructElement().innerText)
|
|
||||||
}
|
|
||||||
|
|
||||||
const vis = new Link(content, "#" + title.id)
|
|
||||||
|
|
||||||
Hash.hash.addCallbackAndRun(h => {
|
|
||||||
if (h === title.id) {
|
|
||||||
vis.SetClass("font-bold")
|
|
||||||
} else {
|
|
||||||
vis.RemoveClass("font-bold")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
els.push({level: title.level, content: vis})
|
|
||||||
|
|
||||||
}
|
|
||||||
if (options.noTopLevel) {
|
|
||||||
const minLevel = Math.min(...els.map(e => e.level))
|
|
||||||
els = els.filter(e => e.level !== minLevel && e.level <= (options.maxDepth + minLevel))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
super(TableOfContents.mergeLevel(els).map(el => el.SetClass("mt-2")));
|
|
||||||
this.SetClass("flex flex-col")
|
|
||||||
this.titles = titles;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static mergeLevel(elements: { level: number, content: BaseUIElement }[]): BaseUIElement[] {
|
|
||||||
const maxLevel = Math.max(...elements.map(e => e.level))
|
|
||||||
const minLevel = Math.min(...elements.map(e => e.level))
|
|
||||||
if (maxLevel === minLevel) {
|
|
||||||
return elements.map(e => e.content)
|
|
||||||
}
|
|
||||||
const result: { level: number, content: BaseUIElement } [] = []
|
|
||||||
let running: BaseUIElement[] = []
|
|
||||||
for (const element of elements) {
|
|
||||||
if (element.level === maxLevel) {
|
|
||||||
running.push(element.content)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if (running.length !== undefined) {
|
|
||||||
result.push({
|
|
||||||
content: new List(running),
|
|
||||||
level: maxLevel - 1
|
|
||||||
})
|
|
||||||
running = []
|
|
||||||
}
|
|
||||||
result.push(element)
|
|
||||||
}
|
|
||||||
if (running.length !== undefined) {
|
|
||||||
result.push({
|
|
||||||
content: new List(running),
|
|
||||||
level: maxLevel - 1
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return TableOfContents.mergeLevel(result)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
AsMarkdown(): string {
|
|
||||||
return super.AsMarkdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Snippet extends Toggleable {
|
class Snippet extends Toggleable {
|
||||||
constructor(translations, ...extraContent: BaseUIElement[]) {
|
constructor(translations, ...extraContent: BaseUIElement[]) {
|
||||||
|
|
40
UI/QueryParameterDocumentation.ts
Normal file
40
UI/QueryParameterDocumentation.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import BaseUIElement from "./BaseUIElement";
|
||||||
|
import Combine from "./Base/Combine";
|
||||||
|
import Title from "./Base/Title";
|
||||||
|
import List from "./Base/List";
|
||||||
|
import Translations from "./i18n/Translations";
|
||||||
|
import {QueryParameters} from "../Logic/Web/QueryParameters";
|
||||||
|
|
||||||
|
export default class QueryParameterDocumentation {
|
||||||
|
|
||||||
|
private static QueryParamDocsIntro = ([
|
||||||
|
new Title("URL-parameters and URL-hash", 1),
|
||||||
|
"This document gives an overview of which URL-parameters can be used to influence MapComplete.",
|
||||||
|
new Title("What is a URL parameter?", 2),
|
||||||
|
"\"URL-parameters are extra parts of the URL used to set the state.",
|
||||||
|
"For example, if the url is `https://mapcomplete.osm.be/cyclofix?lat=51.0&lon=4.3&z=5&test=true#node/1234`, " +
|
||||||
|
"the URL-parameters are stated in the part between the `?` and the `#`. There are multiple, all separated by `&`, namely: ",
|
||||||
|
new List([
|
||||||
|
"The url-parameter `lat` is `51.0` in this instance",
|
||||||
|
"The url-parameter `lon` is `4.3` in this instance",
|
||||||
|
"The url-parameter `z` is `5` in this instance",
|
||||||
|
"The url-parameter `test` is `true` in this instance"
|
||||||
|
].map(s => Translations.W(s))
|
||||||
|
),
|
||||||
|
"Finally, the URL-hash is the part after the `#`. It is `node/1234` in this case."
|
||||||
|
])
|
||||||
|
|
||||||
|
public static GenerateQueryParameterDocs(): BaseUIElement {
|
||||||
|
const docs : (string | BaseUIElement)[] = [...QueryParameterDocumentation.QueryParamDocsIntro];
|
||||||
|
for (const key in QueryParameters.documentation) {
|
||||||
|
const c = new Combine([
|
||||||
|
new Title(key, 2),
|
||||||
|
QueryParameters.documentation[key],
|
||||||
|
QueryParameters.defaults[key] === undefined ? "No default value set" : `The default value is _${QueryParameters.defaults[key]}_`
|
||||||
|
|
||||||
|
])
|
||||||
|
docs.push(c)
|
||||||
|
}
|
||||||
|
return new Combine(docs).SetClass("flex flex-col")
|
||||||
|
}
|
||||||
|
}
|
|
@ -698,16 +698,10 @@ export default class SpecialVisualizations {
|
||||||
]
|
]
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
const toc = new List(
|
|
||||||
SpecialVisualizations.specialVisualizations.map(viz => new Link(viz.funcName, "#" + viz.funcName))
|
|
||||||
)
|
|
||||||
|
|
||||||
return new Combine([
|
return new Combine([
|
||||||
new Title("Special tag renderings", 3),
|
new Title("Special tag renderings", 1),
|
||||||
"In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's.",
|
"In a tagrendering, some special values are substituted by an advanced UI-element. This allows advanced features and visualizations to be reused by custom themes or even to query third-party API's.",
|
||||||
"General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args",
|
"General usage is `{func_name()}`, `{func_name(arg, someotherarg)}` or `{func_name(args):cssStyle}`. Note that you _do not_ need to use quotes around your arguments, the comma is enough to separate them. This also implies you cannot use a comma in your args",
|
||||||
toc,
|
|
||||||
...helpTexts
|
...helpTexts
|
||||||
]
|
]
|
||||||
).SetClass("flex flex-col");
|
).SetClass("flex flex-col");
|
||||||
|
|
2
index.ts
2
index.ts
|
@ -15,8 +15,6 @@ import AvailableBaseLayersImplementation from "./Logic/Actors/AvailableBaseLayer
|
||||||
import ShowOverlayLayerImplementation from "./UI/ShowDataLayer/ShowOverlayLayerImplementation";
|
import ShowOverlayLayerImplementation from "./UI/ShowDataLayer/ShowOverlayLayerImplementation";
|
||||||
import {DefaultGuiState} from "./UI/DefaultGuiState";
|
import {DefaultGuiState} from "./UI/DefaultGuiState";
|
||||||
import {Browser} from "leaflet";
|
import {Browser} from "leaflet";
|
||||||
import win = Browser.win;
|
|
||||||
import ProfessionalGui from "./UI/ProfessionalGui";
|
|
||||||
|
|
||||||
// Workaround for a stupid crash: inject some functions which would give stupid circular dependencies or crash the other nodejs scripts running from console
|
// Workaround for a stupid crash: inject some functions which would give stupid circular dependencies or crash the other nodejs scripts running from console
|
||||||
MinimapImplementation.initialize()
|
MinimapImplementation.initialize()
|
||||||
|
|
|
@ -11,20 +11,35 @@ import {QueryParameters} from "../Logic/Web/QueryParameters";
|
||||||
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig";
|
import LayoutConfig from "../Models/ThemeConfig/LayoutConfig";
|
||||||
import Minimap from "../UI/Base/Minimap";
|
import Minimap from "../UI/Base/Minimap";
|
||||||
import FeatureSwitchState from "../Logic/State/FeatureSwitchState";
|
import FeatureSwitchState from "../Logic/State/FeatureSwitchState";
|
||||||
import AllKnownLayers from "../Customizations/AllKnownLayers";
|
|
||||||
import {AllKnownLayouts} from "../Customizations/AllKnownLayouts";
|
import {AllKnownLayouts} from "../Customizations/AllKnownLayouts";
|
||||||
|
import TableOfContents from "../UI/Base/TableOfContents";
|
||||||
|
import Title from "../UI/Base/Title";
|
||||||
|
import QueryParameterDocumentation from "../UI/QueryParameterDocumentation";
|
||||||
|
|
||||||
Utils.runningFromConsole = true;
|
Utils.runningFromConsole = true;
|
||||||
|
|
||||||
|
|
||||||
function WriteFile(filename, html: string | BaseUIElement, autogenSource: string[]): void {
|
function WriteFile(filename, html: BaseUIElement, autogenSource: string[]): void {
|
||||||
|
|
||||||
|
if (html instanceof Combine) {
|
||||||
|
|
||||||
|
const toc = new TableOfContents(html);
|
||||||
|
const els = html.getElements();
|
||||||
|
html = new Combine(
|
||||||
|
[els.shift(),
|
||||||
|
toc,
|
||||||
|
...els
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
writeFileSync(filename, new Combine([Translations.W(html),
|
writeFileSync(filename, new Combine([Translations.W(html),
|
||||||
"\n\nThis document is autogenerated from " + autogenSource.join(", ")
|
"\n\nThis document is autogenerated from " + autogenSource.join(", ")
|
||||||
]).AsMarkdown());
|
]).AsMarkdown());
|
||||||
}
|
}
|
||||||
|
|
||||||
WriteFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), ["UI/SpecialVisualisations.ts"])
|
WriteFile("./Docs/SpecialRenderings.md", SpecialVisualizations.HelpMessage(), ["UI/SpecialVisualisations.ts"])
|
||||||
WriteFile("./Docs/CalculatedTags.md", new Combine([SimpleMetaTagger.HelpText(), ExtraFunction.HelpText()]).SetClass("flex-col"),
|
WriteFile("./Docs/CalculatedTags.md", new Combine([new Title("Metatags", 1), SimpleMetaTagger.HelpText(), ExtraFunction.HelpText()]).SetClass("flex-col"),
|
||||||
["SimpleMetaTagger", "ExtraFunction"])
|
["SimpleMetaTagger", "ExtraFunction"])
|
||||||
WriteFile("./Docs/SpecialInputElements.md", ValidatedTextField.HelpText(), ["ValidatedTextField.ts"]);
|
WriteFile("./Docs/SpecialInputElements.md", ValidatedTextField.HelpText(), ["ValidatedTextField.ts"]);
|
||||||
WriteFile("./Docs/BuiltinLayers.md", AllKnownLayouts.GenLayerOverviewText(), ["AllKnownLayers.ts"])
|
WriteFile("./Docs/BuiltinLayers.md", AllKnownLayouts.GenLayerOverviewText(), ["AllKnownLayers.ts"])
|
||||||
|
@ -52,7 +67,7 @@ const dummyLayout = new LayoutConfig({
|
||||||
source: {
|
source: {
|
||||||
osmTags: "id~*"
|
osmTags: "id~*"
|
||||||
},
|
},
|
||||||
mapRendering: []
|
mapRendering: null,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -62,7 +77,7 @@ new FeatureSwitchState(dummyLayout)
|
||||||
|
|
||||||
QueryParameters.GetQueryParameter("layer-<layer-id>", "true", "Wether or not the layer with id <layer-id> is shown")
|
QueryParameters.GetQueryParameter("layer-<layer-id>", "true", "Wether or not the layer with id <layer-id> is shown")
|
||||||
|
|
||||||
WriteFile("./Docs/URL_Parameters.md", QueryParameters.GenerateQueryParameterDocs(), ["QueryParameters"])
|
WriteFile("./Docs/URL_Parameters.md", QueryParameterDocumentation.GenerateQueryParameterDocs(), ["QueryParameters"])
|
||||||
|
|
||||||
console.log("Generated docs")
|
console.log("Generated docs")
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue