function tagsForConnectionNodeIfAllowed(entity1, entity2, graph, lessLikelyTags) {
        var featureType1 = getFeatureType(entity1, graph);
        var featureType2 = getFeatureType(entity2, graph);

        var geometry1 = entity1.geometry(graph);
        var geometry2 = entity2.geometry(graph);
        var bothLines = geometry1 === 'line' && geometry2 === 'line';

        /**
         * @typedef {NonNullable<ReturnType<getFeatureType>>} FeatureType
         * @type {`${FeatureType}-${FeatureType}`}
         */
        const featureTypes = [featureType1, featureType2].sort().join('-');

        if (featureTypes === 'aeroway-aeroway') return {};

        if (featureTypes === 'aeroway-highway') {
            const isServiceRoad = entity1.tags.highway === 'service' || entity2.tags.highway === 'service';
            const isPath = entity1.tags.highway in osmPathHighwayTagValues || entity2.tags.highway in osmPathHighwayTagValues;
            // only significant roads get the aeroway=aircraft_crossing tag
            return isServiceRoad || isPath ? {} : { aeroway: 'aircraft_crossing' };
        }

        if (featureTypes === 'aeroway-railway') {
            return { aeroway: 'aircraft_crossing', railway: 'level_crossing' };
        }

        if (featureTypes === 'aeroway-waterway') return null;

        if (featureType1 === featureType2) {
            if (featureType1 === 'highway') {
                var entity1IsPath = osmPathHighwayTagValues[entity1.tags.highway];
                var entity2IsPath = osmPathHighwayTagValues[entity2.tags.highway];
                if ((entity1IsPath || entity2IsPath) && entity1IsPath !== entity2IsPath) {
                    // one feature is a path but not both

                    if (!bothLines) return {};

                    var roadFeature = entity1IsPath ? entity2 : entity1;
                    var pathFeature = entity1IsPath ? entity1 : entity2;
                    // don't mark path connections with tracks as crossings
                    if (roadFeature.tags.highway === 'track') {
                        return {};
                    }
                    // a sidewalk crossing a driveway is unremarkable and unlikely to be interrupted by the driveway
                    // a sidewalk crossing another kind of service road may be similarly unremarkable
                    if (!lessLikelyTags &&
                        roadFeature.tags.highway === 'service' &&
                        pathFeature.tags.highway === 'footway' && pathFeature.tags.footway === 'sidewalk') {
                        return {};
                    }
                    if (['marked', 'unmarked', 'traffic_signals', 'uncontrolled'].indexOf(pathFeature.tags.crossing) !== -1) {
                        // if the path is a crossing, match the crossing type and markings
                        var tags = { highway: 'crossing', crossing: pathFeature.tags.crossing };
                        if ('crossing:markings' in pathFeature.tags) {
                            tags['crossing:markings'] = pathFeature.tags['crossing:markings'];
                        }
                        return tags;
                    }
                    // don't add a `crossing` subtag to ambiguous crossings
                    return { highway: 'crossing' };
                }
                return {};
            }
            if (featureType1 === 'waterway') return {};
            if (featureType1 === 'railway') return {};

        } else {
            if (featureTypes.indexOf('highway') !== -1) {
                if (featureTypes.indexOf('railway') !== -1) {
                    if (!bothLines) return {};

                    var isTram = entity1.tags.railway === 'tram' || entity2.tags.railway === 'tram';

                    if (osmPathHighwayTagValues[entity1.tags.highway] ||
                        osmPathHighwayTagValues[entity2.tags.highway]) {

                        // path-tram connections use this tag
                        if (isTram) return { railway: 'tram_crossing' };

                        // other path-rail connections use this tag
                        return { railway: 'crossing' };
                    } else {
                        // path-tram connections use this tag
                        if (isTram) return { railway: 'tram_level_crossing' };

                        // other road-rail connections use this tag
                        return { railway: 'level_crossing' };
                    }
                }

                if (featureTypes.indexOf('waterway') !== -1) {
                    // do not allow fords on structures
                    if (hasTag(entity1.tags, 'tunnel') && hasTag(entity2.tags, 'tunnel')) return null;
                    if (hasTag(entity1.tags, 'bridge') && hasTag(entity2.tags, 'bridge')) return null;

                    if (highwaysDisallowingFords[entity1.tags.highway] ||
                        highwaysDisallowingFords[entity2.tags.highway]) {
                        // do not allow fords on major highways
                        return null;
                    }
                    return bothLines ? { ford: 'yes' } : {};
                }
            }
        }
        return null;
    }
@returns {object | null} the tags for the connecting node, or null if the entities should not be joined