query:
  (
  way[highway=cycleway];
  way[cyclestreet=yes];
  way[bicycle_road=yes];
  way["cycleway:left"]["cycleway:left"!~"(no|separate)"];
  way["cycleway:right"]["cycleway:right"!~"(no|separate)"];
  way["cycleway:both"]["cycleway:both"!~"(no|separate)"];
  )
feature:
  pre: |
    {% set type = tags.highway %}

    {% if tags.cyclestreet == 'yes' %}
      {% set type = 'cyclestreet' %}
    {% elseif tags.bicycle_road in ['yes', 'designated'] %}
      {% set type = 'bicycle_road' %}
    {% endif %}

    {% set oneway = attribute(tags, 'oneway:bicycle')|default(tags.oneway) %}
    {% if oneway == 'yes' %}
      {% set oneway = 1 %}
    {% elseif oneway == 'no' %}
      {% set oneway = 0 %}
    {% endif %}

    {% set leftCycle = attribute(tags, 'cycleway:left')|default(attribute(tags, 'cycleway:both')) %}
    {% if leftCycle in ['no', 'separate'] %}
      {% set leftCycle = '' %}
    {% endif %}

    {% set leftOneway = attribute(tags, 'cycleway:left:oneway')|default(attribute(tags, 'cycleway:both:oneway')) %}
    {% if not leftOneway or leftOneway in ['yes'] %}
      {% set leftOneway = map.driving_side == 'left' ? 1 : -1 %}
    {% elseif leftOneway in ['no'] %}
      {% set leftOneway = 0 %}
    {% endif %}

    {% set rightCycle = attribute(tags, 'cycleway:right')|default(attribute(tags, 'cycleway:both')) %}
    {% if rightCycle in ['no', 'separate'] %}
      {% set rightCycle = '' %}
    {% endif %}

    {% set rightOneway = attribute(tags, 'cycleway:right:oneway')|default(attribute(tags, 'cycleway:both:oneway')) %}
    {% if not rightOneway or rightOneway in ['yes'] %}
      {% set rightOneway = map.driving_side == 'left' ? -1 : 1 %}
    {% elseif rightOneway in ['no'] %}
      {% set rightOneway = 0 %}
    {% endif %}

  styles: |
    {% if tags.segregated %}
    footway,
    {% endif %}
    default
    {% if leftCycle %}
    ,left
    {% endif %}
    {% if rightCycle %}
    ,right
    {% endif %}
  style:
    width: |
      {% if tags.segregated == 'yes' %}
      {{ const.types[type].width / 2 }}
      {% else %}
      {{ const.types[type].width }}
      {% endif %}

    dashArray: |
      {% if oneway and tags.segregated == 'no' %}
      5,5,5,20
      {% elseif oneway %}
      25,10
      {% elseif tags.segregated == 'no' %}
      5,5
      {% endif %}

    dashOffset: |
      {% if oneway and tags.segregated == 'no' %}
      5
      {% elseif oneway %}
      10
      {% elseif tags.segregated == 'no' %}
      0
      {% endif %}

    lineCap: |
      {% if tags.segregated == 'no' or oneway %}
      butt
      {% else %}
      round
      {% endif %}

    color: |
      {{ const.types[type].color }}

    offset: |
      {% if tags.segregated == 'yes' %}
      {{ const.types[type].width / 2 - 1 }}
      {% endif %}

    pattern: |
      {% if oneway -%}
      arrowHead
      {%- endif %}

    pattern-repeat: |
      35

    pattern-offset: |
      {{ oneway == -1 ? 17 : 22 }}

    noClip: |
      {{ oneway != 0 }}

    pattern-polygon: true

    pattern-pixelSize: 9

    pattern-angleCorrection: |
      {{ oneway == -1 ? 180 : 0 }}

    pattern-path-color: |
      {{ const.types[type].color }}

    pattern-path-width: 0

    pattern-path-fillOpacity: 1

  style:footway:
    color: |
      {{ const.types.footway.color }}

    width: |
      {% if tags.segregated == 'yes' %}
      {{ const.types.footway.width / 2 }}
      {% else %}
      {{ const.types.footway.width }}
      {% endif %}

    dashArray: |
      {% if oneway and tags.segregated == 'no' %}
      5,5,5,5,5,10
      {% elseif oneway %}
      25,10
      {% elseif tags.segregated == 'no' %}
      5,5
      {% endif %}

    dashOffset: |
      {% if oneway %}
      10
      {% elseif tags.segregated == 'no' %}
      5
      {% endif %}

    noClip: |
      {{ oneway != 0 }}

    lineCap: |
      {% if tags.segregated == 'no' or oneway %}
      butt
      {% else %}
      round
      {% endif %}

    offset: |
      {% if tags.segregated == 'yes' %}
      {{ (const.types.footway.width / 2 - 1) * -1 }}
      {% endif %}

  style:left:
    offset: -5

    color: |
      {{ const.types[leftCycle].color|default('#ff0000') }}

    width: 3

    lineCap: |
      {{ leftOneway ? 'butt' : 'round' }}
    dashArray: |
      {{ leftOneway ? '27,8' : '' }}
    dashOffset: |
      {{ leftOneway == -1 ? 28 : 0 }}
    noClip: true
#      {{ leftOneway }}
    pattern: |
      {% if leftOneway %}arrowHead{% endif %}
    pattern-offset: |
      {{ leftOneway == -1 ? 4 : 30.5 }}
    pattern-lineOffset: -5
    pattern-repeat: 35
    pattern-polygon: true
    pattern-pixelSize: 9
    pattern-angleCorrection: |
      {{ leftOneway == -1 ? 180 : 0 }}
    pattern-path-width: 0

    pattern-path-color: |
      {{ const.types[leftCycle].color|default('#ff0000') }}

    pattern-path-fillOpacity: 1

  style:right:
    offset: 5

    color: |
      {{ const.types[rightCycle].color|default('#ff0000') }}

    width: 3

    lineCap: |
      {{ rightOneway ? 'butt' : 'round' }}
    dashArray: |
      {{ rightOneway ? '27,8' : '' }}
    dashOffset: |
      {{ rightOneway == -1 ? 28 : 0 }}
    noClip: true
#      {{ rightOneway }}
    pattern: |
      {% if rightOneway %}arrowHead{% endif %}
    pattern-offset: |
      {{ rightOneway == -1 ? 4 : 30.5 }}
    pattern-lineOffset: 5
    pattern-repeat: 35
    pattern-polygon: true
    pattern-pixelSize: 9
    pattern-angleCorrection: |
      {{ rightOneway == -1 ? 180 : 0 }}
    pattern-path-width: 0

    pattern-path-color: |
      {{ const.types[rightCycle].color|default('#ff0000') }}

    pattern-path-fillOpacity: 1

  description: |
    {% if tags.cyclestreet == 'yes' %}
    {{ keyTrans('cyclestreet') }}
    {% elseif tags.bicycle_road in ['yes', 'designated'] %}
    {{ keyTrans('bicycle_road') }}
    {% elseif tags.segregated %}
    {{ tagTrans('highway', 'cycleway segregated=' ~ tags.segregated) }}
    {% elseif tags.highway %}
    {{ tagTrans('highway', tags.highway) }}
    {% endif %}

  body: |
    <ul>
    {% if tags.highway in ['cycleway'] or attribute(tags, 'cycleway:width') %}
    <li>
      {{ keyTrans('cycleway:width') }}:
      {% if not attribute(tags, 'cycleway:width') %}
        {{ trans('unknown') }}
      {% elseif attribute(tags, 'cycleway:width') matches "/(m|')$/" %}
        {{ attribute(tags, 'cycleway:width') }}
      {% else %}
        {{ attribute(tags, 'cycleway:width') }}m
      {% endif %}
    </li>
    {% endif %}

    {% if leftCycle %}
    <li>{{ keyTrans('cycleway:left') }}:

    {% if const.types[leftCycle].warning %}
      <div class='warning'>{{ const.types[leftCycle].warning }}</div>
    {% elseif not const.types[leftCycle] %}
      <div class='warning'>Invalid tag cycleway:left={{ attribute(tags, 'cycleway:left') }}.</div>
    {% endif %}

    <ul>
      <li>{{ keyTrans('cycleway') }}: {{ tagTrans('cycleway', attribute(tags, 'cycleway:left')|default(attribute(tags, 'cycleway:both'))) }}</li>
      <li>
        {{ keyTrans('cycleway:width') }}:
        {% if not leftWidth %}
          {{ trans('unknown') }}
        {% elseif attribute(tags, 'cycleway:left:width')|default(attribute(tags, 'cycleway:both:width')) matches "/(m|')$/" %}
          {{ attribute(tags, 'cycleway:left:width')|default(attribute(tags, 'cycleway:both:width')) }}
        {% else %}
          {{ leftWidth }}m
        {% endif %}
      </li>
    </ul></li>
    {% endif %}

    {% if rightCycle %}
    <li>{{ keyTrans('cycleway:right') }}:

    {% if const.types[rightCycle].warning %}
    <div class='warning'>{{ const.types[rightCycle].warning }}</div>
    {% elseif not const.types[rightCycle] %}
      <div class='warning'>Invalid tag cycleway:right={{ attribute(tags, 'cycleway:right') }}.</div>
    <div class='warning'>Unknown</div>
    {% endif %}

    <ul>
      <li>{{ keyTrans('cycleway') }}: {{ tagTrans('cycleway', attribute(tags, 'cycleway:right')|default(attribute(tags, 'cycleway:both'))) }}</li>
      <li>
      {{ keyTrans('cycleway:width') }}:
      {% if not rightWidth %}
        {{ trans('unknown') }}
      {% elseif attribute(tags, 'cycleway:right:width')|default(attribute(tags, 'cycleway:both:width')) matches "/(m|')$/" %}
        {{ attribute(tags, 'cycleway:right:width')|default(attribute(tags, 'cycleway:both:width')) }}
      {% else %}
        {{ rightWidth }}m
      {% endif %}
      </li>
    </ul></li>
    {% endif %}
    </ul>

  markerSymbol: ''

info: |
  <table>
    <tr>
      <th>Symbol</th>
      <th></th>
    </tr>
    {% for k, v in const.types %}
    <tr>
      <td>
        {{ markerLine({ width: 4, color: v.color }) }}
      </td>
      <td>
        {{ k }}
      </td>
    </tr>
    {% endfor %}
  </table>
const:
  types:
    cycleway:
      color: '#009f00'
      width: 4
    footway:
      color: '#ff9f00'
      width: 4
    cyclestreet:
      color: '#006f3f'
      width: 8
    bicycle_road:
      color: '#006f4f'
      width: 8
    lane:
      color: '#00df3f'
    track:
      color: '#009f00'
    shared:
      color: '#ff0000'
      warning: 'Deprecated tag! Use oneway:bicycle=no and cycleway=lane, cycleway:oneway=-1 instead.'
    shared_lane:
      color: '#003faf'
    share_busway:
      color: '#ff7f00'
    opposite:
      color: '#ff0000'
      warning: 'Deprecated tag! Use oneway:bicycle=no and cycleway=lane, cycleway:oneway=-1 instead.'
    opposite_lane:
      color: '#ff0000'
      warning: 'Deprecated tag! Use oneway:bicycle=no and cycleway=lane, cycleway:oneway=-1 instead.'
    opposite_share_busway:
      color: '#ff0000'
      warning: 'Deprecated tag! Use oneway:bicycle=no and cycleway=share_busway, cycleway:oneway=-1 instead.'
    opposite_track:
      color: '#ff0000'
      warning: 'Deprecated tag! Use oneway:bicycle=no and cycleway=track, cycleway:oneway=-1 instead.'