瀏覽代碼

简单删减editor,无操作功能版本

HuangKai 4 月之前
當前提交
874459600c
共有 100 個文件被更改,包括 45995 次插入0 次删除
  1. 1 0
      .env
  2. 22 0
      .gitignore
  3. 40 0
      .gitlab-ci.yml
  4. 123 0
      CHANGELOG.md
  5. 46 0
      CODE_OF_CONDUCT.md
  6. 25 0
      CONTRIBUTING.md
  7. 63 0
      DEVELOP.md
  8. 9 0
      LICENSE.md
  9. 43 0
      README.md
  10. 15 0
      USAGE.md
  11. 7 0
      embed_git_hash.sh
  12. 58 0
      fix_i18n_files.js
  13. 45193 0
      package-lock.json
  14. 110 0
      package.json
  15. 67 0
      presets_extract_labels.js
  16. 94 0
      presets_merge_labels.js
  17. 7 0
      public/config.json
  18. 二進制
      public/img/building_levels.png
  19. 二進制
      public/img/floor_height.jpg
  20. 二進制
      public/img/icons/aeroway_aerodrome.png
  21. 二進制
      public/img/icons/aeroway_airport.png
  22. 二進制
      public/img/icons/aeroway_gate.png
  23. 二進制
      public/img/icons/aeroway_helipad.png
  24. 二進制
      public/img/icons/aeroway_terminal.png
  25. 二進制
      public/img/icons/amenity_atm.png
  26. 二進制
      public/img/icons/amenity_bank.png
  27. 二進制
      public/img/icons/amenity_bar.png
  28. 二進制
      public/img/icons/amenity_bench.png
  29. 二進制
      public/img/icons/amenity_bicycle_parking.png
  30. 二進制
      public/img/icons/amenity_bicycle_rental.png
  31. 二進制
      public/img/icons/amenity_biergarten.png
  32. 二進制
      public/img/icons/amenity_bureau_de_change.png
  33. 二進制
      public/img/icons/amenity_bus_station.png
  34. 二進制
      public/img/icons/amenity_cafe.png
  35. 二進制
      public/img/icons/amenity_car_rental.png
  36. 二進制
      public/img/icons/amenity_car_sharing.png
  37. 二進制
      public/img/icons/amenity_casino.png
  38. 二進制
      public/img/icons/amenity_chair.png
  39. 47 0
      public/img/icons/amenity_chair.svg
  40. 二進制
      public/img/icons/amenity_charging_station.png
  41. 二進制
      public/img/icons/amenity_cinema.png
  42. 二進制
      public/img/icons/amenity_clock.png
  43. 二進制
      public/img/icons/amenity_college.png
  44. 二進制
      public/img/icons/amenity_court.png
  45. 二進制
      public/img/icons/amenity_dentist.png
  46. 二進制
      public/img/icons/amenity_doctors.png
  47. 二進制
      public/img/icons/amenity_drinking_water.png
  48. 二進制
      public/img/icons/amenity_embassy.png
  49. 二進制
      public/img/icons/amenity_fast_food.png
  50. 二進制
      public/img/icons/amenity_firestation.png
  51. 二進制
      public/img/icons/amenity_fountain.png
  52. 二進制
      public/img/icons/amenity_heater.png
  53. 二進制
      public/img/icons/amenity_hospital.png
  54. 二進制
      public/img/icons/amenity_ice_cream.png
  55. 二進制
      public/img/icons/amenity_library.png
  56. 二進制
      public/img/icons/amenity_luggage_locker.png
  57. 二進制
      public/img/icons/amenity_marketplace.png
  58. 二進制
      public/img/icons/amenity_nightclub.png
  59. 二進制
      public/img/icons/amenity_nursery.png
  60. 二進制
      public/img/icons/amenity_parking.png
  61. 二進制
      public/img/icons/amenity_pharmacy.png
  62. 二進制
      public/img/icons/amenity_photo_booth.png
  63. 二進制
      public/img/icons/amenity_piano.png
  64. 二進制
      public/img/icons/amenity_place_of_worship.png
  65. 二進制
      public/img/icons/amenity_playground.png
  66. 二進制
      public/img/icons/amenity_police.png
  67. 二進制
      public/img/icons/amenity_post_box.png
  68. 二進制
      public/img/icons/amenity_post_office.png
  69. 二進制
      public/img/icons/amenity_prison.png
  70. 二進制
      public/img/icons/amenity_pub.png
  71. 二進制
      public/img/icons/amenity_public_building.png
  72. 二進制
      public/img/icons/amenity_recycling.png
  73. 二進制
      public/img/icons/amenity_restaurant.png
  74. 二進制
      public/img/icons/amenity_school.png
  75. 二進制
      public/img/icons/amenity_shelter.png
  76. 二進制
      public/img/icons/amenity_showcase.png
  77. 二進制
      public/img/icons/amenity_table.png
  78. 25 0
      public/img/icons/amenity_table.svg
  79. 二進制
      public/img/icons/amenity_taxi.png
  80. 二進制
      public/img/icons/amenity_telephone.png
  81. 二進制
      public/img/icons/amenity_theatre.png
  82. 二進制
      public/img/icons/amenity_ticket_validator.png
  83. 二進制
      public/img/icons/amenity_toilets.png
  84. 二進制
      public/img/icons/amenity_toilets_disabled.png
  85. 二進制
      public/img/icons/amenity_toilets_men.png
  86. 二進制
      public/img/icons/amenity_toilets_women.png
  87. 二進制
      public/img/icons/amenity_townhall.png
  88. 二進制
      public/img/icons/amenity_university.png
  89. 二進制
      public/img/icons/amenity_vending_machine.png
  90. 二進制
      public/img/icons/amenity_veterinary.png
  91. 二進制
      public/img/icons/amenity_waste_basket.png
  92. 二進制
      public/img/icons/barrier_block.png
  93. 二進制
      public/img/icons/barrier_bollard.png
  94. 二進制
      public/img/icons/barrier_cattle_grid.png
  95. 二進制
      public/img/icons/barrier_checkout.png
  96. 二進制
      public/img/icons/barrier_cycle_barrier.png
  97. 二進制
      public/img/icons/barrier_entrance.png
  98. 二進制
      public/img/icons/barrier_exit.png
  99. 二進制
      public/img/icons/barrier_fence.png
  100. 0 0
      public/img/icons/barrier_fence.svg

+ 1 - 0
.env

@@ -0,0 +1 @@
+BROWSER=none

+ 22 - 0
.gitignore

@@ -0,0 +1,22 @@
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+/doc
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*

文件差異過大導致無法顯示
+ 40 - 0
.gitlab-ci.yml


+ 123 - 0
CHANGELOG.md

@@ -0,0 +1,123 @@
+# Changelog
+All notable changes to this project will be documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## Unreleased
+
+
+## 1.0.15 - 2024-03-19
+
+### Changed
+- Switched OSM authentication to OAuth 2
+
+
+## 1.0.14 - 2023-08-16
+
+### Fixed
+- Mapbox tiles without token were breaking the editor (thanks to [Elian Doran](https://framagit.org/elian) for the fix)
+
+
+## 1.0.13 - 2023-03-30
+
+### Changed
+- Update Mapbox tiles URLs to use a dedicated access token
+
+
+## 1.0.12 - 2022-05-12
+
+### Fixed
+- Updated broken libraries (thanks to Alejandro Nigrelli)
+
+
+## 1.0.11 - 2022-01-04
+
+### Added
+- Allow preview current edits on [indoor=](https://indoorequal.org/) (thanks to François de Metz)
+
+### Fixed
+- Prevent empty tag key or value to be sent to OSM
+
+
+## 1.0.10 - 2021-08-16
+
+### Added
+- Button to ask for review when sending changeset (`review_request=yes` changeset tag)
+
+### Fixed
+- Tile providers with `crs` parameter defined caused freeze of UI
+
+
+## 1.0.9 - 2020-03-28
+
+### Fixed
+- Fix duplicate values in `level` tag
+- Better handling of existing `repeat_on` tag
+
+
+## 1.0.8 - 2020-03-05
+
+### Fixed
+- Handle outdoor sports centre as landuse
+- Read URL with hash missing part of level info
+
+
+## 1.0.7 - 2020-02-12
+
+### Changed
+- Updated de + it translations
+
+
+## 1.0.6 - 2019-11-12
+
+### Fixed
+- Deletion of features being part of a non-geometrical relation
+
+
+## 1.0.5 - 2019-10-10
+
+### Added
+- List of used imagery is added to changeset informations (tag `imagery_used`)
+- User can add used source for edits (tag `source` in changeset)
+
+### Changed
+- Support decimal levels when editing (they are visible in level selector)
+
+
+## 1.0.4 - 2019-10-10
+
+### Added
+- 🇩🇪 German translation (thanks to TuringTux and schwukas)
+
+
+## 1.0.3 - 2019-10-05
+
+### Changed
+- Buildings are now filtered on map according to selected level
+- Level selector properly handles areas with many levels
+
+
+## 1.0.2 - 2019-09-26
+
+### Changed
+- Improved metadata in `index.html` file
+
+### Fixed
+- Door nodes are now merged with vertex node if they are overlapping
+- List of edits in changeset pane always display correct name
+
+
+## 1.0.1 - 2019-09-25
+
+### Added
+- 🇮🇹 Italian translation (thanks to napolnx)
+
+### Changed
+- Allow double click zoom on explore mode
+
+
+# 1.0.0 - 2019-09-19
+
+### Added
+- Initial release of the editor, which allows to view indoor data, manage floor plan images, edit OpenStreetMap indoor data and send changes.

+ 46 - 0
CODE_OF_CONDUCT.md

@@ -0,0 +1,46 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [panieravide@riseup.net](mailto:panieravide@riseup.net). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
+
+[homepage]: https://contributor-covenant.org
+[version]: https://contributor-covenant.org/version/1/4/

+ 25 - 0
CONTRIBUTING.md

@@ -0,0 +1,25 @@
+# Contributing
+
+:+1: :tada: First off, thanks for taking the time to contribute! :tada: :+1:
+
+
+## Code of Conduct
+
+This project and everyone participating in it is governed by a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [panieravide@riseup.net](mailto:panieravide@riseup.net).
+
+
+## Reporting Bugs
+
+If you encountered an unexpected behaviour in the editor, or want to share your awesome ideas, please feel free to [open an issue](https://framagit.org/PanierAvide/osminedit/issues) on this repository. Before doing so, you might have a look at existing issues to see if you can join discussion instead.
+
+
+## Translate the application
+
+We use Transifex, which is a simple platform for translating applications. We have all the [labels there](https://www.transifex.com/openlevelup/osminedit), in English, so you can write translations into your language. Let us know when you're done, that way we will update the application to make your language available.
+
+If you run into any issue for doing this (like your language isn't available in the list), please [contact us](mailto:panieravide@riseup.net) or [open an issue](https://framagit.org/PanierAvide/osminedit/issues/new).
+
+
+## Develop feature, offer pull requests
+
+If you are a developer, you can see the [list of open issues](https://framagit.org/PanierAvide/osminedit/issues) and start working on one of them. To start development, please read [development documentation](DEVELOP.md). When you think your work is done, you can open a pull request, so we can integrate your contribution in the editor.

+ 63 - 0
DEVELOP.md

@@ -0,0 +1,63 @@
+# Develop
+
+This application is based on web technologies, and mainly written in ECMAScript 6 (modern JavaScript). This documentation is for people who want to build by themselves or develop the project.
+
+
+## Dependencies
+
+You need to install the given tools before starting:
+* NodeJS (>= 9) - [Documentation](https://nodejs.org/en/download/)
+* Transifex CLI - [Documentation](https://docs.transifex.com/client/installing-the-client)
+
+
+## Run
+
+To run the project locally, you need to first `git clone` this repository.
+
+Then, install project dependencies using `npm install`. Now, you can use following commands to work.
+
+### `npm start`
+
+Runs the app in the development mode.<br>
+Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
+
+The page will reload if you make edits.<br>
+You will also see any lint errors in the console.
+
+### `npm test`
+
+Launches the test runner in the interactive watch mode.<br>
+See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
+
+### `npm run build`
+
+Builds the app for production to the `build` folder.<br>
+It correctly bundles React in production mode and optimizes the build for the best performance.
+
+The build is minified and the filenames include the hashes.<br>
+Your app is ready to be deployed!
+
+See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
+
+
+## Translations
+
+Translations of user interface labels are managed using JSON configuration files, automatically generated using `i18nline` tool. When editing code, launch manually `npm run i18n:build` to update these configuration files.
+
+To retrieve translated labels from Transifex, run command `npm run i18n:pull`.
+
+
+## Documentation
+
+Documentation of the source code uses [JSDoc syntax](http://usejsdoc.org/). Readable documentation can be generated using `npm run doc` command, and will be available as an HTML page in `doc/` folder.
+
+
+## Configuration
+
+Various components of the editor can be configured for the instance manager. Main files you can edit are :
+
+* `public/config.json` : various configurations, in particular [OAuth tokens](https://wiki.openstreetmap.org/wiki/Oauth) and [OSM API URL](https://wiki.openstreetmap.org/wiki/API_v0.6#URL_.2B_authentication) to use
+* `public/style.mapcss` : [MapCSS](https://wiki.openstreetmap.org/wiki/MapCSS) stylesheet for map features
+* `public/presets/*.xml` : [JOSM tagging presets](https://josm.openstreetmap.de/wiki/TaggingPresets) for simple creation and editing of features
+
+You can either make temporary changes by editing these files in your `build/` folder, or making changes permanent by editing in `public/` folder (and rebuild using described procedure above).

+ 9 - 0
LICENSE.md

@@ -0,0 +1,9 @@
+# ISC License (ISC)
+
+Copyright (c) Adrien Pavie 2019
+
+Copyright (c) Daimler AG 2019
+
+Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

+ 43 - 0
README.md

@@ -0,0 +1,43 @@
+# OsmInEdit
+
+OsmInEdit is web tool to allow easy editing of OpenStreetMap indoor-related data.
+
+You can use it at [osminedit.pavie.info](https://osminedit.pavie.info/) (or [here for under development version](https://osminedit.pavie.info/dev/)).
+
+## Purpose
+
+OsmInEdit aims to make [indoor data editing](https://wiki.openstreetmap.org/wiki/Simple_Indoor_Tagging) easy on OpenStreetMap, ideally being as good as [iD editor](https://github.com/openstreetmap/iD), but focused on building indoors. With this tool, you can contribute to make OpenStreetMap the best source of geo-data for both outdoors and indoors.
+
+If you are looking for an indoor data viewer (a map for browsing existing data), have a look at [OpenLevelUp](https://openlevelup.net/).
+
+__Tips and tricks__ for using this editor can be found on [usage documentation](USAGE.md).
+
+
+## Contributing
+
+This project is an open source tool, meaning it is made by volunteers. If you __want to help us__, there are several ways (technical or non-technical ones). You can find how to participate in the [contributing documentation](CONTRIBUTING.md).
+
+
+## Develop/run your own instance
+
+OsmInEdit is already available online, so you can use without any bothering (see link on top of this document). In case you want to run your instance of OsmInEdit, or work on its development, you can read [develop documentation](DEVELOP.md) to have all technical information.
+
+
+## Contributors
+
+OsmInEdit exists and is everyday improving thanks to the __amazing people__ following :
+
+* Adrien Pavie, main developer of OsmInEdit
+* Daimler AG team, for sponsoring and leading the project
+* Florian Lainez, for improving the user experience
+* Thomas Gratier, for his work on [osm-request](https://github.com/osmlab/osm-request) library
+* And all users, for using the tool and sharing their ideas !
+
+
+## License
+
+Copyright (c) Adrien Pavie 2019
+
+Copyright (c) Daimler AG 2019
+
+Released under ISC license, see [LICENSE](LICENSE.md) for complete license text.

+ 15 - 0
USAGE.md

@@ -0,0 +1,15 @@
+# Using OsmInEdit
+
+## Available shortcuts
+
+Various keyboard shortcuts are available to offer advanced features, or to make editing faster:
+
+* `a` : show guidelines to make right angles when drawing
+* `Enter` : validate your drawing
+* `Ctrl + z` : cancel last edit
+* `Ctrl + Shift + z` : restore last cancelled edit
+* `Delete` : delete selected feature
+* `Ctrl + c` : copy selected feature
+* `Ctrl + v` : paste copied feature
+* `Ctrl + Shift + v` : paste tags of copied feature on selected feature
+* `Esc` : unselect selected feature

+ 7 - 0
embed_git_hash.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# This script changes config.json file to include last Git hash (for client-side display)
+# This should be run only on production pipelines
+# config.json source file should have a "GIT_HASH" label properly defined
+
+sed -i "s/GIT_HASH/`git rev-parse --short HEAD`/g" ./public/config.json

+ 58 - 0
fix_i18n_files.js

@@ -0,0 +1,58 @@
+/**
+ * Changes the language in the translation files retrieved from Transifex.
+ */
+
+const fs = require('fs');
+
+const I18N_DIRS = [ "./src/config/locales/ui", "./src/config/locales/presets" ];
+const JSON_RGX = /^[A-Za-z0-9_\-]+\.json$/;
+
+//Read translation files
+I18N_DIRS.forEach(i18n_dir => {
+	fs.readdirSync(i18n_dir).forEach((file) => {
+		if(JSON_RGX.test(file)) {
+			const lng = file.substring(0, file.length - 5).replace("_", "-");
+			try {
+				//Read file
+				const lngData = JSON.parse(fs.readFileSync(i18n_dir+"/"+file, 'utf8'));
+
+				//If not already fixed
+				if(lngData[lng] === undefined) {
+					//Check if en available
+					if(lngData["en"] !== undefined) {
+						//Edit object, put en into lng locale
+						const outData = {};
+						outData[lng] = lngData.en;
+
+						//Overwrite file
+						fs.writeFile(i18n_dir+"/"+file, JSON.stringify(outData, null, 2), function(err) {
+							if(err) {
+								throw new Error(err);
+							}
+							else {
+								console.log("[INFO] Translation file "+i18n_dir+"/"+file+" updated");
+							}
+						});
+					}
+					else {
+						throw new Error("Unknown translation locale: "+i18n_dir+"/"+file);
+					}
+				}
+				else {
+					console.log("[INFO] Translation file "+i18n_dir+"/"+file+" already OK");
+				}
+			}
+			catch(e) {
+				if(e instanceof SyntaxError) {
+					throw new Error("Invalid translation file: "+i18n_dir+"/"+file+" ("+e.message+")");
+				}
+				else {
+					throw e;
+				}
+			}
+		}
+		else {
+			console.log("[INFO] Ignored file "+i18n_dir+"/"+file);
+		}
+	});
+});

文件差異過大導致無法顯示
+ 45193 - 0
package-lock.json


+ 110 - 0
package.json

@@ -0,0 +1,110 @@
+{
+  "name": "indoor-editor",
+  "version": "0.0.15",
+  "description": "Web tool for editing building indoors data",
+  "main": "index.js",
+  "scripts": {
+    "start": "react-scripts start",
+    "build": "react-scripts build",
+    "test": "react-scripts test",
+    "doc": "npm run doc:js:check && npm run doc:js",
+    "doc:js": "documentation build ./src/*.js ./src/ctrl ./src/model ./src/view -f html -o doc/ --shallow",
+    "doc:js:check": "documentation lint ./src/*.js ./src/ctrl ./src/model ./src/view --shallow",
+    "i18n:build": "i18nline synch && node presets_extract_labels.js",
+    "i18n:add": "tx set --auto-local -r osminedit.ui 'src/config/locales/ui/<lang>.json' --source-lang cn --type KEYVALUEJSON",
+    "i18n:push": "tx push -s",
+    "i18n:pull": "tx pull -a --minimum-perc=75 && node fix_i18n_files.js && i18nline index && node presets_merge_labels.js",
+    "i18n:clean": "rm -rf ./src/config/locales/**/*.js*",
+    "icons": "for i in public/img/icons/*.svg ; do inkscape -z -e ${i%.*}.png -w 32 -h 32 $i ; done",
+    "clean": "rm -rf build/* doc/*"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://framagit.org/PanierAvide/osminedit.git"
+  },
+  "keywords": [
+    "openstreetmap",
+    "indoor",
+    "editor",
+    "osm",
+    "building"
+  ],
+  "author": "Adrien PAVIE, Daimler AG",
+  "license": "ISC",
+  "dependencies": {
+    "@turf/along": "^6.0.1",
+    "@turf/area": "^6.0.1",
+    "@turf/bbox": "^6.0.1",
+    "@turf/bearing": "^6.0.1",
+    "@turf/boolean-contains": "^6.0.1",
+    "@turf/boolean-disjoint": "^6.0.2",
+    "@turf/boolean-intersects": "^6.0.2",
+    "@turf/boolean-point-in-polygon": "^6.0.1",
+    "@turf/boolean-point-on-line": "^6.0.1",
+    "@turf/buffer": "^5.1.5",
+    "@turf/center-of-mass": "^6.0.1",
+    "@turf/helpers": "^6.1.4",
+    "@turf/intersect": "^6.1.3",
+    "@turf/meta": "^6.0.2",
+    "@turf/nearest-point": "^6.0.1",
+    "@turf/point-on-feature": "^5.1.5",
+    "@turf/point-to-line-distance": "^6.0.0",
+    "@turf/polygon-to-line": "^6.0.3",
+    "@turf/transform-translate": "^5.1.5",
+    "@turf/turf": "^6.2.0",
+    "array-flat-polyfill": "^1.0.1",
+    "bootstrap": "^4.3.1",
+    "fast-deep-equal": "^2.0.1",
+    "file-saver": "^2.0.2",
+    "fuse.js": "^3.4.5",
+    "geojson-validation": "^0.2.1",
+    "leaflet": "^1.5.1",
+    "leaflet-distortableimage": "^0.6.7",
+    "leaflet-draw": "^1.0.4",
+    "leaflet-editable": "^1.2.0",
+    "leaflet-geometryutil": "^0.9.1",
+    "leaflet-hash": "^0.2.1",
+    "leaflet-polylinedecorator": "^1.6.0",
+    "leaflet-textpath": "^1.2.0",
+    "leaflet-toolbar": "^0.4.0-alpha.2",
+    "martinez-polygon-clipping": "^0.7.3",
+    "mdi-react": "^5.5.0",
+    "mousetrap": "^1.6.3",
+    "nominatim-browser": "^2.0.2",
+    "object-hash": "^1.3.1",
+    "osm-auth": "^2.4.0",
+    "osm-request": "^1.2.4",
+    "osmtogeojson": "^3.0.0-beta.3",
+    "popper.js": "^1.16.1",
+    "pubsub-js": "^1.7.0",
+    "react": "^16.8.6",
+    "react-bootstrap": "^1.0.0-beta.10",
+    "react-bootstrap-multiselect": "^2.4.1",
+    "react-dom": "^16.8.6",
+    "react-dropzone": "^10.1.6",
+    "react-leaflet": "^2.4.0",
+    "react-leaflet-bing": "^4.1.0",
+    "react-scripts": "2.1.5",
+    "react-three-state-checkbox": "^1.2.2",
+    "socket.io-client": "^2.0.4",
+    "xml2js": "^0.4.19"
+  },
+  "devDependencies": {
+    "assert": "^1.5.0",
+    "documentation": "^9.3.1",
+    "i18nline": "^2.0.1"
+  },
+  "eslintConfig": {
+    "extends": "react-app"
+  },
+  "browserslist": [
+    ">0.2%",
+    "not dead",
+    "not ie <= 11",
+    "not op_mini all"
+  ],
+  "i18n": {
+    "out": "src/config/locales/ui"
+  },
+  "homepage": "."
+}

+ 67 - 0
presets_extract_labels.js

@@ -0,0 +1,67 @@
+/*
+ * Creates a JSON file for Transifex to allow translation of XML presets.
+ */
+
+const fs = require('fs');
+const parseString = require('xml2js').parseString;
+const Hash = require("object-hash");
+
+const PRESETS_DIR = "./public/presets";
+const LOCALES_DIR = "./src/config/locales/presets";
+const XML_RGX = /^[A-Za-z0-9_\-]+\.xml$/;
+
+const foundLabels = {};
+
+const entryToLabels = entry => {
+	Object.entries(entry).forEach(e => {
+		const [ k, v ] = e;
+
+		if(k === "$") {
+			Object.entries(v).forEach(ve => {
+				const [ vk, vv ] = ve;
+
+				if([ "text", "name", "display_values", "display_value"].includes(vk)) {
+					foundLabels[Hash(vv)] = vv;
+				}
+			});
+		}
+		else {
+			entryToLabels(v);
+		}
+	});
+};
+
+//Read translation files
+fs.readdirSync(PRESETS_DIR).forEach((file) => {
+	if(XML_RGX.test(file)) {
+		try {
+			const xml = fs.readFileSync(PRESETS_DIR+"/"+file, 'utf8');
+
+			// Parse XML content
+			parseString(xml, (err, result) => {
+				if (err) {
+					throw new Error("Parse error", e.message);
+				}
+				else {
+					entryToLabels(result);
+				}
+			});
+		}
+		catch(e) {
+			throw new Error("Can't read file: "+file+" ("+e.message+")");
+		}
+	}
+	else {
+		console.log("[INFO] Ignored file "+file);
+	}
+});
+
+// Export found labels
+fs.writeFile(LOCALES_DIR+"/en.json", JSON.stringify({ "en": foundLabels }, null, 2), function(err) {
+	if(err) {
+		throw new Error(err);
+	}
+	else {
+		console.log("[INFO] Translation file for presets updated");
+	}
+});

+ 94 - 0
presets_merge_labels.js

@@ -0,0 +1,94 @@
+/*
+ * Updates XML presets files using translations from Transifex
+ */
+
+const fs = require('fs');
+const xml2js = require('xml2js');
+const Hash = require("object-hash");
+
+const PRESETS_DIR = "./public/presets";
+const LOCALES_DIR = "./src/config/locales/presets";
+const XML_RGX = /^[A-Za-z0-9_\-]+\.xml$/;
+const JSON_RGX = /^[A-Za-z0-9_\-]+\.json$/;
+
+// Load in-memory all translation files
+let locales = {};
+
+fs.readdirSync(LOCALES_DIR).forEach((file) => {
+	if(JSON_RGX.test(file) && file !== "en.json") {
+		try {
+			const localeJson = JSON.parse(fs.readFileSync(LOCALES_DIR+"/"+file, 'utf8'));
+			locales = Object.assign(locales, localeJson);
+		}
+		catch(e) {
+			throw new Error("Can't parse translation file: "+file+" ("+e.message+")");
+		}
+	}
+});
+
+
+// Function for adding translation to given object
+const addTranslation = entry => {
+	Object.entries(entry).forEach(e => {
+		const [ k, v ] = e;
+
+		if(k === "$") {
+			Object.entries(v).forEach(ve => {
+				const [ vk, vv ] = ve;
+
+				if([ "text", "name", "display_values", "display_value"].includes(vk)) {
+					const strhash = Hash(vv);
+					Object.keys(locales).forEach(l => {
+						if(locales[l][strhash] && locales[l][strhash] !== vv) {
+							v[l+"."+vk] = locales[l][strhash];
+						}
+					});
+				}
+			});
+		}
+		else {
+			addTranslation(v);
+		}
+	});
+
+	return entry;
+};
+
+
+// Read all presets files, add translations, and rewrite them
+fs.readdirSync(PRESETS_DIR).forEach((file) => {
+	if(XML_RGX.test(file)) {
+		try {
+			const xml = fs.readFileSync(PRESETS_DIR+"/"+file, 'utf8');
+
+			// Parse XML content
+			xml2js.parseString(xml, (err, result) => {
+				if (err) {
+					throw new Error("Parse error", e.message);
+				}
+				else {
+					// Append translations to JS object
+					result = addTranslation(result);
+
+					// Rewrite XML file
+					const newXml = (new xml2js.Builder({ renderOpts: { pretty: true, indent: '\t' } })).buildObject(result);
+
+					fs.writeFile(PRESETS_DIR+"/"+file, newXml, function(err) {
+						if(err) {
+							throw new Error(err);
+						}
+						else {
+							console.log("[INFO] Preset file "+file+" updated");
+						}
+					});
+				}
+			});
+		}
+		catch(e) {
+			throw new Error("Can't update preset: "+file+" ("+e.message+")");
+		}
+	}
+	else {
+		console.log("[INFO] Ignored file "+file);
+	}
+});

+ 7 - 0
public/config.json

@@ -0,0 +1,7 @@
+{
+	"editor_name": "编辑器",
+	"hash": "GIT_HASH",
+	"data_min_zoom": 18,
+	"map_initial_zoom": 18,
+	"map_initial_latlng": [39.8729, 116.5141]
+}

二進制
public/img/building_levels.png


二進制
public/img/floor_height.jpg


二進制
public/img/icons/aeroway_aerodrome.png


二進制
public/img/icons/aeroway_airport.png


二進制
public/img/icons/aeroway_gate.png


二進制
public/img/icons/aeroway_helipad.png


二進制
public/img/icons/aeroway_terminal.png


二進制
public/img/icons/amenity_atm.png


二進制
public/img/icons/amenity_bank.png


二進制
public/img/icons/amenity_bar.png


二進制
public/img/icons/amenity_bench.png


二進制
public/img/icons/amenity_bicycle_parking.png


二進制
public/img/icons/amenity_bicycle_rental.png


二進制
public/img/icons/amenity_biergarten.png


二進制
public/img/icons/amenity_bureau_de_change.png


二進制
public/img/icons/amenity_bus_station.png


二進制
public/img/icons/amenity_cafe.png


二進制
public/img/icons/amenity_car_rental.png


二進制
public/img/icons/amenity_car_sharing.png


二進制
public/img/icons/amenity_casino.png


二進制
public/img/icons/amenity_chair.png


+ 47 - 0
public/img/icons/amenity_chair.svg

@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   height="300px"
+   width="300px"
+   fill="#000000"
+   version="1.1"
+   x="0px"
+   y="0px"
+   viewBox="0 0 100 100"
+   enable-background="new 0 0 100 100"
+   xml:space="preserve"
+   id="svg4"
+   sodipodi:docname="amenity_chair.svg"
+   inkscape:version="0.92.4 5da689c313, 2019-01-14"><metadata
+     id="metadata10"><rdf:RDF><cc:Work
+         rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+     id="defs8" /><sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="1920"
+     inkscape:window-height="1015"
+     id="namedview6"
+     showgrid="false"
+     inkscape:zoom="0.78666667"
+     inkscape:cx="-47.033898"
+     inkscape:cy="150"
+     inkscape:window-x="0"
+     inkscape:window-y="452"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="svg4" /><path
+     d="M77.342,49.317L52.796,37.044L48.98,3.659c-0.188-1.646-1.674-2.828-3.321-2.64c-0.342,0.039-0.708,0.157-1.001,0.297  l-26,13c-1.072,0.557-1.784,1.752-1.639,3.024L21,52.17V83c0,1.657,1.343,3,3,3s3-1.343,3-3V56.854l20,10V96c0,1.657,1.343,3,3,3  c1.657,0,3-1.343,3-3V66.854l20-10V83c0,1.657,1.343,3,3,3s3-1.343,3-3V52C79,50.873,78.262,49.83,77.342,49.317z M46.781,37.255  L26.494,47.399l-2.356-20.614l20.288-10.144L46.781,37.255z"
+     id="path2"
+     style="fill:#8e7409;fill-opacity:1" /></svg>

二進制
public/img/icons/amenity_charging_station.png


二進制
public/img/icons/amenity_cinema.png


二進制
public/img/icons/amenity_clock.png


二進制
public/img/icons/amenity_college.png


二進制
public/img/icons/amenity_court.png


二進制
public/img/icons/amenity_dentist.png


二進制
public/img/icons/amenity_doctors.png


二進制
public/img/icons/amenity_drinking_water.png


二進制
public/img/icons/amenity_embassy.png


二進制
public/img/icons/amenity_fast_food.png


二進制
public/img/icons/amenity_firestation.png


二進制
public/img/icons/amenity_fountain.png


二進制
public/img/icons/amenity_heater.png


二進制
public/img/icons/amenity_hospital.png


二進制
public/img/icons/amenity_ice_cream.png


二進制
public/img/icons/amenity_library.png


二進制
public/img/icons/amenity_luggage_locker.png


二進制
public/img/icons/amenity_marketplace.png


二進制
public/img/icons/amenity_nightclub.png


二進制
public/img/icons/amenity_nursery.png


二進制
public/img/icons/amenity_parking.png


二進制
public/img/icons/amenity_pharmacy.png


二進制
public/img/icons/amenity_photo_booth.png


二進制
public/img/icons/amenity_piano.png


二進制
public/img/icons/amenity_place_of_worship.png


二進制
public/img/icons/amenity_playground.png


二進制
public/img/icons/amenity_police.png


二進制
public/img/icons/amenity_post_box.png


二進制
public/img/icons/amenity_post_office.png


二進制
public/img/icons/amenity_prison.png


二進制
public/img/icons/amenity_pub.png


二進制
public/img/icons/amenity_public_building.png


二進制
public/img/icons/amenity_recycling.png


二進制
public/img/icons/amenity_restaurant.png


二進制
public/img/icons/amenity_school.png


二進制
public/img/icons/amenity_shelter.png


二進制
public/img/icons/amenity_showcase.png


二進制
public/img/icons/amenity_table.png


文件差異過大導致無法顯示
+ 25 - 0
public/img/icons/amenity_table.svg


二進制
public/img/icons/amenity_taxi.png


二進制
public/img/icons/amenity_telephone.png


二進制
public/img/icons/amenity_theatre.png


二進制
public/img/icons/amenity_ticket_validator.png


二進制
public/img/icons/amenity_toilets.png


二進制
public/img/icons/amenity_toilets_disabled.png


二進制
public/img/icons/amenity_toilets_men.png


二進制
public/img/icons/amenity_toilets_women.png


二進制
public/img/icons/amenity_townhall.png


二進制
public/img/icons/amenity_university.png


二進制
public/img/icons/amenity_vending_machine.png


二進制
public/img/icons/amenity_veterinary.png


二進制
public/img/icons/amenity_waste_basket.png


二進制
public/img/icons/barrier_block.png


二進制
public/img/icons/barrier_bollard.png


二進制
public/img/icons/barrier_cattle_grid.png


二進制
public/img/icons/barrier_checkout.png


二進制
public/img/icons/barrier_cycle_barrier.png


二進制
public/img/icons/barrier_entrance.png


二進制
public/img/icons/barrier_exit.png


二進制
public/img/icons/barrier_fence.png


+ 0 - 0
public/img/icons/barrier_fence.svg


部分文件因文件數量過多而無法顯示