forked from MapComplete/MapComplete
Merge develop
This commit is contained in:
commit
5904142402
13 changed files with 80 additions and 40 deletions
|
@ -243,7 +243,9 @@ export class And extends TagsFilter {
|
|||
properties[opt.key] = opt.value
|
||||
}
|
||||
}
|
||||
for (const opt of optimized) {
|
||||
|
||||
for (let i = 0; i < optimized.length; i++){
|
||||
const opt = optimized[i];
|
||||
if (opt instanceof Tag) {
|
||||
const k = opt.key
|
||||
const v = properties[k]
|
||||
|
@ -264,7 +266,23 @@ export class And extends TagsFilter {
|
|||
if (v === undefined) {
|
||||
continue
|
||||
}
|
||||
if (v !== opt.value) {
|
||||
if(opt.invert){
|
||||
// We should _not_ match this value
|
||||
// If 'v' is given, we already know what value it should be
|
||||
// If 'v' is the not-expected value, we have a conflict and return false
|
||||
// Otherwise, we can safely drop this value
|
||||
|
||||
const doesMatch = (typeof opt.value === "string" && v === opt.value) ||
|
||||
(v.match(<RegExp> opt.value) !== null)
|
||||
|
||||
if(doesMatch){
|
||||
// We have a conflict as 'opt' is inverted
|
||||
return false
|
||||
}else{
|
||||
optimized.splice(i, 1)
|
||||
i--
|
||||
}
|
||||
}else if (v !== opt.value) {
|
||||
// detected an internal conflict
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -55,7 +55,9 @@ export default class SourceConfig {
|
|||
throw (
|
||||
"Error at " +
|
||||
context +
|
||||
": the specified tags are conflicting with each other: they will never match anything at all"
|
||||
": the specified tags are conflicting with each other: they will never match anything at all.\n" +
|
||||
"\tThe offending tags are: "+params.osmTags.asHumanString(false, false, {})+
|
||||
"\tThey optmize into 'false' "
|
||||
)
|
||||
}
|
||||
if (optimized === true) {
|
||||
|
|
|
@ -233,7 +233,7 @@
|
|||
{
|
||||
"if": "amenity=cafe",
|
||||
"then": {
|
||||
"en": "A <b>cafe</b> to drink tea, coffee or an alcoholical bevarage in a quiet environment",
|
||||
"en": "A <b>cafe</b> to drink tea, coffee or an alcoholic beverage in a quiet environment",
|
||||
"nl": "Dit is een <b>cafe</b> - een plaats waar men rustig kan zitten om een thee, koffie of alcoholische drank te nuttigen.",
|
||||
"de": "Ein <b>Café</b>, um in ruhiger Umgebung Tee, Kaffee oder ein alkoholisches Getränk zu trinken",
|
||||
"da": "En <b>café</b> til at drikke te, kaffe eller en alkoholisk drik i rolige omgivelser",
|
||||
|
@ -245,7 +245,7 @@
|
|||
{
|
||||
"if": "amenity=restaurant",
|
||||
"then": {
|
||||
"en": "A <b>restuarant</b> where one can get a proper meal",
|
||||
"en": "A <b>restaurant</b> where one can get a proper meal",
|
||||
"nl": "Dit is een <b>restaurant</b> waar men een maaltijd geserveerd krijgt",
|
||||
"de": "Ein <b>Restaurant</b>, in dem man ordentlich essen kann",
|
||||
"da": "En <b>restaurant</b>, hvor man kan få et ordentligt måltid",
|
||||
|
@ -369,4 +369,4 @@
|
|||
"fr": "Une couche montrants les cafés et pubs où l’on peut prendre un verre. Cette couche pose des questions y afférentes.",
|
||||
"ca": "Una capa que mostra cafeteries i bars on un es pot reunir amb una beguda. La capa demana algunes preguntes rellevants"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4699,12 +4699,12 @@
|
|||
"socket:typee=1"
|
||||
],
|
||||
"title": {
|
||||
"en": "a charging station for electrical bikes with a normal european wall plug <img src='./assets/layers/charging_station/typee.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (meant to charge electrical bikes)",
|
||||
"nl": "een oplaadpunt voor elektrische fietsen met een gewoon Europees stopcontact <img src='./assets/layers/charging_station/typee.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (speciaal bedoeld voor fietsen)",
|
||||
"ca": "una estació de càrrega per a bicicletes elèctriques amb un endoll de paret europeu normal<img src='./assets/layers/charging_station/typee.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (destinat a carregar bicicletes elèctriques)",
|
||||
"da": "en ladestation til elektriske cykler med et normalt europæisk vægstik <img src='./assets/layers/charging_station/typee.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (beregnet til opladning af elektriske cykler)",
|
||||
"de": "eine Ladestation für Elektrofahrräder mit einer normalen europäischen Steckdose <img src='./assets/layers/charging_station/typee.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (zum Laden von Elektrofahrrädern)",
|
||||
"es": "una estación de carga para bicicletas eléctricas con un enchufe de pared europeo normal <img src='./assets/layers/charging_station/typee.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (pensado para cargar bicicletas eléctricas)"
|
||||
"en": "a charging station for electrical bikes with a normal european wall plug <img src='./assets/layers/charging_station/TypeE.svg' class=\"w-6 h-6 mx-1 bg-white rounded-full \" style='display: inline-block'/>",
|
||||
"nl": "een oplaadpunt voor elektrische fietsen met een gewoon Europees stopcontact <img src='./assets/layers/charging_station/TypeE.svg' class=\"w-6 h-6 mx-1 bg-white rounded-full\" style='display: inline-block'/>",
|
||||
"ca": "una estació de càrrega per a bicicletes elèctriques amb un endoll de paret europeu normal <img src='./assets/layers/charging_station/TypeE.svg' class=\"w-6 h-6 mx-1 bg-white rounded-full\" style='display: inline-block'/>",
|
||||
"da": "en ladestation til elektriske cykler med et normalt europæisk vægstik <img src='./assets/layers/charging_station/TypeE.svg' class=\"w-6 h-6 mx-1 bg-white rounded-full\" style='display: inline-block'/>",
|
||||
"de": "eine Ladestation für Elektrofahrräder mit einer normalen europäischen Steckdose <img src='./assets/layers/charging_station/TypeE.svg' class=\"w-6 h-6 mx-1 bg-white rounded-full\" style='display: inline-block'/>",
|
||||
"es": "una estación de carga para bicicletas eléctricas con un enchufe de pared europeo normal <img src='./assets/layers/charging_station/TypeE.svg' class=\"w-6 h-6 mx-1 bg-white rounded-full\" style='display: inline-block'/>"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "map"
|
||||
|
|
|
@ -800,8 +800,8 @@
|
|||
"socket:typee=1"
|
||||
],
|
||||
"title": {
|
||||
"en": "charging station for electrical bikes with a normal european wall plug <img src='./assets/layers/charging_station/TypeE.svg' style='width: 2rem; height: 2rem; float: left; background: white; border-radius: 1rem; margin-right: 0.5rem'/> (meant to charge electrical bikes)",
|
||||
"nl": "oplaadpunt voor elektrische fietsen"
|
||||
"en": "charging station for electrical bikes with a normal european wall plug <img src='./assets/layers/charging_station/TypeE.svg' class="w-4 h-4 mx-1 bg-white rounded-full"/>",
|
||||
"nl": "oplaadpunt voor elektrische fietsen met een gewone, europese stekker <img src='./assets/layers/charging_station/TypeE.svg' class="w-4 h-4 mx-1 bg-white rounded-full"/>"
|
||||
},
|
||||
"preciseInput": {
|
||||
"preferredBackground": "map"
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
"source": {
|
||||
"osmTags": {
|
||||
"and": [
|
||||
"shop~*"
|
||||
"shop~*",
|
||||
"shop!=mall"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
|
|
@ -460,7 +460,8 @@
|
|||
"fr": "Méthode de montage : {camera:mount}",
|
||||
"it": "Metodo di montaggio: {camera:mount}",
|
||||
"de": "Montageart: {camera:mount}",
|
||||
"da": "Monteringsmetode: {camera:mount}"
|
||||
"da": "Monteringsmetode: {camera:mount}",
|
||||
"ca": "Mètode de muntatge: {camera:mount}"
|
||||
},
|
||||
"freeform": {
|
||||
"key": "camera:mount"
|
||||
|
|
|
@ -4964,7 +4964,8 @@
|
|||
"then": "Aquesta càmera està posicionada a un arbre"
|
||||
}
|
||||
},
|
||||
"question": "Com està posicionada aquesta càmera?"
|
||||
"question": "Com està posicionada aquesta càmera?",
|
||||
"render": "Mètode de muntatge: {camera:mount}"
|
||||
},
|
||||
"camera_direction": {
|
||||
"question": "En quina direcció geogràfica apunta aquesta càmera?",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "mapcomplete",
|
||||
"version": "0.30.5",
|
||||
"version": "0.30.6",
|
||||
"repository": "https://github.com/pietervdvn/MapComplete",
|
||||
"description": "A small website to edit OSM easily",
|
||||
"bugs": "https://github.com/pietervdvn/MapComplete/issues",
|
||||
|
|
|
@ -1117,10 +1117,6 @@ video {
|
|||
width: 2.75rem;
|
||||
}
|
||||
|
||||
.w-24 {
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.w-1\/2 {
|
||||
width: 50%;
|
||||
}
|
||||
|
@ -1134,6 +1130,10 @@ video {
|
|||
width: 24rem;
|
||||
}
|
||||
|
||||
.w-24 {
|
||||
width: 6rem;
|
||||
}
|
||||
|
||||
.w-10 {
|
||||
width: 2.5rem;
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ import { describe, it } from "vitest"
|
|||
* @param reason
|
||||
* @private
|
||||
*/
|
||||
function detectInCode(forbidden: string, reason: string): (done: () => void) => void {
|
||||
return (done: () => void) => {
|
||||
function detectInCode(forbidden: string, reason: string): Promise<void> {
|
||||
return new Promise<void>((done) => {
|
||||
const excludedDirs = [
|
||||
".git",
|
||||
"node_modules",
|
||||
|
@ -49,14 +49,23 @@ function detectInCode(forbidden: string, reason: string): (done: () => void) =>
|
|||
console.error(found.length, "issues found")
|
||||
throw msg
|
||||
}
|
||||
done()
|
||||
}
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function wrap(promise: Promise<void>): ((done: () => void) => void) {
|
||||
return (done => {
|
||||
promise.then(done)
|
||||
})
|
||||
}
|
||||
|
||||
function itAsync(name: string, promise: Promise<void>){
|
||||
it(name, wrap(promise))
|
||||
}
|
||||
|
||||
describe("Code quality", () => {
|
||||
it(
|
||||
itAsync(
|
||||
"should not contain reverse",
|
||||
detectInCode(
|
||||
"reverse()",
|
||||
|
@ -64,12 +73,12 @@ describe("Code quality", () => {
|
|||
)
|
||||
)
|
||||
|
||||
it(
|
||||
itAsync(
|
||||
"should not contain 'constructor.name'",
|
||||
detectInCode("constructor\\.name", "This is not allowed, as minification does erase names.")
|
||||
)
|
||||
|
||||
it(
|
||||
itAsync(
|
||||
"should not contain 'innerText'",
|
||||
detectInCode(
|
||||
"innerText",
|
||||
|
@ -77,7 +86,7 @@ describe("Code quality", () => {
|
|||
)
|
||||
)
|
||||
|
||||
it(
|
||||
itAsync(
|
||||
"should not contain 'import * as name from \"xyz.json\"'",
|
||||
detectInCode(
|
||||
'import \\* as [a-zA-Z0-9_]\\+ from \\"[.-_/a-zA-Z0-9]\\+\\.json\\"',
|
||||
|
@ -85,7 +94,7 @@ describe("Code quality", () => {
|
|||
)
|
||||
)
|
||||
|
||||
it(
|
||||
itAsync(
|
||||
"should not contain '[\"default\"]'",
|
||||
detectInCode('\\[\\"default\\"\\]', "Possible leftover of faulty default import")
|
||||
)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { TagsFilter } from "../../../Logic/Tags/TagsFilter"
|
||||
import { And } from "../../../Logic/Tags/And"
|
||||
import { Tag } from "../../../Logic/Tags/Tag"
|
||||
import { TagUtils } from "../../../Logic/Tags/TagUtils"
|
||||
import { Or } from "../../../Logic/Tags/Or"
|
||||
import { RegexTag } from "../../../Logic/Tags/RegexTag"
|
||||
import { describe, expect, it } from "vitest"
|
||||
import {TagsFilter} from "../../../Logic/Tags/TagsFilter"
|
||||
import {And} from "../../../Logic/Tags/And"
|
||||
import {Tag} from "../../../Logic/Tags/Tag"
|
||||
import {TagUtils} from "../../../Logic/Tags/TagUtils"
|
||||
import {Or} from "../../../Logic/Tags/Or"
|
||||
import {RegexTag} from "../../../Logic/Tags/RegexTag"
|
||||
import {describe, expect, it} from "vitest"
|
||||
|
||||
describe("Tag optimalization", () => {
|
||||
describe("And", () => {
|
||||
|
@ -71,6 +71,14 @@ describe("Tag optimalization", () => {
|
|||
expect(TagUtils.toString(opt)).toBe("amenity=binoculars&bicycle=yes")
|
||||
})
|
||||
|
||||
it("should correctly optimize key=A&key!=B into key=A", () => {
|
||||
const t = new And([new Tag("shop", "sports"), new RegexTag("shop", "mall", true)])
|
||||
const opt = t.optimize()
|
||||
expect(typeof opt !== "boolean").true
|
||||
expect(TagUtils.toString(<TagsFilter>opt)).toBe("shop=sports")
|
||||
|
||||
})
|
||||
|
||||
it("should optimize nested ORs", () => {
|
||||
const filter = TagUtils.Tag({
|
||||
or: [
|
||||
|
@ -263,7 +271,7 @@ describe("Tag optimalization", () => {
|
|||
or: [
|
||||
"club=climbing",
|
||||
{
|
||||
and: ["sport=climbing", { or: ["club~*", "office~*"] }],
|
||||
and: ["sport=climbing", {or: ["club~*", "office~*"]}],
|
||||
},
|
||||
{
|
||||
and: [
|
||||
|
|
|
@ -6,6 +6,6 @@ export default defineConfig({
|
|||
test: {
|
||||
globals: true,
|
||||
setupFiles: ["./test/testhooks.ts"],
|
||||
include: ["./test", "./*.doctest.ts", "./**/*.doctest.ts"],
|
||||
include: ["./test/*.spec.ts","./test/**/*.spec.ts", "./*.doctest.ts", "./**/*.doctest.ts"],
|
||||
},
|
||||
})
|
||||
|
|
Loading…
Reference in a new issue