{# Display FDF metadata dynamically based on schema display_mapping 100% resilient to schema changes - no code modification needed CSS styling: /public/base/css/fair3r.css (section 14. FDF Metadata Display) #} {% set parse_fdf = h|attr('parse_fdf_json') %} {% if fdf_data is not defined %} {% set fdf_data = parse_fdf(fdf_json) if fdf_json and parse_fdf else {} %} {% endif %} {% set render_only_section = single_section if single_section is defined and single_section else none %} {% set hide_section_heading = hide_heading if hide_heading is defined else false %} {# One subject-scheme row: the primary value(s) for `label`, each followed inline by a small badge/link per cross-reference identifier attached to it (item.crossRefOf == scheme) — e.g. Gene: Apoe [MGI] [NCBI Gene]. #} {# Gene/allele nomenclature writes the allele designation as an HTML superscript (e.g. "ApoeTg(rtTA)1Gaga"). These fields also accept manual free-text entry, so raw HTML from a subject is never trusted or marked safe here: fdf_split_symbol_sup only recognizes this one specific shape and returns its two halves as plain text, which this macro renders through Jinja's normal auto-escaping, wrapped in a tag that is literal template markup, not data. Anything that doesn't match the pattern (including any other markup) comes back as plain text and is shown as-is, autoescaped like any other subject text. #} {% macro render_symbol(text) %} {% set symbol = h.fdf_split_symbol_sup(text) %} {{ symbol.base }}{% if symbol.sup %}{{ symbol.sup }}{% endif %} {% endmacro %} {% macro render_subject_row(label, grouped_items, xref_items) %} {{ label }} {% for item in grouped_items %} {% set uri = item.valueURI if item.valueURI else '' %} {% set is_external_uri = uri.startswith('http://') or uri.startswith('https://') %} {% set display_subject = (item.subject or '') |replace('Gene: ', '') |replace('Allele: ', '') |replace('Gene locus: ', '') |replace('Mutation type: ', '') |replace('Transgene origin: ', '') |replace('Strain: ', '') |replace('Line type: ', '') |replace('Treatment protocol: ', '') |replace('Treatment design: ', '') %} {% if is_external_uri %} {{ render_symbol(display_subject) }} {% else %} {{ render_symbol(display_subject) }} {% endif %} {% if xref_items %} {% for xref in xref_items %} {% set xuri = xref.valueURI if xref.valueURI else '' %} {% if xuri.startswith('http://') or xuri.startswith('https://') %} {{ xref.subjectScheme }} {% endif %} {% endfor %} {% endif %} {% if not loop.last %}
{% endif %} {% endfor %} {% endmacro %} {% if fdf_data %}
{% set schema_sections = [render_only_section] if render_only_section else h.fdf_schema_sections() %} {% for section in schema_sections %} {% set section_data = h.extract_fdf_section_data(fdf_data, section) %} {% set display_type = section.display_mapping.display_type if section.display_mapping else 'text' %} {% set section_accent_color = section.display_mapping.accent_color if section.display_mapping and section.display_mapping.accent_color else '#3c8dbc' %} {% if section_data %} {% if not hide_section_heading %}

{{ section.icon }} {{ section.title }}

{% endif %} {% set section_labels = section.display_mapping.labels if section.display_mapping and section.display_mapping.labels else {} %} {# Composite section (title: publicationYear, types, titles) #} {% if display_type == 'composite' %} {% if section_data is mapping %} {# Detect repeatable composite: check if we have multiple array sources #} {% set array_sources = {} %} {% for key, value in section_data.items() %} {% if value is iterable and value is not string and value|length > 0 %} {% set _ = array_sources.update({key: value}) %} {% endif %} {% endfor %} {% set is_repeatable = array_sources|length > 1 %} {% set single_subject_repeatable = section.repeatable and section.subject_scheme and array_sources|length == 1 and array_sources.subjects is defined %} {% if is_repeatable %} {# REPEATABLE COMPOSITE: Display each iteration as separate card (Chemicals, Involved Genes, etc.) #} {% set ns = namespace(max_len=0) %} {% for values in array_sources.values() %} {% if values|length > ns.max_len %} {% set ns.max_len = values|length %} {% endif %} {% endfor %} {% set num_iterations = ns.max_len %} {% for idx in range(num_iterations) %}
{% for key, values in array_sources.items() %} {% set value_at_idx = values[idx] if idx < values|length else none %} {% if value_at_idx %} {% if value_at_idx is mapping %} {# For object items, display each field as a row #} {% for field_key, field_val in value_at_idx.items() %} {% if field_key != 'valueURI' %} {% endif %} {% endfor %} {% else %} {# For simple values (strings, numbers) #} {% endif %} {% endif %} {% endfor %}
{{ section_labels.get(field_key, field_key|replace('_', ' ')|title) }} {% if field_key == 'subject' and value_at_idx.valueURI %} {# Handle subject with URI link #} {% set uri = value_at_idx.valueURI %} {% set is_external = uri.startswith('http://') or uri.startswith('https://') %} {% if is_external %} {{ field_val }} {% else %} {{ field_val }} {% endif %} {% else %} {{ field_val }} {% endif %}
{{ section_labels.get(key, key|replace('_', ' ')|title) }} {{ value_at_idx }}
{% endfor %} {% elif single_subject_repeatable %} {# REPEATABLE COMPOSITE WITH SINGLE SUBJECT SOURCE: group subjects by primary subject scheme #} {% set grouped = namespace(items=[], current=[]) %} {% for item in array_sources.subjects %} {% if item.subjectScheme == section.subject_scheme and grouped.current %} {% set grouped.items = grouped.items + [grouped.current] %} {% set grouped.current = [item] %} {% else %} {% set grouped.current = grouped.current + [item] %} {% endif %} {% endfor %} {% if grouped.current %} {% set grouped.items = grouped.items + [grouped.current] %} {% endif %} {% for subject_group in grouped.items %} {# Cross-reference subjects (crossRefOf set) are kept out of by_scheme and indexed separately by the primary scheme they attach to, so they render as inline badges on that primary row instead of as their own row. #} {% set ns = namespace(by_scheme={}, xrefs_by_target={}) %} {% for item in subject_group %} {% if item.crossRefOf %} {% set target = item.crossRefOf %} {% set existing = ns.xrefs_by_target.get(target, []) %} {% set _ = ns.xrefs_by_target.update({target: existing + [item]}) %} {% else %} {% set scheme = item.subjectScheme or 'Value' %} {% set existing = ns.by_scheme.get(scheme, []) %} {% set _ = ns.by_scheme.update({scheme: existing + [item]}) %} {% endif %} {% endfor %}
{% if section_labels %} {% for scheme, label in section_labels.items() %} {% set grouped_items = ns.by_scheme.get(scheme, []) %} {% if grouped_items %} {{ render_subject_row(label, grouped_items, ns.xrefs_by_target.get(scheme, [])) }} {% endif %} {% endfor %} {# Any scheme not named in display_mapping.labels still gets shown, under its own raw scheme name — e.g. a subject scheme this section's filter doesn't enumerate ahead of time. #} {% for scheme, grouped_items in ns.by_scheme.items() %} {% if scheme not in section_labels %} {{ render_subject_row(scheme, grouped_items, ns.xrefs_by_target.get(scheme, [])) }} {% endif %} {% endfor %} {% else %} {% for scheme, grouped_items in ns.by_scheme.items() %} {{ render_subject_row(scheme, grouped_items, ns.xrefs_by_target.get(scheme, [])) }} {% endfor %} {% endif %}
{% endfor %} {% else %} {# NON-REPEATABLE COMPOSITE: Original logic (Resource Description, grouped by scheme) #}
{% for key, value in section_data.items() %} {% set first_item = value[0] if value is iterable and value is not string and value|length > 0 else none %} {% if key == 'subjects' and first_item is mapping and first_item.subject is defined %} {% set ns = namespace(grouped={}, xrefs_by_target={}) %} {% for item in value %} {% if item.crossRefOf %} {% set target = item.crossRefOf %} {% set existing = ns.xrefs_by_target.get(target, []) %} {% set _ = ns.xrefs_by_target.update({target: existing + [item]}) %} {% else %} {% set scheme = (item.subjectScheme or 'Value') %} {% set existing = ns.grouped.get(scheme, []) %} {% set _ = ns.grouped.update({scheme: existing + [item]}) %} {% endif %} {% endfor %} {% if section_labels %} {% for scheme, label in section_labels.items() %} {% set grouped_items = ns.grouped.get(scheme, []) %} {% if grouped_items %} {{ render_subject_row(label, grouped_items, ns.xrefs_by_target.get(scheme, [])) }} {% endif %} {% endfor %} {# Any scheme not named in display_mapping.labels still gets shown, under its own raw scheme name — e.g. a subject scheme this section's filter doesn't enumerate ahead of time. #} {% for scheme, grouped_items in ns.grouped.items() %} {% if scheme not in section_labels %} {{ render_subject_row(scheme, grouped_items, ns.xrefs_by_target.get(scheme, [])) }} {% endif %} {% endfor %} {% else %} {% for scheme, grouped_items in ns.grouped.items() %} {{ render_subject_row(scheme, grouped_items, ns.xrefs_by_target.get(scheme, [])) }} {% endfor %} {% endif %} {% else %} {% endif %} {% endfor %}
{{ section_labels.get(key, key|replace('_', ' ')|title) }} {% if value is mapping %} {% for k, v in value.items() %} {{ k|replace('_', ' ')|title }}: {% set nested_uri = (v|string)|trim %} {% if nested_uri.startswith('http://') or nested_uri.startswith('https://') %} {{ nested_uri }} {% else %} {{ v }} {% endif %} {% if not loop.last %}
{% endif %} {% endfor %} {% elif value is iterable and value is not string %} {% for item in value %} {% if item is mapping %} {% for k, v in item.items() %} {% set list_uri = (v|string)|trim %} {% if list_uri.startswith('http://') or list_uri.startswith('https://') %} {{ list_uri }} {% else %} {{ v }} {% endif %}{% if not loop.last %} • {% endif %} {% endfor %} {% else %} {% set list_item_uri = (item|string)|trim %} {% if list_item_uri.startswith('http://') or list_item_uri.startswith('https://') %} {{ list_item_uri }} {% else %} {{ item }} {% endif %} {% endif %} {% if not loop.last %}
{% endif %} {% endfor %} {% else %} {% set raw_uri = (value|string)|trim %} {% if raw_uri.startswith('http://') or raw_uri.startswith('https://') %} {{ raw_uri }} {% else %} {{ value }} {% endif %} {% endif %}
{% endif %} {% endif %} {# Authors & Contributors merged #} {% elif display_type == 'authors_merged' %} {% if section_data is mapping %} {% set merged_data = section_data %} {% elif section_data is iterable and section_data is not string %} {% set merged_data = {'creators': [], 'contributors': section_data} %} {% else %} {% set merged_data = {'creators': [], 'contributors': []} %} {% endif %} {% set allow_new_names_from_contributors = (merged_data.creators|length == 0) %} {% set show_contributor_types = allow_new_names_from_contributors %} {% set ns = namespace(authors={}) %} {# Merge creators and contributors #} {% for creator in merged_data.creators or [] %} {% set creator_name = (creator.organization_name or '')|trim %} {% if not creator_name %} {% set creator_name = ((creator.givenName or '') ~ ' ' ~ (creator.familyName or ''))|trim %} {% endif %} {% if not creator_name %} {% set creator_name = (creator.name or '')|trim %} {% endif %} {% if creator_name and creator_name not in ns.authors %} {% set _ = ns.authors.update({creator_name: { 'name': creator_name, 'email': creator.email, 'affiliation': creator.affiliation or [], 'nameIdentifiers': creator.nameIdentifiers or [], 'contributor_types': [], 'roles': creator.contributorRoles or [] }}) %} {% elif creator_name and creator_name in ns.authors %} {% set existing_creator = ns.authors[creator_name] %} {% set merged_name_ids = (existing_creator.nameIdentifiers or []) + (creator.nameIdentifiers or []) %} {% set merged_affiliations = (existing_creator.affiliation or []) + (creator.affiliation or []) %} {% set merged_roles = (existing_creator.roles or []) + (creator.contributorRoles or []) %} {% set _ = existing_creator.update({ 'email': existing_creator.email or creator.email, 'affiliation': merged_affiliations, 'nameIdentifiers': merged_name_ids, 'roles': merged_roles }) %} {% endif %} {% endfor %} {% for contrib in merged_data.contributors or [] %} {% set contrib_name = (contrib.name or '')|trim %} {% if not contrib_name %} {% set contrib_name = ((contrib.givenName or '') ~ ' ' ~ (contrib.familyName or ''))|trim %} {% endif %} {% if not contrib_name %} {% set contrib_name = (contrib.organization_name or '')|trim %} {% endif %} {% if contrib_name %} {% set contrib_type = (contrib.contributorType or '')|trim %} {% if contrib_name not in ns.authors %} {% if allow_new_names_from_contributors %} {% set _ = ns.authors.update({contrib_name: { 'name': contrib_name, 'email': '', 'affiliation': contrib.affiliation or [], 'nameIdentifiers': contrib.nameIdentifiers or [], 'contributor_types': [contrib_type] if contrib_type else [], 'roles': contrib.contributorRoles or [] }}) %} {% endif %} {% else %} {% set existing = ns.authors[contrib_name] %} {% set merged_types = (existing.contributor_types or []) + ([contrib_type] if contrib_type else []) %} {% set merged_affiliations = (existing.affiliation or []) + (contrib.affiliation or []) %} {% set merged_name_ids = (existing.nameIdentifiers or []) + (contrib.nameIdentifiers or []) %} {% set _ = existing.update({ 'roles': (existing.roles or []) + (contrib.contributorRoles or []), 'contributor_types': merged_types, 'affiliation': merged_affiliations, 'nameIdentifiers': merged_name_ids }) %} {% endif %} {% endif %} {% endfor %}
{% for author_name in ns.authors.keys() | sort %} {% set author = ns.authors[author_name] %}
{{ author.name }}
{% if author.email or author.affiliation or author.nameIdentifiers or (show_contributor_types and author.contributor_types) %} {% if show_contributor_types and author.contributor_types %} {% set seen_types = namespace(values=[]) %} {% for t in author.contributor_types %} {% if t and t not in seen_types.values %} {% set seen_types.values = seen_types.values + [t] %} {% endif %} {% endfor %} {% if seen_types.values %} {% endif %} {% endif %} {% if author.email %} {% endif %} {% if author.affiliation %} {% endif %} {% if author.nameIdentifiers %} {% endif %}
{{ _('Contributor Type') }} {{ seen_types.values|join(', ') }}
{{ _('Email') }} {{ author.email }}
{{ _('Affiliation') }} {% set aff_seen = namespace(values=[], rendered=0) %} {% for aff in author.affiliation %} {% set aff_uri = (aff.affiliationIdentifier or '')|string|trim %} {% if ' — ' in aff_uri %} {% set aff_uri = aff_uri.split(' — ')[0]|trim %} {% endif %} {% if aff_uri and not (aff_uri.startswith('http://') or aff_uri.startswith('https://')) %} {% if aff.affiliationIdentifierScheme == 'ROR' %} {% set aff_candidate = aff_uri |replace('https://ror.org/', '') |replace('http://ror.org/', '') |replace('ror.org/', '') |replace('ROR:', '') |replace('ror:', '') |trim %} {% if aff_candidate and ' ' not in aff_candidate and '/' not in aff_candidate and ':' not in aff_candidate and aff_candidate|length >= 6 and aff_candidate|length <= 12 %} {% set aff_uri = 'https://ror.org/' ~ aff_candidate %} {% endif %} {% endif %} {% endif %} {% set aff_label = (aff.affiliation or '')|string|trim %} {% set aff_key = ((aff_label|lower) ~ '|' ~ (aff_uri|lower)) %} {% if aff_label and aff_key not in aff_seen.values %} {% set aff_seen.values = aff_seen.values + [aff_key] %} {% if aff_seen.rendered > 0 %}
{% endif %} {% if aff_uri.startswith('http://') or aff_uri.startswith('https://') %} {{ aff_label }} {% else %} {{ aff_label }} {% endif %} {% set aff_seen.rendered = aff_seen.rendered + 1 %} {% endif %} {% endfor %} {% if aff_seen.rendered == 0 %}-{% endif %}
{{ _('Identifiers') }} {% set id_seen = namespace(values=[], rendered=0) %} {% for id in author.nameIdentifiers %} {% set identifier_uri = (id.nameIdentifier or '')|string|trim %} {% if ' — ' in identifier_uri %} {% set identifier_uri = identifier_uri.split(' — ')[0]|trim %} {% endif %} {% if identifier_uri and not (identifier_uri.startswith('http://') or identifier_uri.startswith('https://')) %} {% if id.nameIdentifierScheme == 'ORCID' %} {% set identifier_uri = 'https://orcid.org/' ~ identifier_uri %} {% elif id.nameIdentifierScheme == 'ROR' %} {% set identifier_uri = 'https://ror.org/' ~ identifier_uri %} {% endif %} {% endif %} {% set id_scheme = (id.nameIdentifierScheme or 'ID')|string|trim %} {% set id_key = ((id_scheme|lower) ~ '|' ~ (identifier_uri|lower)) %} {% if id_key not in id_seen.values %} {% set id_seen.values = id_seen.values + [id_key] %} {% if id_seen.rendered > 0 %}
{% endif %} {% if identifier_uri.startswith('http://') or identifier_uri.startswith('https://') %} {{ id_scheme }} {% else %} {{ id_scheme }} {% endif %} {% set id_seen.rendered = id_seen.rendered + 1 %} {% endif %} {% endfor %} {% if id_seen.rendered == 0 %}-{% endif %}
{% endif %} {% if author.roles %} {{ _('Roles (CRediT)') }} {% endif %}
{% endfor %}
{# Descriptions (abstract, methods, etc.) #} {% elif display_type == 'descriptions' %} {% for desc in section_data %}
{{ desc.descriptionType }}:

{{ desc.description }}

{% endfor %} {# Related resources / references #} {% elif display_type == 'related_identifiers' %}
{% for item in section_data %} {% set rid = (item.relatedIdentifier or '')|string|trim %} {% set rid_type = item.relatedIdentifierType or '' %} {% set relation = item.relationType or '' %} {% set is_external_uri = rid.startswith('http://') or rid.startswith('https://') %} {% endfor %}
{{ section_labels.get('relatedIdentifier', _('Identifier')) }} {{ section_labels.get('relatedIdentifierType', _('Type')) }} {{ section_labels.get('relationType', _('Relation')) }}
{% if is_external_uri %} {{ rid }} {% else %} {{ rid }} {% endif %} {{ rid_type }} {{ relation }}
{# List with links (genes, chemicals, organisms, anatomy) #} {% elif display_type == 'list_links' %} {# List with links showing scheme (diseases with DOID/EFO) #} {% elif display_type == 'list_links_with_scheme' %} {# Badges (experimental interventions) #} {% elif display_type == 'badges' %}

{% for item in section_data %} {{ item }} {% endfor %}

{# Plain text #} {% elif display_type == 'text' %}

{{ section_data }}

{# Resilient fallback for unknown display_type values #} {% else %} {% if section_data is mapping %} {% for key, value in section_data.items() %} {% endfor %}
{{ key }} {{ value }}
{% elif section_data is iterable and section_data is not string %} {% else %}

{{ section_data }}

{% endif %} {% endif %} {% endif %} {% endfor %}
{% elif fdf_json %}
{{ _('FAIR Metadata (raw JSON)') }}
{{ fdf_json }}
{% endif %}