├── .dockerignore ├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── infrastructure-enhancement.md ├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE.md ├── README.md ├── _posts └── docs │ └── reference │ ├── 0204-01-01-introduction.md │ ├── 0204-02-01-usage.md │ ├── 0204-02-02-basics.md │ ├── 0204-02-04-interface-tour.md │ ├── 0204-02-05-files-and-directories.md │ ├── 0204-03-01-adding-layers.md │ ├── 0204-03-01-project-settings.md │ ├── 0204-04-01-carto.md │ ├── 0204-05-01-exporting.md │ ├── 0204-06-01-mapbox-geodata.md │ └── 0204-07-01-tilemill-settings.md ├── appveyor.yml ├── assets ├── css │ ├── code.css │ ├── codemirror.css │ ├── controls.css │ ├── reset.css │ └── style.css ├── fonts │ ├── DroidSans.ttf │ ├── DroidSans.woff │ ├── DroidSansBold.ttf │ ├── DroidSansBold.woff │ └── DroidSansMono.ttf ├── images │ ├── bg.png │ ├── bg.svg │ ├── controls.png │ ├── controls.svg │ ├── controls_2x.png │ ├── favicon.ico │ ├── favicon.svg │ ├── mask-0-25.png │ ├── mask-0-50.png │ ├── mask-255-90.png │ ├── mask-48-90.png │ ├── mask.png │ ├── mask.svg │ ├── spinner-reverse.gif │ ├── spinner-reverse_2x.gif │ ├── spinner.gif │ ├── spinner_2x.gif │ ├── sprite.png │ ├── sprite.svg │ ├── sprite_2x.png │ ├── tilemill.png │ ├── tilemill.svg │ ├── tilemill_2x.png │ └── top.png ├── js │ ├── codemirror.carto.complete.js │ ├── codemirror.carto.js │ ├── codemirror.js │ ├── codemirror.mustache.js │ ├── codemirror.overlay.js │ ├── codemirror.xml.js │ ├── colorpicker.classic.js │ ├── jquery.ui.js │ ├── mustache.js │ └── showdown.js └── manual │ ├── editor.png │ ├── editor.svg │ ├── export.png │ ├── inspector-hover.png │ ├── inspector.png │ ├── inspector.svg │ ├── legend.png │ ├── map.png │ ├── map.svg │ ├── project.png │ ├── project.svg │ ├── symbolizer-1.png │ ├── symbolizer-2.png │ ├── tools.png │ └── tools.svg ├── commands ├── core.bones ├── export.bones ├── global.bones ├── start.bones ├── test.bones └── tile.bones ├── configure.js ├── controllers └── Router.bones ├── data └── 82945364-10m-admin-0-countries │ └── 82945364-10m-admin-0-countries.zip ├── docker-compose.yml ├── examples ├── control-room │ ├── .thumb.png │ ├── labels.mss │ ├── project.mml │ └── style.mss ├── geography-class │ ├── .thumb.png │ ├── flags │ │ ├── ABW.svgz │ │ ├── AFG.svgz │ │ ├── AGO.svgz │ │ ├── AIA.svgz │ │ ├── ALB.svgz │ │ ├── ALD.svgz │ │ ├── AND.svgz │ │ ├── ARE.svgz │ │ ├── ARG.svgz │ │ ├── ARM.svgz │ │ ├── ASM.svgz │ │ ├── ATA.svgz │ │ ├── ATC.svgz │ │ ├── ATF.svgz │ │ ├── ATG.svgz │ │ ├── AUS.svgz │ │ ├── AUT.svgz │ │ ├── AZE.svgz │ │ ├── BDI.svgz │ │ ├── BEL.svgz │ │ ├── BEN.svgz │ │ ├── BFA.svgz │ │ ├── BGD.svgz │ │ ├── BGR.svgz │ │ ├── BHR.svgz │ │ ├── BHS.svgz │ │ ├── BIH.svgz │ │ ├── BLM.svgz │ │ ├── BLR.svgz │ │ ├── BLZ.svgz │ │ ├── BMU.svgz │ │ ├── BOL.svgz │ │ ├── BRA.svgz │ │ ├── BRB.svgz │ │ ├── BRN.svgz │ │ ├── BTN.svgz │ │ ├── BWA.svgz │ │ ├── CAF.svgz │ │ ├── CAN.svgz │ │ ├── CHE.svgz │ │ ├── CHL.svgz │ │ ├── CHN.svgz │ │ ├── CIV.svgz │ │ ├── CLP.svgz │ │ ├── CMR.svgz │ │ ├── CNM.svgz │ │ ├── COD.svgz │ │ ├── COG.svgz │ │ ├── COK.svgz │ │ ├── COL.svgz │ │ ├── COM.svgz │ │ ├── CPV.svgz │ │ ├── CRI.svgz │ │ ├── CSI.svgz │ │ ├── CUB.svgz │ │ ├── CUW.svgz │ │ ├── CYM.svgz │ │ ├── CYN.svgz │ │ ├── CYP.svgz │ │ ├── CZE.svgz │ │ ├── DEU.svgz │ │ ├── DJI.svgz │ │ ├── DMA.svgz │ │ ├── DNK.svgz │ │ ├── DOM.svgz │ │ ├── DZA.svgz │ │ ├── ECU.svgz │ │ ├── EGY.svgz │ │ ├── ERI.svgz │ │ ├── ESB.svgz │ │ ├── ESP.svgz │ │ ├── EST.svgz │ │ ├── ETH.svgz │ │ ├── FIN.svgz │ │ ├── FJI.svgz │ │ ├── FLK.svgz │ │ ├── FRA.svgz │ │ ├── FRO.svgz │ │ ├── FSM.svgz │ │ ├── GAB.svgz │ │ ├── GAZ.svgz │ │ ├── GBR.svgz │ │ ├── GEO.svgz │ │ ├── GGY.svgz │ │ ├── GHA.svgz │ │ ├── GIB.svgz │ │ ├── GIN.svgz │ │ ├── GMB.svgz │ │ ├── GNB.svgz │ │ ├── GNQ.svgz │ │ ├── GRC.svgz │ │ ├── GRD.svgz │ │ ├── GRL.svgz │ │ ├── GTM.svgz │ │ ├── GUM.svgz │ │ ├── GUY.svgz │ │ ├── HKG.svgz │ │ ├── HMD.svgz │ │ ├── HND.svgz │ │ ├── HRV.svgz │ │ ├── HTI.svgz │ │ ├── HUN.svgz │ │ ├── IDN.svgz │ │ ├── IMN.svgz │ │ ├── IND.svgz │ │ ├── IOA.svgz │ │ ├── IOT.svgz │ │ ├── IRL.svgz │ │ ├── IRN.svgz │ │ ├── IRQ.svgz │ │ ├── ISL.svgz │ │ ├── ISR.svgz │ │ ├── ITA.svgz │ │ ├── JAM.svgz │ │ ├── JEY.svgz │ │ ├── JOR.svgz │ │ ├── JPN.svgz │ │ ├── KAB.svgz │ │ ├── KAS.svgz │ │ ├── KAZ.svgz │ │ ├── KEN.svgz │ │ ├── KGZ.svgz │ │ ├── KHM.svgz │ │ ├── KIR.svgz │ │ ├── KNA.svgz │ │ ├── KNM.svgz │ │ ├── KOR.svgz │ │ ├── KOS.svgz │ │ ├── KWT.svgz │ │ ├── LAO.svgz │ │ ├── LBN.svgz │ │ ├── LBR.svgz │ │ ├── LBY.svgz │ │ ├── LCA.svgz │ │ ├── LIE.svgz │ │ ├── LKA.svgz │ │ ├── LSO.svgz │ │ ├── LTU.svgz │ │ ├── LUX.svgz │ │ ├── LVA.svgz │ │ ├── MAC.svgz │ │ ├── MAF.svgz │ │ ├── MAR.svgz │ │ ├── MCO.svgz │ │ ├── MDA.svgz │ │ ├── MDG.svgz │ │ ├── MDV.svgz │ │ ├── MEX.svgz │ │ ├── MHL.svgz │ │ ├── MKD.svgz │ │ ├── MLI.svgz │ │ ├── MLT.svgz │ │ ├── MMR.svgz │ │ ├── MNE.svgz │ │ ├── MNG.svgz │ │ ├── MNP.svgz │ │ ├── MOZ.svgz │ │ ├── MRT.svgz │ │ ├── MSR.svgz │ │ ├── MUS.svgz │ │ ├── MWI.svgz │ │ ├── MYS.svgz │ │ ├── NAM.svgz │ │ ├── NCL.svgz │ │ ├── NER.svgz │ │ ├── NFK.svgz │ │ ├── NGA.svgz │ │ ├── NIC.svgz │ │ ├── NIU.svgz │ │ ├── NLD.svgz │ │ ├── NOR.svgz │ │ ├── NPL.svgz │ │ ├── NRU.svgz │ │ ├── NZL.svgz │ │ ├── OMN.svgz │ │ ├── PAK.svgz │ │ ├── PAN.svgz │ │ ├── PCN.svgz │ │ ├── PER.svgz │ │ ├── PHL.svgz │ │ ├── PLW.svgz │ │ ├── PNG.svgz │ │ ├── POL.svgz │ │ ├── PRI.svgz │ │ ├── PRK.svgz │ │ ├── PRT.svgz │ │ ├── PRY.svgz │ │ ├── PYF.svgz │ │ ├── QAT.svgz │ │ ├── ROU.svgz │ │ ├── RUS.svgz │ │ ├── RWA.svgz │ │ ├── SAH.svgz │ │ ├── SAU.svgz │ │ ├── SDN.svgz │ │ ├── SDS.svgz │ │ ├── SEN.svgz │ │ ├── SGP.svgz │ │ ├── SGS.svgz │ │ ├── SHN.svgz │ │ ├── SLB.svgz │ │ ├── SLE.svgz │ │ ├── SLV.svgz │ │ ├── SMR.svgz │ │ ├── SOL.svgz │ │ ├── SOM.svgz │ │ ├── SPM.svgz │ │ ├── SRB.svgz │ │ ├── STP.svgz │ │ ├── SUR.svgz │ │ ├── SVK.svgz │ │ ├── SVN.svgz │ │ ├── SWE.svgz │ │ ├── SWZ.svgz │ │ ├── SXM.svgz │ │ ├── SYC.svgz │ │ ├── SYR.svgz │ │ ├── TCA.svgz │ │ ├── TCD.svgz │ │ ├── TGO.svgz │ │ ├── THA.svgz │ │ ├── TJK.svgz │ │ ├── TKM.svgz │ │ ├── TLS.svgz │ │ ├── TON.svgz │ │ ├── TTO.svgz │ │ ├── TUN.svgz │ │ ├── TUR.svgz │ │ ├── TUV.svgz │ │ ├── TWN.svgz │ │ ├── TZA.svgz │ │ ├── UGA.svgz │ │ ├── UKR.svgz │ │ ├── UMI.svgz │ │ ├── URY.svgz │ │ ├── USA.svgz │ │ ├── USG.svgz │ │ ├── UZB.svgz │ │ ├── VAT.svgz │ │ ├── VCT.svgz │ │ ├── VEN.svgz │ │ ├── VGB.svgz │ │ ├── VIR.svgz │ │ ├── VNM.svgz │ │ ├── VUT.svgz │ │ ├── WEB.svgz │ │ ├── WLF.svgz │ │ ├── WSB.svgz │ │ ├── WSM.svgz │ │ ├── YEM.svgz │ │ ├── ZAF.svgz │ │ ├── ZMB.svgz │ │ └── ZWE.svgz │ ├── icons │ │ ├── circle-7.png │ │ └── star-10.png │ ├── insert_flags.sh │ ├── labels.mss │ ├── layers │ │ ├── country-interaction.geojson │ │ └── world_extent_wgs84.geojson │ ├── project.mml │ ├── rainbow.mss │ ├── style.mss │ └── textures │ │ ├── paperfolds_256.png │ │ └── paperfolds_512.png ├── open-streets-dc │ ├── .thumb.png │ ├── highway.mss │ ├── images │ │ ├── water.png │ │ └── wood.png │ ├── labels.mss │ ├── layers │ │ ├── dc-coastline.dbf │ │ ├── dc-coastline.prj │ │ ├── dc-coastline.shp │ │ ├── dc-coastline.shx │ │ ├── dcgis_water │ │ │ ├── WaterPly_900913.dbf │ │ │ ├── WaterPly_900913.index │ │ │ ├── WaterPly_900913.prj │ │ │ ├── WaterPly_900913.shp │ │ │ └── WaterPly_900913.shx │ │ ├── osm-landusages.dbf │ │ ├── osm-landusages.prj │ │ ├── osm-landusages.shp │ │ ├── osm-landusages.shx │ │ ├── osm-mainroads.dbf │ │ ├── osm-mainroads.prj │ │ ├── osm-mainroads.shp │ │ ├── osm-mainroads.shx │ │ ├── osm-motorways.dbf │ │ ├── osm-motorways.prj │ │ ├── osm-motorways.shp │ │ ├── osm-motorways.shx │ │ ├── osm-places.dbf │ │ ├── osm-places.prj │ │ ├── osm-places.shp │ │ ├── osm-places.shx │ │ ├── osm-roads.dbf │ │ ├── osm-roads.prj │ │ ├── osm-roads.shp │ │ ├── osm-roads.shx │ │ ├── osm-waterareas.dbf │ │ ├── osm-waterareas.prj │ │ ├── osm-waterareas.shp │ │ └── osm-waterareas.shx │ ├── project.mml │ └── style.mss └── road-trip │ ├── .thumb.png │ ├── labels.mss │ ├── project.mml │ ├── roads.mss │ └── style.mss ├── fonts ├── DejaVuSans-Bold.ttf ├── DejaVuSans-BoldOblique.ttf ├── DejaVuSans-ExtraLight.ttf ├── DejaVuSans-Oblique.ttf ├── DejaVuSans.ttf ├── DejaVuSansCondensed-Bold.ttf ├── DejaVuSansCondensed-BoldOblique.ttf ├── DejaVuSansCondensed-Oblique.ttf ├── DejaVuSansCondensed.ttf ├── DejaVuSansMono-Bold.ttf ├── DejaVuSansMono-BoldOblique.ttf ├── DejaVuSansMono-Oblique.ttf ├── DejaVuSansMono.ttf ├── DejaVuSerif-Bold.ttf ├── DejaVuSerif-BoldItalic.ttf ├── DejaVuSerif-Italic.ttf ├── DejaVuSerif.ttf ├── DejaVuSerifCondensed-Bold.ttf ├── DejaVuSerifCondensed-BoldItalic.ttf ├── DejaVuSerifCondensed-Italic.ttf ├── DejaVuSerifCondensed.ttf ├── LICENSE ├── unifont-7.0.05.ttf └── unifont_license.txt ├── index.js ├── lib ├── config.defaults.json ├── crashutil.js ├── create_files.js ├── fsutil.js ├── gitutil.js ├── queue.js ├── redirect.js └── s3.js ├── models ├── Base.bones ├── Config.bones ├── Config.server.bones ├── Datasource.bones ├── Datasource.server.bones ├── Export.bones ├── Exports.bones ├── Exports.server.bones ├── Favorite.bones ├── Favorites.bones ├── Layer.bones ├── Layers.bones ├── Library.bones ├── Library.server.bones ├── Page.bones ├── Page.server.bones ├── Pages.bones ├── Pages.server.bones ├── Preview.bones ├── Preview.server.bones ├── Project.bones ├── Project.server.bones ├── Projects.bones ├── Projects.server.bones ├── Stylesheet.bones └── Stylesheets.bones ├── package-lock.json ├── package.json ├── platforms └── osx │ └── codesign.sh ├── plugins ├── carto │ ├── package.json │ ├── templates │ │ └── Reference._ │ └── views │ │ └── Carto.bones ├── colors │ ├── package.json │ ├── templates │ │ └── Colors._ │ └── views │ │ └── Colors.bones ├── editor │ ├── package.json │ ├── templates │ │ ├── Colorpicker._ │ │ ├── Editor._ │ │ ├── ProjectStylesheet._ │ │ ├── ProjectSwatch._ │ │ └── Stylesheet._ │ └── views │ │ ├── Stylesheet.bones │ │ └── Stylesheets.bones ├── fonts │ ├── package.json │ ├── templates │ │ └── Fonts._ │ └── views │ │ └── Fonts.bones └── templates │ ├── package.json │ ├── templates │ └── Templates._ │ └── views │ └── Templates.bones ├── rebuild_cxx.sh ├── servers ├── App.bones ├── Core.bones ├── Route.bones └── Tile.bones ├── templates ├── App._ ├── Autostyle._ ├── Config._ ├── Datasource._ ├── DatasourceRows._ ├── Error._ ├── Exports._ ├── Layer._ ├── Layers._ ├── Library._ ├── Manual._ ├── Map._ ├── Metadata._ ├── Modal._ ├── Pane._ ├── Plugin._ ├── Plugins._ ├── Preview._ ├── Project._ ├── ProjectAdd._ ├── ProjectLayer._ └── Projects._ ├── test ├── abilities.test.js ├── check_shared_libs.py ├── config.test.js ├── datasource.test.js ├── duplicate_module.test.js ├── export.test.js ├── fixtures │ ├── anti-meridian-export-job.json │ ├── countries.sqlite │ ├── create-project.json │ ├── created-project.json │ ├── datasource-postgis-features.json │ ├── datasource-postgis.json │ ├── datasource-shp-features.json │ ├── datasource-shp.json │ ├── datasource-sqlite.json │ ├── existing-project.json │ ├── export-job.json │ ├── invalid-project.json │ ├── pristine │ │ └── project │ │ │ └── demo_01 │ │ │ ├── project.mml │ │ │ └── style.mss │ └── tilemill_test.sql ├── init.js ├── project.test.js ├── support │ └── start.js └── tile.test.js ├── tilemill.sh ├── utils ├── OLD │ ├── 900913.sql │ └── legacy-postgis-gist.sql ├── counts.sql ├── default.style ├── indexes.sql ├── installdb.sh ├── installtilemill.sh ├── loadosm.sh └── runclient.sh └── views ├── App.bones ├── Config.bones ├── Datasource.bones ├── Error.bones ├── Exports.bones ├── Layer.bones ├── Layers.bones ├── Library.bones ├── Manual.bones ├── Map.bones ├── Metadata.bones ├── Modal.bones ├── Plugins.bones ├── Preview.bones ├── Project.bones ├── ProjectAdd.bones └── Projects.bones /.dockerignore: -------------------------------------------------------------------------------- 1 | .dockerignore 2 | node_modules 3 | npm-debug.log 4 | Dockerfile 5 | .git 6 | .gitignore 7 | utils 8 | test 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve TileMill 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Environment: (Note: We are not setup to test on Linux or Windows so help may be slower on those OSs)** 14 | - OS & Version: [e.g. MacOS Mojave] 15 | - Browser & Version: [e.g. Safari 12.0.3] 16 | - Node Version [e.g. v8.15.0] (you can type nvm version at a terminal prompt to find this) 17 | 18 | **To Reproduce** 19 | Steps to reproduce the behavior: 20 | 1. Go to '...' 21 | 2. Click on '....' 22 | 3. Scroll down to '....' 23 | 4. See error 24 | 25 | **Expected behavior** 26 | A clear and concise description of what you expected to happen. 27 | 28 | **Installation Method** 29 | If this is a problem installing or running TileMill after an installation, please describe the method you used to install TileMill. 30 | 31 | **Screenshots and logfile** 32 | If applicable, add screenshots or a copy of your terminal output to help explain your problem. 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? If yes, please describe. If no, remove this section.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution or feature that you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/infrastructure-enhancement.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Infrastructure Enhancement 3 | about: Describe an enhancement that should be made to the TileMill infrastructure. 4 | title: '' 5 | labels: infrastructure 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Description of the infrastructure enhancement.** 11 | A clear and concise description of what should be improved/changed. 12 | 13 | **Reason for improving this aspect of the infrastructure?** 14 | A clear and concise description of why this enhancement is needed or a good idea. 15 | 16 | **Additional context** 17 | Add any other context about the request. 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /_site 3 | /platforms/osx/build 4 | /node_modules 5 | /test/fixtures/files 6 | npm-debug.log 7 | VERSION 8 | platforms/osx/Externals/Sparkle/source 9 | examples/geography-class/layers 10 | examples/road-trip/layers 11 | examples/control-room/layers 12 | /.vscode 13 | plugins/tilemill-autopilot/ 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | sudo: false 4 | 5 | node_js: 6 | - "0.10" 7 | # tests failing for unknown reasons 8 | #- "4" 9 | 10 | addons: 11 | postgresql: "9.3" 12 | apt: 13 | sources: 14 | - ubuntu-toolchain-r-test 15 | packages: 16 | - libstdc++6 # upgrade libstdc++ on linux to support C++11 17 | - libwebkit-dev 18 | 19 | before_install: 20 | - createdb template_postgis 21 | - psql -c "CREATE EXTENSION postgis" template_postgis 22 | 23 | install: 24 | - npm install --fallback-to-build=false 25 | - python test/check_shared_libs.py node_modules/ 26 | 27 | before_script: 28 | - npm ls 29 | 30 | script: 31 | - npm test 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build Stage 2 | FROM node:8.15 AS BUILD 3 | 4 | WORKDIR /usr/src/app 5 | # Copy content of git repo to container 6 | COPY ./package.json /usr/src/app/ 7 | COPY ./package-lock.json /usr/src/app/ 8 | 9 | RUN npm install --only=production && npm prune --production 10 | 11 | # Production Stage 12 | FROM node:8.15-slim 13 | 14 | # Copy tilemill and node modules to new container 15 | WORKDIR /usr/src/app 16 | COPY --chown=node:node --from=BUILD /usr/src/app/node_modules /usr/src/app/node_modules 17 | COPY --chown=node:node . /usr/src/app 18 | 19 | USER node 20 | # Export port for tiles 21 | EXPOSE 20008 22 | # Export port for webpage 23 | EXPOSE 20009 24 | 25 | CMD ["node", "/usr/src/app/index.js", "--listenHost=0.0.0.0"] 26 | 27 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c), MapBox 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | - Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | - Redistributions in binary form must reproduce the above copyright notice, this 10 | list of conditions and the following disclaimer in the documentation and/or 11 | other materials provided with the distribution. 12 | - Neither the name "MapBox" nor the names of its contributors may be used to 13 | endorse or promote products derived from this software without specific prior 14 | written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 20 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 23 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /_posts/docs/reference/0204-03-01-project-settings.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: docs 3 | section: help 4 | category: reference 5 | tag: Reference 6 | title: Project settings 7 | permalink: /docs/manual/project-settings/ 8 | --- 9 | You can adjust a variety project settings using the **Settings** panel. The panel is divided into three sections. 10 | 11 | ## Project 12 | 13 | You can set the name, description, bounding box and other metadata for the project on the **Project** tab. 14 | 15 | ## Tooltips 16 | 17 | The **Tooltips** tab allows you to make your maps interactive with dynamic tooltips that appear when you hover or click on a feature (any point or polygon). The tooltips can contain HTML and are useful for revealing additional data or images about the data on the map. 18 | 19 | First, select the **Layer** that you would like to use for interaction data. TileMill only supports one interactive layer at a time. After selecting a layer, the available data fields for the layer will be listed in the form of [Mustache](http://mustache.github.com/) tags. 20 | 21 | These tags can be used in Location, Teaser, or Full fields and they will be replaced with the appropriate value when you interact with the map. 22 | 23 | By default, the **Teaser** content appears when you hover over a feature and the **Full** content appears when you click on the feature. 24 | 25 | You can use the **Location** field to define a URL to be loaded when a feature is clicked. 26 | 27 | ### Allowed HTML 28 | 29 | For security, unsafe HTML in tooltips is sanitized and JavaScript code is removed. If you want to build sophisticated map interaction with JavaScript on your own website, you can write custom code using the [Wax](http://mapbox.com/wax/) library. 30 | 31 | ## Legend 32 | 33 | The **Legend** tab allows to you to create a legend for your map. Use it to explain what the colors and symbols used in your map mean. By default, the legend is always visible. 34 | 35 | ![Example legend]({{site.baseurl}}/assets/manual/legend.png) 36 | 37 | Like tooltips, the HTML in legends is sanitized for security. 38 | 39 | -------------------------------------------------------------------------------- /_posts/docs/reference/0204-07-01-tilemill-settings.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: docs 3 | section: help 4 | category: reference 5 | tag: Reference 6 | title: TileMill settings 7 | permalink: /docs/manual/tilemill-settings/ 8 | --- 9 | 10 | ## Documents 11 | 12 | The directory where TileMill stores files for projects and exports. If you want to keep your current projects, move the directory before changing this setting. 13 | 14 | ## Mapbox Account 15 | 16 | The [Mapbox](https://mapbox.com) account TileMill is authorized to upload maps to. MapBox provides hosting for maps created in TileMill. [Register](http://mapbox.com/plans/) for a free MapBox account. 17 | 18 | ## HTTP Proxy 19 | 20 | If your computer uses a HTTP proxy, you will need to specify the details for TileMill to work correctly. The proxy details need to be entered in the form of `http://user:pass@hostname:port` where *user*, *pass*, *hostname* and *port* are replaced with the relevant proxy details. After entering and saving this setting, you will need to restart TileMill. You should then be able to make use of TileMill's features requiring network access. 21 | 22 | *Note: TileMill does not support proxies for authorization. To authorize, open `http://localhost:20009` in a browser after starting TileMill.* 23 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | - NODE_VERSION: 0.10.33 4 | platform: x64 5 | - NODE_VERSION: 0.10.33 6 | platform: x86 7 | 8 | shallow_clone: true 9 | 10 | services: 11 | - postgresql94 #if changing this, also change PATH below 12 | 13 | install: 14 | - SET PGUSER=postgres 15 | - SET PGPASSWORD=Password12! 16 | - SET PATH=C:\Program Files\PostgreSQL\9.4\bin\;%PATH% 17 | # find and remove default node.exe to avoid conflicts 18 | - node -e "console.log(process.execPath)" > node_path.txt 19 | - SET /p NODE_EXE_PATH= /dev/null \ 27 | || sqlite3 $db "ALTER TABLE $table ADD COLUMN flag_png text;" 28 | 29 | for flagpng in flags/*.png; do 30 | adm0_a3="$(basename $flagpng .png)" 31 | flagdata="$(base64 -w0 $flagpng)" 32 | sqlite3 $db "UPDATE $table SET flag_png = '$flagdata' WHERE adm0_a3 = '$adm0_a3';" 33 | done 34 | 35 | echo "Done." 36 | -------------------------------------------------------------------------------- /examples/geography-class/layers/world_extent_wgs84.geojson: -------------------------------------------------------------------------------- 1 | { 2 | "type": "FeatureCollection", 3 | "features": [ 4 | 5 | { "type": "Feature", 6 | "properties": { "FID": 0.000000 }, 7 | "geometry": 8 | { "type": "Polygon", 9 | "coordinates": [ [ 10 | [ -180.0, -85.051129 ], 11 | [ -180.0, 85.051129 ], 12 | [ 180.0, 85.051129 ], 13 | [ 180.0, -85.051129 ], 14 | [ -180.0, -85.051129 ] 15 | ] ] 16 | } 17 | } 18 | 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /examples/geography-class/textures/paperfolds_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/geography-class/textures/paperfolds_256.png -------------------------------------------------------------------------------- /examples/geography-class/textures/paperfolds_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/geography-class/textures/paperfolds_512.png -------------------------------------------------------------------------------- /examples/open-streets-dc/.thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/.thumb.png -------------------------------------------------------------------------------- /examples/open-streets-dc/images/water.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/images/water.png -------------------------------------------------------------------------------- /examples/open-streets-dc/images/wood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/images/wood.png -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dc-coastline.dbf: -------------------------------------------------------------------------------- 1 | _A WFIDN 9713 9790 -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dc-coastline.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Popular_Visualisation_CRS_Mercator_deprecated",GEOGCS["GCS_Popular Visualisation CRS",DATUM["D_Popular_Visualisation_Datum",SPHEROID["Popular_Visualisation_Sphere",6378137,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator"],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],PARAMETER["standard_parallel_1",0.0]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dc-coastline.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/dc-coastline.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dc-coastline.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/dc-coastline.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.dbf -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.index: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.index -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Google_Maps_Global_Mercator",GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator_2SP"],PARAMETER["standard_parallel_1",0],PARAMETER["latitude_of_origin",0],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/dcgis_water/WaterPly_900913.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-landusages.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-landusages.dbf -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-landusages.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Popular_Visualisation_CRS_Mercator_deprecated",GEOGCS["GCS_Popular Visualisation CRS",DATUM["D_Popular_Visualisation_Datum",SPHEROID["Popular_Visualisation_Sphere",6378137,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator"],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],PARAMETER["standard_parallel_1",0.0]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-landusages.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-landusages.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-landusages.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-landusages.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-mainroads.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-mainroads.dbf -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-mainroads.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Popular_Visualisation_CRS_Mercator_deprecated",GEOGCS["GCS_Popular Visualisation CRS",DATUM["D_Popular_Visualisation_Datum",SPHEROID["Popular_Visualisation_Sphere",6378137,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator"],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],PARAMETER["standard_parallel_1",0.0]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-mainroads.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-mainroads.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-mainroads.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-mainroads.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-motorways.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-motorways.dbf -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-motorways.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Popular_Visualisation_CRS_Mercator_deprecated",GEOGCS["GCS_Popular Visualisation CRS",DATUM["D_Popular_Visualisation_Datum",SPHEROID["Popular_Visualisation_Sphere",6378137,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator"],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],PARAMETER["standard_parallel_1",0.0]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-motorways.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-motorways.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-motorways.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-motorways.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-places.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-places.dbf -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-places.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Popular_Visualisation_CRS_Mercator_deprecated",GEOGCS["GCS_Popular Visualisation CRS",DATUM["D_Popular_Visualisation_Datum",SPHEROID["Popular_Visualisation_Sphere",6378137,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator"],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],PARAMETER["standard_parallel_1",0.0]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-places.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-places.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-places.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-places.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-roads.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-roads.dbf -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-roads.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Popular_Visualisation_CRS_Mercator_deprecated",GEOGCS["GCS_Popular Visualisation CRS",DATUM["D_Popular_Visualisation_Datum",SPHEROID["Popular_Visualisation_Sphere",6378137,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator"],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],PARAMETER["standard_parallel_1",0.0]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-roads.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-roads.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-roads.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-roads.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-waterareas.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-waterareas.dbf -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-waterareas.prj: -------------------------------------------------------------------------------- 1 | PROJCS["Popular_Visualisation_CRS_Mercator_deprecated",GEOGCS["GCS_Popular Visualisation CRS",DATUM["D_Popular_Visualisation_Datum",SPHEROID["Popular_Visualisation_Sphere",6378137,0]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Mercator"],PARAMETER["central_meridian",0],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],PARAMETER["standard_parallel_1",0.0]] -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-waterareas.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-waterareas.shp -------------------------------------------------------------------------------- /examples/open-streets-dc/layers/osm-waterareas.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/open-streets-dc/layers/osm-waterareas.shx -------------------------------------------------------------------------------- /examples/open-streets-dc/style.mss: -------------------------------------------------------------------------------- 1 | /********************************************************** 2 | 3 | Open Streets, DC 4 | ================ 5 | 6 | *An example of street-level map design.* 7 | 8 | Data used by this map is © OpenStreetMap contributors and 9 | distributed under the terms of the Open Database License. 10 | See for details. 11 | 12 | Pattern images derived from designs by Subtle Patterns and 13 | licensed CC-BY-SA. See for details. 14 | 15 | The shapefiles used in this project are based on those 16 | provided by Mike Migurski at . 17 | You can swap out the DC data for any other city there by 18 | downloading the Imposm shapefile package. 19 | 20 | ***********************************************************/ 21 | 22 | /* ---- PALETTE ---- */ 23 | 24 | @water:#c0d8ff; 25 | @park:#cea; 26 | @land:#f5fdf0; 27 | @school:#f8e8c8; 28 | 29 | Map { 30 | background-color:@land; 31 | } 32 | 33 | #water, 34 | #ocean { 35 | polygon-fill:@water; 36 | polygon-gamma:0.5; // reduces gaps between shapes 37 | polygon-pattern-file:url(images/water.png); 38 | polygon-pattern-comp-op:color-burn; 39 | polygon-pattern-alignment:global; // keeps it seamless 40 | } 41 | 42 | #landusages[zoom>6] { 43 | [type='forest'], 44 | [type='wood'] { 45 | polygon-fill:@park; 46 | polygon-pattern-file:url(images/wood.png); 47 | polygon-pattern-comp-op:multiply; 48 | } 49 | [type='cemetery'], 50 | [type='common'], 51 | [type='golf_course'], 52 | [type='park'], 53 | [type='pitch'], 54 | [type='recreation_ground'], 55 | [type='village_green'] { 56 | polygon-fill:@park; 57 | } 58 | } 59 | 60 | #landusages[zoom>=12] { 61 | [type='school'], 62 | [type='college'], 63 | [type='university'] { 64 | polygon-fill: @school; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /examples/road-trip/.thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/examples/road-trip/.thumb.png -------------------------------------------------------------------------------- /examples/road-trip/labels.mss: -------------------------------------------------------------------------------- 1 | @serif:"Times New Roman Regular","FreeSerif Medium","DejaVu Serif Book"; 2 | @serif_italic:"Times New Roman Italic","FreeSerif Italic","DejaVu Serif Italic"; 3 | @sans:"Arial Regular","Liberation Sans Regular","DejaVu Sans Book"; 4 | @sans-bold:"Arial Bold","Liberation Sans Bold","DejaVu Sans Bold"; 5 | 6 | #country_label[zoom>2][zoom<6][ADM0_A3='CAN'], 7 | #country_label[zoom>2][zoom<6][ADM0_A3='USA'], 8 | #country_label[zoom>2][zoom<6][ADM0_A3='MEX'] { 9 | text-name:"[NAME]"; 10 | text-face-name:@serif; 11 | text-transform:uppercase; 12 | text-character-spacing:1; 13 | text-line-spacing:4; 14 | text-size:14; 15 | text-wrap-width:120; 16 | text-allow-overlap:true; 17 | text-halo-radius:2; 18 | text-halo-fill:rgba(255,255,255,0.75); 19 | } 20 | 21 | #city[SOV_A3='USA'][SCALERANK<4][zoom>2], 22 | #city[SOV_A3='USA'][SCALERANK=4][zoom>3], 23 | #city[SOV_A3='USA'][SCALERANK=5][zoom>4], 24 | #city[SOV_A3='USA'][SCALERANK>=6][zoom>5] { 25 | text-name:"[NAME]"; 26 | text-face-name:@sans-bold; 27 | text-size:9; 28 | text-halo-radius:1; 29 | text-halo-fill:rgba(255,255,255,0.75); 30 | } 31 | 32 | #park_label[zoom>5] { 33 | text-name:"[Unit_Name]"; 34 | text-face-name:@serif_italic; 35 | text-fill:#063; 36 | text-size:11; 37 | text-halo-radius:1; 38 | text-halo-fill:rgba(255,255,255,0.75); 39 | text-wrap-width:30; 40 | text-line-spacing:2; 41 | } 42 | 43 | #geo-region { 44 | text-name:"[Name]"; 45 | text-face-name:@serif_italic; 46 | text-fill:#036; 47 | text-size:11; 48 | text-halo-radius:1; 49 | text-halo-fill:rgba(255,255,255,0.75); 50 | text-wrap-width:30; 51 | text-line-spacing:2; 52 | } 53 | -------------------------------------------------------------------------------- /examples/road-trip/roads.mss: -------------------------------------------------------------------------------- 1 | #road::l[Type='Major Highway'][zoom>2], 2 | #road::l[Type='Secondary Highway'][zoom>2] { 3 | line-color:#C33; 4 | } 5 | /*#road[SOV_A3='USA'][Type='Major Highway'][zoom>1], 6 | #road[SOV_A3='USA'][Type='Secondary Highway'][zoom>1] { 7 | line-color:#F00; 8 | }*/ 9 | 10 | /* Roads - Z3 */ 11 | #road::l[Type='Major Highway'][zoom=3] { line-width:0.5; } 12 | #road::l[Type='Secondary Highway'][zoom=3] { line-width:0.2; } 13 | /* Roads - Z4 */ 14 | #road::l[Type='Major Highway'][zoom=4] { line-width:0.6; } 15 | #road::l[Type='Secondary Highway'][zoom=4] { line-width:0.3; } 16 | /* Roads - Z5 */ 17 | #road::l[Type='Major Highway'][zoom=5] { line-width:1.2; } 18 | #road::l[Type='Secondary Highway'][zoom=5] { line-width:0.6; } 19 | /* Roads - Z6 */ 20 | #road::l[Type='Major Highway'][zoom=6] { line-width:2; } 21 | #road::l[Type='Secondary Highway'][zoom=6] { line-width:0.8; } 22 | /* Roads - Z7 */ 23 | #road::l[Type='Major Highway'][zoom=7] { line-width:2.6; } 24 | #road::l[Type='Secondary Highway'][zoom=7] { line-width:1.3; } 25 | 26 | #road_na[zoom>5][TYPE='Primary'] { 27 | line-color:#E63; 28 | line-width:0.8; 29 | } 30 | 31 | /* Railroads */ 32 | #rail[zoom>4] { 33 | line-color:#999; 34 | line-width:0.6; 35 | } -------------------------------------------------------------------------------- /examples/road-trip/style.mss: -------------------------------------------------------------------------------- 1 | /*********************************************************************** 2 | 3 | 'Road Trip' 4 | =========== 5 | 6 | A map of the United States inspired by the impossible-to-fold maps in 7 | your glovebox. 8 | 9 | ***********************************************************************/ 10 | 11 | @land: #fff1cf; 12 | @water: #C0E0F8; 13 | @waterline: #8CE; 14 | 15 | Map { 16 | background-color:@water; 17 | } 18 | 19 | #countries::outline { 20 | line-color:@waterline; 21 | line-width:1.6; 22 | } 23 | #countries::fill { 24 | polygon-fill:@land; 25 | polygon-gamma:0.75; 26 | [ADM0_A3='USA'] { polygon-fill:lighten(@land, 7); } 27 | } 28 | 29 | #lake[zoom>=0][ScaleRank<=2], 30 | #lake[zoom>=1][ScaleRank=3], 31 | #lake[zoom>=2][ScaleRank=4], 32 | #lake[zoom>=3][ScaleRank=5], 33 | #lake[zoom>=4][ScaleRank=6], 34 | #lake[zoom>=5][ScaleRank=7], 35 | #lake[zoom>=6][ScaleRank=8], 36 | #lake[zoom>=7][ScaleRank=9] { 37 | ::outline { line-color:@waterline; } 38 | ::fill { polygon-fill:@water; } 39 | } 40 | 41 | .park { line-color:#AD9; } 42 | .park.area { polygon-fill:#DEB; } 43 | 44 | #country_border::glow[zoom>2] { 45 | line-color:#F60; 46 | line-opacity:0.33; 47 | line-width:4; 48 | } 49 | 50 | #country_border { line-color:#408; } 51 | #country_border[zoom<3] { line-width:0.4; } 52 | #country_border[zoom=3] { line-width:0.6; } 53 | #country_border[zoom=4] { line-width:0.8; } 54 | #country_border[zoom=5] { line-width:1.0; } 55 | 56 | #country_border_marine { 57 | line-color:#A06; 58 | line-dasharray:8,2; 59 | line-opacity:0.3; 60 | line-width:0.8; 61 | } 62 | 63 | #state_line::glow[ADM0_A3='USA'], 64 | #state_line::glow[ADM0_A3='CAN'] { 65 | [zoom>2] { 66 | line-color:#FD0; 67 | line-opacity:0.2; 68 | line-width:3; 69 | } 70 | } 71 | #state_line[ADM0_A3='USA'], 72 | #state_line[ADM0_A3='CAN'] { 73 | [zoom>2] { 74 | line-dasharray:2,2,10,2; 75 | line-width:0.6; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /fonts/DejaVuSans-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSans-Bold.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans-BoldOblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSans-BoldOblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans-ExtraLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSans-ExtraLight.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans-Oblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSans-Oblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSans.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansCondensed-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansCondensed-Bold.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansCondensed-BoldOblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansCondensed-BoldOblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansCondensed-Oblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansCondensed-Oblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansCondensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansCondensed.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansMono-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansMono-Bold.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansMono-BoldOblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansMono-BoldOblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansMono-Oblique.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansMono-Oblique.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSansMono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSansMono.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerif-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerif-Bold.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerif-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerif-BoldItalic.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerif-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerif-Italic.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerif.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerif.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerifCondensed-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerifCondensed-Bold.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerifCondensed-BoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerifCondensed-BoldItalic.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerifCondensed-Italic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerifCondensed-Italic.ttf -------------------------------------------------------------------------------- /fonts/DejaVuSerifCondensed.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/DejaVuSerifCondensed.ttf -------------------------------------------------------------------------------- /fonts/unifont-7.0.05.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/fonts/unifont-7.0.05.ttf -------------------------------------------------------------------------------- /fonts/unifont_license.txt: -------------------------------------------------------------------------------- 1 | Unifoundry.com exists to help get Unicode fonts and utilities into the hands of those who need them. 2 | 3 | My first endeavor was to create several utilities for the free GNU Unifont bitmap font of Roman Czyborra. As of 20 June 2008 (by coincidence the Summer Solstice), the GNU Unifont has a glyph for every printable code point in the Unicode Basic Multilingual Plane (BMP). The BMP is the first Unicode "plane" of 65,536 code points, and includes character encoding for most of the world's modern scripts. Roman Czyborra began this effort 10 years ago. 4 | 5 | The "unifont" font has undergone further refinement and correction since then. Please replace all previous versions with the 2008-08-20 release. 6 | 7 | Two utilities convert any 256-code point block of Unifont glyphs to and from Windows Bitmap and Wireless Bitmap files, with code points displayed in a labeled 16 by 16 grid. These blocks aren't restricted to the BMP, though the GNU Unifont only supports the BMP. The software was developed using the cygwin package in a Microsoft Windows XP environment, but should compile on just about any platform that has a C compiler, especially on Unix/Linux systems. 8 | 9 | By converting GNU Unifont's .hex encoding into bitmaps, these utilities allow glyphs to be viewed and edited in their correct aspect ratio with a graphics editor. Hopefully this will make adding new glyphs to the GNU Unifont easier. 10 | 11 | My software and is released under the terms of the GNU General Public License (GNU GPL) version 2.0, or (at your option) a later version. The precompiled fonts are released under the terms of the GNU GPL version 2, with the exception that embedding the font in a document does not in itself bind that document to the terms of the GPL. 12 | 13 | If you have any questions, please email unifoundry at this domain name (not spelled out because of spammers). 14 | 15 | — Paul Hardy, GPG Key ID E6E6E390 -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // increase the libuv threadpool size to 1.5x the number of logical CPUs. 4 | process.env.UV_THREADPOOL_SIZE = Math.ceil(Math.max(4, require('os').cpus().length * 1.5)); 5 | process.env.OPENFILEGDB_IN_MEMORY_SPI = "OFF"; 6 | var path = require('path'); 7 | process.env.MAPNIK_FONT_PATH = path.join(__dirname,'fonts'); 8 | 9 | var fs = require('fs'); 10 | // node v6 -> v8 compatibility 11 | var existsSync = require('fs').existsSync || require('path').existsSync; 12 | 13 | process.title = 'tilemill'; 14 | 15 | // This is necessary to make optimist not special-case into coffeescript as 16 | // certain node installs (e.g. ubuntu node ppa) do not use `node` as the binary 17 | // name. 18 | process.argv[0] = 'node'; 19 | 20 | if (process.platform === 'win32') { 21 | // HOME is undefined on windows 22 | process.env.HOME = process.env.USERPROFILE; 23 | // Add custom library paths to the PATH 24 | process.env.PATH = path.join(__dirname,"node_modules/mapnik/lib/binding/"); 25 | } 26 | 27 | // Default --config flag to user's home .tilemill.json config file. 28 | // @TODO find a more elegant way to set a default for this value 29 | // upstream in bones. 30 | var config = path.join(process.env.HOME, '.tilemill/config.json'); 31 | if (existsSync(config)) { 32 | var argv = require('optimist').argv; 33 | argv.config = argv.config || config; 34 | } 35 | 36 | require('@mapbox/tilelive-mapnik').registerProtocols(require('tilelive')); 37 | require('@mapbox/mbtiles').registerProtocols(require('tilelive')); 38 | 39 | require('bones').load(__dirname); 40 | !module.parent && require('bones').start(); 41 | -------------------------------------------------------------------------------- /lib/config.defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 20009, 3 | "tilePort": 20008, 4 | "files": "~/Documents/MapBox", 5 | "examples": true, 6 | "sampledata": true, 7 | "host": false, 8 | "listenHost": "127.0.0.1", 9 | "server": true, 10 | "verbose": "on" 11 | } 12 | -------------------------------------------------------------------------------- /lib/create_files.js: -------------------------------------------------------------------------------- 1 | var existsSync = require('fs').existsSync || require('path').existsSync; 2 | var fsutil = require('./fsutil'); 3 | var path = require('path'); 4 | 5 | function init_dirs(dirs, settings) { 6 | if (!existsSync(settings.files)) { 7 | console.warn('Creating files dir %s', settings.files); 8 | if (process.platform === 'win32') { 9 | var match = settings.files.match(/^[a-zA-Z]:/); 10 | if (match) { 11 | throw new Error("Drive does not exist: " + match[0]); 12 | } 13 | } 14 | fsutil.mkdirpSync(settings.files, 0755); 15 | } 16 | dirs.forEach(function(key) { 17 | var dir = path.join(settings.files, key); 18 | if (!existsSync(dir)) { 19 | fsutil.mkdirpSync(dir, 0755); 20 | console.warn('Creating %s dir %s', key, dir); 21 | if (key === 'project' && settings.examples) { 22 | var examples = path.resolve(path.join(__dirname, '..', 'examples')); 23 | fsutil.cprSync(examples, dir); 24 | } else if (key === 'cache' && settings.sampledata) { 25 | var shapefile = '82945364-10m-admin-0-countries'; 26 | var data = path.resolve(path.join(__dirname, '..', 'data', shapefile)); 27 | fsutil.cprSync(data, path.resolve(path.join(dir, shapefile))); 28 | } 29 | } 30 | }); 31 | } 32 | 33 | module.exports = { 34 | init_dirs: init_dirs 35 | }; 36 | -------------------------------------------------------------------------------- /lib/gitutil.js: -------------------------------------------------------------------------------- 1 | // Create the VERSION file which will be read by commands/core.bones to populate the unique version 2 | // in the heading of the project settings page. 3 | var exec = require('child_process').exec; 4 | var fs = require('fs'); 5 | var package_json = require('../package.json'); 6 | 7 | var child = exec('git describe --tags --always', 8 | function(error, stdout, stderr) { 9 | if (error !== null) { 10 | console.log('exec error: ' + error); 11 | } else { 12 | var hash = stdout; 13 | if (hash[0] == 'v') { 14 | //var version_file = hash + hash.slice(1, -10).replace('-', '.') + '\n'; 15 | var version_file = hash; 16 | fs.writeFileSync('VERSION', version_file); 17 | } else { 18 | // no tag found likely due to shallow clone (--depth=N) 19 | var version_file = 'v' + package_json.version + '-' + hash; 20 | fs.writeFileSync('VERSION', version_file); 21 | } 22 | } 23 | }); 24 | -------------------------------------------------------------------------------- /lib/queue.js: -------------------------------------------------------------------------------- 1 | var util = require('util'); 2 | var EventEmitter = require('events').EventEmitter; 3 | 4 | module.exports = Queue; 5 | function Queue(callback, concurrency, timeout) { 6 | this.callback = callback; 7 | this.concurrency = concurrency || 10; 8 | this.timeout = timeout || 0; 9 | this.add = this.add.bind(this); 10 | this.next = this.next.bind(this); 11 | this.invoke = this.invoke.bind(this); 12 | this.queue = []; 13 | this.running = 0; 14 | } 15 | util.inherits(Queue, EventEmitter); 16 | 17 | Queue.prototype.add = function(item) { 18 | this.queue.push(item); 19 | if (this.running < this.concurrency) { 20 | this.running++; 21 | this.next(); 22 | } 23 | }; 24 | 25 | Queue.prototype.invoke = function() { 26 | if (this.queue.length) { 27 | this.callback(this.queue.shift(), this.next); 28 | } else { 29 | this.next(); 30 | } 31 | }; 32 | 33 | Queue.prototype.next = function(err) { 34 | if (this.queue.length) { 35 | if (this.timeout) { 36 | setTimeout(this.invoke, this.timeout); 37 | } else { 38 | process.nextTick(this.invoke); 39 | } 40 | } else { 41 | this.running--; 42 | if (!this.running) { 43 | this.emit('empty'); 44 | } 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /lib/redirect.js: -------------------------------------------------------------------------------- 1 | function format(output) { 2 | var prefix = '[' + process.title + '] '; 3 | if (output[output.length - 1] === '\n') { 4 | output = output.substring(0, output.length - 1); 5 | } 6 | console.warn(prefix + output.split('\n').join('\n' + prefix)); 7 | } 8 | 9 | function onData(proc) { 10 | proc.stdout.setEncoding('utf8'); 11 | proc.stdout.on('data', format.bind(global)); 12 | proc.stderr.setEncoding('utf8'); 13 | proc.stderr.on('data', format.bind(global)); 14 | } 15 | 16 | module.exports = { 17 | onData: onData 18 | }; 19 | -------------------------------------------------------------------------------- /models/Config.bones: -------------------------------------------------------------------------------- 1 | // Config 2 | // ------ 3 | model = Backbone.Model.extend({}); 4 | 5 | model.prototype.schema = { 6 | 'id': 'Config', 7 | 'type': 'object', 8 | 'properties': { 9 | 'port': { 10 | 'type': 'integer' 11 | }, 12 | 'files': { 13 | 'type': 'string' 14 | }, 15 | 'httpProxy': { 16 | 'type': 'string' 17 | }, 18 | 'verbose': { 19 | 'type': 'string', 20 | 'enum': ['on', 'off'], 21 | } 22 | } 23 | }; 24 | 25 | model.prototype.initialize = function() { 26 | this.id = 'config'; 27 | }; 28 | 29 | model.prototype.url = function() { 30 | return '/api/Config/config'; 31 | }; 32 | -------------------------------------------------------------------------------- /models/Datasource.bones: -------------------------------------------------------------------------------- 1 | // Datasource (read-only) 2 | // ---------------------- 3 | // Model. Inspection metadata about a map layer. Use `fetchFeatures()` to do 4 | // a datasource fetch that includes layer feature objects. 5 | model = Backbone.Model.extend({}); 6 | 7 | // @TODO either as a feature or a bug, object attributes are not set 8 | // automatically when passed to the constructor. We set it manually here. 9 | model.prototype.initialize = function(attributes, options) { 10 | this.set({'fields': attributes.fields}); 11 | this.options = options; 12 | }; 13 | 14 | model.prototype.url = function() { 15 | if (Bones.server) return; 16 | 17 | var attr = this.attributes; 18 | if (this.getFeatures) attr.features = true; 19 | if (this.getInfo) attr.info = true; 20 | return 'http://' 21 | + window.abilities.tileUrl 22 | + '/datasource/' 23 | + this.get('id') 24 | + '?' + $.param(attr); 25 | }; 26 | 27 | model.prototype.fetchFeatures = function(options) { 28 | this.getFeatures = true; 29 | this.fetch(options); 30 | }; 31 | 32 | model.prototype.fetchInfo = function(options) { 33 | this.getInfo = true; 34 | this.fetch(options); 35 | }; 36 | -------------------------------------------------------------------------------- /models/Exports.bones: -------------------------------------------------------------------------------- 1 | // Exports 2 | // ------- 3 | // Collection. List of all Exports. 4 | model = Backbone.Collection.extend({}); 5 | 6 | model.prototype.model = models.Export; 7 | model.prototype.url = '/api/Export'; 8 | model.prototype.comparator = function(m) { return m.get('created') * -1; } 9 | -------------------------------------------------------------------------------- /models/Favorite.bones: -------------------------------------------------------------------------------- 1 | // Favorite 2 | // -------- 3 | // Model. A URI favorite. 4 | model = Backbone.Model.extend(); 5 | 6 | model.prototype.schema = { 7 | 'id': 'Favorite', 8 | 'type': 'object', 9 | 'properties': { 10 | 'id': { 11 | 'type': 'string', 12 | 'required': true 13 | }, 14 | 'created': { 15 | 'type': 'integer' 16 | } 17 | } 18 | }; 19 | 20 | model.prototype.url = function() { 21 | return '/api/Favorite/' + encodeURIComponent(this.id); 22 | }; 23 | -------------------------------------------------------------------------------- /models/Layers.bones: -------------------------------------------------------------------------------- 1 | // Layers 2 | // ------ 3 | // Collection. List of Layer models. This collection is a child of the 4 | // Project model and updates its parent on update events. 5 | // **This collection is not backed directly by the server.** 6 | model = Backbone.Collection.extend({}); 7 | 8 | model.prototype.model = models.Layer; 9 | 10 | model.prototype.initialize = function(models, options) { 11 | var that = this; 12 | var change = function() { 13 | this.parent.set({ 'Layer': that }); 14 | this.parent.change(); 15 | }; 16 | this.parent = options.parent; 17 | this.bind('refresh', change); 18 | this.bind('change', change); 19 | this.bind('add', change); 20 | this.bind('remove', change); 21 | }; 22 | -------------------------------------------------------------------------------- /models/Library.bones: -------------------------------------------------------------------------------- 1 | // Library 2 | // -------- 3 | // Model. Stores settings for a given asset library type, e.g. a local file 4 | // directory or an Amazon S3 bucket. 5 | model = Backbone.Model.extend(); 6 | 7 | model.prototype.schema = { 8 | 'type': 'object', 9 | 'properties': { 10 | 'id': { 11 | 'type': 'string', 12 | 'required': true 13 | }, 14 | 'location': { 15 | 'type': 'string', 16 | 'description': 'Current working dir or URL location.' 17 | }, 18 | 'assets': { 19 | 'type': 'array', 20 | 'description': 'Objects in this library.', 21 | 'items': { 22 | 'type': 'object', 23 | 'properties': { 24 | 'name': { 25 | 'type': 'string', 26 | 'description': 'Human readable name of this asset.' 27 | }, 28 | 'location': { 29 | 'type': 'string', 30 | 'description': 'Asset changes the Library\'s location.' 31 | }, 32 | 'uri': { 33 | 'type': 'string', 34 | 'description': 'URI of this asset.' 35 | } 36 | } 37 | } 38 | } 39 | } 40 | }; 41 | 42 | model.prototype.url = function() { 43 | var url = '/api/Library/' + this.id; 44 | if (!Bones.server && this.get('location') && this.get('project')) { 45 | url += '?' + $.param({location:this.get('location'), project:this.get('project')}); 46 | } 47 | return url; 48 | }; 49 | 50 | model.prototype.initialize = function(attributes, options) { 51 | options = options || {}; 52 | if (options.location) this.set({'location': options.location, project:options.project}); 53 | }; 54 | 55 | -------------------------------------------------------------------------------- /models/Page.bones: -------------------------------------------------------------------------------- 1 | // Doc 2 | // --- 3 | // Model. Retrieve a text doc page from the server. 4 | model = Backbone.Model.extend({}); 5 | model.prototype.url = function() { return '/api/Page/' + this.get('id'); }; 6 | model.prototype.defaults = {id: '0204-01-01-introduction.md'}; 7 | -------------------------------------------------------------------------------- /models/Page.server.bones: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | 4 | models.Page.prototype.sync = function(method, model, success, error) { 5 | if (method !== 'read') return error('Method not supported.'); 6 | var filepath = path.resolve(path.join(__dirname, '..', '_posts', 'docs', 'reference', model.id)); 7 | fs.readFile(filepath, 'utf8', function(err, data) { 8 | if (err) return error(err); 9 | data = data.substring(data.indexOf('---', 3) + 3); 10 | data = data.replace(/{{site.baseurl}}\/assets/g, '/assets/tilemill'); 11 | return success({id: model.id, data: data}); 12 | }); 13 | }; 14 | -------------------------------------------------------------------------------- /models/Pages.bones: -------------------------------------------------------------------------------- 1 | model = Backbone.Collection.extend({ 2 | model: models.Page, 3 | url: '/api/Page', 4 | comparator: function(m) { return m.id } 5 | }); 6 | -------------------------------------------------------------------------------- /models/Pages.server.bones: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | 4 | models.Pages.prototype.sync = function(method, model, success, error) { 5 | if (method !== 'read') return error('Method not supported.'); 6 | var filepath = path.resolve(path.join(__dirname, '..', '_posts', 'docs', 'reference')); 7 | fs.readdir(filepath, function(err, data) { 8 | if (err) return error(err); 9 | var models = _(data).map(function(id) { 10 | var title = id.match(/[\d]{4}-[\d]{2}-[\d]{2}-([\w-]+)/)[1]. 11 | replace(/-/g, ' '). 12 | replace(/mapbox/, 'MapBox'); 13 | return { 14 | id: id, 15 | title: title.charAt(0).toUpperCase() + title.slice(1) 16 | }; 17 | }); 18 | return success(models); 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /models/Preview.bones: -------------------------------------------------------------------------------- 1 | // Preview of an mbtiles export. 2 | model = Backbone.Model.extend({}); 3 | model.prototype.url = function() { return '/api/Preview/' + this.id; }; 4 | -------------------------------------------------------------------------------- /models/Preview.server.bones: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var tilelive = require('tilelive'); 3 | var settings = Bones.plugin.config; 4 | 5 | models.Preview.prototype.sync = function(method, model, success, error) { 6 | if (method !== 'read') return error(new Error('Method not supported.')); 7 | var filepath = path.join(settings.files, 'export', model.id); 8 | var uri = {protocol:'mbtiles:',pathname:filepath}; 9 | tilelive.load(uri, function(err, source) { 10 | if (err) return error(err); 11 | source.getInfo(function(err, info) { 12 | if (err) return error(err); 13 | info.tiles = ['http://' + settings.tileUrl + '/tile/' + model.id + '/{z}/{x}/{y}.png?' + (+new Date)]; 14 | info.grids = ['http://' + settings.tileUrl + '/tile/' + model.id + '/{z}/{x}/{y}.grid.json?' + (+new Date)]; 15 | success(_(info).extend({id: model.id })); 16 | }); 17 | }); 18 | }; 19 | 20 | -------------------------------------------------------------------------------- /models/Projects.bones: -------------------------------------------------------------------------------- 1 | // ProjectList 2 | // ----------- 3 | // Collection. All project models. 4 | model = Backbone.Collection.extend({ 5 | model: models.Project, 6 | url: '/api/Project', 7 | comparator: function(project) { 8 | return (project.get('name') || project.get('id')).toLowerCase(); 9 | } 10 | }); 11 | 12 | -------------------------------------------------------------------------------- /models/Projects.server.bones: -------------------------------------------------------------------------------- 1 | models.Projects.prototype.sync = models.Project.prototype.sync; 2 | -------------------------------------------------------------------------------- /models/Stylesheet.bones: -------------------------------------------------------------------------------- 1 | // Stylesheet 2 | // ---------- 3 | // Model. Represents a single map MSS stylesheet. This model is a child of 4 | // the Project model and is saved serialized as part of the parent. 5 | // **This model is not backed directly by the server.** 6 | model = Backbone.Model.extend({}); 7 | 8 | model.prototype.schema = { 9 | 'id': 'Stylesheet', 10 | 'type': 'object', 11 | 'properties': { 12 | 'id': { 13 | 'type': 'string', 14 | 'required': true, 15 | 'pattern': '^[A-Za-z0-9\-_.]+$', 16 | 'title': 'Name', 17 | 'description': 'Name may only include alphanumeric characters, dots, dashes and underscores.' 18 | }, 19 | 'data': { 20 | 'type': 'string', 21 | 'required': true 22 | } 23 | } 24 | }; 25 | 26 | model.prototype.defaults = { 'data': '' }; 27 | 28 | model.prototype.validate = function(attr) { 29 | if (attr.id && 30 | this.collection && 31 | this.collection.get(attr.id) && 32 | this.collection.get(attr.id) !== this) 33 | return new Error(_('Stylesheet "<%=id%>" already exists.').template(attr)); 34 | }; 35 | -------------------------------------------------------------------------------- /models/Stylesheets.bones: -------------------------------------------------------------------------------- 1 | // Stylesheets 2 | // ----------- 3 | // Collection. List of Stylesheet models. This collection is a child of the 4 | // Project model and updates its parent on update events. 5 | // **This collection is not backed directly by the server.** 6 | model = Backbone.Collection.extend({}); 7 | 8 | model.prototype.model = models.Stylesheet; 9 | 10 | model.prototype.initialize = function(models, options) { 11 | var that = this; 12 | var change = function() { 13 | this.parent.set({ 'Stylesheet': that }); 14 | this.parent.change(); 15 | }; 16 | this.parent = options.parent; 17 | this.bind('refresh', change); 18 | this.bind('change', change); 19 | this.bind('add', change); 20 | this.bind('remove', change); 21 | }; 22 | -------------------------------------------------------------------------------- /platforms/osx/codesign.sh: -------------------------------------------------------------------------------- 1 | aws s3 cp "s3://mapbox/mapbox-studio/keys/Developer ID Certification Authority.cer" authority.cer 2 | aws s3 cp "s3://mapbox/mapbox-studio/keys/Developer ID Application: Mapbox, Inc. (GJZR2MEM28).cer" signing-key.cer 3 | aws s3 cp "s3://mapbox/mapbox-studio/keys/Mac Developer ID Application: Mapbox, Inc..p12" signing-key.p12 4 | security create-keychain -p travis signing.keychain \ 5 | && echo "+ signing keychain created" 6 | security import authority.cer -k ~/Library/Keychains/signing.keychain -T /usr/bin/codesign \ 7 | && echo "+ authority cer added to keychain" 8 | security import signing-key.cer -k ~/Library/Keychains/signing.keychain -T /usr/bin/codesign \ 9 | && echo "+ signing cer added to keychain" 10 | security import signing-key.p12 -k ~/Library/Keychains/signing.keychain -P "" -T /usr/bin/codesign \ 11 | && echo "+ signing key added to keychain" 12 | rm authority.cer 13 | rm signing-key.cer 14 | rm signing-key.p12 15 | 16 | # update time to try to avoid occaisonal codesign error of "timestamps differ by N seconds - check your system clock" 17 | sudo ntpdate -u time.apple.com 18 | 19 | # Sign .app file. 20 | echo "signing" 21 | PRODUCT=build/Release/TileMill.app 22 | codesign --keychain ~/Library/Keychains/signing.keychain --sign "Developer ID Application: Mapbox, Inc." --deep --verbose --force ${PRODUCT} 23 | codesign --verify -v ${PRODUCT} 24 | 25 | # Nuke signin keychain. 26 | echo "dropping keychain" 27 | security delete-keychain signing.keychain 28 | -------------------------------------------------------------------------------- /plugins/carto/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "carto", 3 | "description": "Carto syntax reference for editing.", 4 | "engines": {"tilemill":"*"}, 5 | "private": true 6 | } 7 | -------------------------------------------------------------------------------- /plugins/carto/views/Carto.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.events = { 4 | 'click .toggler a': 'toggler' 5 | } 6 | 7 | view.prototype.initialize = function(options) { 8 | this.render(); 9 | this._carto_state = options._carto_state; 10 | if (this._carto_state.section) { 11 | $('a[href=' + this._carto_state.section + ']').click(); 12 | } 13 | }; 14 | 15 | view.prototype.toggler = function(ev) { 16 | this._carto_state.section = $(ev.currentTarget).attr('href'); 17 | }; 18 | 19 | view.prototype.render = function() { 20 | if (this.$('.manual').size()) return this; 21 | 22 | this.$('.content').html(templates.Reference(abilities.carto)); 23 | /*this.$('pre.carto-snippet').each(function(i, elem) { 24 | CodeMirror(function(el) { 25 | $(elem).replaceWith(el); 26 | }, { 27 | readOnly: 'nocursor', 28 | mode: { 29 | name: 'carto', 30 | reference: abilities.carto 31 | }, 32 | value: $(elem).text() 33 | } 34 | ); 35 | });*/ 36 | return this; 37 | }; 38 | 39 | // Hook in to project view with an augment. 40 | views.Project.augment({ 41 | events: { 'click a[href=#carto]': 'carto' }, 42 | carto: function() { 43 | new view({ 44 | el:$('#drawer'), 45 | _carto_state: this._carto_state 46 | }) 47 | }, 48 | initialize: function(p, o) { 49 | _(this).bindAll('carto'); 50 | // Minor state saving for the carto window 51 | this._carto_state = {}; 52 | return p.call(this, o); 53 | }, 54 | render: function(p) { 55 | p.call(this); 56 | this.$('.palette').prepend("Carto"); 57 | return this; 58 | } 59 | }); 60 | 61 | -------------------------------------------------------------------------------- /plugins/colors/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "colors", 3 | "description": "List of system defined colors.", 4 | "engines": {"tilemill":"*"}, 5 | "private": true 6 | } 7 | -------------------------------------------------------------------------------- /plugins/colors/templates/Colors._: -------------------------------------------------------------------------------- 1 |
2 | 3 | 24 | 25 |
26 | <% _(colors).each(function(f) { %> 27 | 28 |  <%= f.name %> 29 | 30 | 31 | 32 | 33 | <% }); %> 34 |
35 | 36 |
37 | -------------------------------------------------------------------------------- /plugins/colors/views/Colors.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.events = { 4 | 'click a.color': 'insert', 5 | 'keydown a.color input': 'keydown' 6 | }; 7 | 8 | view.prototype.initialize = function(options) { 9 | _(this).bindAll('insert', 'keydown'); 10 | this.render(); 11 | }; 12 | 13 | view.prototype.render = function() { 14 | if (this.$('.colors').size()) return this; 15 | var groups = {}; 16 | allColors = abilities.carto.colors; 17 | colorKeys = Object.keys(allColors); 18 | 19 | var colors = _(colorKeys).map(function(color) { 20 | var group = color.toUpperCase().charCodeAt(0); 21 | groups[group] = groups[group] || 0; 22 | groups[group]++ 23 | var code = allColors[color]; 24 | return { name:color, group:group, rgbcode:code }; 25 | }); 26 | this.$('.content').html(templates.Colors({ 27 | colors: colors, 28 | groups: groups 29 | })); 30 | return this; 31 | }; 32 | 33 | // Select color text. 34 | view.prototype.insert = function(ev) { 35 | var target = $(ev.currentTarget); 36 | target.addClass('insert').siblings().removeClass('insert'); 37 | $('input', target).select(); 38 | return false; 39 | }; 40 | 41 | // Catch non-action keypress (e.g. Ctrl-C) events when a color input field 42 | // is selected to prevent users from tampering with a color name. 43 | view.prototype.keydown = function(ev) { 44 | if (ev.ctrlKey || ev.metaKey || ev.altKey) return; 45 | return false; 46 | } 47 | 48 | // Hook in to projet view with an augment. 49 | views.Project.augment({ 50 | events: { 'click a[href=#colors]': 'colors' }, 51 | colors: function() { 52 | new view({ el:$('#drawer') }) 53 | }, 54 | render: function(p) { 55 | p.call(this); 56 | this.$('.palette').prepend("Colors"); 57 | return this; 58 | } 59 | }); 60 | 61 | -------------------------------------------------------------------------------- /plugins/editor/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "editor", 3 | "description": "Stylesheet code editor.", 4 | "engines": {"tilemill":"*"}, 5 | "private": true 6 | } 7 | -------------------------------------------------------------------------------- /plugins/editor/templates/Colorpicker._: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | Save 5 | Cancel 6 |
7 | 8 |
9 | -------------------------------------------------------------------------------- /plugins/editor/templates/Editor._: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 |
    6 |
    7 | Add stylesheet 8 |
    9 |
    10 |
    11 |
    12 | Close 13 |
    14 |
    15 |
    16 | 17 | -------------------------------------------------------------------------------- /plugins/editor/templates/ProjectStylesheet._: -------------------------------------------------------------------------------- 1 |
  • 2 | ' href='#stylesheet-<%= id.replace(/[\.]/g, '-') %>'> 3 | <%= id %> 4 | 5 | 6 |
  • 7 | -------------------------------------------------------------------------------- /plugins/editor/templates/ProjectSwatch._: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /plugins/editor/templates/Stylesheet._: -------------------------------------------------------------------------------- 1 |
    2 |
      3 |
    • 4 |
      Add a new Carto stylesheet. Stylesheets are applied to the project in the order they appear.
      5 |
    • 6 |
    • 7 | 8 | 9 |
    • 10 |
    • 11 | 12 | 13 |
    • 14 |
    15 |
    16 | -------------------------------------------------------------------------------- /plugins/editor/views/Stylesheet.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.events = { 4 | 'click input[type=submit]': 'save' 5 | }; 6 | 7 | view.prototype.initialize = function(options) { 8 | _(this).bindAll('render', 'save'); 9 | this.render(); 10 | }; 11 | 12 | view.prototype.render = function() { 13 | this.$('.content').html(templates.Stylesheet({})); 14 | 15 | // Autofocus first field. 16 | this.$('input[type=text]:first').focus(); 17 | return this; 18 | }; 19 | 20 | view.prototype.save = function() { 21 | var attr = Bones.utils.form(this.$('.form'), this.model); 22 | var options = { error: function(m, resp) { 23 | console.log('error saving project: ' + m.id); 24 | new views.Modal(resp); 25 | } 26 | }; 27 | if (this.model.set(attr, options)) { 28 | this.model.collection.add(this.model); 29 | this.$('a[href="#close"]').click(); 30 | } 31 | return false; 32 | }; 33 | -------------------------------------------------------------------------------- /plugins/fonts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fonts", 3 | "description": "List of available fonts.", 4 | "engines": {"tilemill":"*"}, 5 | "private": true 6 | } 7 | -------------------------------------------------------------------------------- /plugins/fonts/templates/Fonts._: -------------------------------------------------------------------------------- 1 |
    2 | 3 | 24 | 25 |
    26 | <% _(fonts).each(function(f) { %> 27 | 28 | 29 | Copy + paste into editor 30 | 31 | <% }); %> 32 |
    33 | 34 |
    35 | -------------------------------------------------------------------------------- /plugins/fonts/views/Fonts.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.events = { 4 | 'click a.font': 'insert', 5 | 'keydown a.font input': 'keydown' 6 | }; 7 | 8 | view.prototype.initialize = function(options) { 9 | _(this).bindAll('insert', 'keydown'); 10 | this.render(); 11 | }; 12 | 13 | view.prototype.render = function() { 14 | if (this.$('.fonts').size()) return this; 15 | var groups = {}; 16 | var fonts = _(abilities.fonts).map(function(font) { 17 | var group = font.toUpperCase().charCodeAt(0); 18 | groups[group] = groups[group] || 0; 19 | groups[group]++ 20 | return { name:font, group:group }; 21 | }); 22 | this.$('.content').html(templates.Fonts({ 23 | fonts: fonts, 24 | groups: groups 25 | })); 26 | return this; 27 | }; 28 | 29 | // Select font text. 30 | view.prototype.insert = function(ev) { 31 | var target = $(ev.currentTarget); 32 | target.addClass('insert').siblings().removeClass('insert'); 33 | $('input', target).select(); 34 | return false; 35 | }; 36 | 37 | // Catch non-action keypress (e.g. Ctrl-C) events when a font input field 38 | // is selected to prevent users from tampering with a font name. 39 | view.prototype.keydown = function(ev) { 40 | if (ev.ctrlKey || ev.metaKey || ev.altKey) return; 41 | return false; 42 | } 43 | 44 | // Hook in to projet view with an augment. 45 | views.Project.augment({ 46 | events: { 'click a[href=#fonts]': 'fonts' }, 47 | fonts: function() { 48 | new view({ el:$('#drawer') }) 49 | }, 50 | render: function(p) { 51 | p.call(this); 52 | this.$('.palette').prepend("Fonts"); 53 | return this; 54 | } 55 | }); 56 | 57 | -------------------------------------------------------------------------------- /plugins/templates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "templates", 3 | "description": "Legend and tooltip template editor.", 4 | "engines": {"tilemill":"*"}, 5 | "private": true 6 | } 7 | -------------------------------------------------------------------------------- /rebuild_cxx.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | echo 'rebuilding node cxx modules' 3 | CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 4 | cd ${CURRENT_DIR} 5 | echo "starting work in ${CURRENT_DIR}" 6 | TILEMILL_ROOT=`pwd` 7 | PATH=${TILEMILL_ROOT}/node_modules/.bin:${PATH} 8 | PATH="`npm explore npm -g -- pwd`/bin/node-gyp-bin":${PATH} 9 | 10 | RUN_SETUP=false 11 | while getopts "s" OPT; do 12 | case $OPT in 13 | s) 14 | RUN_SETUP=true 15 | ;; 16 | esac 17 | done 18 | 19 | BUILD_ROOT=${TILEMILL_ROOT}/node_root_dir 20 | 21 | if [ "${RUN_SETUP}" = true ]; then 22 | NVER=`node -e "console.log(process.versions.node)"` 23 | echo "Running node-gyp setup for ${NVER}" 24 | node-gyp install ${NVER} 25 | BUILD_ROOT=${TILEMILL_ROOT}/node_root_dir 26 | cp -r ~/.node-gyp/${NVER}/ ${BUILD_ROOT} 27 | rm -rf ~/.node-gyp/ 28 | fi 29 | npm rebuild --nodedir=${BUILD_ROOT} --build-from-source 30 | 31 | -------------------------------------------------------------------------------- /servers/Core.bones: -------------------------------------------------------------------------------- 1 | var env = process.env.NODE_ENV || 'development'; 2 | 3 | servers['Core'].prototype.port = 20009; 4 | servers['Core'].prototype.start = function(callback) { 5 | if (this.plugin.config.coreSocket) { 6 | this.port = null; 7 | this.listen(this.plugin.config.coreSocket, callback); 8 | } else if (this.port) { 9 | this.listen(this.port, this.plugin.config.listenHost, callback); 10 | } 11 | return this; 12 | }; 13 | servers['Core'].prototype.initialize = function(app) { 14 | this.port = app.config.port || this.port; 15 | this.use(new servers['Middleware'](app)); 16 | this.use(new servers['App'](app)); 17 | if (env === 'development') this.use(new servers['Debug'](app)); 18 | this.use(new servers['Route'](app)); 19 | this.use(new servers['Asset'](app)); 20 | this.enable('jsonp callback'); 21 | }; 22 | -------------------------------------------------------------------------------- /servers/Route.bones: -------------------------------------------------------------------------------- 1 | servers['Route'].augment({ 2 | assets: { 3 | styles: [ 4 | require.resolve('../assets/css/reset.css'), 5 | require.resolve('../assets/css/style.css'), 6 | require.resolve('../assets/css/controls.css'), 7 | require.resolve('../assets/css/codemirror.css'), 8 | require.resolve('../assets/css/code.css') 9 | ], 10 | scripts: [ 11 | require.resolve('../assets/js/colorpicker.classic.js'), 12 | require.resolve('../assets/js/mustache.js'), 13 | require.resolve('../assets/js/jquery.ui.js'), 14 | require.resolve('chrono/lib/chrono.js'), 15 | require.resolve('modestmaps/modestmaps.js'), 16 | require.resolve('wax/dist/wax.mm.min.js'), 17 | require.resolve('JSV/lib/uri/uri.js'), 18 | require.resolve('JSV/lib/jsv.js'), 19 | require.resolve('JSV/lib/json-schema-draft-03.js'), 20 | require.resolve('../assets/js/codemirror.js'), 21 | require.resolve('../assets/js/codemirror.overlay.js'), 22 | require.resolve('../assets/js/codemirror.carto.js'), 23 | require.resolve('../assets/js/codemirror.carto.complete.js'), 24 | require.resolve('../assets/js/codemirror.xml.js'), 25 | require.resolve('../assets/js/codemirror.mustache.js'), 26 | require.resolve('../assets/js/showdown.js'), 27 | require.resolve('@mapbox/sphericalmercator') 28 | ] 29 | }, 30 | initializeAssets: function(parent, app) { 31 | parent.call(this, app); 32 | this.get('/assets/tilemill/css/vendor.css', 33 | mirror.assets(this.assets.styles, { type: '.css' }).handler); 34 | this.get('/assets/tilemill/js/vendor.js', 35 | mirror.assets(this.assets.scripts, { type: '.js' }).handler); 36 | } 37 | }); 38 | 39 | -------------------------------------------------------------------------------- /templates/Autostyle._: -------------------------------------------------------------------------------- 1 | <% if (get('geometry') == 'polygon' || get('geometry') == 'multipolygon') { %> 2 | 3 | #<%= get('id') %> { 4 | line-color:#594; 5 | line-width:0.5; 6 | polygon-opacity:1; 7 | polygon-fill:#ae8; 8 | }<% } %><% if (get('geometry') == 'point' || get('geometry') == 'multipoint') { %> 9 | 10 | #<%= get('id') %> { 11 | marker-width:6; 12 | marker-fill:#f45; 13 | marker-line-color:#813; 14 | marker-allow-overlap:true; 15 | marker-ignore-placement:true; 16 | }<% } %><% if (get('geometry') == 'linestring' || get('geometry') == 'multilinestring') { %> 17 | 18 | #<%= get('id') %> { 19 | line-width:1; 20 | line-color:#168; 21 | }<% } %><% if (get('geometry') == 'raster') { %> 22 | 23 | #<%= get('id') %> { 24 | raster-opacity:1; 25 | }<% } %> 26 | -------------------------------------------------------------------------------- /templates/Datasource._: -------------------------------------------------------------------------------- 1 | <% 2 | /* @TODO not using underscore 1.2's escape method as it is 3 | still stabilizing. Consider switching once 1.2 stable. */ 4 | obj.escape = function(string) { 5 | return (''+string) 6 | .replace(/&/g, '&') 7 | .replace(//g, '>'); 9 | }; %> 10 | 16 |
    17 | 18 | 19 | 20 | <% _(fields).each(function (field, name) { %> 21 | 22 | <% }); %> 23 | 24 | 25 | 26 | 27 | <% _(fields).each(function (field) { %> 28 | <% if (field.type === 'Number') { %> 29 | 30 | <% } else { %> 31 | 32 | <% } %> 33 | <% }); %> 34 | 35 | 36 | <% _(fields).each(function (field) { %> 37 | <% if (field.type === 'Number') { %> 38 | 39 | <% } else { %> 40 | 41 | <% } %> 42 | <% }); %> 43 | 44 | <%= this['DatasourceRows'](obj) %> 45 | 46 |
    <%= name %>
    min <%= obj.escape(field.min) %><%= obj.escape(field.min) %> min
    max <%= obj.escape(field.max) %><%= obj.escape(field.max) %> max
    47 | <% if (moreFields.length) { %> 48 |
    49 | <%= moreFields.join(', ') %> fields omitted.
    Use fewer fields for better performance. 50 |
    51 | <% } %> 52 | <% if (more) { %> 53 | 54 | <% } %> 55 |
    56 | -------------------------------------------------------------------------------- /templates/DatasourceRows._: -------------------------------------------------------------------------------- 1 | <% 2 | /* @TODO not using underscore 1.2's escape method as it is 3 | still stabilizing. Consider switching once 1.2 stable. */ 4 | obj.escape = function(string) { 5 | return (''+string) 6 | .replace(/&/g, '&') 7 | .replace(//g, '>'); 9 | }; %> 10 | <% _(features).each(function (feature) { %> 11 | 12 | <% _(fields).each(function (value, key) { if (key !== '__id__') { %> 13 | <%= obj.escape(feature[key]) %> 14 | <% }}); %> 15 | 16 | <% }); %> 17 | -------------------------------------------------------------------------------- /templates/Error._: -------------------------------------------------------------------------------- 1 |
    2 |
    <%= content.toString() %>
    3 |
    4 | 5 | -------------------------------------------------------------------------------- /templates/Layers._: -------------------------------------------------------------------------------- 1 | 8 |
      9 | -------------------------------------------------------------------------------- /templates/Library._: -------------------------------------------------------------------------------- 1 |
      2 |
      3 | <% if (model.id === 'favoritesPostGIS') { %> 4 | Favorites 5 | <% } else if (model.id === 'sqlite') { %> 6 | FileFavorites 8 | <% } else { %> 9 | FileMapBoxFavorites 12 | <% } %> 13 |
      14 | 15 | 26 | 27 |
      28 | <% if (model.get('assets').length === 0) { %> 29 |
      No items found.
      30 | <% } %> 31 | 32 | <% _(model.get('assets')).each(function(asset) { %> 33 | '> 34 | <% if (asset.location) { %><% } %> 35 | <% if (asset.uri) { %><% } %> 36 | <%= asset.name %> 37 | <% if (asset.size) { %><%= asset.size %><% } %> 38 | 39 | <% }); %> 40 |
      41 |
      42 | -------------------------------------------------------------------------------- /templates/Manual._: -------------------------------------------------------------------------------- 1 |
      2 | 10 |
      <%= obj.model.get('data') %>
      11 |
      12 | -------------------------------------------------------------------------------- /templates/Map._: -------------------------------------------------------------------------------- 1 | 12 |
      13 |
      Zoom
      14 |
      15 | -------------------------------------------------------------------------------- /templates/Modal._: -------------------------------------------------------------------------------- 1 | <% if (type === 'confirm') { %> 2 |
      <%= content.toString() %>
      3 |
      4 | <% if (affirmative) %><% ; %> 5 | <% if (negative) %><% ; %> 6 |
      7 | <% } else { %> 8 | Close 9 |
      <%= content.toString().replace(//g, '>') %>
      10 |
      Is this a bug? Report it on github.
      11 | <% } %> 12 | -------------------------------------------------------------------------------- /templates/Pane._: -------------------------------------------------------------------------------- 1 |

      2 | Close 3 |
      4 |
      5 | Cancel 6 | -------------------------------------------------------------------------------- /templates/Plugin._: -------------------------------------------------------------------------------- 1 | <% 2 | var installed = !!window.abilities.plugins[id]; 3 | var compatible = semver.satisfies(window.abilities.tilemill.version, get('engines').tilemill); 4 | var upgradable = installed && get('latest') && semver.gt(get('latest'), get('version')); 5 | %> 6 |
    • '> 7 | <%= escape('name') %> 8 | 9 | <%= escape('description') || 'No description.' %>
      10 | <% if (get('core')) %>TileMill <%=window.abilities.tilemill.version%><%;%> 11 | <% if (!get('core')) %>Version <%= escape('version') || 'unknown' %><%;%> 12 | <% if (!compatible) %> 13 | Incompatible with TileMill <%=window.abilities.tilemill.version%> 14 | <%;%> 15 | <% if (get('broken')) %> 16 | Broken, uninstalling is highly recommended 17 | <%;%> 18 | 19 |
      20 |
      21 | <% if (get('core')) { %> 22 | Core 23 | <% } else { %> 24 | <% if (upgradable) %>Upgrade<% ; %> 25 | <% if (installed) %>Uninstall<% ; %> 26 | <% if (!installed && compatible) %>Install<% ; %> 27 | <% } %> 28 |
      29 |
    • 30 | 31 | -------------------------------------------------------------------------------- /templates/Plugins._: -------------------------------------------------------------------------------- 1 |
        2 |
      • 3 |

        Installed plugins

        4 |
      • 5 |
        • 6 | 10 | <%= collection.map(templates.Plugin).join('') %> 11 |
      • 12 |
        13 |
      14 |
        15 |
      • 16 |

        Available plugins

        17 |
      • 18 |
        • 19 | <% var show = available.chain() 20 | .filter(function(m) { return !window.abilities.plugins[m.id] }) 21 | .map(templates.Plugin) 22 | .value(); 23 | show = show.length ? show.join('') : available.length ? '
          No plugins found.
          ' : ''; 24 | %> 25 | <%= show %> 26 |
      • 27 |
        28 |
      29 | -------------------------------------------------------------------------------- /templates/Preview._: -------------------------------------------------------------------------------- 1 |
      2 | 11 |
      12 |
      13 | -------------------------------------------------------------------------------- /templates/ProjectAdd._: -------------------------------------------------------------------------------- 1 |
        2 |
      • 3 |

        Project information

        4 |
        Provide information about your project. You can edit these fields later.
        5 |
      • 6 |
      • 7 | 8 | ' /> 9 |
      • 10 |
      • 11 | 12 | ' /> 13 |
      • 14 |
      • 15 | 16 | ' /> 17 |
      • 18 |
      • 19 | 20 | 28 |
      • 29 |
      • 30 | 31 | 32 | Include world layer and styles. 33 |
      • 34 |
      • 35 | 36 | 37 |
      • 38 |
      39 | -------------------------------------------------------------------------------- /templates/ProjectLayer._: -------------------------------------------------------------------------------- 1 | class='status-off'<% } %>> 2 | 3 | ' class='icon geometry geometry-<%= get('geometry') %>'> 4 | 5 | 6 | 7 | <% if (get('geometry') !== 'raster') { %> 8 | Features (<%= id %>) 9 | <% } %> 10 | Zoom to <%= id %> 11 | Hide <%= id %> 12 | Edit <%= id %> 13 | Clone <%= id %> 14 | Delete <%= id %> 15 | 16 | 17 | -------------------------------------------------------------------------------- /templates/Projects._: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /test/duplicate_module.test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var exec = require('child_process').exec; 3 | 4 | var count_module = function(name,callback) { 5 | var cmd = 'npm ls ' + name; 6 | exec(cmd, 7 | function (error, stdout, stderr) { 8 | // Added check to remove deduped results. CJS 1/24/19 9 | var pattern = new RegExp(name+'@\\d+.\\d+.\\d+\\s+\\\n','g') 10 | var match = stdout.match(pattern); 11 | if (!match) { 12 | return callback(null,0); 13 | } 14 | return callback(null,match.length); 15 | }); 16 | }; 17 | 18 | describe('Testing Config Functions [config loading pwnage] (duplicate_module.test.js)', function() { 19 | 20 | ['optimist','sqlite3','mapnik'].forEach(function(mod) { 21 | it('there should only be one ' + mod + ' module otherwise you are hosed', function(done) { 22 | count_module(mod, function(err,count) { 23 | if (err) throw err; 24 | assert.notEqual(count,0,'you are missing the ' + mod + ' module (`npm ls ' + mod + '`)'); 25 | assert.equal(count,1,'you have more than one copy of ' + mod + ' (`npm ls ' + mod + '`)'); 26 | done(); 27 | }); 28 | }); 29 | }); 30 | 31 | }); -------------------------------------------------------------------------------- /test/fixtures/anti-meridian-export-job.json: -------------------------------------------------------------------------------- 1 | { 2 | "progress": 0, 3 | "status": "waiting", 4 | "format": "mbtiles", 5 | "project": "demo_01", 6 | "tile_format": "png", 7 | "id": "", 8 | "filename": "demo_anti-meridian.mbtiles", 9 | "bbox": [ 175, 31.8402, -175, 71.9245 ], 10 | "minzoom": 0, 11 | "maxzoom": 2, 12 | "bones.token": "zbx6dr0ghgvRNZOuu8PXtt2VCAIKO2qK" 13 | } -------------------------------------------------------------------------------- /test/fixtures/countries.sqlite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tilemill-project/tilemill/1672dad5cc2283b1c8efdc8adb9ab496267fba00/test/fixtures/countries.sqlite -------------------------------------------------------------------------------- /test/fixtures/create-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "bounds": [ -180, -85.05112877980659, 180, 85.05112877980659], 3 | "center": [0, 0, 2], 4 | "format": "png", 5 | "interactivity": false, 6 | "minzoom": 0, 7 | "maxzoom": 22, 8 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 9 | "Stylesheet": [{ 10 | "data": "Map {\n background-color: #fff;\n}\n\n#world {\n polygon-fill: #eee;\n line-color: #ccc;\n line-width: 0.5;\n}", 11 | "id": "style.mss" 12 | }], 13 | "Layer": [{ 14 | "id": "world", 15 | "name": "world", 16 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 17 | "geometry": "polygon", 18 | "Datasource": { 19 | "file": "http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip", 20 | "type": "shape" 21 | } 22 | }], 23 | "id": "demo_02", 24 | "bones.token": "NTdptwhjvjRcJy89kqsV9Hgk0AkG3Y5O" 25 | } 26 | -------------------------------------------------------------------------------- /test/fixtures/created-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "Layer": [ 3 | { 4 | "Datasource": { 5 | "file": "http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip", 6 | "type": "shape" 7 | }, 8 | "geometry": "polygon", 9 | "id": "world", 10 | "name": "world", 11 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" 12 | } 13 | ], 14 | "Stylesheet": [ 15 | { 16 | "data": "Map {\n background-color: #fff;\n}\n\n#world {\n polygon-fill: #eee;\n line-color: #ccc;\n line-width: 0.5;\n}", 17 | "id": "style.mss" 18 | } 19 | ], 20 | "bounds": [ -180, -85.05112877980659, 180, 85.05112877980659 ], 21 | "center": [ 0, 0, 2 ], 22 | "format": "png", 23 | "grids": [ "http://127.0.0.1:20008/tile/demo_02/{z}/{x}/{y}.grid.json" ], 24 | "tiles": [ "http://127.0.0.1:20008/tile/demo_02/{z}/{x}/{y}.png" ], 25 | "scale": 1, 26 | "metatile": 2, 27 | "id": "demo_02", 28 | "interactivity": false, 29 | "maxzoom": 22, 30 | "minzoom": 0, 31 | "scheme": "xyz", 32 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 33 | "tilejson": "2.0.0" 34 | } 35 | -------------------------------------------------------------------------------- /test/fixtures/datasource-postgis.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": [], 3 | "fields": { 4 | "featurecla": { "type": "String" }, 5 | "gid": { "type": "Number" }, 6 | "scalerank": { "type": "Number" } 7 | }, 8 | "geometry_type": "linestring", 9 | "id": "postgis", 10 | "project": "demo_01", 11 | "type": "vector", 12 | "unproj_extent" : [ 13 | -137.55088970390102, 14 | -52.986907341349465, 15 | 140.97763013616188, 16 | 70.07531103545583 17 | ], 18 | "extent" : "-15312095,-6980576.5,15693558,11093272", 19 | "sticky_options":{} 20 | } -------------------------------------------------------------------------------- /test/fixtures/datasource-shp.json: -------------------------------------------------------------------------------- 1 | { 2 | "fields": { 3 | "AREA": { "type": "Number" }, 4 | "FIPS": { "type": "String" }, 5 | "ISO2": { "type": "String" }, 6 | "ISO3": {"type": "String" }, 7 | "LAT": { "type": "Number" }, 8 | "LON": { "type": "Number" }, 9 | "NAME": { "type": "String" }, 10 | "POP2005": { "type": "Number" }, 11 | "REGION": { "type": "Number" }, 12 | "SUBREGION": { "type": "Number" }, 13 | "UN": { "type": "Number" } 14 | }, 15 | "geometry_type": "polygon", 16 | "id": "world", 17 | "project": "demo_01", 18 | "type": "vector", 19 | "url": "http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip", 20 | "features": [] 21 | } 22 | -------------------------------------------------------------------------------- /test/fixtures/datasource-sqlite.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "world", 3 | "project": "demo_01", 4 | "fields": { 5 | "OGC_FID": { "type": "Number" }, 6 | "scalerank": { "type": "Number" }, 7 | "labelrank": { "type": "Number" }, 8 | "featurecla": { "type": "String" }, 9 | "sovereignt": { "type": "String" }, 10 | "sov_a3": { "type": "String" }, 11 | "adm0_dif": { "type": "Number" }, 12 | "level": { "type": "Number" }, 13 | "type": { "type": "String" }, 14 | "admin": { "type": "String" }, 15 | "adm0_a3": { "type": "String" }, 16 | "geou_dif": { "type": "Number" }, 17 | "name": { "type": "String" }, 18 | "abbrev": { "type": "String" }, 19 | "postal": { "type": "String" }, 20 | "name_forma": { "type": "String" }, 21 | "terr_": { "type": "String" }, 22 | "name_sort": { "type": "String" }, 23 | "map_color": { "type": "Number" }, 24 | "pop_est": { "type": "Number" }, 25 | "gdp_md_est": { "type": "Number" }, 26 | "fips_10_": { "type": "Number" }, 27 | "iso_a2": { "type": "String" }, 28 | "iso_a3": { "type": "String" }, 29 | "iso_n3": { "type": "Number" } 30 | }, 31 | "features": [], 32 | "type": "vector", 33 | "geometry_type": "polygon", 34 | "unproj_extent" : [ 35 | -70.06163470944716, 36 | 12.41753750275562, 37 | 74.89230718349421, 38 | 38.47367493851016 39 | ], 40 | "extent" : "-7799225.5,1393264.125,8336973.5,4646558", 41 | "sticky_options":{} 42 | } 43 | -------------------------------------------------------------------------------- /test/fixtures/existing-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "bounds": [-180, -85.05112877980659, 180, 85.05112877980659], 3 | "center": [0, 0, 2], 4 | "format": "png8:m=h", 5 | "interactivity": { 6 | "layer": "world", 7 | "template_teaser": "{{NAME}}", 8 | "template_full": "", 9 | "template_location": "", 10 | "fields": ["NAME"] 11 | }, 12 | "template": "{{#__location__}}{{/__location__}}{{#__teaser__}}{{NAME}}{{/__teaser__}}{{#__full__}}{{/__full__}}", 13 | "minzoom": 0, 14 | "maxzoom": 22, 15 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 16 | "Stylesheet": [{ 17 | "id": "style.mss", 18 | "data": "Map {\n background-color: #fff;\n}\n\n#world {\n polygon-fill: #eee;\n line-color: #ccc;\n line-width: 0.5;\n}" 19 | }], 20 | "Layer": [{ 21 | "id": "world", 22 | "name": "world", 23 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 24 | "geometry": "polygon", 25 | "Datasource": { 26 | "file": "http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip", 27 | "type": "shape" 28 | } 29 | }], 30 | "id": "demo_01", 31 | "tilejson": "2.0.0", 32 | "scheme": "xyz", 33 | "tiles": ["http://127.0.0.1:20008/tile/demo_01/{z}/{x}/{y}.png"], 34 | "grids": ["http://127.0.0.1:20008/tile/demo_01/{z}/{x}/{y}.grid.json"] 35 | } 36 | -------------------------------------------------------------------------------- /test/fixtures/export-job.json: -------------------------------------------------------------------------------- 1 | { 2 | "progress": 0, 3 | "status": "waiting", 4 | "format": "mbtiles", 5 | "project": "demo_01", 6 | "tile_format": "png", 7 | "id": "", 8 | "filename": "demo_01.mbtiles", 9 | "bbox": [ -29.5642, 31.8402, 42.1545, 71.9245 ], 10 | "minzoom": 0, 11 | "maxzoom": 2, 12 | "bones.token": "zbx6dr0ghgvRNZOuu8PXtt2VCAIKO2qK" 13 | } -------------------------------------------------------------------------------- /test/fixtures/invalid-project.json: -------------------------------------------------------------------------------- 1 | { 2 | "bounds": [-180, -85.05112877980659, 180, 85.05112877980659], 3 | "center": [0, 0, 2], 4 | "format": "png", 5 | "interactivity": false, 6 | "minzoom": 0, 7 | "maxzoom": 22, 8 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 9 | "Stylesheet": [{ 10 | "id": "style.mss", 11 | "data": "Map {\n background-color: blurb;\n}\n\n#world {\n polygon-fill: #eee;\n line-color: #ccc;\n line-width: 0.5;\n}" 12 | }], 13 | "Layer": [{ 14 | "id": "world", 15 | "name": "world", 16 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 17 | "geometry": "polygon", 18 | "Datasource": { 19 | "file": "http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip", 20 | "type": "shape" 21 | } 22 | }], 23 | "id": "demo_01", 24 | "tilejson": "2.0.0", 25 | "scheme": "xyz", 26 | "tiles": ["http://127.0.0.1:20008/tile/demo_01/{z}/{x}/{y}.png"], 27 | "grids": ["http://127.0.0.1:20008/tile/demo_01/{z}/{x}/{y}.grid.json"], 28 | "bones.token": "qUPgDcUqcee7RkBieVn7bfhZxAZALOyx" 29 | } 30 | -------------------------------------------------------------------------------- /test/fixtures/pristine/project/demo_01/project.mml: -------------------------------------------------------------------------------- 1 | { 2 | "bounds": [ 3 | -180, 4 | -85.05112877980659, 5 | 180, 6 | 85.05112877980659 7 | ], 8 | "center": [ 9 | 0, 10 | 0, 11 | 2 12 | ], 13 | "format": "png8:m=h", 14 | "interactivity": { 15 | "layer": "world", 16 | "template_teaser": "{{NAME}}", 17 | "template_full": "", 18 | "template_location": "" 19 | }, 20 | "minzoom": 0, 21 | "maxzoom": 22, 22 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 23 | "Stylesheet": [ 24 | "style.mss" 25 | ], 26 | "Layer": [ 27 | { 28 | "id": "world", 29 | "name": "world", 30 | "srs": "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over", 31 | "geometry": "polygon", 32 | "Datasource": { 33 | "file": "http://tilemill-data.s3.amazonaws.com/world_borders_merc.zip", 34 | "type": "shape" 35 | } 36 | } 37 | ] 38 | } 39 | -------------------------------------------------------------------------------- /test/fixtures/pristine/project/demo_01/style.mss: -------------------------------------------------------------------------------- 1 | Map { 2 | background-color: #fff; 3 | } 4 | 5 | #world { 6 | polygon-fill: #eee; 7 | line-color: #ccc; 8 | line-width: 0.5; 9 | } -------------------------------------------------------------------------------- /test/init.js: -------------------------------------------------------------------------------- 1 | 2 | // global init - run once 3 | before(function(done) { 4 | require('./support/start').reset(function() { 5 | done(); 6 | }); 7 | }); 8 | 9 | -------------------------------------------------------------------------------- /test/tile.test.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var core; 3 | var tile; 4 | 5 | describe('Testing Tile Enpoint (tile.test.js) tile endpoint', function() { 6 | 7 | before(function(done) { 8 | require('./support/start').start(function(command) { 9 | core = command.servers['Core']; 10 | tile = command.servers['Tile']; 11 | done(); 12 | }); 13 | }); 14 | 15 | after(function(done) { 16 | core.close(); 17 | tile.close(); 18 | done(); 19 | }); 20 | 21 | it('should 404 for missing project', function(done) { 22 | assert.response(tile, 23 | { url: '/tile/does_not_exist/0/0/0.png', encoding: 'binary' }, 24 | { body: /Project does not exist/, status: 404 }, 25 | function() { done(); } 26 | ); 27 | }); 28 | it ('should 200 (tile) for existing project', function(done) { 29 | assert.response(tile, 30 | { url: '/tile/demo_01/2/2/1.png', encoding: 'binary' }, 31 | { status: 200 }, 32 | function(res) { 33 | assert.equal(res.body.length, 7983); 34 | done(); 35 | } 36 | ); 37 | }); 38 | it ('should 200 (grid) for existing project', function(done) { 39 | assert.response(tile, 40 | { url: '/tile/demo_01/2/2/1.grid.json' }, 41 | { status: 200 }, 42 | function(res) { 43 | function grid(data) { return data; }; 44 | var data = eval(res.body); 45 | assert.equal(data.grid.length, 64); 46 | assert.equal(data.keys.length, 90); 47 | assert.equal(Object.keys(data.data).length, 89); 48 | assert.equal(data.keys[1], '154'); 49 | assert.equal(data.data['154'].NAME, 'Norway'); 50 | done(); 51 | } 52 | ); 53 | }); 54 | 55 | }); 56 | -------------------------------------------------------------------------------- /tilemill.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Source bash profile just in case they have not done that between installing nvm/npm and this. 4 | source ${HOME}/.bash_profile 5 | 6 | info=`tput setaf 6`;error=`tput setaf 1`;success=`tput setaf 2`;reset=`tput sgr0` # Colors for text 7 | echo "${info}This script will run the TileMill server. You will need to leave this server running while you are using TileMill. When you are finished using TileMill you can shutdown the server by holding the control key while hitting the c key. Or, you can close the Terminal window.${reset}" 8 | echo "${info}----------------------------------------------------------------------${reset}" 9 | echo "" 10 | 11 | # Run the client. This script will launch the browser once the server has successfully started. 12 | ./utils/runclient.sh & 13 | 14 | # Start the server. 15 | npm start -------------------------------------------------------------------------------- /utils/OLD/900913.sql: -------------------------------------------------------------------------------- 1 | INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, srtext, proj4text) 2 | VALUES ( 3 | 900913, 4 | 'EPSG', 5 | 900913, 6 | 'PROJCS["WGS84 / Simple Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS_1984", 6378137.0, 298.257223563]],PRIMEM["Greenwich", 0.0],UNIT["degree", 0.017453292519943295],AXIS["Longitude", EAST],AXIS["Latitude", NORTH]],PROJECTION["Mercator_1SP_Google"],PARAMETER["latitude_of_origin", 0.0],PARAMETER["central_meridian", 0.0],PARAMETER["scale_factor", 1.0],PARAMETER["false_easting", 0.0],PARAMETER["false_northing", 0.0],UNIT["m", 1.0],AXIS["x", EAST],AXIS["y", NORTH],AUTHORITY["EPSG","900913"]]', 7 | '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs'); 8 | -------------------------------------------------------------------------------- /utils/OLD/legacy-postgis-gist.sql: -------------------------------------------------------------------------------- 1 | CREATE OPERATOR CLASS gist_geometry_ops 2 | FOR TYPE geometry USING GIST AS 3 | STORAGE box2df, 4 | OPERATOR 1 << , 5 | OPERATOR 2 &< , 6 | OPERATOR 3 && , 7 | OPERATOR 4 &> , 8 | OPERATOR 5 >> , 9 | OPERATOR 6 ~= , 10 | OPERATOR 7 ~ , 11 | OPERATOR 8 @ , 12 | OPERATOR 9 &<| , 13 | OPERATOR 10 <<| , 14 | OPERATOR 11 |>> , 15 | OPERATOR 12 |&> , 16 | 17 | OPERATOR 13 <-> FOR ORDER BY pg_catalog.float_ops, 18 | OPERATOR 14 <#> FOR ORDER BY pg_catalog.float_ops, 19 | FUNCTION 8 geometry_gist_distance_2d (internal, geometry, int4), 20 | 21 | FUNCTION 1 geometry_gist_consistent_2d (internal, geometry, int4), 22 | FUNCTION 2 geometry_gist_union_2d (bytea, internal), 23 | FUNCTION 3 geometry_gist_compress_2d (internal), 24 | FUNCTION 4 geometry_gist_decompress_2d (internal), 25 | FUNCTION 5 geometry_gist_penalty_2d (internal, internal, internal), 26 | FUNCTION 6 geometry_gist_picksplit_2d (internal, internal), 27 | FUNCTION 7 geometry_gist_same_2d (geom1 geometry, geom2 geometry, internal); -------------------------------------------------------------------------------- /utils/counts.sql: -------------------------------------------------------------------------------- 1 | select count(*) from planet_osm_point; 2 | select count(*) from planet_osm_line; 3 | select count(*) from planet_osm_polygon; 4 | select count(*) from planet_osm_roads; 5 | select count(*) from spatial_ref_sys; 6 | 7 | -------------------------------------------------------------------------------- /utils/indexes.sql: -------------------------------------------------------------------------------- 1 | CREATE INDEX idx_planet_osm_point_tags ON planet_osm_point USING gist(tags); 2 | CREATE INDEX idx_planet_osm_line_tags ON planet_osm_line USING gist(tags); 3 | CREATE INDEX idx_planet_osm_polygon_tags ON planet_osm_polygon USING gist(tags); 4 | CREATE INDEX idx_planet_osm_roads_tags ON planet_osm_roads USING gist(tags); 5 | -------------------------------------------------------------------------------- /utils/runclient.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Check if TileMill port is open... 4 | host="127.0.0.1" 5 | port="20009" 6 | port_status="closed" 7 | timeout=30 8 | counter=0 9 | 10 | while [ $port_status != "open" ] 11 | do 12 | sleep 1 13 | (( counter += 1 )) 14 | #echo "Checking if ${host}:${port} is open..." 15 | port_status=`(echo >/dev/tcp/$host/$port) &>/dev/null && echo "open" || echo "close"` 16 | if [ $counter == $timeout ]; then 17 | echo "TileMill is not available at ${host}:${port}";exit 1; 18 | fi 19 | done 20 | echo "Opening TileMill session in browser..." 21 | open "http://${host}:${port}" 22 | exit 0 23 | -------------------------------------------------------------------------------- /views/Datasource.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.events = { 4 | 'click a[href=#back]': 'back', 5 | 'click a.showall': 'showAll' 6 | }; 7 | 8 | view.prototype.featureLimit = 100; 9 | 10 | view.prototype.initialize = function(options) { 11 | this.render(); 12 | }; 13 | 14 | view.prototype.back = function() { 15 | $('.palette a[href=#layers]').click(); 16 | return false; 17 | }; 18 | 19 | view.prototype.render = function() { 20 | var features = this.model.get('features'); 21 | var fields = _(this.model.get('fields')).reduce(function(memo, v, k) { 22 | if (_(memo).keys().length < 50) memo[k] = v; 23 | return memo; 24 | }, {}); 25 | this.$('.content').html(templates.Datasource({ 26 | fields: fields, 27 | features: _(features).first(this.featureLimit), 28 | more: _(features).size() > this.featureLimit, 29 | moreFields: _(_(this.model.get('fields')).keys()).difference(_(fields).keys()) 30 | })); 31 | return this; 32 | }; 33 | 34 | view.prototype.showAll = function() { 35 | this.$('a.showall').hide(); 36 | this.$('.content table tbody').append(templates.DatasourceRows({ 37 | fields: this.model.get('fields'), 38 | features: _(this.model.get('features')).rest(this.featureLimit) 39 | })); 40 | return false; 41 | } 42 | 43 | -------------------------------------------------------------------------------- /views/Error.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | // Override _ensureElement. 4 | view.prototype._ensureElement = function() { 5 | this.el = this.el || $('#page'); 6 | }; 7 | 8 | view.prototype.initialize = function(options) { 9 | _(this).bindAll('render'); 10 | 11 | // Attempt to handle jqXHR objects. 12 | if (options.responseText) { 13 | try { 14 | options = { content: JSON.parse(options.responseText).message }; 15 | } catch(e) { 16 | options = { content: options.responseText }; 17 | } 18 | } else if (options.status === 0) { 19 | options = { content: 'No response from server.' }; 20 | } else if (typeof options === 'string') { 21 | options = { content: options }; 22 | } else if (options instanceof Error) { 23 | options = { content: options.toString() }; 24 | } 25 | 26 | options = options || {}; 27 | options.content = options.content || {}; 28 | this.options = options; 29 | this.render(); 30 | }; 31 | 32 | view.prototype.render = function() { 33 | $(this.el).html(templates.Error(this.options)); 34 | return this; 35 | }; 36 | 37 | -------------------------------------------------------------------------------- /views/Manual.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.initialize = function(options) { 4 | _(this).bindAll('render'); 5 | this.render(); 6 | }; 7 | 8 | view.prototype.render = function() { 9 | $('.bleed .active').removeClass('active'); 10 | $('.bleed .manual').addClass('active'); 11 | 12 | $(this.el).html(templates.Manual({model: this.model, collection: this.collection})); 13 | this.$('.md').each(function() { 14 | var html = $('
      ') 15 | .html((new Showdown.converter()).makeHtml($(this).html())) 16 | .attr('class', $(this).attr('class')) 17 | .attr('id', $(this).attr('id')); 18 | $(this).hide().after(html); 19 | $('h2, h3, h4, h5, h6', html).each(function() { 20 | var heading = this; 21 | var cleaned = $(heading).text().replace(/[\s\W]+/g, '-').toLowerCase(); 22 | $(this).attr('id', 'manual-' + cleaned); 23 | this.className = this.nodeName; 24 | }); 25 | $('a', html).each(function() { $(this).get(0).target = '_blank'; }); 26 | }); 27 | }; 28 | 29 | -------------------------------------------------------------------------------- /views/Preview.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.events = { 4 | 'click a.upload': 'upload' 5 | }; 6 | 7 | view.prototype.initialize = function(options) { 8 | _(this).bindAll('render'); 9 | 10 | Bones.utils.fetch({ 11 | preview: new models.Preview({id:this.model.get('filename')}), 12 | config: new models.Config() 13 | }, _(function(err, models) { 14 | if (err) return new views.Modal(err); 15 | this.preview = models.preview; 16 | this.config = models.config; 17 | this.render(); 18 | }).bind(this)); 19 | }; 20 | 21 | view.prototype.render = function() { 22 | this.$('.content').html(templates.Preview({ 23 | model: this.model, 24 | config: this.config 25 | })); 26 | 27 | if (!MM) throw new Error('ModestMaps not found.'); 28 | this.map = new MM.Map('preview', 29 | new wax.mm.connector(this.preview.attributes)); 30 | wax.mm.interaction() 31 | .map(this.map) 32 | .tilejson(this.preview.attributes) 33 | .on(wax.tooltip().parent(this.map.parent).events()); 34 | wax.mm.legend(this.map, this.preview.attributes).appendTo(this.map.parent); 35 | wax.mm.zoombox(this.map); 36 | wax.mm.zoomer(this.map).appendTo(this.map.parent); 37 | 38 | var center = this.preview.get('center'); 39 | this.map.setCenterZoom(new MM.Location( 40 | center[1], 41 | center[0]), 42 | center[2]); 43 | 44 | this.map.setZoomRange( 45 | this.model.get('minzoom'), 46 | this.model.get('maxzoom')); 47 | 48 | return this; 49 | }; 50 | 51 | view.prototype.upload = function(ev) { 52 | (new models.Export({ 53 | filename: this.model.get('filename'), 54 | project: this.model.get('project'), 55 | format: 'upload' 56 | }).save({}, { 57 | success: _(function(model) { 58 | this.collection.add(model); 59 | $('a.close', this.el).click(); 60 | }).bind(this) 61 | })); 62 | return false; 63 | }; 64 | -------------------------------------------------------------------------------- /views/ProjectAdd.bones: -------------------------------------------------------------------------------- 1 | view = Backbone.View.extend(); 2 | 3 | view.prototype.events = { 4 | 'click input[type=submit]': 'save' 5 | }; 6 | 7 | view.prototype.initialize = function(options) { 8 | _(this).bindAll('render', 'save'); 9 | this.render(); 10 | }; 11 | 12 | view.prototype.render = function() { 13 | this.$('.content').html(templates.ProjectAdd(this.model)); 14 | this.$('input[type=text]:first').focus(); 15 | return this; 16 | }; 17 | 18 | view.prototype.save = function() { 19 | var attr = Bones.utils.form(this.$('form'), this.model); 20 | var error = function(m, e) { new views.Modal(e); }; 21 | if (!this.model.set(attr, {error:error})) return false; 22 | 23 | $(this.el).addClass('loading'); 24 | this.model.setDefaults(this.$('input[name=use-default]')[0].checked); 25 | this.model.save({}, { 26 | success: _(function(model) { 27 | Bones.utils.until(model.thumb(), _(function() { 28 | this.model.collection.add(this.model); 29 | $(this.el).removeClass('loading'); 30 | window.location.hash = '#/project/' + this.model.get('id'); 31 | this.$('a[href="#close"]').click(); 32 | }).bind(this)); 33 | }).bind(this), 34 | error:error 35 | }); 36 | return false; 37 | }; 38 | 39 | --------------------------------------------------------------------------------