├── .github └── workflows │ └── nodejs.yml ├── .gitignore ├── CHANGELOG.md ├── CNAME ├── LICENSE ├── README.md ├── biome.json ├── docs ├── .nojekyll ├── CNAME ├── assets │ ├── highlight.css │ ├── main.js │ ├── search.js │ └── style.css ├── functions │ ├── foldersToKML.html │ └── toKML.html ├── index.html └── modules.html ├── lib └── index.ts ├── mise.toml ├── package.json ├── pnpm-lock.yaml ├── rollup.config.mjs ├── test └── index.test.ts ├── tsconfig.json └── typedoc.json /.github/workflows/nodejs.yml: -------------------------------------------------------------------------------- 1 | name: Test 2 | on: 3 | push: 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-22.04 8 | strategy: 9 | matrix: 10 | node-version: [22] 11 | steps: 12 | - uses: actions/checkout@v4 13 | - name: Install pnpm 14 | uses: pnpm/action-setup@v4 15 | with: 16 | version: 9 17 | - name: Use Node.js ${{ matrix.node-version }} 18 | uses: actions/setup-node@v4 19 | with: 20 | node-version: ${{ matrix.node-version }} 21 | cache: 'pnpm' 22 | - name: Install dependencies 23 | run: pnpm install 24 | - name: Lint 25 | run: pnpm lint 26 | - name: Lint 27 | run: pnpm test 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | yarn-error.log 5 | index.js 6 | dist 7 | index.test.js 8 | index.test.d.ts 9 | index.d.ts 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [0.3.3](https://github.com/placemark/tokml/compare/v0.3.2...v0.3.3) (2022-08-09) 6 | 7 | ### [0.3.2](https://github.com/placemark/tokml/compare/v0.3.1...v0.3.2) (2022-06-12) 8 | 9 | 10 | ### Features 11 | 12 | * Round-trip type: html values ([#21](https://github.com/placemark/tokml/issues/21)) ([1ee571d](https://github.com/placemark/tokml/commit/1ee571dfa659c5b250eb95c224c96fe2eb743f56)) 13 | 14 | ### [0.3.2-0](https://github.com/placemark/tokml/compare/v0.3.1...v0.3.2-0) (2022-06-12) 15 | 16 | 17 | ### Features 18 | 19 | * Round-trip @\type: html values ([b467ab8](https://github.com/placemark/tokml/commit/b467ab84ff6efa483b994144f323537d94a1bbd2)) 20 | 21 | ### [0.3.1](https://github.com/placemark/tokml/compare/v0.3.0...v0.3.1) (2022-05-23) 22 | 23 | ## [0.3.0](https://github.com/placemark/tokml/compare/v0.3.0-2...v0.3.0) (2022-05-01) 24 | 25 | 26 | ### Features 27 | 28 | * Include Feature ID in exports ([#18](https://github.com/placemark/tokml/issues/18)) ([59717dc](https://github.com/placemark/tokml/commit/59717dc5a8545ad14d048b39114414591c37a48e)) 29 | 30 | ## [0.3.0-2](https://github.com/placemark/tokml/compare/v0.3.0-1...v0.3.0-2) (2022-03-15) 31 | 32 | ## [0.3.0-1](https://github.com/placemark/tokml/compare/v0.2.2...v0.3.0-1) (2022-03-15) 33 | 34 | 35 | ### Features 36 | 37 | * Indent and line-break generated XML ([#13](https://github.com/placemark/tokml/issues/13)) ([e9dd76a](https://github.com/placemark/tokml/commit/e9dd76adc39287d1c67bb36154512b61f3c2a434)) 38 | 39 | 40 | ### Bug Fixes 41 | 42 | * Fix test path ([bd15b59](https://github.com/placemark/tokml/commit/bd15b594b03be6fe516a0a83c4b6cf5a84a697eb)) 43 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | tokml.docs.placemark.io 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Placemark 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tokml 2 | 3 | Convert GeoJSON to KML. 4 | 5 | ## Install 6 | 7 | This package is [`@placemarkio/tokml`](https://www.npmjs.com/package/@placemarkio/tokml) 8 | 9 | ## [📕 API Documentation](http://tokml.docs.placemark.io/) 10 | 11 | Notes: 12 | 13 | - This method does not validate the GeoJSON inputs. Invalid FeatureCollections 14 | may produce an exception. 15 | - GeoJSON properties can have any kind of value, including objects and arrays. 16 | KML properties are strings. Any non-string GeoJSON properties will be stringified 17 | with JSON.stringify when converting to KML. 18 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", 3 | "vcs": { 4 | "enabled": false, 5 | "clientKind": "git", 6 | "useIgnoreFile": false 7 | }, 8 | "files": { 9 | "ignoreUnknown": false, 10 | "ignore": [], 11 | "include": ["lib"] 12 | }, 13 | "formatter": { 14 | "enabled": true, 15 | "indentStyle": "tab" 16 | }, 17 | "organizeImports": { 18 | "enabled": true 19 | }, 20 | "linter": { 21 | "enabled": true, 22 | "rules": { 23 | "recommended": true, 24 | "suspicious": { 25 | "noExplicitAny": "off" 26 | } 27 | } 28 | }, 29 | "javascript": { 30 | "formatter": { 31 | "quoteStyle": "double" 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | tokml.docs.placemark.io 2 | -------------------------------------------------------------------------------- /docs/assets/highlight.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --light-code-background: #FFFFFF; 3 | --dark-code-background: #1E1E1E; 4 | } 5 | 6 | @media (prefers-color-scheme: light) { :root { 7 | --code-background: var(--light-code-background); 8 | } } 9 | 10 | @media (prefers-color-scheme: dark) { :root { 11 | --code-background: var(--dark-code-background); 12 | } } 13 | 14 | :root[data-theme='light'] { 15 | --code-background: var(--light-code-background); 16 | } 17 | 18 | :root[data-theme='dark'] { 19 | --code-background: var(--dark-code-background); 20 | } 21 | 22 | pre, code { background: var(--code-background); } 23 | -------------------------------------------------------------------------------- /docs/assets/main.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | "use strict";(()=>{var Qe=Object.create;var ae=Object.defineProperty;var Pe=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var Oe=Object.getPrototypeOf,Re=Object.prototype.hasOwnProperty;var _e=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Me=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ce(e))!Re.call(t,i)&&i!==n&&ae(t,i,{get:()=>e[i],enumerable:!(r=Pe(e,i))||r.enumerable});return t};var De=(t,e,n)=>(n=t!=null?Qe(Oe(t)):{},Me(e||!t||!t.__esModule?ae(n,"default",{value:t,enumerable:!0}):n,t));var de=_e((ce,he)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var h=t.utils.clone(n)||{};h.position=[a,l],h.index=s.length,s.push(new t.Token(r.slice(a,o),h))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. 3 | `,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ou?h+=2:a==u&&(n+=r[l+1]*i[h+1],l+=2,h+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}if(s.str.length==0&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}s.str.length==1&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var h=s.str.charAt(0),m=s.str.charAt(1),v;m in s.node.edges?v=s.node.edges[m]:(v=new t.TokenSet,s.node.edges[m]=v),s.str.length==1&&(v.final=!0),i.push({node:v,editsRemaining:s.editsRemaining-1,str:h+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),u=0;u1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof ce=="object"?he.exports=n():e.lunr=n()}(this,function(){return t})})()});var le=[];function j(t,e){le.push({selector:e,constructor:t})}var Y=class{constructor(){this.createComponents(document.body)}createComponents(e){le.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r}),r.dataset.hasInstance=String(!0))})})}};var k=class{constructor(e){this.el=e.el}};var J=class{constructor(){this.listeners={}}addEventListener(e,n){e in this.listeners||(this.listeners[e]=[]),this.listeners[e].push(n)}removeEventListener(e,n){if(!(e in this.listeners))return;let r=this.listeners[e];for(let i=0,s=r.length;i{let n=Date.now();return(...r)=>{n+e-Date.now()<0&&(t(...r),n=Date.now())}};var re=class extends J{constructor(){super();this.scrollTop=0;this.lastY=0;this.width=0;this.height=0;this.showToolbar=!0;this.toolbar=document.querySelector(".tsd-page-toolbar"),this.navigation=document.querySelector(".col-menu"),window.addEventListener("scroll",ne(()=>this.onScroll(),10)),window.addEventListener("resize",ne(()=>this.onResize(),10)),this.searchInput=document.querySelector("#tsd-search input"),this.searchInput&&this.searchInput.addEventListener("focus",()=>{this.hideShowToolbar()}),this.onResize(),this.onScroll()}triggerResize(){let n=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(n)}onResize(){this.width=window.innerWidth||0,this.height=window.innerHeight||0;let n=new CustomEvent("resize",{detail:{width:this.width,height:this.height}});this.dispatchEvent(n)}onScroll(){this.scrollTop=window.scrollY||0;let n=new CustomEvent("scroll",{detail:{scrollTop:this.scrollTop}});this.dispatchEvent(n),this.hideShowToolbar()}hideShowToolbar(){let n=this.showToolbar;this.showToolbar=this.lastY>=this.scrollTop||this.scrollTop<=0||!!this.searchInput&&this.searchInput===document.activeElement,n!==this.showToolbar&&(this.toolbar.classList.toggle("tsd-page-toolbar--hide"),this.navigation?.classList.toggle("col-menu--hide")),this.lastY=this.scrollTop}},R=re;R.instance=new re;var X=class extends k{constructor(n){super(n);this.anchors=[];this.index=-1;R.instance.addEventListener("resize",()=>this.onResize()),R.instance.addEventListener("scroll",r=>this.onScroll(r)),this.createAnchors()}createAnchors(){let n=window.location.href;n.indexOf("#")!=-1&&(n=n.substring(0,n.indexOf("#"))),this.el.querySelectorAll("a").forEach(r=>{let i=r.href;if(i.indexOf("#")==-1||i.substring(0,n.length)!=n)return;let s=i.substring(i.indexOf("#")+1),o=document.querySelector("a.tsd-anchor[name="+s+"]"),a=r.parentNode;!o||!a||this.anchors.push({link:a,anchor:o,position:0})}),this.onResize()}onResize(){let n;for(let i=0,s=this.anchors.length;ii.position-s.position);let r=new CustomEvent("scroll",{detail:{scrollTop:R.instance.scrollTop}});this.onScroll(r)}onScroll(n){let r=n.detail.scrollTop+5,i=this.anchors,s=i.length-1,o=this.index;for(;o>-1&&i[o].position>r;)o-=1;for(;o-1&&this.anchors[this.index].link.classList.remove("focus"),this.index=o,this.index>-1&&this.anchors[this.index].link.classList.add("focus"))}};var ue=(t,e=100)=>{let n;return(...r)=>{clearTimeout(n),n=setTimeout(()=>t(r),e)}};var me=De(de());function ve(){let t=document.getElementById("tsd-search");if(!t)return;let e=document.getElementById("search-script");t.classList.add("loading"),e&&(e.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),e.addEventListener("load",()=>{t.classList.remove("loading"),t.classList.add("ready")}),window.searchData&&t.classList.remove("loading"));let n=document.querySelector("#tsd-search input"),r=document.querySelector("#tsd-search .results");if(!n||!r)throw new Error("The input field or the result list wrapper was not found");let i=!1;r.addEventListener("mousedown",()=>i=!0),r.addEventListener("mouseup",()=>{i=!1,t.classList.remove("has-focus")}),n.addEventListener("focus",()=>t.classList.add("has-focus")),n.addEventListener("blur",()=>{i||(i=!1,t.classList.remove("has-focus"))});let s={base:t.dataset.base+"/"};Fe(t,r,n,s)}function Fe(t,e,n,r){n.addEventListener("input",ue(()=>{Ae(t,e,n,r)},200));let i=!1;n.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?Ve(e,n):s.key=="Escape"?n.blur():s.key=="ArrowUp"?fe(e,-1):s.key==="ArrowDown"?fe(e,1):i=!1}),n.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!n.matches(":focus")&&s.key==="/"&&(n.focus(),s.preventDefault())})}function He(t,e){t.index||window.searchData&&(e.classList.remove("loading"),e.classList.add("ready"),t.data=window.searchData,t.index=me.Index.load(window.searchData.index))}function Ae(t,e,n,r){if(He(r,t),!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s=i?r.index.search(`*${i}*`):[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o${pe(u.parent,i)}.${l}`);let h=document.createElement("li");h.classList.value=u.classes??"";let m=document.createElement("a");m.href=r.base+u.url,m.innerHTML=l,h.append(m),e.appendChild(h)}}function fe(t,e){let n=t.querySelector(".current");if(!n)n=t.querySelector(e==1?"li:first-child":"li:last-child"),n&&n.classList.add("current");else{let r=n;if(e===1)do r=r.nextElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);else do r=r.previousElementSibling??void 0;while(r instanceof HTMLElement&&r.offsetParent==null);r&&(n.classList.remove("current"),r.classList.add("current"))}}function Ve(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),e.blur()}}function pe(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(ie(t.substring(s,o)),`${ie(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(ie(t.substring(s))),i.join("")}var Ne={"&":"&","<":"<",">":">","'":"'",'"':"""};function ie(t){return t.replace(/[&<>"'"]/g,e=>Ne[e])}var F="mousedown",ye="mousemove",B="mouseup",Z={x:0,y:0},ge=!1,se=!1,je=!1,H=!1,xe=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(xe?"is-mobile":"not-mobile");xe&&"ontouchstart"in document.documentElement&&(je=!0,F="touchstart",ye="touchmove",B="touchend");document.addEventListener(F,t=>{se=!0,H=!1;let e=F=="touchstart"?t.targetTouches[0]:t;Z.y=e.pageY||0,Z.x=e.pageX||0});document.addEventListener(ye,t=>{if(!!se&&!H){let e=F=="touchstart"?t.targetTouches[0]:t,n=Z.x-(e.pageX||0),r=Z.y-(e.pageY||0);H=Math.sqrt(n*n+r*r)>10}});document.addEventListener(B,()=>{se=!1});document.addEventListener("click",t=>{ge&&(t.preventDefault(),t.stopImmediatePropagation(),ge=!1)});var K=class extends k{constructor(n){super(n);this.className=this.el.dataset.toggle||"",this.el.addEventListener(B,r=>this.onPointerUp(r)),this.el.addEventListener("click",r=>r.preventDefault()),document.addEventListener(F,r=>this.onDocumentPointerDown(r)),document.addEventListener(B,r=>this.onDocumentPointerUp(r))}setActive(n){if(this.active==n)return;this.active=n,document.documentElement.classList.toggle("has-"+this.className,n),this.el.classList.toggle("active",n);let r=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(r),setTimeout(()=>document.documentElement.classList.remove(r),500)}onPointerUp(n){H||(this.setActive(!0),n.preventDefault())}onDocumentPointerDown(n){if(this.active){if(n.target.closest(".col-menu, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(n){if(!H&&this.active&&n.target.closest(".col-menu")){let r=n.target.closest("a");if(r){let i=window.location.href;i.indexOf("#")!=-1&&(i=i.substring(0,i.indexOf("#"))),r.href.substring(0,i.length)==i&&setTimeout(()=>this.setActive(!1),250)}}}};var oe;try{oe=localStorage}catch{oe={getItem(){return null},setItem(){}}}var Q=oe;var Le=document.head.appendChild(document.createElement("style"));Le.dataset.for="filters";var ee=class extends k{constructor(n){super(n);this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),Le.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } 4 | `}fromLocalStorage(){let n=Q.getItem(this.key);return n?n==="true":this.el.checked}setLocalStorage(n){Q.setItem(this.key,n.toString()),this.value=n,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),document.querySelectorAll(".tsd-index-section").forEach(n=>{n.style.display="block";let r=Array.from(n.querySelectorAll(".tsd-index-link")).every(i=>i.offsetParent==null);n.style.display=r?"none":"block"})}};var te=class extends k{constructor(n){super(n);this.calculateHeights(),this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.textContent.replace(/\s+/g,"-").toLowerCase()}`,this.setLocalStorage(this.fromLocalStorage(),!0),this.summary.addEventListener("click",r=>this.toggleVisibility(r)),this.icon.style.transform=this.getIconRotation()}getIconRotation(n=this.el.open){return`rotate(${n?0:-90}deg)`}calculateHeights(){let n=this.el.open,{position:r,left:i}=this.el.style;this.el.style.position="fixed",this.el.style.left="-9999px",this.el.open=!0,this.expandedHeight=this.el.offsetHeight+"px",this.el.open=!1,this.collapsedHeight=this.el.offsetHeight+"px",this.el.open=n,this.el.style.height=n?this.expandedHeight:this.collapsedHeight,this.el.style.position=r,this.el.style.left=i}toggleVisibility(n){n.preventDefault(),this.el.style.overflow="hidden",this.el.open?this.collapse():this.expand()}expand(n=!0){this.el.open=!0,this.animate(this.collapsedHeight,this.expandedHeight,{opening:!0,duration:n?300:0})}collapse(n=!0){this.animate(this.expandedHeight,this.collapsedHeight,{opening:!1,duration:n?300:0})}animate(n,r,{opening:i,duration:s=300}){if(this.animation)return;let o={duration:s,easing:"ease"};this.animation=this.el.animate({height:[n,r]},o),this.icon.animate({transform:[this.icon.style.transform||this.getIconRotation(!i),this.getIconRotation(i)]},o).addEventListener("finish",()=>{this.icon.style.transform=this.getIconRotation(i)}),this.animation.addEventListener("finish",()=>this.animationEnd(i))}animationEnd(n){this.el.open=n,this.animation=void 0,this.el.style.height="auto",this.el.style.overflow="visible",this.setLocalStorage(n)}fromLocalStorage(){let n=Q.getItem(this.key);return n?n==="true":this.el.open}setLocalStorage(n,r=!1){this.fromLocalStorage()===n&&!r||(Q.setItem(this.key,n.toString()),this.el.open=n,this.handleValueChange(r))}handleValueChange(n=!1){this.fromLocalStorage()===this.el.open&&!n||(this.fromLocalStorage()?this.expand(!1):this.collapse(!1))}};function be(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,Ee(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),Ee(t.value)})}function Ee(t){document.documentElement.dataset.theme=t}ve();j(X,".menu-highlight");j(K,"a[data-toggle]");j(te,".tsd-index-accordion");j(ee,".tsd-filter-item input[type=checkbox]");var Se=document.getElementById("theme");Se&&be(Se);var Be=new Y;Object.defineProperty(window,"app",{value:Be});})(); 5 | /*! 6 | * lunr.Builder 7 | * Copyright (C) 2020 Oliver Nightingale 8 | */ 9 | /*! 10 | * lunr.Index 11 | * Copyright (C) 2020 Oliver Nightingale 12 | */ 13 | /*! 14 | * lunr.Pipeline 15 | * Copyright (C) 2020 Oliver Nightingale 16 | */ 17 | /*! 18 | * lunr.Set 19 | * Copyright (C) 2020 Oliver Nightingale 20 | */ 21 | /*! 22 | * lunr.TokenSet 23 | * Copyright (C) 2020 Oliver Nightingale 24 | */ 25 | /*! 26 | * lunr.Vector 27 | * Copyright (C) 2020 Oliver Nightingale 28 | */ 29 | /*! 30 | * lunr.stemmer 31 | * Copyright (C) 2020 Oliver Nightingale 32 | * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt 33 | */ 34 | /*! 35 | * lunr.stopWordFilter 36 | * Copyright (C) 2020 Oliver Nightingale 37 | */ 38 | /*! 39 | * lunr.tokenizer 40 | * Copyright (C) 2020 Oliver Nightingale 41 | */ 42 | /*! 43 | * lunr.trimmer 44 | * Copyright (C) 2020 Oliver Nightingale 45 | */ 46 | /*! 47 | * lunr.utils 48 | * Copyright (C) 2020 Oliver Nightingale 49 | */ 50 | /** 51 | * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 52 | * Copyright (C) 2020 Oliver Nightingale 53 | * @license MIT 54 | */ 55 | -------------------------------------------------------------------------------- /docs/assets/search.js: -------------------------------------------------------------------------------- 1 | window.searchData = JSON.parse("{\"kinds\":{\"64\":\"Function\"},\"rows\":[{\"kind\":64,\"name\":\"foldersToKML\",\"url\":\"functions/foldersToKML.html\",\"classes\":\"tsd-kind-function\"},{\"kind\":64,\"name\":\"toKML\",\"url\":\"functions/toKML.html\",\"classes\":\"tsd-kind-function\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,6.931]],[\"comment/0\",[]],[\"name/1\",[1,6.931]],[\"comment/1\",[]]],\"invertedIndex\":[[\"folderstokml\",{\"_index\":0,\"name\":{\"0\":{}},\"comment\":{}}],[\"tokml\",{\"_index\":1,\"name\":{\"1\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); -------------------------------------------------------------------------------- /docs/assets/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* Light */ 3 | --light-color-background: #f2f4f8; 4 | --light-color-background-secondary: #eff0f1; 5 | --light-color-icon-background: var(--light-color-background); 6 | --light-color-accent: #c5c7c9; 7 | --light-color-text: #222; 8 | --light-color-text-aside: #707070; 9 | --light-color-link: #4da6ff; 10 | --light-color-ts: #db1373; 11 | --light-color-ts-interface: #139d2c; 12 | --light-color-ts-enum: #9c891a; 13 | --light-color-ts-class: #2484e5; 14 | --light-color-ts-function: #572be7; 15 | --light-color-ts-namespace: #b111c9; 16 | --light-color-ts-private: #707070; 17 | --light-color-ts-variable: #4d68ff; 18 | --light-external-icon: url("data:image/svg+xml;utf8,"); 19 | --light-color-scheme: light; 20 | 21 | /* Dark */ 22 | --dark-color-background: #2b2e33; 23 | --dark-color-background-secondary: #1e2024; 24 | --dark-color-icon-background: var(--dark-color-background-secondary); 25 | --dark-color-accent: #9096a2; 26 | --dark-color-text: #f5f5f5; 27 | --dark-color-text-aside: #dddddd; 28 | --dark-color-link: #00aff4; 29 | --dark-color-ts: #ff6492; 30 | --dark-color-ts-interface: #6cff87; 31 | --dark-color-ts-enum: #f4d93e; 32 | --dark-color-ts-class: #61b0ff; 33 | --dark-color-ts-function: #9772ff; 34 | --dark-color-ts-namespace: #e14dff; 35 | --dark-color-ts-private: #e2e2e2; 36 | --dark-color-ts-variable: #4d68ff; 37 | --dark-external-icon: url("data:image/svg+xml;utf8,"); 38 | --dark-color-scheme: dark; 39 | } 40 | 41 | @media (prefers-color-scheme: light) { 42 | :root { 43 | --color-background: var(--light-color-background); 44 | --color-background-secondary: var(--light-color-background-secondary); 45 | --color-icon-background: var(--light-color-icon-background); 46 | --color-accent: var(--light-color-accent); 47 | --color-text: var(--light-color-text); 48 | --color-text-aside: var(--light-color-text-aside); 49 | --color-link: var(--light-color-link); 50 | --color-ts: var(--light-color-ts); 51 | --color-ts-interface: var(--light-color-ts-interface); 52 | --color-ts-enum: var(--light-color-ts-enum); 53 | --color-ts-class: var(--light-color-ts-class); 54 | --color-ts-function: var(--light-color-ts-function); 55 | --color-ts-namespace: var(--light-color-ts-namespace); 56 | --color-ts-private: var(--light-color-ts-private); 57 | --color-ts-variable: var(--light-color-ts-variable); 58 | --external-icon: var(--light-external-icon); 59 | --color-scheme: var(--light-color-scheme); 60 | } 61 | } 62 | 63 | @media (prefers-color-scheme: dark) { 64 | :root { 65 | --color-background: var(--dark-color-background); 66 | --color-background-secondary: var(--dark-color-background-secondary); 67 | --color-icon-background: var(--dark-color-icon-background); 68 | --color-accent: var(--dark-color-accent); 69 | --color-text: var(--dark-color-text); 70 | --color-text-aside: var(--dark-color-text-aside); 71 | --color-link: var(--dark-color-link); 72 | --color-ts: var(--dark-color-ts); 73 | --color-ts-interface: var(--dark-color-ts-interface); 74 | --color-ts-enum: var(--dark-color-ts-enum); 75 | --color-ts-class: var(--dark-color-ts-class); 76 | --color-ts-function: var(--dark-color-ts-function); 77 | --color-ts-namespace: var(--dark-color-ts-namespace); 78 | --color-ts-private: var(--dark-color-ts-private); 79 | --color-ts-variable: var(--dark-color-ts-variable); 80 | --external-icon: var(--dark-external-icon); 81 | --color-scheme: var(--dark-color-scheme); 82 | } 83 | } 84 | 85 | html { 86 | color-scheme: var(--color-scheme); 87 | } 88 | 89 | body { 90 | margin: 0; 91 | } 92 | 93 | :root[data-theme="light"] { 94 | --color-background: var(--light-color-background); 95 | --color-background-secondary: var(--light-color-background-secondary); 96 | --color-icon-background: var(--light-color-icon-background); 97 | --color-accent: var(--light-color-accent); 98 | --color-text: var(--light-color-text); 99 | --color-text-aside: var(--light-color-text-aside); 100 | --color-link: var(--light-color-link); 101 | --color-ts: var(--light-color-ts); 102 | --color-ts-interface: var(--light-color-ts-interface); 103 | --color-ts-enum: var(--light-color-ts-enum); 104 | --color-ts-class: var(--light-color-ts-class); 105 | --color-ts-function: var(--light-color-ts-function); 106 | --color-ts-namespace: var(--light-color-ts-namespace); 107 | --color-ts-private: var(--light-color-ts-private); 108 | --color-ts-variable: var(--light-color-ts-variable); 109 | --external-icon: var(--light-external-icon); 110 | --color-scheme: var(--light-color-scheme); 111 | } 112 | 113 | :root[data-theme="dark"] { 114 | --color-background: var(--dark-color-background); 115 | --color-background-secondary: var(--dark-color-background-secondary); 116 | --color-icon-background: var(--dark-color-icon-background); 117 | --color-accent: var(--dark-color-accent); 118 | --color-text: var(--dark-color-text); 119 | --color-text-aside: var(--dark-color-text-aside); 120 | --color-link: var(--dark-color-link); 121 | --color-ts: var(--dark-color-ts); 122 | --color-ts-interface: var(--dark-color-ts-interface); 123 | --color-ts-enum: var(--dark-color-ts-enum); 124 | --color-ts-class: var(--dark-color-ts-class); 125 | --color-ts-function: var(--dark-color-ts-function); 126 | --color-ts-namespace: var(--dark-color-ts-namespace); 127 | --color-ts-private: var(--dark-color-ts-private); 128 | --color-ts-variable: var(--dark-color-ts-variable); 129 | --external-icon: var(--dark-external-icon); 130 | --color-scheme: var(--dark-color-scheme); 131 | } 132 | 133 | h1, 134 | h2, 135 | h3, 136 | h4, 137 | h5, 138 | h6 { 139 | line-height: 1.2; 140 | } 141 | 142 | h1 { 143 | font-size: 1.875rem; 144 | margin: 0.67rem 0; 145 | } 146 | 147 | h2 { 148 | font-size: 1.5rem; 149 | margin: 0.83rem 0; 150 | } 151 | 152 | h3 { 153 | font-size: 1.25rem; 154 | margin: 1rem 0; 155 | } 156 | 157 | h4 { 158 | font-size: 1.05rem; 159 | margin: 1.33rem 0; 160 | } 161 | 162 | h5 { 163 | font-size: 1rem; 164 | margin: 1.5rem 0; 165 | } 166 | 167 | h6 { 168 | font-size: 0.875rem; 169 | margin: 2.33rem 0; 170 | } 171 | 172 | .uppercase { 173 | text-transform: uppercase; 174 | } 175 | 176 | pre { 177 | white-space: pre; 178 | white-space: pre-wrap; 179 | word-wrap: break-word; 180 | } 181 | 182 | dl, 183 | menu, 184 | ol, 185 | ul { 186 | margin: 1em 0; 187 | } 188 | 189 | dd { 190 | margin: 0 0 0 40px; 191 | } 192 | 193 | .container { 194 | max-width: 1600px; 195 | padding: 0 2rem; 196 | } 197 | 198 | @media (min-width: 640px) { 199 | .container { 200 | padding: 0 4rem; 201 | } 202 | } 203 | @media (min-width: 1200px) { 204 | .container { 205 | padding: 0 8rem; 206 | } 207 | } 208 | @media (min-width: 1600px) { 209 | .container { 210 | padding: 0 12rem; 211 | } 212 | } 213 | 214 | /* Footer */ 215 | .tsd-generator { 216 | border-top: 1px solid var(--color-accent); 217 | padding-top: 1rem; 218 | padding-bottom: 1rem; 219 | max-height: 3.5rem; 220 | } 221 | 222 | .tsd-generator > p { 223 | margin-top: 0; 224 | margin-bottom: 0; 225 | padding: 0 1rem; 226 | } 227 | 228 | .container-main { 229 | display: flex; 230 | justify-content: space-between; 231 | position: relative; 232 | margin: 0 auto; 233 | } 234 | 235 | .col-4, 236 | .col-8 { 237 | box-sizing: border-box; 238 | float: left; 239 | padding: 2rem 1rem; 240 | } 241 | 242 | .col-4 { 243 | flex: 0 0 25%; 244 | } 245 | .col-8 { 246 | flex: 1 0; 247 | flex-wrap: wrap; 248 | padding-left: 0; 249 | } 250 | 251 | @keyframes fade-in { 252 | from { 253 | opacity: 0; 254 | } 255 | to { 256 | opacity: 1; 257 | } 258 | } 259 | @keyframes fade-out { 260 | from { 261 | opacity: 1; 262 | visibility: visible; 263 | } 264 | to { 265 | opacity: 0; 266 | } 267 | } 268 | @keyframes fade-in-delayed { 269 | 0% { 270 | opacity: 0; 271 | } 272 | 33% { 273 | opacity: 0; 274 | } 275 | 100% { 276 | opacity: 1; 277 | } 278 | } 279 | @keyframes fade-out-delayed { 280 | 0% { 281 | opacity: 1; 282 | visibility: visible; 283 | } 284 | 66% { 285 | opacity: 0; 286 | } 287 | 100% { 288 | opacity: 0; 289 | } 290 | } 291 | @keyframes shift-to-left { 292 | from { 293 | transform: translate(0, 0); 294 | } 295 | to { 296 | transform: translate(-25%, 0); 297 | } 298 | } 299 | @keyframes unshift-to-left { 300 | from { 301 | transform: translate(-25%, 0); 302 | } 303 | to { 304 | transform: translate(0, 0); 305 | } 306 | } 307 | @keyframes pop-in-from-right { 308 | from { 309 | transform: translate(100%, 0); 310 | } 311 | to { 312 | transform: translate(0, 0); 313 | } 314 | } 315 | @keyframes pop-out-to-right { 316 | from { 317 | transform: translate(0, 0); 318 | visibility: visible; 319 | } 320 | to { 321 | transform: translate(100%, 0); 322 | } 323 | } 324 | body { 325 | background: var(--color-background); 326 | font-family: "Segoe UI", sans-serif; 327 | font-size: 16px; 328 | color: var(--color-text); 329 | } 330 | 331 | a { 332 | color: var(--color-link); 333 | text-decoration: none; 334 | } 335 | a:hover { 336 | text-decoration: underline; 337 | } 338 | a.external[target="_blank"] { 339 | background-image: var(--external-icon); 340 | background-position: top 3px right; 341 | background-repeat: no-repeat; 342 | padding-right: 13px; 343 | } 344 | 345 | code, 346 | pre { 347 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 348 | padding: 0.2em; 349 | margin: 0; 350 | font-size: 0.875rem; 351 | border-radius: 0.8em; 352 | } 353 | 354 | pre { 355 | padding: 10px; 356 | border: 0.1em solid var(--color-accent); 357 | } 358 | pre code { 359 | padding: 0; 360 | font-size: 100%; 361 | } 362 | 363 | blockquote { 364 | margin: 1em 0; 365 | padding-left: 1em; 366 | border-left: 4px solid gray; 367 | } 368 | 369 | .tsd-typography { 370 | line-height: 1.333em; 371 | } 372 | .tsd-typography ul { 373 | list-style: square; 374 | padding: 0 0 0 20px; 375 | margin: 0; 376 | } 377 | .tsd-typography h4, 378 | .tsd-typography .tsd-index-panel h3, 379 | .tsd-index-panel .tsd-typography h3, 380 | .tsd-typography h5, 381 | .tsd-typography h6 { 382 | font-size: 1em; 383 | margin: 0; 384 | } 385 | .tsd-typography h5, 386 | .tsd-typography h6 { 387 | font-weight: normal; 388 | } 389 | .tsd-typography p, 390 | .tsd-typography ul, 391 | .tsd-typography ol { 392 | margin: 1em 0; 393 | } 394 | 395 | @media (max-width: 1024px) { 396 | html .col-content { 397 | float: none; 398 | max-width: 100%; 399 | width: 100%; 400 | padding-top: 3rem; 401 | } 402 | html .col-menu { 403 | position: fixed !important; 404 | overflow-y: auto; 405 | -webkit-overflow-scrolling: touch; 406 | z-index: 1024; 407 | top: 0 !important; 408 | bottom: 0 !important; 409 | left: auto !important; 410 | right: 0 !important; 411 | padding: 1.5rem 1.5rem 0 0; 412 | max-width: 25rem; 413 | visibility: hidden; 414 | background-color: var(--color-background); 415 | transform: translate(100%, 0); 416 | } 417 | html .col-menu > *:last-child { 418 | padding-bottom: 20px; 419 | } 420 | html .overlay { 421 | content: ""; 422 | display: block; 423 | position: fixed; 424 | z-index: 1023; 425 | top: 0; 426 | left: 0; 427 | right: 0; 428 | bottom: 0; 429 | background-color: rgba(0, 0, 0, 0.75); 430 | visibility: hidden; 431 | } 432 | 433 | .to-has-menu .overlay { 434 | animation: fade-in 0.4s; 435 | } 436 | 437 | .to-has-menu :is(header, footer, .col-content) { 438 | animation: shift-to-left 0.4s; 439 | } 440 | 441 | .to-has-menu .col-menu { 442 | animation: pop-in-from-right 0.4s; 443 | } 444 | 445 | .from-has-menu .overlay { 446 | animation: fade-out 0.4s; 447 | } 448 | 449 | .from-has-menu :is(header, footer, .col-content) { 450 | animation: unshift-to-left 0.4s; 451 | } 452 | 453 | .from-has-menu .col-menu { 454 | animation: pop-out-to-right 0.4s; 455 | } 456 | 457 | .has-menu body { 458 | overflow: hidden; 459 | } 460 | .has-menu .overlay { 461 | visibility: visible; 462 | } 463 | .has-menu :is(header, footer, .col-content) { 464 | transform: translate(-25%, 0); 465 | } 466 | .has-menu .col-menu { 467 | visibility: visible; 468 | transform: translate(0, 0); 469 | display: grid; 470 | align-items: center; 471 | grid-template-rows: auto 1fr; 472 | grid-gap: 1.5rem; 473 | max-height: 100vh; 474 | padding: 1rem 2rem; 475 | } 476 | .has-menu .tsd-navigation { 477 | max-height: 100%; 478 | } 479 | } 480 | 481 | .tsd-breadcrumb { 482 | margin: 0; 483 | padding: 0; 484 | color: var(--color-text-aside); 485 | } 486 | .tsd-breadcrumb a { 487 | color: var(--color-text-aside); 488 | text-decoration: none; 489 | } 490 | .tsd-breadcrumb a:hover { 491 | text-decoration: underline; 492 | } 493 | .tsd-breadcrumb li { 494 | display: inline; 495 | } 496 | .tsd-breadcrumb li:after { 497 | content: " / "; 498 | } 499 | 500 | .tsd-comment-tags { 501 | display: flex; 502 | flex-direction: column; 503 | } 504 | dl.tsd-comment-tag-group { 505 | display: flex; 506 | align-items: center; 507 | overflow: hidden; 508 | margin: 0.5em 0; 509 | } 510 | dl.tsd-comment-tag-group dt { 511 | display: flex; 512 | margin-right: 0.5em; 513 | font-size: 0.875em; 514 | font-weight: normal; 515 | } 516 | dl.tsd-comment-tag-group dd { 517 | margin: 0; 518 | } 519 | code.tsd-tag { 520 | padding: 0.25em 0.4em; 521 | border: 0.1em solid var(--color-accent); 522 | margin-right: 0.25em; 523 | font-size: 70%; 524 | } 525 | h1 code.tsd-tag:first-of-type { 526 | margin-left: 0.25em; 527 | } 528 | 529 | dl.tsd-comment-tag-group dd:before, 530 | dl.tsd-comment-tag-group dd:after { 531 | content: " "; 532 | } 533 | dl.tsd-comment-tag-group dd pre, 534 | dl.tsd-comment-tag-group dd:after { 535 | clear: both; 536 | } 537 | dl.tsd-comment-tag-group p { 538 | margin: 0; 539 | } 540 | 541 | .tsd-panel.tsd-comment .lead { 542 | font-size: 1.1em; 543 | line-height: 1.333em; 544 | margin-bottom: 2em; 545 | } 546 | .tsd-panel.tsd-comment .lead:last-child { 547 | margin-bottom: 0; 548 | } 549 | 550 | .tsd-filter-visibility h4 { 551 | font-size: 1rem; 552 | padding-top: 0.75rem; 553 | padding-bottom: 0.5rem; 554 | margin: 0; 555 | } 556 | .tsd-filter-item:not(:last-child) { 557 | margin-bottom: 0.5rem; 558 | } 559 | .tsd-filter-input { 560 | display: flex; 561 | width: fit-content; 562 | width: -moz-fit-content; 563 | align-items: center; 564 | user-select: none; 565 | -webkit-user-select: none; 566 | -moz-user-select: none; 567 | -ms-user-select: none; 568 | cursor: pointer; 569 | } 570 | .tsd-filter-input input[type="checkbox"] { 571 | cursor: pointer; 572 | position: absolute; 573 | width: 1.5em; 574 | height: 1.5em; 575 | opacity: 0; 576 | } 577 | .tsd-filter-input input[type="checkbox"]:disabled { 578 | pointer-events: none; 579 | } 580 | .tsd-filter-input svg { 581 | cursor: pointer; 582 | width: 1.5em; 583 | height: 1.5em; 584 | margin-right: 0.5em; 585 | border-radius: 0.33em; 586 | /* Leaving this at full opacity breaks event listeners on Firefox. 587 | Don't remove unless you know what you're doing. */ 588 | opacity: 0.99; 589 | } 590 | .tsd-filter-input input[type="checkbox"]:focus + svg { 591 | transform: scale(0.95); 592 | } 593 | .tsd-filter-input input[type="checkbox"]:focus:not(:focus-visible) + svg { 594 | transform: scale(1); 595 | } 596 | .tsd-checkbox-background { 597 | fill: var(--color-accent); 598 | } 599 | input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { 600 | stroke: var(--color-text); 601 | } 602 | .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { 603 | fill: var(--color-background); 604 | stroke: var(--color-accent); 605 | stroke-width: 0.25rem; 606 | } 607 | .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { 608 | stroke: var(--color-accent); 609 | } 610 | 611 | .tsd-theme-toggle { 612 | padding-top: 0.75rem; 613 | } 614 | .tsd-theme-toggle > h4 { 615 | display: inline; 616 | vertical-align: middle; 617 | margin-right: 0.75rem; 618 | } 619 | 620 | .tsd-hierarchy { 621 | list-style: square; 622 | margin: 0; 623 | } 624 | .tsd-hierarchy .target { 625 | font-weight: bold; 626 | } 627 | 628 | .tsd-panel-group.tsd-index-group { 629 | margin-bottom: 0; 630 | } 631 | .tsd-index-panel .tsd-index-list { 632 | list-style: none; 633 | line-height: 1.333em; 634 | margin: 0; 635 | padding: 0.25rem 0 0 0; 636 | overflow: hidden; 637 | display: grid; 638 | grid-template-columns: repeat(3, 1fr); 639 | column-gap: 1rem; 640 | grid-template-rows: auto; 641 | } 642 | @media (max-width: 1024px) { 643 | .tsd-index-panel .tsd-index-list { 644 | grid-template-columns: repeat(2, 1fr); 645 | } 646 | } 647 | @media (max-width: 768px) { 648 | .tsd-index-panel .tsd-index-list { 649 | grid-template-columns: repeat(1, 1fr); 650 | } 651 | } 652 | .tsd-index-panel .tsd-index-list li { 653 | -webkit-page-break-inside: avoid; 654 | -moz-page-break-inside: avoid; 655 | -ms-page-break-inside: avoid; 656 | -o-page-break-inside: avoid; 657 | page-break-inside: avoid; 658 | } 659 | .tsd-index-panel a, 660 | .tsd-index-panel a.tsd-parent-kind-module { 661 | color: var(--color-ts); 662 | } 663 | .tsd-index-panel a.tsd-parent-kind-interface { 664 | color: var(--color-ts-interface); 665 | } 666 | .tsd-index-panel a.tsd-parent-kind-enum { 667 | color: var(--color-ts-enum); 668 | } 669 | .tsd-index-panel a.tsd-parent-kind-class { 670 | color: var(--color-ts-class); 671 | } 672 | .tsd-index-panel a.tsd-kind-module { 673 | color: var(--color-ts-namespace); 674 | } 675 | .tsd-index-panel a.tsd-kind-interface { 676 | color: var(--color-ts-interface); 677 | } 678 | .tsd-index-panel a.tsd-kind-enum { 679 | color: var(--color-ts-enum); 680 | } 681 | .tsd-index-panel a.tsd-kind-class { 682 | color: var(--color-ts-class); 683 | } 684 | .tsd-index-panel a.tsd-kind-function { 685 | color: var(--color-ts-function); 686 | } 687 | .tsd-index-panel a.tsd-kind-namespace { 688 | color: var(--color-ts-namespace); 689 | } 690 | .tsd-index-panel a.tsd-kind-variable { 691 | color: var(--color-ts-variable); 692 | } 693 | .tsd-index-panel a.tsd-is-private { 694 | color: var(--color-ts-private); 695 | } 696 | 697 | .tsd-flag { 698 | display: inline-block; 699 | padding: 0.25em 0.4em; 700 | border-radius: 4px; 701 | color: var(--color-comment-tag-text); 702 | background-color: var(--color-comment-tag); 703 | text-indent: 0; 704 | font-size: 75%; 705 | line-height: 1; 706 | font-weight: normal; 707 | } 708 | 709 | .tsd-anchor { 710 | position: absolute; 711 | top: -100px; 712 | } 713 | 714 | .tsd-member { 715 | position: relative; 716 | } 717 | .tsd-member .tsd-anchor + h3 { 718 | display: flex; 719 | align-items: center; 720 | margin-top: 0; 721 | margin-bottom: 0; 722 | border-bottom: none; 723 | } 724 | .tsd-member [data-tsd-kind] { 725 | color: var(--color-ts); 726 | } 727 | .tsd-member [data-tsd-kind="Interface"] { 728 | color: var(--color-ts-interface); 729 | } 730 | .tsd-member [data-tsd-kind="Enum"] { 731 | color: var(--color-ts-enum); 732 | } 733 | .tsd-member [data-tsd-kind="Class"] { 734 | color: var(--color-ts-class); 735 | } 736 | .tsd-member [data-tsd-kind="Private"] { 737 | color: var(--color-ts-private); 738 | } 739 | 740 | .tsd-navigation a { 741 | display: block; 742 | margin: 0.4rem 0; 743 | border-left: 2px solid transparent; 744 | color: var(--color-text); 745 | text-decoration: none; 746 | transition: border-left-color 0.1s; 747 | } 748 | .tsd-navigation a:hover { 749 | text-decoration: underline; 750 | } 751 | .tsd-navigation ul { 752 | margin: 0; 753 | padding: 0; 754 | list-style: none; 755 | } 756 | .tsd-navigation li { 757 | padding: 0; 758 | } 759 | 760 | .tsd-navigation.primary .tsd-accordion-details > ul { 761 | margin-top: 0.75rem; 762 | } 763 | .tsd-navigation.primary a { 764 | padding: 0.75rem 0.5rem; 765 | margin: 0; 766 | } 767 | .tsd-navigation.primary ul li a { 768 | margin-left: 0.5rem; 769 | } 770 | .tsd-navigation.primary ul li li a { 771 | margin-left: 1.5rem; 772 | } 773 | .tsd-navigation.primary ul li li li a { 774 | margin-left: 2.5rem; 775 | } 776 | .tsd-navigation.primary ul li li li li a { 777 | margin-left: 3.5rem; 778 | } 779 | .tsd-navigation.primary ul li li li li li a { 780 | margin-left: 4.5rem; 781 | } 782 | .tsd-navigation.primary ul li li li li li li a { 783 | margin-left: 5.5rem; 784 | } 785 | .tsd-navigation.primary li.current > a { 786 | border-left: 0.15rem var(--color-text) solid; 787 | } 788 | .tsd-navigation.primary li.selected > a { 789 | font-weight: bold; 790 | border-left: 0.2rem var(--color-text) solid; 791 | } 792 | .tsd-navigation.primary ul li a:hover { 793 | border-left: 0.2rem var(--color-text-aside) solid; 794 | } 795 | .tsd-navigation.primary li.globals + li > span, 796 | .tsd-navigation.primary li.globals + li > a { 797 | padding-top: 20px; 798 | } 799 | 800 | .tsd-navigation.secondary.tsd-navigation--toolbar-hide { 801 | max-height: calc(100vh - 1rem); 802 | top: 0.5rem; 803 | } 804 | .tsd-navigation.secondary > ul { 805 | display: inline; 806 | padding-right: 0.5rem; 807 | transition: opacity 0.2s; 808 | } 809 | .tsd-navigation.secondary ul li a { 810 | padding-left: 0; 811 | } 812 | .tsd-navigation.secondary ul li li a { 813 | padding-left: 1.1rem; 814 | } 815 | .tsd-navigation.secondary ul li li li a { 816 | padding-left: 2.2rem; 817 | } 818 | .tsd-navigation.secondary ul li li li li a { 819 | padding-left: 3.3rem; 820 | } 821 | .tsd-navigation.secondary ul li li li li li a { 822 | padding-left: 4.4rem; 823 | } 824 | .tsd-navigation.secondary ul li li li li li li a { 825 | padding-left: 5.5rem; 826 | } 827 | 828 | #tsd-sidebar-links a { 829 | margin-top: 0; 830 | margin-bottom: 0.5rem; 831 | line-height: 1.25rem; 832 | } 833 | #tsd-sidebar-links a:last-of-type { 834 | margin-bottom: 0; 835 | } 836 | 837 | a.tsd-index-link { 838 | margin: 0.25rem 0; 839 | font-size: 1rem; 840 | line-height: 1.25rem; 841 | display: inline-flex; 842 | align-items: center; 843 | } 844 | .tsd-accordion-summary > h1, 845 | .tsd-accordion-summary > h2, 846 | .tsd-accordion-summary > h3, 847 | .tsd-accordion-summary > h4, 848 | .tsd-accordion-summary > h5 { 849 | display: inline-flex; 850 | align-items: center; 851 | vertical-align: middle; 852 | margin-bottom: 0; 853 | user-select: none; 854 | -moz-user-select: none; 855 | -webkit-user-select: none; 856 | -ms-user-select: none; 857 | } 858 | .tsd-accordion-summary { 859 | display: block; 860 | cursor: pointer; 861 | } 862 | .tsd-accordion-summary > * { 863 | margin-top: 0; 864 | margin-bottom: 0; 865 | padding-top: 0; 866 | padding-bottom: 0; 867 | } 868 | .tsd-accordion-summary::-webkit-details-marker { 869 | display: none; 870 | } 871 | .tsd-index-accordion .tsd-accordion-summary svg { 872 | margin-right: 0.25rem; 873 | } 874 | .tsd-index-content > :not(:first-child) { 875 | margin-top: 0.75rem; 876 | } 877 | .tsd-index-heading { 878 | margin-top: 1.5rem; 879 | margin-bottom: 0.75rem; 880 | } 881 | 882 | .tsd-kind-icon { 883 | margin-right: 0.5rem; 884 | width: 1.25rem; 885 | height: 1.25rem; 886 | min-width: 1.25rem; 887 | min-height: 1.25rem; 888 | } 889 | .tsd-kind-icon path { 890 | transform-origin: center; 891 | transform: scale(1.1); 892 | } 893 | .tsd-signature > .tsd-kind-icon { 894 | margin-right: 0.8rem; 895 | } 896 | 897 | @media (min-width: 1024px) { 898 | .col-content { 899 | margin: 2rem auto; 900 | } 901 | 902 | .menu-sticky-wrap { 903 | position: sticky; 904 | height: calc(100vh - 2rem); 905 | top: 4rem; 906 | right: 0; 907 | padding: 0 1.5rem; 908 | padding-top: 1rem; 909 | margin-top: 3rem; 910 | transition: 0.3s ease-in-out; 911 | transition-property: top, padding-top, padding, height; 912 | overflow-y: auto; 913 | } 914 | .col-menu { 915 | border-left: 1px solid var(--color-accent); 916 | } 917 | .col-menu--hide { 918 | top: 1rem; 919 | } 920 | .col-menu .tsd-navigation:not(:last-child) { 921 | padding-bottom: 1.75rem; 922 | } 923 | } 924 | 925 | .tsd-panel { 926 | margin-bottom: 2.5rem; 927 | } 928 | .tsd-panel.tsd-member { 929 | margin-bottom: 4rem; 930 | } 931 | .tsd-panel:empty { 932 | display: none; 933 | } 934 | .tsd-panel > h1, 935 | .tsd-panel > h2, 936 | .tsd-panel > h3 { 937 | margin: 1.5rem -1.5rem 0.75rem -1.5rem; 938 | padding: 0 1.5rem 0.75rem 1.5rem; 939 | } 940 | .tsd-panel > h1.tsd-before-signature, 941 | .tsd-panel > h2.tsd-before-signature, 942 | .tsd-panel > h3.tsd-before-signature { 943 | margin-bottom: 0; 944 | border-bottom: none; 945 | } 946 | 947 | .tsd-panel-group { 948 | margin: 4rem 0; 949 | } 950 | .tsd-panel-group.tsd-index-group { 951 | margin: 2rem 0; 952 | } 953 | .tsd-panel-group.tsd-index-group details { 954 | margin: 2rem 0; 955 | } 956 | 957 | #tsd-search { 958 | transition: background-color 0.2s; 959 | } 960 | #tsd-search .title { 961 | position: relative; 962 | z-index: 2; 963 | } 964 | #tsd-search .field { 965 | position: absolute; 966 | left: 0; 967 | top: 0; 968 | right: 2.5rem; 969 | height: 100%; 970 | } 971 | #tsd-search .field input { 972 | box-sizing: border-box; 973 | position: relative; 974 | top: -50px; 975 | z-index: 1; 976 | width: 100%; 977 | padding: 0 10px; 978 | opacity: 0; 979 | outline: 0; 980 | border: 0; 981 | background: transparent; 982 | color: var(--color-text); 983 | } 984 | #tsd-search .field label { 985 | position: absolute; 986 | overflow: hidden; 987 | right: -40px; 988 | } 989 | #tsd-search .field input, 990 | #tsd-search .title, 991 | #tsd-toolbar-links a { 992 | transition: opacity 0.2s; 993 | } 994 | #tsd-search .results { 995 | position: absolute; 996 | visibility: hidden; 997 | top: 40px; 998 | width: 100%; 999 | margin: 0; 1000 | padding: 0; 1001 | list-style: none; 1002 | box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); 1003 | } 1004 | #tsd-search .results li { 1005 | padding: 0 10px; 1006 | background-color: var(--color-background); 1007 | } 1008 | #tsd-search .results li:nth-child(even) { 1009 | background-color: var(--color-background-secondary); 1010 | } 1011 | #tsd-search .results li.state { 1012 | display: none; 1013 | } 1014 | #tsd-search .results li.current, 1015 | #tsd-search .results li:hover { 1016 | background-color: var(--color-accent); 1017 | } 1018 | #tsd-search .results a { 1019 | display: block; 1020 | } 1021 | #tsd-search .results a:before { 1022 | top: 10px; 1023 | } 1024 | #tsd-search .results span.parent { 1025 | color: var(--color-text-aside); 1026 | font-weight: normal; 1027 | } 1028 | #tsd-search.has-focus { 1029 | background-color: var(--color-accent); 1030 | } 1031 | #tsd-search.has-focus .field input { 1032 | top: 0; 1033 | opacity: 1; 1034 | } 1035 | #tsd-search.has-focus .title, 1036 | #tsd-search.has-focus #tsd-toolbar-links a { 1037 | z-index: 0; 1038 | opacity: 0; 1039 | } 1040 | #tsd-search.has-focus .results { 1041 | visibility: visible; 1042 | } 1043 | #tsd-search.loading .results li.state.loading { 1044 | display: block; 1045 | } 1046 | #tsd-search.failure .results li.state.failure { 1047 | display: block; 1048 | } 1049 | 1050 | #tsd-toolbar-links { 1051 | position: absolute; 1052 | top: 0; 1053 | right: 2rem; 1054 | height: 100%; 1055 | display: flex; 1056 | align-items: center; 1057 | justify-content: flex-end; 1058 | } 1059 | #tsd-toolbar-links a { 1060 | margin-left: 1.5rem; 1061 | } 1062 | #tsd-toolbar-links a:hover { 1063 | text-decoration: underline; 1064 | } 1065 | 1066 | .tsd-signature { 1067 | margin: 0 0 1rem 0; 1068 | padding: 1rem 0.5rem; 1069 | border: 1px solid var(--color-accent); 1070 | font-family: Menlo, Monaco, Consolas, "Courier New", monospace; 1071 | font-size: 14px; 1072 | overflow-x: auto; 1073 | } 1074 | 1075 | .tsd-signature-symbol { 1076 | color: var(--color-text-aside); 1077 | font-weight: normal; 1078 | } 1079 | 1080 | .tsd-signature-type { 1081 | font-style: italic; 1082 | font-weight: normal; 1083 | } 1084 | 1085 | .tsd-signatures { 1086 | padding: 0; 1087 | margin: 0 0 1em 0; 1088 | list-style-type: none; 1089 | } 1090 | .tsd-signatures .tsd-signature { 1091 | margin: 0; 1092 | border-color: var(--color-accent); 1093 | border-width: 1px 0; 1094 | transition: background-color 0.1s; 1095 | } 1096 | .tsd-description .tsd-signatures .tsd-signature { 1097 | border-width: 1px; 1098 | } 1099 | 1100 | ul.tsd-parameter-list, 1101 | ul.tsd-type-parameter-list { 1102 | list-style: square; 1103 | margin: 0; 1104 | padding-left: 20px; 1105 | } 1106 | ul.tsd-parameter-list > li.tsd-parameter-signature, 1107 | ul.tsd-type-parameter-list > li.tsd-parameter-signature { 1108 | list-style: none; 1109 | margin-left: -20px; 1110 | } 1111 | ul.tsd-parameter-list h5, 1112 | ul.tsd-type-parameter-list h5 { 1113 | font-size: 16px; 1114 | margin: 1em 0 0.5em 0; 1115 | } 1116 | .tsd-sources { 1117 | margin-top: 1rem; 1118 | font-size: 0.875em; 1119 | } 1120 | .tsd-sources a { 1121 | color: var(--color-text-aside); 1122 | text-decoration: underline; 1123 | } 1124 | .tsd-sources ul { 1125 | list-style: none; 1126 | padding: 0; 1127 | } 1128 | 1129 | .tsd-page-toolbar { 1130 | position: fixed; 1131 | z-index: 1; 1132 | top: 0; 1133 | left: 0; 1134 | width: 100%; 1135 | color: var(--color-text); 1136 | background: var(--color-background-secondary); 1137 | border-bottom: 1px var(--color-accent) solid; 1138 | transition: transform 0.3s ease-in-out; 1139 | } 1140 | .tsd-page-toolbar a { 1141 | color: var(--color-text); 1142 | text-decoration: none; 1143 | } 1144 | .tsd-page-toolbar a.title { 1145 | font-weight: bold; 1146 | } 1147 | .tsd-page-toolbar a.title:hover { 1148 | text-decoration: underline; 1149 | } 1150 | .tsd-page-toolbar .tsd-toolbar-contents { 1151 | display: flex; 1152 | justify-content: space-between; 1153 | height: 2.5rem; 1154 | margin: 0 auto; 1155 | } 1156 | .tsd-page-toolbar .table-cell { 1157 | position: relative; 1158 | white-space: nowrap; 1159 | line-height: 40px; 1160 | } 1161 | .tsd-page-toolbar .table-cell:first-child { 1162 | width: 100%; 1163 | } 1164 | .tsd-page-toolbar .tsd-toolbar-icon { 1165 | box-sizing: border-box; 1166 | line-height: 0; 1167 | padding: 12px 0; 1168 | } 1169 | 1170 | .tsd-page-toolbar--hide { 1171 | transform: translateY(-100%); 1172 | } 1173 | 1174 | .tsd-widget { 1175 | display: inline-block; 1176 | overflow: hidden; 1177 | opacity: 0.8; 1178 | height: 40px; 1179 | transition: opacity 0.1s, background-color 0.2s; 1180 | vertical-align: bottom; 1181 | cursor: pointer; 1182 | } 1183 | .tsd-widget:hover { 1184 | opacity: 0.9; 1185 | } 1186 | .tsd-widget.active { 1187 | opacity: 1; 1188 | background-color: var(--color-accent); 1189 | } 1190 | .tsd-widget.no-caption { 1191 | width: 40px; 1192 | } 1193 | .tsd-widget.no-caption:before { 1194 | margin: 0; 1195 | } 1196 | 1197 | .tsd-widget.options, 1198 | .tsd-widget.menu { 1199 | display: none; 1200 | } 1201 | @media (max-width: 1024px) { 1202 | .tsd-widget.options, 1203 | .tsd-widget.menu { 1204 | display: inline-block; 1205 | } 1206 | } 1207 | input[type="checkbox"] + .tsd-widget:before { 1208 | background-position: -120px 0; 1209 | } 1210 | input[type="checkbox"]:checked + .tsd-widget:before { 1211 | background-position: -160px 0; 1212 | } 1213 | 1214 | img { 1215 | max-width: 100%; 1216 | } 1217 | 1218 | .tsd-anchor-icon { 1219 | display: inline-flex; 1220 | align-items: center; 1221 | margin-left: 0.5rem; 1222 | vertical-align: middle; 1223 | color: var(--color-text); 1224 | } 1225 | 1226 | .tsd-anchor-icon svg { 1227 | width: 1em; 1228 | height: 1em; 1229 | visibility: hidden; 1230 | } 1231 | 1232 | .tsd-anchor-link:hover > .tsd-anchor-icon svg { 1233 | visibility: visible; 1234 | } 1235 | 1236 | .deprecated { 1237 | text-decoration: line-through; 1238 | } 1239 | 1240 | * { 1241 | scrollbar-width: thin; 1242 | scrollbar-color: var(--color-accent) var(--color-icon-background); 1243 | } 1244 | 1245 | *::-webkit-scrollbar { 1246 | width: 0.75rem; 1247 | } 1248 | 1249 | *::-webkit-scrollbar-track { 1250 | background: var(--color-icon-background); 1251 | } 1252 | 1253 | *::-webkit-scrollbar-thumb { 1254 | background-color: var(--color-accent); 1255 | border-radius: 999rem; 1256 | border: 0.25rem solid var(--color-icon-background); 1257 | } 1258 | -------------------------------------------------------------------------------- /docs/functions/foldersToKML.html: -------------------------------------------------------------------------------- 1 | foldersToKML | @placemarkio/tokml
2 |
3 | 10 |
11 |
12 |
13 |
14 | 17 |

Function foldersToKML

18 |
19 |
    20 | 21 |
  • 22 |

    Convert nested folder structure to KML. This expects 23 | input that follows the same patterns as toGeoJSON's 24 | kmlWithFolders method: a tree of folders and features, 25 | starting with a root element.

    26 |
    27 |
    28 |

    Parameters

    29 |
      30 |
    • 31 |
      root: Root
    32 |

    Returns string

35 |
60 |
61 |

Generated using TypeDoc

62 |
-------------------------------------------------------------------------------- /docs/functions/toKML.html: -------------------------------------------------------------------------------- 1 | toKML | @placemarkio/tokml
2 |
3 | 10 |
11 |
12 |
13 |
14 | 17 |

Function toKML

18 |
19 |
    20 | 21 |
  • 22 |

    Convert a GeoJSON FeatureCollection to a string of 23 | KML data.

    24 |
    25 |
    26 |

    Parameters

    27 |
      28 |
    • 29 |
      featureCollection: FeatureCollection<null | Geometry, GeoJsonProperties>
    30 |

    Returns string

33 |
58 |
59 |

Generated using TypeDoc

60 |
-------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | @placemarkio/tokml
2 |
3 | 10 |
11 |
12 |
13 |
14 |

@placemarkio/tokml

15 |
16 | 17 |

tokml

18 |
19 |

Convert GeoJSON to KML.

20 | 21 | 22 |

Install

23 |
24 |

This package is @placemarkio/tokml

25 | 26 | 27 |

📕 API Documentation

28 | 29 |

Notes:

30 |
    31 |
  • This method does not validate the GeoJSON inputs. Invalid FeatureCollections 32 | may produce an exception.
  • 33 |
  • GeoJSON properties can have any kind of value, including objects and arrays. 34 | KML properties are strings. Any non-string GeoJSON properties will be stringified 35 | with JSON.stringify when converting to KML.
  • 36 |
37 |
38 |
63 |
64 |

Generated using TypeDoc

65 |
-------------------------------------------------------------------------------- /docs/modules.html: -------------------------------------------------------------------------------- 1 | @placemarkio/tokml
2 |
3 | 10 |
11 |
12 |
13 |
14 |

@placemarkio/tokml

15 |
16 |
17 |

Index

18 |
19 |

Functions

20 |
foldersToKML 21 | toKML 22 |
23 |
48 |
49 |

Generated using TypeDoc

50 |
-------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import type { Folder, Root } from "@tmcw/togeojson"; 2 | import type { Feature, FeatureCollection, Geometry, Position } from "geojson"; 3 | import { u } from "unist-builder"; 4 | import type { Element } from "xast"; 5 | import { toXml } from "xast-util-to-xml"; 6 | import { x } from "xastscript"; 7 | 8 | type F = Feature; 9 | 10 | const BR = u("text", "\n"); 11 | const TAB = u("text", " "); 12 | 13 | type Literal = typeof BR; 14 | 15 | /** 16 | * Convert nested folder structure to KML. This expects 17 | * input that follows the same patterns as [toGeoJSON](https://github.com/placemark/togeojson)'s 18 | * kmlWithFolders method: a tree of folders and features, 19 | * starting with a root element. 20 | */ 21 | export function foldersToKML(root: Root): string { 22 | return toXml( 23 | u("root", [ 24 | x( 25 | "kml", 26 | { xmlns: "http://www.opengis.net/kml/2.2" }, 27 | x( 28 | "Document", 29 | root.children.flatMap((child) => convertChild(child)), 30 | ), 31 | ), 32 | ]), 33 | ); 34 | } 35 | 36 | /** 37 | * Convert a GeoJSON FeatureCollection to a string of 38 | * KML data. 39 | */ 40 | export function toKML( 41 | featureCollection: FeatureCollection, 42 | ): string { 43 | return toXml( 44 | u("root", [ 45 | x( 46 | "kml", 47 | { xmlns: "http://www.opengis.net/kml/2.2" }, 48 | x( 49 | "Document", 50 | featureCollection.features.flatMap((feature) => 51 | convertFeature(feature), 52 | ), 53 | ), 54 | ), 55 | ]), 56 | ); 57 | } 58 | 59 | function convertChild(child: F | Folder) { 60 | switch (child.type) { 61 | case "Feature": 62 | return convertFeature(child); 63 | case "folder": 64 | return convertFolder(child); 65 | } 66 | } 67 | 68 | function convertFolder(folder: Folder): Array { 69 | const id = ["string", "number"].includes(typeof folder.meta.id) 70 | ? { 71 | id: String(folder.meta.id), 72 | } 73 | : {}; 74 | return [ 75 | BR, 76 | x("Folder", id, [ 77 | BR, 78 | ...folderMeta(folder.meta), 79 | BR, 80 | TAB, 81 | ...folder.children.flatMap((child) => convertChild(child)), 82 | ]), 83 | ]; 84 | } 85 | 86 | const META_PROPERTIES = [ 87 | "address", 88 | "description", 89 | "name", 90 | "open", 91 | "visibility", 92 | "phoneNumber", 93 | ] as const; 94 | 95 | function folderMeta(meta: Folder["meta"]): Element[] { 96 | return META_PROPERTIES.filter((p) => meta[p] !== undefined).map((p) => { 97 | return x(p, [u("text", String(meta[p]))]); 98 | }); 99 | } 100 | 101 | function convertFeature(feature: F) { 102 | const { id } = feature; 103 | const idMember = ["string", "number"].includes(typeof id) 104 | ? { 105 | id: id, 106 | } 107 | : {}; 108 | return [ 109 | BR, 110 | x("Placemark", idMember, [ 111 | BR, 112 | ...propertiesToTags(feature.properties), 113 | BR, 114 | TAB, 115 | ...(feature.geometry ? [convertGeometry(feature.geometry)] : []), 116 | ]), 117 | ]; 118 | } 119 | 120 | function join(position: Position): string { 121 | return `${position[0]},${position[1]}`; 122 | } 123 | 124 | function coord1(coordinates: Position): Element { 125 | return x("coordinates", [u("text", join(coordinates))]); 126 | } 127 | 128 | function coord2(coordinates: Position[]): Element { 129 | return x("coordinates", [u("text", coordinates.map(join).join("\n"))]); 130 | } 131 | 132 | function valueToString(value: any): string { 133 | switch (typeof value) { 134 | case "string": { 135 | return value; 136 | } 137 | case "boolean": 138 | case "number": { 139 | return String(value); 140 | } 141 | case "object": { 142 | try { 143 | return JSON.stringify(value); 144 | } catch (e) { 145 | return ""; 146 | } 147 | } 148 | } 149 | return ""; 150 | } 151 | 152 | function maybeCData(value: any) { 153 | if ( 154 | value && 155 | typeof value === "object" && 156 | "@type" in value && 157 | value["@type"] === "html" && 158 | "value" in value && 159 | typeof value.value === "string" 160 | ) { 161 | return u("cdata", value.value); 162 | } 163 | 164 | return valueToString(value); 165 | } 166 | 167 | function propertiesToTags(properties: Feature["properties"]): Element[] { 168 | if (!properties) return []; 169 | const { name, description, visibility, ...otherProperties } = properties; 170 | 171 | return [ 172 | name && x("name", [u("text", valueToString(name))]), 173 | description && x("description", [u("text", maybeCData(description))]), 174 | visibility !== undefined && 175 | x("visibility", [u("text", visibility ? "1" : "0")]), 176 | x( 177 | "ExtendedData", 178 | Object.entries(otherProperties).flatMap(([name, value]) => [ 179 | BR, 180 | TAB, 181 | x("Data", { name: name }, [ 182 | x("value", [ 183 | u( 184 | "text", 185 | typeof value === "string" ? value : JSON.stringify(value), 186 | ), 187 | ]), 188 | ]), 189 | ]), 190 | ), 191 | ].filter(Boolean); 192 | } 193 | 194 | const linearRing = (ring: Position[]): Element => 195 | x("LinearRing", [coord2(ring)]); 196 | 197 | function convertMultiPoint(geometry: GeoJSON.MultiPoint): Element { 198 | return x( 199 | "MultiGeometry", 200 | geometry.coordinates.flatMap((coordinates) => [ 201 | BR, 202 | convertGeometry({ 203 | type: "Point", 204 | coordinates, 205 | }), 206 | ]), 207 | ); 208 | } 209 | function convertMultiLineString(geometry: GeoJSON.MultiLineString): Element { 210 | return x( 211 | "MultiGeometry", 212 | geometry.coordinates.flatMap((coordinates) => [ 213 | BR, 214 | convertGeometry({ 215 | type: "LineString", 216 | coordinates, 217 | }), 218 | ]), 219 | ); 220 | } 221 | 222 | function convertMultiPolygon(geometry: GeoJSON.MultiPolygon): Element { 223 | return x( 224 | "MultiGeometry", 225 | geometry.coordinates.flatMap((coordinates) => [ 226 | BR, 227 | convertGeometry({ 228 | type: "Polygon", 229 | coordinates, 230 | }), 231 | ]), 232 | ); 233 | } 234 | 235 | function convertPolygon(geometry: GeoJSON.Polygon): Element { 236 | const [outerBoundary, ...innerRings] = geometry.coordinates; 237 | return x("Polygon", [ 238 | BR, 239 | x("outerBoundaryIs", [BR, TAB, linearRing(outerBoundary)]), 240 | ...innerRings.flatMap((innerRing) => [ 241 | BR, 242 | x("innerBoundaryIs", [BR, TAB, linearRing(innerRing)]), 243 | ]), 244 | ]); 245 | } 246 | 247 | function convertGeometry(geometry: Geometry): Element { 248 | switch (geometry.type) { 249 | case "Point": 250 | return x("Point", [coord1(geometry.coordinates)]); 251 | case "MultiPoint": 252 | return convertMultiPoint(geometry); 253 | case "LineString": 254 | return x("LineString", [coord2(geometry.coordinates)]); 255 | case "MultiLineString": 256 | return convertMultiLineString(geometry); 257 | case "Polygon": 258 | return convertPolygon(geometry); 259 | case "MultiPolygon": 260 | return convertMultiPolygon(geometry); 261 | case "GeometryCollection": 262 | return x( 263 | "MultiGeometry", 264 | geometry.geometries.flatMap((geometry) => [ 265 | BR, 266 | convertGeometry(geometry), 267 | ]), 268 | ); 269 | } 270 | } 271 | -------------------------------------------------------------------------------- /mise.toml: -------------------------------------------------------------------------------- 1 | [tools] 2 | node = "22" 3 | pnpm = "latest" 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@placemarkio/tokml", 3 | "version": "0.3.7", 4 | "description": "Convert GeoJSON to KML", 5 | "main": "dist/tokml.cjs", 6 | "module": "dist/tokml.es.mjs", 7 | "typings": "dist/index.d.ts", 8 | "author": "Tom MacWright", 9 | "license": "MIT", 10 | "exports": { 11 | "require": "./dist/tokml.cjs", 12 | "types": "./dist/index.d.ts", 13 | "default": "./dist/tokml.es.mjs" 14 | }, 15 | "keywords": [ 16 | "kml", 17 | "geojson" 18 | ], 19 | "publishConfig": { 20 | "access": "public" 21 | }, 22 | "husky": { 23 | "hooks": { 24 | "pre-commit": "pnpm lint" 25 | } 26 | }, 27 | "files": [ 28 | "dist" 29 | ], 30 | "scripts": { 31 | "test": "vitest", 32 | "lint": "biome check", 33 | "doc": "typedoc --options typedoc.json", 34 | "prepublish": "rollup -c rollup.config.mjs && cp CNAME docs/CNAME", 35 | "release": "standard-version" 36 | }, 37 | "devDependencies": { 38 | "@biomejs/biome": "^1.9.4", 39 | "@rollup/plugin-node-resolve": "^15.0.1", 40 | "@rollup/plugin-typescript": "^9.0.2", 41 | "@tmcw/togeojson": "5.4.0", 42 | "@types/geojson": "^7946.0.8", 43 | "@types/xast": "^2.0.4", 44 | "eslint": "^8.18.0", 45 | "rollup": "4.28.1", 46 | "rollup-plugin-dts": "^5.0.0", 47 | "rollup-plugin-terser": "^7.0.2", 48 | "standard-version": "^9.5.0", 49 | "tslib": "^2.4.0", 50 | "typedoc": "^0.23.19", 51 | "typescript": "^4.7.4", 52 | "unist-builder": "^3.0.0", 53 | "vitest": "^0.24.4", 54 | "xast-util-to-xml": "^3.0.0", 55 | "xastscript": "^3.0.0" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import { terser } from 'rollup-plugin-terser'; 2 | import typescript from '@rollup/plugin-typescript'; 3 | import dts from 'rollup-plugin-dts'; 4 | import { nodeResolve } from '@rollup/plugin-node-resolve'; 5 | 6 | const input = './lib/index.ts'; 7 | const sourcemap = true; 8 | 9 | export default [ 10 | { 11 | input, 12 | output: { 13 | file: 'dist/tokml.es.mjs', 14 | format: 'es', 15 | sourcemap, 16 | }, 17 | plugins: [typescript(), nodeResolve()], 18 | }, 19 | { 20 | input, 21 | output: { 22 | file: 'dist/index.d.ts', 23 | format: 'es', 24 | }, 25 | plugins: [dts()], 26 | }, 27 | { 28 | input, 29 | output: { 30 | file: 'dist/tokml.cjs', 31 | format: 'cjs', 32 | sourcemap, 33 | }, 34 | plugins: [typescript(), nodeResolve()], 35 | }, 36 | { 37 | input, 38 | output: { 39 | file: 'dist/tokml.umd.js', 40 | format: 'umd', 41 | name: 'toKML', 42 | sourcemap, 43 | }, 44 | plugins: [typescript(), nodeResolve(), terser()], 45 | }, 46 | ]; 47 | -------------------------------------------------------------------------------- /test/index.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect } from 'vitest'; 2 | import { toKML, foldersToKML } from '../lib/index'; 3 | 4 | describe('foldersToKML', () => { 5 | it('#foldersToKML', () => { 6 | expect( 7 | foldersToKML({ 8 | type: 'root', 9 | children: [ 10 | { 11 | type: 'Feature', 12 | properties: { 13 | foo: 'bar', 14 | }, 15 | 16 | geometry: { 17 | type: 'Point', 18 | coordinates: [0, 2], 19 | }, 20 | }, 21 | 22 | { 23 | type: 'folder', 24 | meta: { name: 'Hi', id: 'f00' }, 25 | children: [], 26 | }, 27 | 28 | { 29 | type: 'folder', 30 | meta: { name: 'Hi' }, 31 | children: [ 32 | { 33 | type: 'Feature', 34 | properties: { 35 | foo: 'bar', 36 | }, 37 | 38 | geometry: { 39 | type: 'LineString', 40 | coordinates: [ 41 | [0, 2], 42 | [1, 2], 43 | ], 44 | }, 45 | }, 46 | ], 47 | }, 48 | ], 49 | }) 50 | ).toMatchInlineSnapshot(` 51 | " 52 | 53 | 54 | bar 55 | 0,2 56 | 57 | Hi 58 | 59 | 60 | Hi 61 | 62 | 63 | 64 | bar 65 | 0,2 66 | 1,2" 67 | `); 68 | expect( 69 | foldersToKML({ 70 | type: 'root', 71 | children: [ 72 | { 73 | type: 'Feature', 74 | properties: { 75 | foo: 'bar', 76 | }, 77 | 78 | geometry: { 79 | type: 'Point', 80 | coordinates: [0, 2], 81 | }, 82 | }, 83 | 84 | { 85 | type: 'Feature', 86 | properties: { 87 | foo: 'bar', 88 | }, 89 | 90 | geometry: { 91 | type: 'LineString', 92 | coordinates: [ 93 | [0, 2], 94 | [1, 2], 95 | ], 96 | }, 97 | }, 98 | ], 99 | }) 100 | ).toMatchInlineSnapshot(` 101 | " 102 | 103 | 104 | bar 105 | 0,2 106 | 107 | 108 | bar 109 | 0,2 110 | 1,2" 111 | `); 112 | }); 113 | }); 114 | 115 | describe('toKML', () => { 116 | it('#toKML', () => { 117 | expect( 118 | toKML({ 119 | type: 'FeatureCollection', 120 | features: [ 121 | { 122 | type: 'Feature', 123 | properties: { 124 | foo: 'bar', 125 | }, 126 | 127 | geometry: { 128 | type: 'Point', 129 | coordinates: [0, 2], 130 | }, 131 | }, 132 | 133 | { 134 | type: 'Feature', 135 | properties: { 136 | foo: 'bar', 137 | }, 138 | 139 | geometry: { 140 | type: 'MultiPoint', 141 | coordinates: [ 142 | [0, 2], 143 | [1, 2], 144 | ], 145 | }, 146 | }, 147 | 148 | { 149 | type: 'Feature', 150 | properties: { 151 | foo: 'bar', 152 | }, 153 | 154 | geometry: { 155 | type: 'LineString', 156 | coordinates: [ 157 | [0, 2], 158 | [1, 2], 159 | ], 160 | }, 161 | }, 162 | ], 163 | }) 164 | ).toMatchInlineSnapshot(` 165 | " 166 | 167 | 168 | bar 169 | 0,2 170 | 171 | 172 | bar 173 | 174 | 0,2 175 | 1,2 176 | 177 | 178 | bar 179 | 0,2 180 | 1,2" 181 | `); 182 | 183 | expect( 184 | toKML({ 185 | type: 'FeatureCollection', 186 | features: [ 187 | { 188 | type: 'Feature', 189 | properties: { 190 | foo: 'bar', 191 | }, 192 | 193 | geometry: { 194 | type: 'Polygon', 195 | coordinates: [ 196 | [ 197 | [0, 2], 198 | [1, 2], 199 | [2, 2], 200 | [0, 2], 201 | ], 202 | 203 | [ 204 | [0, 3], 205 | [1, 3], 206 | [2, 3], 207 | [0, 3], 208 | ], 209 | ], 210 | }, 211 | }, 212 | ], 213 | }) 214 | ).toMatchInlineSnapshot(` 215 | " 216 | 217 | 218 | bar 219 | 220 | 221 | 0,2 222 | 1,2 223 | 2,2 224 | 0,2 225 | 226 | 0,3 227 | 1,3 228 | 2,3 229 | 0,3" 230 | `); 231 | 232 | expect( 233 | toKML({ 234 | type: 'FeatureCollection', 235 | features: [ 236 | { 237 | type: 'Feature', 238 | properties: { 239 | foo: 'bar', 240 | }, 241 | 242 | geometry: { 243 | type: 'MultiLineString', 244 | coordinates: [ 245 | [ 246 | [0, 2], 247 | [1, 2], 248 | [2, 2], 249 | [0, 2], 250 | ], 251 | 252 | [ 253 | [0, 3], 254 | [1, 3], 255 | [2, 3], 256 | [0, 3], 257 | ], 258 | ], 259 | }, 260 | }, 261 | ], 262 | }) 263 | ).toMatchInlineSnapshot(` 264 | " 265 | 266 | 267 | bar 268 | 269 | 0,2 270 | 1,2 271 | 2,2 272 | 0,2 273 | 0,3 274 | 1,3 275 | 2,3 276 | 0,3" 277 | `); 278 | 279 | expect( 280 | toKML({ 281 | type: 'FeatureCollection', 282 | features: [ 283 | { 284 | type: 'Feature', 285 | properties: { 286 | foo: 'bar', 287 | }, 288 | 289 | geometry: { 290 | type: 'MultiPolygon', 291 | coordinates: [ 292 | [ 293 | [ 294 | [0, 2], 295 | [1, 2], 296 | [2, 2], 297 | [0, 2], 298 | ], 299 | 300 | [ 301 | [0, 3], 302 | [1, 3], 303 | [2, 3], 304 | [0, 3], 305 | ], 306 | ], 307 | ], 308 | }, 309 | }, 310 | ], 311 | }) 312 | ).toMatchInlineSnapshot(` 313 | " 314 | 315 | 316 | bar 317 | 318 | 319 | 320 | 0,2 321 | 1,2 322 | 2,2 323 | 0,2 324 | 325 | 0,3 326 | 1,3 327 | 2,3 328 | 0,3" 329 | `); 330 | 331 | expect( 332 | toKML({ 333 | type: 'FeatureCollection', 334 | features: [ 335 | { 336 | type: 'Feature', 337 | properties: { 338 | foo: 'bar', 339 | bar: { x: 1 }, 340 | q: 1, 341 | }, 342 | 343 | geometry: { 344 | type: 'GeometryCollection', 345 | geometries: [{ type: 'Point', coordinates: [0, 1] }], 346 | }, 347 | }, 348 | ], 349 | }) 350 | ).toMatchInlineSnapshot(` 351 | " 352 | 353 | 354 | bar 355 | {\\"x\\":1} 356 | 1 357 | 358 | 0,1" 359 | `); 360 | 361 | expect( 362 | toKML({ 363 | type: 'FeatureCollection', 364 | features: [ 365 | { 366 | type: 'Feature', 367 | properties: null, 368 | geometry: { type: 'Point', coordinates: [0, 1] }, 369 | }, 370 | ], 371 | }) 372 | ).toMatchInlineSnapshot(` 373 | " 374 | 375 | 376 | 0,1" 377 | `); 378 | 379 | expect( 380 | toKML({ 381 | type: 'FeatureCollection', 382 | features: [ 383 | { 384 | type: 'Feature', 385 | properties: { 386 | description: 'test', 387 | }, 388 | 389 | geometry: { type: 'Point', coordinates: [0, 1] }, 390 | }, 391 | ], 392 | }) 393 | ).toMatchInlineSnapshot(` 394 | " 395 | 396 | test 397 | 0,1" 398 | `); 399 | 400 | expect( 401 | toKML({ 402 | type: 'FeatureCollection', 403 | features: [ 404 | { 405 | type: 'Feature', 406 | properties: { 407 | name: 'bar', 408 | }, 409 | 410 | geometry: null, 411 | }, 412 | ], 413 | }) 414 | ).toMatchInlineSnapshot(` 415 | " 416 | 417 | bar 418 | " 419 | `); 420 | 421 | expect( 422 | toKML({ 423 | type: 'FeatureCollection', 424 | features: [ 425 | { 426 | type: 'Feature', 427 | properties: { 428 | name: 'bar', 429 | }, 430 | 431 | geometry: { type: 'Point', coordinates: [0, 1] }, 432 | }, 433 | ], 434 | }) 435 | ).toMatchInlineSnapshot(` 436 | " 437 | 438 | bar 439 | 0,1" 440 | `); 441 | }); 442 | 443 | it('ignores coordinates past #2', () => { 444 | expect( 445 | toKML({ 446 | type: 'FeatureCollection', 447 | features: [ 448 | { 449 | type: 'Feature', 450 | properties: { 451 | name: 'bar', 452 | }, 453 | 454 | geometry: { type: 'Point', coordinates: [0, 1, 2] }, 455 | }, 456 | ], 457 | }) 458 | ).toMatchInlineSnapshot(` 459 | " 460 | 461 | bar 462 | 0,1" 463 | `); 464 | }); 465 | 466 | it('includes feature id', () => { 467 | expect( 468 | toKML({ 469 | type: 'FeatureCollection', 470 | features: [ 471 | { 472 | type: 'Feature', 473 | id: 42, 474 | properties: { 475 | name: 'bar', 476 | }, 477 | geometry: { type: 'Point', coordinates: [0, 1] }, 478 | }, 479 | ], 480 | }) 481 | ).toMatchInlineSnapshot(` 482 | " 483 | 484 | bar 485 | 0,1" 486 | `); 487 | }); 488 | 489 | it('json values', () => { 490 | expect( 491 | toKML({ 492 | type: 'FeatureCollection', 493 | features: [ 494 | { 495 | type: 'Feature', 496 | id: 42, 497 | properties: { 498 | name: { x: 'bar' }, 499 | }, 500 | 501 | geometry: { type: 'Point', coordinates: [0, 1] }, 502 | }, 503 | ], 504 | }) 505 | ).toMatchInlineSnapshot(` 506 | " 507 | 508 | {\\"x\\":\\"bar\\"} 509 | 0,1" 510 | `); 511 | }); 512 | 513 | it('visibility', () => { 514 | expect( 515 | toKML({ 516 | type: 'FeatureCollection', 517 | features: [ 518 | { 519 | type: 'Feature', 520 | properties: { 521 | visibility: false, 522 | }, 523 | 524 | geometry: { type: 'Point', coordinates: [0, 1] }, 525 | }, 526 | 527 | { 528 | type: 'Feature', 529 | properties: { 530 | visibility: true, 531 | }, 532 | 533 | geometry: { type: 'Point', coordinates: [0, 1] }, 534 | }, 535 | ], 536 | }) 537 | ).toMatchInlineSnapshot(` 538 | " 539 | 540 | 0 541 | 0,1 542 | 543 | 1 544 | 0,1" 545 | `); 546 | }); 547 | 548 | it('html values', () => { 549 | expect( 550 | toKML({ 551 | type: 'FeatureCollection', 552 | features: [ 553 | { 554 | type: 'Feature', 555 | id: 42, 556 | properties: { 557 | name: 'bar', 558 | description: { '@type': 'html', value: 'bar' }, 559 | }, 560 | 561 | geometry: { type: 'Point', coordinates: [0, 1] }, 562 | }, 563 | ], 564 | }) 565 | ).toMatchInlineSnapshot(` 566 | " 567 | 568 | barbar]]> 569 | 0,1" 570 | `); 571 | }); 572 | }); 573 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Basic Options */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | "target": "es2019", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ 8 | "module": "ESNext", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ 9 | // "lib": [], /* Specify library files to be included in the compilation. */ 10 | // "allowJs": true, /* Allow javascript files to be compiled. */ 11 | // "checkJs": true, /* Report errors in .js files. */ 12 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 13 | "declaration": true, /* Generates corresponding '.d.ts' file. */ 14 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 15 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 16 | // "outFile": "./", /* Concatenate and emit output to single file. */ 17 | "outDir": "./dist/", /* Redirect output structure to the directory. */ 18 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 19 | // "composite": true, /* Enable project compilation */ 20 | // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ 21 | // "removeComments": true, /* Do not emit comments to output. */ 22 | // "noEmit": true, /* Do not emit outputs. */ 23 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 24 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 25 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 26 | 27 | /* Strict Type-Checking Options */ 28 | "strict": true, /* Enable all strict type-checking options. */ 29 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 30 | // "strictNullChecks": true, /* Enable strict null checks. */ 31 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 32 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 33 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 34 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 35 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 36 | 37 | /* Additional Checks */ 38 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 39 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 40 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 41 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 42 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 43 | 44 | /* Module Resolution Options */ 45 | "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 46 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 47 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 48 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 49 | "typeRoots": ["./types"], /* List of folders to include type definitions from. */ 50 | // "types": [], /* Type declaration files to be included in compilation. */ 51 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 52 | "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 53 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 54 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 55 | 56 | /* Source Map Options */ 57 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 58 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 59 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 60 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 61 | 62 | /* Experimental Options */ 63 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 64 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 65 | 66 | /* Advanced Options */ 67 | "skipLibCheck": true, /* Skip type checking of declaration files. */ 68 | "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ 69 | }, 70 | "include": [ 71 | "lib" 72 | ], 73 | "exclude": [ 74 | "test" 75 | ] 76 | } 77 | -------------------------------------------------------------------------------- /typedoc.json: -------------------------------------------------------------------------------- 1 | { 2 | "entryPoints": ["./lib/index.ts"], 3 | "entryPointStrategy":"Expand", 4 | "out": "docs" 5 | } 6 | --------------------------------------------------------------------------------