mirror of https://github.com/zulip/zulip.git
templates: Mark all void tags as self-closing.
This reverses the policy that was set, but incompletely enforced, by
commit 951514dd7d
. The self-closing tag
syntax is clearer, more consistent, simpler to parse, compatible with
XML, preferred by Prettier, and (most importantly now) required by
FormatJS.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
7177529107
commit
dd3fa4ac52
|
@ -584,8 +584,8 @@ class TestSupportEndpoint(ZulipTestCase):
|
|||
'<span class="label">user</span>\n',
|
||||
f"<h3>{full_name}</h3>",
|
||||
f"<b>Email</b>: {email}",
|
||||
"<b>Is active</b>: True<br>",
|
||||
f"<b>Role</b>: {role}<br>",
|
||||
"<b>Is active</b>: True<br />",
|
||||
f"<b>Role</b>: {role}<br />",
|
||||
],
|
||||
html_response,
|
||||
)
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="UTF-8" />
|
||||
<title>Zulip - 500 internal server error</title>
|
||||
<base href="/static/webpack-bundles/">
|
||||
<base href="/static/webpack-bundles/" />
|
||||
|
||||
<meta http-equiv="refresh" content="60;URL='/'">
|
||||
<meta http-equiv="refresh" content="60;URL='/'" />
|
||||
|
||||
</head>
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
<div class="input-group">
|
||||
<label for="profile_field_choices_edit">{{t "Field choices" }}</label>
|
||||
<div class="profile-field-choices" name="profile_field_choices_edit">
|
||||
<hr>
|
||||
<hr />
|
||||
<div class="edit_profile_field_choices_container">
|
||||
{{#each choices}}
|
||||
{{> settings/profile_field_choice }}
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
{{/if}}
|
||||
</span>
|
||||
{{#if second_line}}
|
||||
<br><span class="tooltip_inner_content">{{second_line}}</span>
|
||||
<br /><span class="tooltip_inner_content">{{second_line}}</span>
|
||||
{{/if}}
|
||||
{{#if third_line}}
|
||||
<br><span class="tooltip_inner_content">{{third_line}}</span>
|
||||
<br /><span class="tooltip_inner_content">{{third_line}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<a role="button" class="compose_control_button fa fa-smile-o" aria-label="{{t 'Add emoji' }}" id="emoji_map" tabindex=0 title="{{t 'Add emoji' }}"></a>
|
||||
{{#if giphy_api_available }}
|
||||
<a role="button" class="compose_control_button" aria-label="{{t 'Add GIF' }}" id="compose_box_giphy_grid" title="{{t 'Add GIF' }}">
|
||||
<img class="compose_giphy_logo" tabindex=0 src="/static/images/GIPHY_logo.png">
|
||||
<img class="compose_giphy_logo" tabindex=0 src="/static/images/GIPHY_logo.png" />
|
||||
</a>
|
||||
{{/if}}
|
||||
<a class="message-control-link drafts-link" href="#drafts" title="{{t 'Drafts' }} (d)">{{t 'Drafts' }}</a>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div class="arrow"></div>
|
||||
<div class="popover-inner">
|
||||
<div class="search-box">
|
||||
<input type="text" tabindex=0 id="giphy-search-query" class="search-query" placeholder="{{t 'Search GIFs' }}">
|
||||
<input type="text" tabindex=0 id="giphy-search-query" class="search-query" placeholder="{{t 'Search GIFs' }}" />
|
||||
<button type="button" class="btn clear_search_button" id="giphy_search_clear">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||
</button>
|
||||
|
@ -15,7 +15,7 @@
|
|||
<div class="giphy-content"></div>
|
||||
</div>
|
||||
<div class="popover-footer">
|
||||
<img src="/static/images/GIPHY_attribution.png" alt="{{t 'GIPHY attribution' }}">
|
||||
<img src="/static/images/GIPHY_attribution.png" alt="{{t 'GIPHY attribution' }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<p class="hotspot-description">{{description}}</p>
|
||||
</div>
|
||||
<div class="hotspot-popover-bottom">
|
||||
<img class="hotspot-img" alt=_("hotspot illustration") src="{{img}}">
|
||||
<img class="hotspot-img" alt=_("hotspot illustration") src="{{img}}" />
|
||||
<button class="hotspot-confirm">{{t 'Got it!' }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="hotspot-inline trailing_bookend bookend hotspot-message" id="hotspot_intro_reply_icon">
|
||||
<div class="hotspot-inline-top"><h1 class="hotspot-title">Send a reply</h1></div>
|
||||
<div class="hotspot-inline-left">
|
||||
<img class="hotspot-img" alt="" src="/static/images/hotspots/whale.svg">
|
||||
<img class="hotspot-img" alt="" src="/static/images/hotspots/whale.svg" />
|
||||
</div>
|
||||
<div class="hotspot-inline-right">
|
||||
<p>{{t 'Click anywhere on a message to reply.' }}</p>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<a href="/help/format-your-message-using-markdown" target="_blank" rel="noopener noreferrer">{{t "Detailed message formatting documentation" }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -20,13 +20,13 @@
|
|||
<input type="text" placeholder="{{topic}}" value="{{topic}}" class="message_edit_topic" id="message_edit_topic" />
|
||||
<div class="message_edit_breadcrumb_messages" style='display:none;'>
|
||||
<label class="checkbox">
|
||||
<input class="send_notification_to_new_thread" name="send_notification_to_new_thread" type="checkbox" {{#if notify_new_thread}}checked="checked"{{/if}}>
|
||||
<input class="send_notification_to_new_thread" name="send_notification_to_new_thread" type="checkbox" {{#if notify_new_thread}}checked="checked"{{/if}} />
|
||||
<span></span>
|
||||
</label>
|
||||
<label for="send_notification_to_new_thread">{{t "Send notification to new topic" }}</label>
|
||||
<div class="break-row"></div> <!-- break -->
|
||||
<label class="checkbox">
|
||||
<input class="send_notification_to_old_thread" name="send_notification_to_old_thread" type="checkbox" {{#if notify_old_thread}}checked="checked"{{/if}}>
|
||||
<input class="send_notification_to_old_thread" name="send_notification_to_old_thread" type="checkbox" {{#if notify_old_thread}}checked="checked"{{/if}} />
|
||||
<span></span>
|
||||
</label>
|
||||
<label for="send_notification_to_old_thread">{{t "Send notification to old topic" }}</label>
|
||||
|
@ -70,7 +70,7 @@
|
|||
<a role="button" tabindex=0 class="compose_control_button fa fa-smile-o" aria-label="{{t 'Add emoji' }}" id="emoji_map" data-message-id="{{message_id}}" title="{{t 'Add emoji' }}"></a>
|
||||
{{#if giphy_api_available }}
|
||||
<a role="button" class="compose_control_button" aria-label="{{t 'Add GIF' }}" id="compose_box_giphy_grid" title="{{t 'Add GIF' }}">
|
||||
<img class="compose_giphy_logo" tabindex=0 src="/static/images/GIPHY_logo.png" data-message-id="{{message_id}}">
|
||||
<img class="compose_giphy_logo" tabindex=0 src="/static/images/GIPHY_logo.png" data-message-id="{{message_id}}" />
|
||||
</a>
|
||||
{{/if}}
|
||||
<a role="button" tabindex=0 class="message-control-link" data-overlay-trigger="message-formatting" >{{t 'Help' }}</a>
|
||||
|
|
|
@ -14,5 +14,5 @@
|
|||
{{/if}}
|
||||
<div class="message_author"><div class="author_details">{{ posted_or_edited }} {{ edited_by }}</div></div>
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
{{/each}}
|
||||
|
|
|
@ -20,17 +20,17 @@
|
|||
{{/each}}
|
||||
</select>
|
||||
<i class="fa fa-angle-right" aria-hidden="true"></i>
|
||||
<input name="new_topic_name" type="text" class="inline_topic_edit" value="{{topic_name}}">
|
||||
<input name="old_topic_name" type="hidden" class="inline_topic_edit" value="{{topic_name}}">
|
||||
<input name="current_stream_id" type="hidden" value="{{current_stream_id}}">
|
||||
<input name="new_topic_name" type="text" class="inline_topic_edit" value="{{topic_name}}" />
|
||||
<input name="old_topic_name" type="hidden" class="inline_topic_edit" value="{{topic_name}}" />
|
||||
<input name="current_stream_id" type="hidden" value="{{current_stream_id}}" />
|
||||
<div class="topic_move_breadcrumb_messages new-style">
|
||||
<label class="checkbox">
|
||||
<input class="send_notification_to_new_thread" name="send_notification_to_new_thread" type="checkbox" {{#if notify_new_thread}}checked="checked"{{/if}}>
|
||||
<input class="send_notification_to_new_thread" name="send_notification_to_new_thread" type="checkbox" {{#if notify_new_thread}}checked="checked"{{/if}} />
|
||||
<span></span>
|
||||
</label>
|
||||
<label for="send_notification_to_new_thread">{{t "Send notification to new topic" }}</label>
|
||||
<label class="checkbox">
|
||||
<input class="send_notification_to_old_thread" name="send_notification_to_old_thread" type="checkbox" {{#if notify_old_thread}}checked="checked"{{/if}}>
|
||||
<input class="send_notification_to_old_thread" name="send_notification_to_old_thread" type="checkbox" {{#if notify_old_thread}}checked="checked"{{/if}} />
|
||||
<span></span>
|
||||
</label>
|
||||
<label for="send_notification_to_old_thread">{{t "Send notification to old topic" }}</label>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
{{/each}}
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
<input class="add-user-list-filter" name="user_list_filter" type="text"
|
||||
autocomplete="off" placeholder="{{t "Filter" }}" />
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{{> recent_topics_filters}}
|
||||
</div>
|
||||
<div class="search_group" role="group">
|
||||
<input type="text" id="recent_topics_search" value="{{ search_val }}" placeholder="{{t 'Filter topics (t)' }}">
|
||||
<input type="text" id="recent_topics_search" value="{{ search_val }}" placeholder="{{t 'Filter topics (t)' }}" />
|
||||
<button type="button" class="btn clear_search_button" id="recent_topics_search_clear">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||
</button>
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="settings_separator">
|
||||
<hr class="settings_separator" />
|
||||
|
||||
<div class="form-horizontal" id="api_key_button_box">
|
||||
<h3>{{t "API key" }}</h3>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<div class="settings-section-title">{{t "Add new default stream" }}</div>
|
||||
<div class="inline-block" id="default_stream_inputs">
|
||||
<label for="default_stream_name">{{t "Stream name" }}</label>
|
||||
<input class="create_default_stream" type="text" placeholder="{{t "Stream name" }}" name="stream_name" autocomplete="off" aria-label="{{t "Stream name" }}">
|
||||
<input class="create_default_stream" type="text" placeholder="{{t "Stream name" }}" name="stream_name" autocomplete="off" aria-label="{{t "Stream name" }}" />
|
||||
</div>
|
||||
<div class="inline-block">
|
||||
<button type="submit" id="do_submit_stream" class="button rounded sea-green">{{t "Add stream" }}</button>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
</p>
|
||||
</li>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
{{! tabindex="0" Makes anchor tag focusable. Needed for keyboard support. }}
|
||||
<li>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{{/if}}
|
||||
<a data-user-id="{{user_id}}" class="view_user_profile">{{full_name}}</a>{{#unless @last}},{{else}}.{{/unless}}
|
||||
{{/each}}
|
||||
<br>
|
||||
<br />
|
||||
{{#each already_subscribed_users}}
|
||||
{{#if @first}}
|
||||
{{t "Already subscribed users:" }}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</p>
|
||||
</li>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
{{#if can_mute_topic}}
|
||||
<li>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{{group_description}}
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<ul class="nav nav-list member-list" data-simplebar data-simplebar-auto-hide="false">
|
||||
{{#each members}}
|
||||
<li>
|
||||
|
@ -20,7 +20,7 @@
|
|||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
<hr>
|
||||
<hr />
|
||||
<ul class="nav nav-list manage-group">
|
||||
<li>
|
||||
<a href="#organization/user-groups-admin">
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
</div>
|
||||
|
||||
{{#if is_me}}
|
||||
<hr>
|
||||
<hr />
|
||||
{{#if can_set_away}}
|
||||
<li>
|
||||
<a tabindex="0" class="set_away_status">
|
||||
|
@ -80,7 +80,7 @@
|
|||
{{/if}}
|
||||
|
||||
{{#if status_text}}
|
||||
{{#unless is_me}}<hr>{{/unless}}
|
||||
{{#unless is_me}}<hr />{{/unless}}
|
||||
<li class="user_info_status_text">
|
||||
<span id="status_message">
|
||||
{{status_text}}
|
||||
|
@ -89,7 +89,7 @@
|
|||
</li>
|
||||
{{/if}}
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
{{#if show_user_profile}}
|
||||
<li>
|
||||
<a tabindex="0" class="view_full_user_profile">
|
||||
|
@ -134,7 +134,7 @@
|
|||
</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
<hr>
|
||||
<hr />
|
||||
<li>
|
||||
<a href="{{ pm_with_uri }}" class="narrow_to_private_messages">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
<br>
|
||||
<br />
|
||||
{{#if show_email}}
|
||||
<div id="email" class="default-field">
|
||||
<span class="name">{{#tr}}Email{{/tr}}</span>
|
||||
|
@ -40,7 +40,7 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<div id="content">
|
||||
{{#each profile_data}}
|
||||
<div data-type="{{this.type}}" class="field-section custom_user_field" data-field-id="{{this.id}}">
|
||||
|
|
|
@ -18,5 +18,5 @@
|
|||
<input type="text" class="poll-option" placeholder="{{t 'New choice'}}" />
|
||||
<button class="poll-option">{{t "Add choice" }}</button>
|
||||
</div>
|
||||
<br>
|
||||
<br />
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<br>
|
||||
<br />
|
||||
{{#each pending_tasks}}
|
||||
<li>
|
||||
<button class="task" data-key="{{ key }}">
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{% block customhead %}
|
||||
{{ super() }}
|
||||
<meta http-equiv="refresh" content="60;URL='/'">
|
||||
<meta http-equiv="refresh" content="60;URL='/'" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_class_name %}error{% endblock %}
|
||||
|
|
|
@ -12,13 +12,13 @@
|
|||
|
||||
{% if not is_home %}
|
||||
<a class="show-all" href="/activity">Home</a>
|
||||
<br>
|
||||
<br />
|
||||
{% endif %}
|
||||
|
||||
<h4>{{ title }}</h4>
|
||||
|
||||
{% if realm_link %}
|
||||
<a href="{{ realm_link }}">Graph</a><br>
|
||||
<a href="{{ realm_link }}">Graph</a><br />
|
||||
{% endif %}
|
||||
|
||||
<ul class="nav nav-tabs">
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<span class="label">realm</span>
|
||||
<h3><img src="{{ realm_icon_url(realm) }}" class="support-realm-icon"> {{ realm.name }}</h3>
|
||||
<h3><img src="{{ realm_icon_url(realm) }}" class="support-realm-icon" /> {{ realm.name }}</h3>
|
||||
<b>URL</b>: <a target="_blank" rel="noopener noreferrer" href="{{ realm.uri }}">{{ realm.uri }}</a> |
|
||||
<a target="_blank" rel="noopener noreferrer" href="/stats/realm/{{ realm.string_id }}/">stats</a> |
|
||||
<a target="_blank" rel="noopener noreferrer" href="/realm_activity/{{ realm.string_id }}/">activity</a><br>
|
||||
<b>Date created</b>: {{ realm.date_created|timesince }} ago<br>
|
||||
<a target="_blank" rel="noopener noreferrer" href="/realm_activity/{{ realm.string_id }}/">activity</a><br />
|
||||
<b>Date created</b>: {{ realm.date_created|timesince }} ago<br />
|
||||
{% set owner_emails_string = get_realm_owner_emails_as_string(realm) %}
|
||||
<b>Owners</b>: {{ owner_emails_string }}
|
||||
{% if owner_emails_string %}
|
||||
|
@ -11,7 +11,7 @@
|
|||
<i class="fa fa-copy"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<br>
|
||||
<br />
|
||||
{% set admin_emails_string = get_realm_admin_emails_as_string(realm) %}
|
||||
<b>Admins</b>: {{ admin_emails_string }}
|
||||
{% if admin_emails_string %}
|
||||
|
@ -19,7 +19,7 @@
|
|||
<i class="fa fa-copy"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
<br>
|
||||
<br />
|
||||
{% set first_human_user = realm.get_first_human_user() %}
|
||||
{% if first_human_user %}
|
||||
<b>First human user</b>: {{ first_human_user.delivery_email }}
|
||||
|
@ -31,7 +31,7 @@
|
|||
{% endif %}
|
||||
|
||||
<form method="POST" class="support-realm-status-form">
|
||||
<b>Status</b>:<br>
|
||||
<b>Status</b>:<br />
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
<select name="status">
|
||||
|
@ -41,14 +41,14 @@
|
|||
<button type="submit" class="button rounded small support-submit-button">Update</button>
|
||||
</form>
|
||||
<form method="POST">
|
||||
<b>New subdomain</b>:<br>
|
||||
<b>New subdomain</b>:<br />
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
<input type="text" name="new_subdomain" required>
|
||||
<input type="text" name="new_subdomain" required />
|
||||
<button type="submit" class="button rounded small support-submit-button">Update</button>
|
||||
</form>
|
||||
<form method="POST" class="support-plan-type-form">
|
||||
<b>Plan type</b>:<br>
|
||||
<b>Plan type</b>:<br />
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
<select name="plan_type">
|
||||
|
@ -60,7 +60,7 @@
|
|||
<button type="submit" class="button rounded small support-submit-button">Update</button>
|
||||
</form>
|
||||
<form method="POST" class="sponsorship-pending-form">
|
||||
<b>Sponsorship pending</b>:<br>
|
||||
<b>Sponsorship pending</b>:<br />
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
<select name="sponsorship_pending">
|
||||
|
@ -83,35 +83,35 @@
|
|||
{% endif %}
|
||||
|
||||
<form method="POST" class="support-discount-form">
|
||||
<b>Discount (use 85 for nonprofits)</b>:<br>
|
||||
<b>Discount (use 85 for nonprofits)</b>:<br />
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
{% if realm.current_plan and realm.current_plan.fixed_price %}
|
||||
<input type="number" name="discount" value="{{ get_discount_for_realm(realm) }}" disabled>
|
||||
<input type="number" name="discount" value="{{ get_discount_for_realm(realm) }}" disabled />
|
||||
<button type="submit" class="button rounded small support-submit-button" disabled>Update</button>
|
||||
{% else %}
|
||||
<input type="number" name="discount" value="{{ get_discount_for_realm(realm) }}" required>
|
||||
<input type="number" name="discount" value="{{ get_discount_for_realm(realm) }}" required />
|
||||
<button type="submit" class="button rounded small support-submit-button">Update</button>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% if realm.current_plan %}
|
||||
<div class="current-plan-details">
|
||||
<h3>📅 Current plan</h3>
|
||||
<b>Name</b>: {{ realm.current_plan.name }}<br>
|
||||
<b>Status</b>: {{realm.current_plan.get_plan_status_as_text()}}<br>
|
||||
<b>Billing schedule</b>: {% if realm.current_plan.billing_schedule == realm.current_plan.ANNUAL %}Annual{% else %}Monthly{% endif %}<br>
|
||||
<b>Licenses</b>: {{ realm.current_plan.licenses_used }}/{{ realm.current_plan.licenses }} ({% if realm.current_plan.automanage_licenses %}Automatic{% else %}Manual{% endif %})<br>
|
||||
<b>Name</b>: {{ realm.current_plan.name }}<br />
|
||||
<b>Status</b>: {{realm.current_plan.get_plan_status_as_text()}}<br />
|
||||
<b>Billing schedule</b>: {% if realm.current_plan.billing_schedule == realm.current_plan.ANNUAL %}Annual{% else %}Monthly{% endif %}<br />
|
||||
<b>Licenses</b>: {{ realm.current_plan.licenses_used }}/{{ realm.current_plan.licenses }} ({% if realm.current_plan.automanage_licenses %}Automatic{% else %}Manual{% endif %})<br />
|
||||
{% if realm.current_plan.price_per_license %}
|
||||
<b>Price per license</b>: ${{ realm.current_plan.price_per_license/100 }}<br>
|
||||
<b>Price per license</b>: ${{ realm.current_plan.price_per_license/100 }}<br />
|
||||
{% else %}
|
||||
<b>Fixed price</b>: ${{ realm.current_plan.fixed_price/100 }}<br>
|
||||
<b>Fixed price</b>: ${{ realm.current_plan.fixed_price/100 }}<br />
|
||||
{% endif %}
|
||||
<b>Next invoice date</b>: {{ realm.current_plan.next_invoice_date.strftime('%d %B %Y') }}<br>
|
||||
<b>Next invoice date</b>: {{ realm.current_plan.next_invoice_date.strftime('%d %B %Y') }}<br />
|
||||
</div>
|
||||
|
||||
<form method="POST" class="billing-method-form">
|
||||
<br>
|
||||
<b>Billing method</b><br>
|
||||
<br />
|
||||
<b>Billing method</b><br />
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
<select name="billing_method" class="billing-method-select" required>
|
||||
|
@ -122,8 +122,8 @@
|
|||
</form>
|
||||
|
||||
<form method="POST" class="downgrade-plan-form">
|
||||
<br>
|
||||
<b>Downgrade plan</b><br>
|
||||
<br />
|
||||
<b>Downgrade plan</b><br />
|
||||
{{ csrf_input }}
|
||||
<input type="hidden" name="realm_id" value="{{ realm.id }}" />
|
||||
<select name="downgrade_method" class="downgrade-plan-method-select" required>
|
||||
|
|
|
@ -125,7 +125,7 @@
|
|||
<span class="last_update_tooltip" data-tippy-content="{% trans %}A full update of all the graphs happens once a day. The “messages sent over time” graph is updated once an hour.{% endtrans %}">
|
||||
<span class="fa fa-info-circle" id="id_last_update_question_sign"></span>
|
||||
</span>
|
||||
<br>
|
||||
<br />
|
||||
<span class="docs_link"><a href="/help/analytics">{{ _("Analytics documentation") }}</a></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,10 +9,10 @@
|
|||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<br>
|
||||
<br />
|
||||
<form class="new-style">
|
||||
<center>
|
||||
<input type="text" name="q" class="input-xxlarge search-query" placeholder="full names, emails, string_ids, organization URLs separated by commas" value="{{ request.GET.get('q', '') }}" autofocus>
|
||||
<input type="text" name="q" class="input-xxlarge search-query" placeholder="full names, emails, string_ids, organization URLs separated by commas" value="{{ request.GET.get('q', '') }}" autofocus />
|
||||
<button type="submit" class="button small support-search-button">Search</button>
|
||||
</center>
|
||||
</form>
|
||||
|
@ -37,15 +37,15 @@
|
|||
<div class="support-query-result new-style">
|
||||
<span class="label">user</span>
|
||||
<h3>{{ user.full_name }}</h3>
|
||||
<b>Email</b>: {{ user.delivery_email }}<br>
|
||||
<b>Date joined</b>: {{ user.date_joined|timesince }} ago<br>
|
||||
<b>Is active</b>: {{ user.is_active }}<br>
|
||||
<b>Role</b>: {{ user.get_role_name() }}<br>
|
||||
<hr>
|
||||
<b>Email</b>: {{ user.delivery_email }}<br />
|
||||
<b>Date joined</b>: {{ user.date_joined|timesince }} ago<br />
|
||||
<b>Is active</b>: {{ user.is_active }}<br />
|
||||
<b>Role</b>: {{ user.get_role_name() }}<br />
|
||||
<hr />
|
||||
<div>
|
||||
{% include "analytics/realm_details.html" %}
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
|
@ -83,32 +83,32 @@
|
|||
{% set realm = object %}
|
||||
{% set show_realm_details = False %}
|
||||
{% endif %}
|
||||
<br>
|
||||
<br>
|
||||
<br />
|
||||
<br />
|
||||
{% if email %}
|
||||
<b>Email</b>: {{ email }}<br>
|
||||
<b>Email</b>: {{ email }}<br />
|
||||
{% endif %}
|
||||
<b>Link</b>: {{ confirmation.url }}
|
||||
<a title="Copy link" class="copy-button" data-copytext="{{ confirmation.url }}">
|
||||
<i class="fa fa-copy"></i>
|
||||
</a><br>
|
||||
<b>Expires in</b>: {{ confirmation.expires_in }}<br>
|
||||
</a><br />
|
||||
<b>Expires in</b>: {{ confirmation.expires_in }}<br />
|
||||
{% if confirmation.link_status %}
|
||||
<b>Status</b>: {{ confirmation.link_status }}
|
||||
{% endif %}
|
||||
<br>
|
||||
<br />
|
||||
{% if show_realm_details %}
|
||||
<hr>
|
||||
<hr />
|
||||
<div>
|
||||
{% include "analytics/realm_details.html" %}
|
||||
</div>
|
||||
{% elif realm %}
|
||||
<b>Realm</b>: {{ realm.string_id }}
|
||||
<br>
|
||||
<br />
|
||||
{% endif %}
|
||||
<br>
|
||||
<br />
|
||||
</div>
|
||||
<br>
|
||||
<br />
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% set entrypoint = "billing" %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script src="https://checkout.stripe.com/checkout.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
|||
<li><a data-toggle="tab" href="#settings">Settings</a></li>
|
||||
</ul>
|
||||
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="overview">
|
||||
{% if free_trial %}
|
||||
|
@ -133,13 +133,13 @@
|
|||
</div>
|
||||
<div id="goto-zulip-organization-link">
|
||||
{% if onboarding %}
|
||||
<br>
|
||||
<br />
|
||||
<h3>
|
||||
<b><a href="/">Go to your Zulip organization</a></b>
|
||||
</h3>
|
||||
{% endif %}
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<div class="support-link">
|
||||
<p>
|
||||
Contact <a href="mailto:support@zulip.com">support@zulip.com</a>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
@ -176,8 +176,8 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<hr>
|
||||
<br />
|
||||
<hr />
|
||||
|
||||
<h2 id="fullstack">Senior Full Stack Engineer</h2>
|
||||
<p>
|
||||
|
@ -245,8 +245,8 @@
|
|||
</li>
|
||||
</ul>
|
||||
|
||||
<br>
|
||||
<hr>
|
||||
<br />
|
||||
<hr />
|
||||
|
||||
<h2>How to apply for a job</h2>
|
||||
<p>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% set entrypoint = "upgrade" %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<script src="https://checkout.stripe.com/checkout.js"></script>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -37,18 +37,18 @@
|
|||
<li><a data-toggle="tab" href="#sponsorship">💚 Request sponsorship</a></li>
|
||||
</ul>
|
||||
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
|
||||
<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}" />
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="autopay">
|
||||
<div id="autopay-input-section">
|
||||
<form id="autopay-form" data-key="{{ publishable_key }}" data-email="{{ email }}" method="post">
|
||||
<input type="hidden" name="seat_count" value="{{ seat_count }}">
|
||||
<input type="hidden" name="signed_seat_count" value="{{ signed_seat_count }}">
|
||||
<input type="hidden" name="salt" value="{{ salt }}">
|
||||
<input type="hidden" name="billing_modality" value="charge_automatically">
|
||||
<input type="hidden" name="seat_count" value="{{ seat_count }}" />
|
||||
<input type="hidden" name="signed_seat_count" value="{{ signed_seat_count }}" />
|
||||
<input type="hidden" name="salt" value="{{ salt }}" />
|
||||
<input type="hidden" name="billing_modality" value="charge_automatically" />
|
||||
{% if onboarding and free_trial_days %}
|
||||
<p><b>Not ready to start your trial?</b> <a href="/">Continue with the Zulip Cloud Free plan</a>.</p>
|
||||
<hr>
|
||||
<hr />
|
||||
<h2>Zulip Standard free trial</h2>
|
||||
{% endif %}
|
||||
<div class="payment-schedule">
|
||||
|
@ -104,7 +104,7 @@
|
|||
{% if free_trial_days %}
|
||||
After the Free Trial, you’ll be charged
|
||||
<b>$<span id="charged_amount"></span></b> for <b>{{ seat_count }}</b>
|
||||
users (or more if you later add more users).<br>
|
||||
users (or more if you later add more users).<br />
|
||||
|
||||
We'll automatically charge you for additional licenses as users
|
||||
are added, and remove licenses not in use at the end of each billing
|
||||
|
@ -112,31 +112,31 @@
|
|||
{% else %}
|
||||
You’ll initially be charged
|
||||
<b>$<span id="charged_amount"></span></b> for <b>{{ seat_count }}</b>
|
||||
users.<br>
|
||||
users.<br />
|
||||
We'll automatically charge you for additional licenses as users
|
||||
are added, and remove licenses not in use at the end of each billing
|
||||
period.
|
||||
{% endif %}
|
||||
</p>
|
||||
<input type="hidden" name="licenses" id="automatic_license_count" value="{{ seat_count }}">
|
||||
<input type="hidden" name="licenses" id="automatic_license_count" value="{{ seat_count }}" />
|
||||
</div>
|
||||
|
||||
<div id="license-manual-section">
|
||||
|
||||
<p>
|
||||
{% if free_trial_days %}
|
||||
Enter the number of users you would like to pay for after the Free Trial.<br>
|
||||
Enter the number of users you would like to pay for after the Free Trial.<br />
|
||||
You'll need to manually add licenses to add or invite
|
||||
additional users.
|
||||
{% else %}
|
||||
Enter the number of users you would like to pay for.<br>
|
||||
Enter the number of users you would like to pay for.<br />
|
||||
You'll need to manually add licenses to add or invite
|
||||
additional users.
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<h4>Number of licenses (minimum {{ seat_count }})</h4>
|
||||
<input type="number" name="licenses" min="{{ seat_count }}" autocomplete="off" id="manual_license_count" required/><br>
|
||||
<input type="number" name="licenses" min="{{ seat_count }}" autocomplete="off" id="manual_license_count" required/><br />
|
||||
</div>
|
||||
|
||||
<button id="add-card-button" class="stripe-button-el">
|
||||
|
@ -164,12 +164,12 @@
|
|||
<form id="invoice-form" method="post">
|
||||
{% if onboarding and free_trial_days %}
|
||||
<p><b>Not ready to start your trial?</b> <a href="/">Continue with the Zulip Cloud Free plan</a>.</p>
|
||||
<hr>
|
||||
<hr />
|
||||
<h2>Zulip Standard free trial</h2>
|
||||
{% endif %}
|
||||
<input type="hidden" name="signed_seat_count" value="{{ signed_seat_count }}">
|
||||
<input type="hidden" name="salt" value="{{ salt }}">
|
||||
<input type="hidden" name="billing_modality" value="send_invoice">
|
||||
<input type="hidden" name="signed_seat_count" value="{{ signed_seat_count }}" />
|
||||
<input type="hidden" name="salt" value="{{ salt }}" />
|
||||
<input type="hidden" name="billing_modality" value="send_invoice" />
|
||||
<div class="payment-schedule">
|
||||
<h3>{{ _("Payment schedule") }}</h3>
|
||||
<label>
|
||||
|
@ -187,18 +187,18 @@
|
|||
</div>
|
||||
<p>
|
||||
{% if free_trial_days %}
|
||||
Enter the number of users you would like to pay for.<br>
|
||||
Enter the number of users you would like to pay for.<br />
|
||||
We'll email you an invoice after the free trial.
|
||||
Invoices can be paid by ACH transfer or credit card.
|
||||
{% else %}
|
||||
Enter the number of users you would like to pay for.<br>
|
||||
Enter the number of users you would like to pay for.<br />
|
||||
We'll email you an invoice in 1-2 hours. Invoices can be paid by
|
||||
ACH transfer or credit card.
|
||||
{% endif %}
|
||||
</p>
|
||||
<h4>Number of licenses (minimum {{ min_invoiced_licenses }})</h4>
|
||||
<input type="number" min="{{ min_invoiced_licenses }}" autocomplete="off"
|
||||
id="invoiced_licenses" name="licenses" required/><br>
|
||||
id="invoiced_licenses" name="licenses" required/><br />
|
||||
<button type="submit" id="invoice-button" class="stripe-button-el invoice-button">Buy Standard</button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -232,7 +232,7 @@
|
|||
<option value="event">{{_('Event (hackathons, conferences, etc.)')}}</option>
|
||||
<option value="other">{{_('Other')}}</option>
|
||||
</select>
|
||||
<br>
|
||||
<br />
|
||||
<label>
|
||||
<h4>Organization website</h4>
|
||||
</label>
|
||||
|
@ -241,7 +241,7 @@
|
|||
<h4>Describe your organization briefly</h4>
|
||||
</label>
|
||||
<textarea name="description" style="width: 100%;" cols="100" rows="5" required></textarea>
|
||||
<br>
|
||||
<br />
|
||||
<p id="sponsorship-discount-details"></p>
|
||||
<button type="submit" id="sponsorship-button" class="stripe-button-el invoice-button">Submit</button>
|
||||
</form>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
@ -38,7 +38,7 @@
|
|||
<li><p>Get your Zulip API key from the Zulip "Settings" panel and put it in a file in your
|
||||
Athena home directory called <code>~/Private/.zulip-api-key</code>.</p></li>
|
||||
|
||||
<li><p>Run the following command to copy over all of your subscriptions:<br>
|
||||
<li><p>Run the following command to copy over all of your subscriptions:<br />
|
||||
<code>/mit/tabbott/zulip/zephyr_mirror.py --sync-subscriptions</code></p>
|
||||
|
||||
<p> <strong>NOTE</strong>: Zulip supports several ways to control what messages you want to read
|
||||
|
|
|
@ -48,10 +48,10 @@ the registration flow has its own (nearly identical) copy of the fields below in
|
|||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<br>
|
||||
<br />
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<input type="submit" class="btn btn-primary" value="{{ _('Enter') }}" /><br>
|
||||
<input type="submit" class="btn btn-primary" value="{{ _('Enter') }}" /><br />
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -29,7 +29,7 @@ page can be easily identified in it's respective JavaScript file -->
|
|||
</div>
|
||||
|
||||
<div class="invite-required">
|
||||
<hr>
|
||||
<hr />
|
||||
<i class="fa fa-lock"></i>{{ _("You need an invitation to join this organization.") }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -159,6 +159,6 @@
|
|||
<div id="compose" {% if embedded %}data-embedded{% endif %}>
|
||||
</div>
|
||||
<audio id="notification-sound-audio">
|
||||
<source id="notification-sound-source-ogg" type="audio/ogg">
|
||||
<source id="notification-sound-source-mp3" type="audio/mpeg">
|
||||
<source id="notification-sound-source-ogg" type="audio/ogg" />
|
||||
<source id="notification-sound-source-mp3" type="audio/mpeg" />
|
||||
</audio>
|
||||
|
|
|
@ -4,12 +4,12 @@
|
|||
{# Includes some other templates as tabs. #}
|
||||
|
||||
{% block meta_viewport %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<link href="/static/images/logo/apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
<link href="/static/images/logo/apple-touch-icon-precomposed.png" rel="apple-touch-icon-precomposed" />
|
||||
<style>
|
||||
#app-loading {
|
||||
background-color: hsl(0, 0%, 100%);
|
||||
|
|
|
@ -328,7 +328,7 @@
|
|||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<a href="/help/keyboard-shortcuts" target="_blank" rel="noopener noreferrer">{% trans %}Detailed keyboard shortcuts documentation{% endtrans %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -112,7 +112,7 @@
|
|||
<span class="operator_value">{{ placeholder_keyword }}</span>.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
<hr>
|
||||
<hr />
|
||||
<a href="/help/search-for-messages#search-operators" target="_blank" rel="noopener noreferrer">{% trans %}Detailed search operators documentation{% endtrans %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% set entrypoint = "landing-page" %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<style media="screen">
|
||||
.app.portico-page { padding-bottom: 0px; }
|
||||
</style>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{# Base template for the whole site. #}
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="UTF-8" />
|
||||
{% block title %}
|
||||
{% if user_profile and user_profile.realm.name %}
|
||||
<title>{{user_profile.realm.name}} - Zulip</title>
|
||||
|
@ -16,10 +16,10 @@
|
|||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
<link id="favicon" rel="icon" href="/static/images/favicon.svg?v=4">
|
||||
<link rel="alternate icon" href="/static/images/favicon.png?v=4">
|
||||
<link id="favicon" rel="icon" href="/static/images/favicon.svg?v=4" />
|
||||
<link rel="alternate icon" href="/static/images/favicon.png?v=4" />
|
||||
{% block meta_viewport %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
{% if not user_profile %}
|
||||
{% include 'zerver/meta_tags.html' %}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<div class="errorbox config-error">
|
||||
<div class="errorcontent">
|
||||
<h1 class="lead">Configuration error</h1>
|
||||
<br>
|
||||
<br />
|
||||
{% if error_name == "ldap_error_realm_is_none" %}
|
||||
{% trans %}
|
||||
You are trying to log in using LDAP without creating an
|
||||
|
|
|
@ -26,14 +26,14 @@
|
|||
{{ _("Log in with another account") }}
|
||||
</button>
|
||||
</form>
|
||||
<br>
|
||||
<br />
|
||||
<form class="form-inline" id="send_confirm" name="send_confirm"
|
||||
action="{{ continue_link }}" method="get">
|
||||
<button class="outline">
|
||||
{{ _("Continue to registration") }}
|
||||
</button>
|
||||
{% if full_name %}
|
||||
<input type="hidden" name="full_name" value="{{ full_name }}">
|
||||
<input type="hidden" name="full_name" value="{{ full_name }}" />
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
{% block customhead %}
|
||||
{{ super() }}
|
||||
<meta http-equiv="refresh" content="60;URL='/'">
|
||||
<meta http-equiv="refresh" content="60;URL='/'" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{% block content %}
|
||||
<div class="flex new-style">
|
||||
<div class="desktop-redirect-box white-box">
|
||||
<img class="avatar desktop-redirect-image" src="{{ realm_icon_url }}" alt=""/><br>
|
||||
<img class="avatar desktop-redirect-image" src="{{ realm_icon_url }}" alt=""/><br />
|
||||
<p class="copy-token-info">{% trans %}Copy this login token and return to your Zulip app to finish logging in:{% endtrans %}</p>
|
||||
<p>
|
||||
<span class="input-box">
|
||||
|
|
|
@ -41,14 +41,14 @@
|
|||
</tr>
|
||||
<tr>
|
||||
<td><a href="/emails">/emails</a></td>
|
||||
<td><code>./scripts/setup/inline_email_css.py</code><br>
|
||||
<td><code>./scripts/setup/inline_email_css.py</code><br />
|
||||
Run the command if you made changes to source.html email templates.
|
||||
</td>
|
||||
<td>View outgoing and example emails.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/stats/realm/analytics/">/stats/realm/analytics/</a></td>
|
||||
<td><code>./manage.py populate_analytics_db</code><br>
|
||||
<td><code>./manage.py populate_analytics_db</code><br />
|
||||
Run the command after changing analytics data population logic.
|
||||
</td>
|
||||
<td>View the /stats page with some pre-populated data</td>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
<label for="forward_address"><strong>Address to which emails should be forwarded</strong></label>
|
||||
<input type="text" id="address" name="forward_address" placeholder="eg: your-email@example.com" value="{{forward_address}}"/>
|
||||
</div>
|
||||
<br>
|
||||
<br />
|
||||
<div class="alert alert-info">
|
||||
You must set up SMTP as described
|
||||
<a target="_blank" rel="noopener noreferrer" href="https://zulip.readthedocs.io/en/latest/subsystems/email.html#development-and-testing">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
{% block customhead %}
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
@ -67,21 +67,21 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<div class="row2">
|
||||
<label for="URL"><b>URL</b> (Automatically Generated)</label>
|
||||
<input id="URL" type="text" />
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<div class="row3">
|
||||
<label for="custom_http_headers"><b>Custom HTTP Headers</b></label>
|
||||
<textarea id="custom_http_headers"></textarea>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<div class="row4">
|
||||
<div class="col1">
|
||||
|
@ -104,6 +104,6 @@
|
|||
</div>
|
||||
|
||||
<div class="pad-small"></div>
|
||||
<input id="csrftoken" type="hidden" value="{{ csrf_token }}">
|
||||
<input id="csrftoken" type="hidden" value="{{ csrf_token }}" />
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
{{ render_markdown_path(article, api_uri_context) }}
|
||||
|
||||
<div id="footer" class="documentation-footer">
|
||||
<hr>
|
||||
<hr />
|
||||
<p>We're here to help! Email us at <a href="mailto:{{ support_email }}">{{ support_email }}</a> with questions, feedback, or feature requests.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -23,4 +23,4 @@
|
|||
<div class="email-text" style="display: none;">
|
||||
<pre>{{ body }}</pre>
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<p>{{ new_streams.html|display_list(1000)|safe }}.</p>
|
||||
{% endif %}
|
||||
|
||||
<br>
|
||||
<br />
|
||||
|
||||
<p><a href="{{ realm_uri }}">{% trans %}Click here to log in to Zulip and catch up.{% endtrans %}</a></p>
|
||||
{% endblock %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta charset="UTF-8" />
|
||||
<title>Zulip</title>
|
||||
</head>
|
||||
{% if has_preheader %}
|
||||
|
|
|
@ -17,15 +17,15 @@
|
|||
|
||||
<p>
|
||||
{{ _('Your account details:') }}
|
||||
<li>{% trans organization_url=macros.link_tag(realm_uri) %}Organization URL: {{ organization_url }}{% endtrans %}<br></li>
|
||||
<li>{% trans organization_url=macros.link_tag(realm_uri) %}Organization URL: {{ organization_url }}{% endtrans %}<br /></li>
|
||||
{% if ldap %}
|
||||
{% if ldap_username %}
|
||||
<li>{% trans %}Username: {{ ldap_username }}{% endtrans %}<br></li>
|
||||
<li>{% trans %}Username: {{ ldap_username }}{% endtrans %}<br /></li>
|
||||
{% else %}
|
||||
<li>{{ _('Use your LDAP account to log in') }}<br></li>
|
||||
<li>{{ _('Use your LDAP account to log in') }}<br /></li>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<li>{% trans email=macros.email_tag(email) %}Email: {{ email }}{% endtrans %}<br></li>
|
||||
<li>{% trans email=macros.email_tag(email) %}Email: {{ email }}{% endtrans %}<br /></li>
|
||||
{% endif %}
|
||||
{% trans apps_page_link="https://zulip.com/apps" %}(you'll need these to sign in to the <a href="{{ apps_page_link }}">mobile and desktop</a> apps){% endtrans %}
|
||||
</p>
|
||||
|
@ -39,7 +39,7 @@
|
|||
</p>
|
||||
|
||||
<p>
|
||||
{{ _("Cheers,") }}<br>
|
||||
{{ _("Cheers,") }}<br />
|
||||
{{ _("Team Zulip") }}
|
||||
</p>
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
<p><a href="{{ realm_uri }}">{{ _("Take it for a spin now.") }}</a></p>
|
||||
|
||||
<p>{{ _("Thanks,") }}<br>{{ _("Zulip") }}</p>
|
||||
<p>{{ _("Thanks,") }}<br />{{ _("Zulip") }}</p>
|
||||
{% endblock %}
|
||||
|
||||
{% block manage_preferences %}
|
||||
|
|
|
@ -24,19 +24,19 @@
|
|||
|
||||
{% block manage_preferences %}
|
||||
<div class="email-preferences">
|
||||
—<br>
|
||||
—<br />
|
||||
{% if mention %}
|
||||
{% trans %}You are receiving this because you were mentioned in {{ realm_name }}.{% endtrans %}<br>
|
||||
{% trans %}You are receiving this because you were mentioned in {{ realm_name }}.{% endtrans %}<br />
|
||||
{% elif stream_email_notify %}
|
||||
{% trans %}You are receiving this because you have email notifications enabled for this stream.{% endtrans %}<br>
|
||||
{% trans %}You are receiving this because you have email notifications enabled for this stream.{% endtrans %}<br />
|
||||
{% endif %}
|
||||
{% if reply_to_zulip %}
|
||||
{% trans notif_url=realm_uri + "/#settings/notifications" %}Reply to this email directly, <a href="{{ narrow_url }}">view it in Zulip</a>, or <a href="{{ notif_url }}">manage email preferences</a>.{% endtrans %}
|
||||
{% elif not show_message_content %}
|
||||
{% trans notif_url=realm_uri + "/#settings/notifications" %}<a href="{{ narrow_url }}">View or reply in Zulip</a>, or <a href="{{ notif_url }}">manage email preferences</a>.{% endtrans %} <br>
|
||||
{% trans notif_url=realm_uri + "/#settings/notifications" %}<a href="{{ narrow_url }}">View or reply in Zulip</a>, or <a href="{{ notif_url }}">manage email preferences</a>.{% endtrans %} <br />
|
||||
{% else %}
|
||||
{% trans notif_url=realm_uri + "/#settings/notifications" %}<a href="{{ narrow_url }}">Reply in Zulip</a>, or <a href="{{ notif_url }}">manage email preferences</a>.{% endtrans %} <br>
|
||||
<br>
|
||||
{% trans notif_url=realm_uri + "/#settings/notifications" %}<a href="{{ narrow_url }}">Reply in Zulip</a>, or <a href="{{ notif_url }}">manage email preferences</a>.{% endtrans %} <br />
|
||||
<br />
|
||||
{% trans url="https://zulip.readthedocs.io/en/latest/production/email-gateway.html" %}
|
||||
Do not reply to this email. This Zulip server is not configured to accept incoming emails (<a href="{{ url }}">help</a>).
|
||||
{% endtrans %}
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{% trans new_email=macros.email_tag(new_email), support_email=macros.email_tag(support_email) %}The email associated with your Zulip account was recently changed to {{ new_email }}. If you did not request this change, please contact us immediately at {{ support_email }}.{% endtrans %}
|
||||
</p>
|
||||
<p>
|
||||
{{ _("Best,") }}<br>
|
||||
{{ _("Best,") }}<br />
|
||||
{{ _("Team Zulip") }}
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
</p>
|
||||
|
||||
<p>
|
||||
{{ _("Thanks,") }}<br>
|
||||
{{ _("Thanks,") }}<br />
|
||||
{{ _("Zulip Security") }}
|
||||
</p>
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,21 +3,21 @@
|
|||
{% block content %}
|
||||
<b>Support URL</b>: <a href="{{ support_url }}">{{ support_url }}</a>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<b>Website</b>: <a href="{{ website }}">{{ website }}</a>
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<b>Organization type</b>: {{ organization_type }}
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<b>Description</b>:
|
||||
<br>
|
||||
<br />
|
||||
{{ description }}
|
||||
|
||||
<br><br>
|
||||
<br /><br />
|
||||
|
||||
<b>Requested by</b>: {{ requested_by }} ({{ user_role }})
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
@ -104,7 +104,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<div class="company-container">
|
||||
<header>
|
||||
|
|
|
@ -11,7 +11,7 @@ conversations and focus work.' %}
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% set entrypoint = "landing-page" %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<style>
|
||||
.portico-page {
|
||||
|
@ -30,7 +30,7 @@
|
|||
<h1>Chat for distributed teams.</h1>
|
||||
<p>
|
||||
Zulip combines the immediacy of real-time chat with an email
|
||||
threading model. <br class="line-break-desktop">With Zulip, you can catch
|
||||
threading model. <br class="line-break-desktop" />With Zulip, you can catch
|
||||
up on important conversations while ignoring
|
||||
irrelevant ones.
|
||||
</p>
|
||||
|
@ -44,7 +44,7 @@
|
|||
<div class="item-inner">
|
||||
|
||||
<button data-target="#tour-carousel" data-slide="next" type="button" name="button" class="start-button">Take the tour</button>
|
||||
<img src="/static/images/story-tutorial/zulip-topic-blurred.png" alt="" class="start-image">
|
||||
<img src="/static/images/story-tutorial/zulip-topic-blurred.png" alt="" class="start-image" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
|
@ -53,11 +53,11 @@
|
|||
<div class="zulip-slack-comparison">
|
||||
<div class="comparison-zulip">
|
||||
<div class="caption">Zulip</div>
|
||||
<img src="/static/images/story-tutorial/zulip-streams.png" class="zulip-streams" alt="{{ _('Streams in Zulip') }}">
|
||||
<img src="/static/images/story-tutorial/zulip-streams.png" class="zulip-streams" alt="{{ _('Streams in Zulip') }}" />
|
||||
</div>
|
||||
<div class="comparison-slack">
|
||||
<div class="caption">Other team chat</div>
|
||||
<img src="/static/images/story-tutorial/slack-streams.png" class="slack-streams" alt="{{ _('Streams in Slack') }}">
|
||||
<img src="/static/images/story-tutorial/slack-streams.png" class="slack-streams" alt="{{ _('Streams in Slack') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -68,11 +68,11 @@
|
|||
<div class="zulip-slack-comparison">
|
||||
<div class="comparison-zulip">
|
||||
<div class="caption">Zulip</div>
|
||||
<img src="/static/images/story-tutorial/zulip-streams-selected.png" class="zulip-streams-selected" alt="{{ _('Topics in Zulip') }}">
|
||||
<img src="/static/images/story-tutorial/zulip-streams-selected.png" class="zulip-streams-selected" alt="{{ _('Topics in Zulip') }}" />
|
||||
</div>
|
||||
<div class="comparison-slack">
|
||||
<div class="caption">Other team chat</div>
|
||||
<img src="/static/images/story-tutorial/slack-streams-selected.png" class="slack-streams-selected" alt="{{ _('Streams in Slack') }}">
|
||||
<img src="/static/images/story-tutorial/slack-streams-selected.png" class="slack-streams-selected" alt="{{ _('Streams in Slack') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,11 +83,11 @@
|
|||
<div class="zulip-slack-comparison">
|
||||
<div class="comparison-zulip">
|
||||
<div class="caption comparison-2-caption-zulip">Zulip</div>
|
||||
<img src="/static/images/story-tutorial/zulip-streams-unreads-arrows.png" alt="{{ _('Stream topics in Zulip') }}" class="zulip-unreads-arrows">
|
||||
<img src="/static/images/story-tutorial/zulip-streams-unreads-arrows.png" alt="{{ _('Stream topics in Zulip') }}" class="zulip-unreads-arrows" />
|
||||
</div>
|
||||
<div class="comparison-slack">
|
||||
<div class="caption comparison-2-caption-slack">Other team chat</div>
|
||||
<img src="/static/images/story-tutorial/slack-streams-unreads.png" class="slack-stream-unreads" alt="{{ _('Streams in Slack') }}">
|
||||
<img src="/static/images/story-tutorial/slack-streams-unreads.png" class="slack-stream-unreads" alt="{{ _('Streams in Slack') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -95,27 +95,27 @@
|
|||
<div class="item">
|
||||
<div class="item-inner">
|
||||
<p class="tour-item-header">Let’s click on “Tuesday night catering.”</p>
|
||||
<img src="/static/images/story-tutorial/zulip-topic.png" alt="{{ _('The Tuesday night catering topic in Zulip') }}" class="zulip-topic mobile-hide">
|
||||
<img src="/static/images/story-tutorial/zulip-topic-crop.png" alt="{{ _('The Tuesday night catering topic in Zulip') }}" class="centered-image zulip-topic mobile-show">
|
||||
<img src="/static/images/story-tutorial/zulip-topic.png" alt="{{ _('The Tuesday night catering topic in Zulip') }}" class="zulip-topic mobile-hide" />
|
||||
<img src="/static/images/story-tutorial/zulip-topic-crop.png" alt="{{ _('The Tuesday night catering topic in Zulip') }}" class="centered-image zulip-topic mobile-show" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="item-inner">
|
||||
<p class="tour-item-header">Messages in Zulip retain their context even if they’re sent hours after the conversation started:</p>
|
||||
<img src="/static/images/story-tutorial/zulip-streams-easy.png" alt="{{ _('The Tuesday night catering topic in Zulip') }}" class="zulip-easy mobile-hide">
|
||||
<img src="/static/images/story-tutorial/zulip-streams-easy.png" alt="{{ _('The Tuesday night catering topic in Zulip') }}" class="zulip-easy mobile-hide" />
|
||||
<div class="mobile-show">
|
||||
<img src="/static/images/story-tutorial/zulip-streams-easy-mobile-top.png" class="centered-image" alt="{{ _('The Tuesday night catering topic in Zulip') }}">
|
||||
<img src="/static/images/story-tutorial/zulip-streams-easy-mobile-top.png" class="centered-image" alt="{{ _('The Tuesday night catering topic in Zulip') }}" />
|
||||
<p class="tour-explanation">Messages sent hours apart are linked in the same topic.</p>
|
||||
<img src="/static/images/story-tutorial/zulip-streams-easy-mobile-bottom.png" class="centered-image" alt="{{ _('The Tuesday night catering topic in Zulip - compose box') }}">
|
||||
<img src="/static/images/story-tutorial/zulip-streams-easy-mobile-bottom.png" class="centered-image" alt="{{ _('The Tuesday night catering topic in Zulip - compose box') }}" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="item-inner">
|
||||
<p class="tour-item-header">Without topics, it’s hard to catch up efficiently, and hard to participate in conversations that started while you were away.</p>
|
||||
<img src="/static/images/story-tutorial/slack-overwhelming.png" alt="{{ _('The Tuesday night catering topic in Slack') }}" class="slack-overwhelming mobile-hide">
|
||||
<img src="/static/images/story-tutorial/slack-overwhelming.png" alt="{{ _('The Tuesday night catering topic in Slack') }}" class="slack-overwhelming mobile-hide" />
|
||||
<div class="mobile-show">
|
||||
<img src="/static/images/story-tutorial/slack-overwhelming-mobile.png" class="centered-image" alt="{{ _('The Tuesday night catering topic in Slack') }}">
|
||||
<img src="/static/images/story-tutorial/slack-overwhelming-mobile.png" class="centered-image" alt="{{ _('The Tuesday night catering topic in Slack') }}" />
|
||||
<p class="tour-explanation">The last message about Tuesday night catering is hidden 56 messages ago. Meanwhile, you just see a mix of unrelated messages.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -128,11 +128,11 @@
|
|||
</a>
|
||||
<div class="other-resources">
|
||||
<div class="other-resources-section">
|
||||
<a href="/why-zulip"><img src="/static/images/landing-page/organised.svg" alt=""></a>
|
||||
<a href="/why-zulip"><img src="/static/images/landing-page/organised.svg" alt="" /></a>
|
||||
<p><a href="/why-zulip">Zulip vs Slack →</a></p>
|
||||
</div>
|
||||
<div class="other-resources-section">
|
||||
<a href="/features"><img src="/static/images/landing-page/featured.svg" alt=""></a>
|
||||
<a href="/features"><img src="/static/images/landing-page/featured.svg" alt="" /></a>
|
||||
<p><a href="/features">See all features →</a></p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -169,7 +169,7 @@
|
|||
Zulip has modern apps for every major platform,
|
||||
powered by Electron and React Native.
|
||||
</p>
|
||||
<br>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<div class="platform-icons">
|
||||
|
@ -389,49 +389,49 @@
|
|||
<div class="integration-icons">
|
||||
<a href="/integrations/doc/travis">
|
||||
<div class="group">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/travis.svg" alt="{{ _('Travis logo') }}">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/travis.svg" alt="{{ _('Travis logo') }}" />
|
||||
<h3 class="integration-name">Travis CI</h3>
|
||||
<p class="integration-description">See build results immediately</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/integrations/doc/github">
|
||||
<div class="group">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/github.svg" alt="{{ _('GitHub logo') }}">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/github.svg" alt="{{ _('GitHub logo') }}" />
|
||||
<h3 class="integration-name">GitHub</h3>
|
||||
<p class="integration-description">Track issues and pull requests</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/integrations/doc/heroku">
|
||||
<div class="group">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/heroku.svg" alt="{{ _('Heroku logo') }}">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/heroku.svg" alt="{{ _('Heroku logo') }}" />
|
||||
<h3 class="integration-name">Heroku</h3>
|
||||
<p class="integration-description">Keep up with deployments</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/integrations/doc/zendesk">
|
||||
<div class="group">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/zendesk.svg" alt="{{ _('Zendesk logo') }}">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/zendesk.svg" alt="{{ _('Zendesk logo') }}" />
|
||||
<h3 class="integration-name">Zendesk</h3>
|
||||
<p class="integration-description">Receive support tickets and updates</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/integrations/doc/jira">
|
||||
<div class="group">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/jira.svg" alt="{{ _('JIRA logo') }}">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/jira.svg" alt="{{ _('JIRA logo') }}" />
|
||||
<h3 class="integration-name">JIRA</h3>
|
||||
<p class="integration-description">Monitor project bugs and issues</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/integrations/doc/sentry">
|
||||
<div class="group">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/sentry.svg" alt="{{ _('Sentry logo') }}">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/sentry.svg" alt="{{ _('Sentry logo') }}" />
|
||||
<h3 class="integration-name">Sentry</h3>
|
||||
<p class="integration-description">See real-time error tracking</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="/integrations/doc/pagerduty" class="hide-1">
|
||||
<div class="group">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/pagerduty.svg" alt="{{ _('Pagerduty logo') }}">
|
||||
<img class="integration-logo" src="/static/images/integrations/logos/pagerduty.svg" alt="{{ _('Pagerduty logo') }}" />
|
||||
<h3 class="integration-name">Pagerduty</h3>
|
||||
<p class="integration-description">Connect to your monitoring systems</p>
|
||||
</div>
|
||||
|
@ -501,7 +501,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<hr />
|
||||
|
||||
<div class="company-container">
|
||||
<header>
|
||||
|
|
|
@ -18,7 +18,7 @@ Markdown
|
|||
|
||||
HTML
|
||||
```
|
||||
<a href="https://chat.zulip.org"><img src="https://img.shields.io/badge/zulip-join_chat-brightgreen.svg"></a>
|
||||
<a href="https://chat.zulip.org"><img src="https://img.shields.io/badge/zulip-join_chat-brightgreen.svg" /></a>
|
||||
```
|
||||
|
||||
## Link to a stream or topic
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% set entrypoint = "integrations" %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block hello_page_container %} hello-main{% endblock %}
|
||||
|
@ -85,7 +85,7 @@
|
|||
</h4>
|
||||
</a>
|
||||
{% endfor %}
|
||||
<hr>
|
||||
<hr />
|
||||
<h3>{% trans %}Custom integrations{% endtrans %}</h3>
|
||||
<a href="/api/incoming-webhooks-overview">
|
||||
<h4>{% trans %}Incoming webhooks{% endtrans %}</h4>
|
||||
|
@ -125,7 +125,7 @@
|
|||
</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<hr>
|
||||
<hr />
|
||||
<div class="integration-request center">
|
||||
<p>Don't see an integration you need? We'd love to help.</p>
|
||||
<a href="/api/integrations-overview" class="button green">
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
<div class="app-main white-box">
|
||||
{{ _('Hi there! Thank you for your interest in Zulip.') }}
|
||||
<br>
|
||||
<br />
|
||||
{% trans %}There is no Zulip organization hosted at this subdomain.{% endtrans %}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -42,7 +42,7 @@ page can be easily identified in it's respective JavaScript file. -->
|
|||
{% if password_auth_enabled %}
|
||||
<form name="login_form" id="login_form" method="post" class="login-form"
|
||||
action="{{ url('login') }}">
|
||||
<input type="hidden" name="next" value="{{ next }}">
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
|
||||
{% if two_factor_authentication_enabled %}
|
||||
{{ wizard.management_form }}
|
||||
|
@ -112,7 +112,7 @@ page can be easily identified in it's respective JavaScript file. -->
|
|||
{% for backend in page_params.external_authentication_methods %}
|
||||
<div class="login-social">
|
||||
<form class="social_login_form form-inline" action="{{ backend.login_url }}" method="get">
|
||||
<input type="hidden" name="next" value="{{ next }}">
|
||||
<input type="hidden" name="next" value="{{ next }}" />
|
||||
<button id="login_{{ backend.button_id_suffix }}" class="login-social-button"
|
||||
{% if backend.display_icon %} style="background-image:url({{ backend.display_icon }})" {% endif %}> {{ _('Log in with %(identity_provider)s', identity_provider=backend.display_name) }}
|
||||
</button>
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
<!-- Google / Search Engine Tags -->
|
||||
{% if allow_search_engine_indexing %}
|
||||
{% if OPEN_GRAPH_DESCRIPTION %}
|
||||
<meta name="description" content="{{ OPEN_GRAPH_DESCRIPTION }}">
|
||||
<meta name="description" content="{{ OPEN_GRAPH_DESCRIPTION }}" />
|
||||
{% else %}
|
||||
<meta name="description" content="Zulip combines the immediacy of real-time chat with an email threading model. With Zulip, you can catch up on important conversations while ignoring irrelevant ones.">
|
||||
<meta name="description" content="Zulip combines the immediacy of real-time chat with an email threading model. With Zulip, you can catch up on important conversations while ignoring irrelevant ones." />
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<meta name="robots" content="noindex,nofollow">
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
{% endif %}
|
||||
|
||||
<!-- Open Graph / Facebook / Twitter Meta Tags -->
|
||||
<meta property="og:url" content="{{ OPEN_GRAPH_URL }}">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Zulip">
|
||||
<meta property="og:url" content="{{ OPEN_GRAPH_URL }}" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:site_name" content="Zulip" />
|
||||
{% if OPEN_GRAPH_TITLE %}
|
||||
<meta property="og:title" content="{{ OPEN_GRAPH_TITLE }}">
|
||||
<meta property="og:description" content="{{ OPEN_GRAPH_DESCRIPTION }}">
|
||||
<meta property="og:title" content="{{ OPEN_GRAPH_TITLE }}" />
|
||||
<meta property="og:description" content="{{ OPEN_GRAPH_DESCRIPTION }}" />
|
||||
{% else %}
|
||||
<meta property="og:title" content="Chat for distributed teams">
|
||||
<meta property="og:description" content="Zulip combines the immediacy of real-time chat with an email threading model. With Zulip, you can catch up on important conversations while ignoring irrelevant ones.">
|
||||
<meta property="og:title" content="Chat for distributed teams" />
|
||||
<meta property="og:description" content="Zulip combines the immediacy of real-time chat with an email threading model. With Zulip, you can catch up on important conversations while ignoring irrelevant ones." />
|
||||
{% endif %}
|
||||
{% if OPEN_GRAPH_IMAGE %}
|
||||
<meta property="og:image" content="{{ OPEN_GRAPH_IMAGE }}">
|
||||
<meta property="og:image" content="{{ OPEN_GRAPH_IMAGE }}" />
|
||||
{% else %}
|
||||
<meta property="og:image" content="{{ realm_uri }}/static/images/logo/zulip-icon-128x128.png">
|
||||
<meta property="og:image" content="{{ realm_uri }}/static/images/logo/zulip-icon-128x128.png" />
|
||||
{% endif %}
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:card" content="summary" />
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% set entrypoint = "landing-page" %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
@ -28,7 +28,7 @@
|
|||
<div class="description">
|
||||
Try Zulip for an unlimited period of time.
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<ul class="feature-list">
|
||||
<li>10,000 messages of search history</li>
|
||||
<li>File storage up to 5 GB total</li>
|
||||
|
@ -61,7 +61,7 @@
|
|||
<div class="description">
|
||||
Make Zulip your home.
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<ul class="feature-list">
|
||||
<li>Full search history</li>
|
||||
<li>File storage up to 10 GB per user</li>
|
||||
|
@ -77,7 +77,7 @@
|
|||
<div class="price">6<span class="price-cents">.67</span></div>
|
||||
<div class="details">
|
||||
per user per month
|
||||
<br>
|
||||
<br />
|
||||
$8/month billed monthly
|
||||
</div>
|
||||
</div>
|
||||
|
@ -122,7 +122,7 @@
|
|||
<div class="description">
|
||||
Install your own Zulip server.
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<ul class="feature-list">
|
||||
<li>Easy self-service installation</li>
|
||||
<li>Free and open source forever under Apache 2.0 license</li>
|
||||
|
@ -148,7 +148,7 @@
|
|||
<div class="description">
|
||||
For mission-critical installations.
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
<ul class="feature-list">
|
||||
<li>Easy self-service installation</li>
|
||||
<li>Support response SLAs</li>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
{% set entrypoint = "landing-page" %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -180,7 +180,7 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
|
|||
{% endif %}
|
||||
</fieldset>
|
||||
{% if default_stream_groups %}
|
||||
<hr>
|
||||
<hr />
|
||||
<div class="default-stream-groups">
|
||||
<p class="margin">{{ _('What are you interested in?') }}</p>
|
||||
{% for default_stream_group in default_stream_groups %}
|
||||
|
@ -206,7 +206,7 @@ Form is validated both client-side using jquery-validate (see signup.js) and ser
|
|||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<hr>
|
||||
<hr />
|
||||
{% endif %}
|
||||
|
||||
<div class="input-group margin terms-of-service">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -86,28 +86,28 @@
|
|||
</p>
|
||||
|
||||
<div class="contributors-list">
|
||||
<input id="total" type="radio" name="tabs" checked>
|
||||
<input id="total" type="radio" name="tabs" checked />
|
||||
<label for="total"><i class="fa fa-globe" aria-hidden="true"></i> Total</label>
|
||||
|
||||
<input id="server" type="radio" name="tabs">
|
||||
<input id="server" type="radio" name="tabs" />
|
||||
<label for="server"><i class="fa fa-server" aria-hidden="true"></i> Server</label>
|
||||
|
||||
<input id="desktop" type="radio" name="tabs">
|
||||
<input id="desktop" type="radio" name="tabs" />
|
||||
<label for="desktop"><i class="fa fa-desktop" aria-hidden="true"></i> Desktop</label>
|
||||
|
||||
<input id="mobile" type="radio" name="tabs">
|
||||
<input id="mobile" type="radio" name="tabs" />
|
||||
<label for="mobile"><i class="fa fa-mobile" aria-hidden="true"></i> Mobile</label>
|
||||
|
||||
<input id="python-zulip-api" type="radio" name="tabs">
|
||||
<input id="python-zulip-api" type="radio" name="tabs" />
|
||||
<label for="python-zulip-api"><i class="fa fa-code" aria-hidden="true"></i> Python API</label>
|
||||
|
||||
<input id="zulip-js" type="radio" name="tabs">
|
||||
<input id="zulip-js" type="radio" name="tabs" />
|
||||
<label for="zulip-js"><i class="fa fa-code" aria-hidden="true"></i> JS API</label>
|
||||
|
||||
<input id="zulipbot" type="radio" name="tabs">
|
||||
<input id="zulipbot" type="radio" name="tabs" />
|
||||
<label for="zulipbot"><i class="fa fa-at" aria-hidden="true"></i> Zulipbot</label>
|
||||
|
||||
<input id="terminal" type="radio" name="tabs">
|
||||
<input id="terminal" type="radio" name="tabs" />
|
||||
<label for="terminal"><i class="fa fa-terminal" aria-hidden="true"></i> Terminal</label>
|
||||
|
||||
<div id="tab-total" class="contributors"></div>
|
||||
|
@ -128,7 +128,7 @@
|
|||
<img class="avatar_img" src="<%= avatar %>" alt="{{ _('Avatar') }}" />
|
||||
</div>
|
||||
<div class='info'>
|
||||
<b><%= name %></b><br>
|
||||
<b><%= name %></b><br />
|
||||
<%= commits %> <%= commits === 1 ? 'commit' : 'commits' %>
|
||||
</div>
|
||||
</a>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
{# Terms of Service. #}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
{% endblock %}
|
||||
|
||||
{% block customhead %}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
{% endblock %}
|
||||
|
||||
{% block portico_content %}
|
||||
|
|
|
@ -8,7 +8,7 @@ Mattermost, Discord, Spark, and others.
|
|||
|
||||
Anyone who wakes up to this frequently can tell you it is not fun.
|
||||
|
||||
<img src="/static/images/why-zulip/slack-unreads.png" class="slack-image" alt="Slack unreads">
|
||||
<img src="/static/images/why-zulip/slack-unreads.png" class="slack-image" alt="Slack unreads" />
|
||||
|
||||
The lack of organization and context in Slack channels means that anyone
|
||||
using Slack heavily has to manually scan through hundreds of messages a day
|
||||
|
@ -124,13 +124,13 @@ effective threading model: Every channel message has a topic, just
|
|||
like every message in email has a subject line. (Channels are called
|
||||
streams in Zulip.)
|
||||
|
||||
<img src="/static/images/why-zulip/zulip-topics.png" class="zulip-topics-image" alt="Zulip topics">
|
||||
<img src="/static/images/why-zulip/zulip-topics.png" class="zulip-topics-image" alt="Zulip topics" />
|
||||
|
||||
Topics hold Zulip conversations together, just like subject lines hold email
|
||||
conversations together. They allow you to efficiently catch up on messages
|
||||
and reply in context, even to conversations that started hours or days ago.
|
||||
|
||||
<img src="/static/images/why-zulip/zulip-reply-later.png" class="zulip-reply-later-image" alt="Zulip reply later">
|
||||
<img src="/static/images/why-zulip/zulip-reply-later.png" class="zulip-reply-later-image" alt="Zulip reply later" />
|
||||
|
||||
## Zulip changes how you can operate.
|
||||
|
||||
|
|
|
@ -120,9 +120,9 @@ def tokenize(text: str) -> List[Token]:
|
|||
|
||||
tag = tag_parts[0]
|
||||
|
||||
if is_special_html_tag(s, tag):
|
||||
kind = "html_special"
|
||||
elif is_self_closing_html_tag(s, tag):
|
||||
if tag == "!DOCTYPE":
|
||||
kind = "html_doctype"
|
||||
elif s.endswith("/>"):
|
||||
kind = "html_singleton"
|
||||
else:
|
||||
kind = "html_start"
|
||||
|
@ -203,6 +203,26 @@ def tokenize(text: str) -> List[Token]:
|
|||
return tokens
|
||||
|
||||
|
||||
HTML_VOID_TAGS = {
|
||||
"area",
|
||||
"base",
|
||||
"br",
|
||||
"col",
|
||||
"command",
|
||||
"embed",
|
||||
"hr",
|
||||
"img",
|
||||
"input",
|
||||
"keygen",
|
||||
"link",
|
||||
"meta",
|
||||
"param",
|
||||
"source",
|
||||
"track",
|
||||
"wbr",
|
||||
}
|
||||
|
||||
|
||||
def validate(
|
||||
fn: Optional[str] = None, text: Optional[str] = None, check_indent: bool = True
|
||||
) -> None:
|
||||
|
@ -227,6 +247,7 @@ def validate(
|
|||
class State:
|
||||
def __init__(self, func: Callable[[Token], None]) -> None:
|
||||
self.depth = 0
|
||||
self.foreign = False
|
||||
self.matcher = func
|
||||
|
||||
def no_start_tag(token: Token) -> None:
|
||||
|
@ -249,6 +270,10 @@ def validate(
|
|||
start_col = start_token.col
|
||||
|
||||
old_matcher = state.matcher
|
||||
old_foreign = state.foreign
|
||||
|
||||
if start_tag in ["math", "svg"]:
|
||||
state.foreign = True
|
||||
|
||||
def f(end_token: Token) -> None:
|
||||
|
||||
|
@ -283,6 +308,7 @@ def validate(
|
|||
"""
|
||||
)
|
||||
state.matcher = old_matcher
|
||||
state.foreign = old_foreign
|
||||
state.depth -= 1
|
||||
|
||||
state.matcher = f
|
||||
|
@ -292,7 +318,16 @@ def validate(
|
|||
tag = token.tag
|
||||
|
||||
if kind == "html_start":
|
||||
if not state.foreign and tag in HTML_VOID_TAGS:
|
||||
raise TemplateParserException(
|
||||
f"Tag must be self-closing: {tag} at {fn} line {token.line}, col {token.col}"
|
||||
)
|
||||
start_tag_matcher(token)
|
||||
elif kind == "html_singleton":
|
||||
if not state.foreign and tag not in HTML_VOID_TAGS:
|
||||
raise TemplateParserException(
|
||||
f"Tag must not be self-closing: {tag} at {fn} line {token.line}, col {token.col}"
|
||||
)
|
||||
elif kind == "html_end":
|
||||
state.matcher(token)
|
||||
|
||||
|
@ -315,45 +350,6 @@ def validate(
|
|||
raise TemplateParserException("Missing end tag")
|
||||
|
||||
|
||||
def is_special_html_tag(s: str, tag: str) -> bool:
|
||||
return tag in ["link", "meta", "!DOCTYPE"]
|
||||
|
||||
|
||||
OPTIONAL_CLOSING_TAGS = [
|
||||
"br",
|
||||
"circle",
|
||||
"img",
|
||||
"input",
|
||||
"path",
|
||||
"polygon",
|
||||
"stop",
|
||||
]
|
||||
|
||||
|
||||
def is_self_closing_html_tag(s: str, tag: str) -> bool:
|
||||
if s.endswith("/>"):
|
||||
if tag in OPTIONAL_CLOSING_TAGS:
|
||||
return True
|
||||
raise TokenizationException("Singleton tag not allowed", tag)
|
||||
self_closing_tag = tag in [
|
||||
"area",
|
||||
"base",
|
||||
"br",
|
||||
"col",
|
||||
"embed",
|
||||
"hr",
|
||||
"img",
|
||||
"input",
|
||||
"param",
|
||||
"source",
|
||||
"track",
|
||||
"wbr",
|
||||
]
|
||||
if self_closing_tag:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def is_django_block_tag(tag: str) -> bool:
|
||||
return tag in [
|
||||
"autoescape",
|
||||
|
|
|
@ -3,6 +3,7 @@ import unittest
|
|||
|
||||
import tools.lib.template_parser
|
||||
from tools.lib.html_branches import (
|
||||
Node,
|
||||
build_id_dict,
|
||||
get_tag_info,
|
||||
html_branches,
|
||||
|
@ -49,35 +50,40 @@ class TestHtmlBranches(unittest.TestCase):
|
|||
|
||||
tree = html_tag_tree(html)
|
||||
|
||||
assert tree.children[0].token is not None
|
||||
self.assertEqual(tree.children[0].token.kind, "html_start")
|
||||
self.assertEqual(tree.children[0].token.tag, "html")
|
||||
def serialize(node: Node) -> object:
|
||||
return (
|
||||
node.token and (node.token.kind, node.token.tag),
|
||||
[serialize(child) for child in node.children],
|
||||
)
|
||||
|
||||
assert tree.children[0].children[0].token is not None
|
||||
self.assertEqual(tree.children[0].children[0].token.kind, "html_start")
|
||||
self.assertEqual(tree.children[0].children[0].token.tag, "head")
|
||||
|
||||
assert tree.children[0].children[0].children[0].token is not None
|
||||
self.assertEqual(tree.children[0].children[0].children[0].token.kind, "html_start")
|
||||
self.assertEqual(tree.children[0].children[0].children[0].token.tag, "title")
|
||||
|
||||
assert tree.children[0].children[1].token is not None
|
||||
self.assertEqual(tree.children[0].children[1].token.kind, "html_start")
|
||||
self.assertEqual(tree.children[0].children[1].token.tag, "body")
|
||||
|
||||
assert tree.children[0].children[1].children[0].token is not None
|
||||
self.assertEqual(tree.children[0].children[1].children[0].token.kind, "html_start")
|
||||
self.assertEqual(tree.children[0].children[1].children[0].token.tag, "p")
|
||||
|
||||
assert tree.children[0].children[1].children[0].children[0].token is not None
|
||||
self.assertEqual(
|
||||
tree.children[0].children[1].children[0].children[0].token.kind, "html_singleton"
|
||||
expected = (
|
||||
None,
|
||||
[
|
||||
(
|
||||
("html_start", "html"),
|
||||
[
|
||||
(
|
||||
("html_start", "head"),
|
||||
[
|
||||
(("html_start", "title"), []),
|
||||
(("html_singleton", "meta"), []),
|
||||
(("html_singleton", "link"), []),
|
||||
],
|
||||
),
|
||||
(
|
||||
("html_start", "body"),
|
||||
[
|
||||
(
|
||||
("html_start", "p"),
|
||||
[(("html_start", "br"), []), (("html_start", "p"), [])],
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
)
|
||||
self.assertEqual(tree.children[0].children[1].children[0].children[0].token.tag, "br")
|
||||
|
||||
assert tree.children[0].children[1].children[1].token is not None
|
||||
self.assertEqual(tree.children[0].children[1].children[1].token.kind, "html_start")
|
||||
self.assertEqual(tree.children[0].children[1].children[1].token.tag, "p")
|
||||
self.assertEqual(serialize(tree), expected)
|
||||
|
||||
def test_html_branches(self) -> None:
|
||||
html = """
|
||||
|
@ -99,19 +105,16 @@ class TestHtmlBranches(unittest.TestCase):
|
|||
"""
|
||||
|
||||
branches = html_branches(html)
|
||||
|
||||
self.assertEqual(branches[0].text(), "html head title")
|
||||
self.assertEqual(branches[1].text(), "html body p br")
|
||||
self.assertEqual(branches[2].text(), "html body p")
|
||||
|
||||
self.assertEqual(
|
||||
branches[0].staircase_text(), "\n html\n head\n title\n"
|
||||
[(branch.text(), branch.staircase_text()) for branch in branches],
|
||||
[
|
||||
("html head title", "\n html\n head\n title\n"),
|
||||
("html head meta", "\n html\n head\n meta\n"),
|
||||
("html head link", "\n html\n head\n link\n"),
|
||||
("html body p br", "\n html\n body\n p\n br\n"),
|
||||
("html body p p", "\n html\n body\n p\n p\n"),
|
||||
],
|
||||
)
|
||||
self.assertEqual(
|
||||
branches[1].staircase_text(),
|
||||
"\n html\n body\n p\n br\n",
|
||||
)
|
||||
self.assertEqual(branches[2].staircase_text(), "\n html\n body\n p\n")
|
||||
|
||||
def test_build_id_dict(self) -> None:
|
||||
templates = ["test_template1.html", "test_template2.html"]
|
||||
|
|
|
@ -20,7 +20,7 @@ BAD_HTML = """
|
|||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div><p>Hello<br>world!</p></div>
|
||||
<div><p>Hello<br />world!</p></div>
|
||||
<p>Goodbye<!-- test -->world!</p>
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -52,7 +52,7 @@ GOOD_HTML = """
|
|||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div><p>Hello<br>world!</p></div>
|
||||
<div><p>Hello<br />world!</p></div>
|
||||
<p>Goodbye<!-- test -->world!</p>
|
||||
<table>
|
||||
<tr>
|
||||
|
@ -338,7 +338,7 @@ BAD_HTML13 = """
|
|||
{{#if this.is_realm_emoji}}
|
||||
<img src="{{this.url}}" class="emoji" />
|
||||
{{else}}
|
||||
<br>
|
||||
<br />
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<div>{{this.count}}</div>
|
||||
|
@ -353,7 +353,7 @@ GOOD_HTML13 = """
|
|||
{{#if this.is_realm_emoji}}
|
||||
<img src="{{this.url}}" class="emoji" />
|
||||
{{else}}
|
||||
<br>
|
||||
<br />
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<div>{{this.count}}</div>
|
||||
|
|
|
@ -260,23 +260,23 @@ class ParserTest(unittest.TestCase):
|
|||
validate(text=my_html)
|
||||
|
||||
def test_tokenize(self) -> None:
|
||||
tag = "<meta whatever>bla"
|
||||
tag = "<!DOCTYPE html>"
|
||||
token = tokenize(tag)[0]
|
||||
self.assertEqual(token.kind, "html_special")
|
||||
self.assertEqual(token.kind, "html_doctype")
|
||||
|
||||
tag = "<a>bla"
|
||||
token = tokenize(tag)[0]
|
||||
self.assertEqual(token.kind, "html_start")
|
||||
self.assertEqual(token.tag, "a")
|
||||
|
||||
tag = "<br>bla"
|
||||
tag = "<br />bla"
|
||||
token = tokenize(tag)[0]
|
||||
self.assertEqual(token.kind, "html_singleton")
|
||||
self.assertEqual(token.tag, "br")
|
||||
|
||||
tag = "<input>bla"
|
||||
token = tokenize(tag)[0]
|
||||
self.assertEqual(token.kind, "html_singleton")
|
||||
self.assertEqual(token.kind, "html_start") # We later mark this an error.
|
||||
self.assertEqual(token.tag, "input")
|
||||
|
||||
tag = "<input />bla"
|
||||
|
|
|
@ -45,4 +45,4 @@ API_FEATURE_LEVEL = 57
|
|||
# historical commits sharing the same major version, in which case a
|
||||
# minor version bump suffices.
|
||||
|
||||
PROVISION_VERSION = "141.1"
|
||||
PROVISION_VERSION = "141.2"
|
||||
|
|
|
@ -54,7 +54,7 @@ class DocPageTest(ZulipTestCase):
|
|||
self.assertIn(s, str(result.content))
|
||||
if not doc_html_str:
|
||||
self.assert_in_success_response(
|
||||
['<meta name="robots" content="noindex,nofollow">'], result
|
||||
['<meta name="robots" content="noindex,nofollow" />'], result
|
||||
)
|
||||
|
||||
# Test the URL on the root subdomain
|
||||
|
@ -65,7 +65,7 @@ class DocPageTest(ZulipTestCase):
|
|||
self.assertIn(expected_content, str(result.content))
|
||||
if not doc_html_str:
|
||||
self.assert_in_success_response(
|
||||
['<meta name="robots" content="noindex,nofollow">'], result
|
||||
['<meta name="robots" content="noindex,nofollow" />'], result
|
||||
)
|
||||
|
||||
for s in extra_strings:
|
||||
|
@ -88,7 +88,7 @@ class DocPageTest(ZulipTestCase):
|
|||
# Every page has a meta-description
|
||||
self.assert_in_success_response(['<meta name="description" content="'], result)
|
||||
self.assert_not_in_success_response(
|
||||
['<meta name="robots" content="noindex,nofollow">'], result
|
||||
['<meta name="robots" content="noindex,nofollow" />'], result
|
||||
)
|
||||
|
||||
# Test the URL on the "zephyr" subdomain with the landing page setting
|
||||
|
@ -101,7 +101,7 @@ class DocPageTest(ZulipTestCase):
|
|||
self.assertIn(s, str(result.content))
|
||||
if not doc_html_str:
|
||||
self.assert_in_success_response(
|
||||
['<meta name="robots" content="noindex,nofollow">'], result
|
||||
['<meta name="robots" content="noindex,nofollow" />'], result
|
||||
)
|
||||
|
||||
def test_api_doc_endpoints(self) -> None:
|
||||
|
@ -172,14 +172,14 @@ class DocPageTest(ZulipTestCase):
|
|||
def test_portico_pages_open_graph_metadata(self) -> None:
|
||||
# Why Zulip
|
||||
url = "/why-zulip/"
|
||||
title = '<meta property="og:title" content="Team chat with first-class threading">'
|
||||
title = '<meta property="og:title" content="Team chat with first-class threading" />'
|
||||
description = '<meta property="og:description" content="Most team chats are overwhelming'
|
||||
self._test(url, title, doc_html_str=True)
|
||||
self._test(url, description, doc_html_str=True)
|
||||
|
||||
# Features
|
||||
url = "/features/"
|
||||
title = '<meta property="og:title" content="Zulip Features">'
|
||||
title = '<meta property="og:title" content="Zulip Features" />'
|
||||
description = '<meta property="og:description" content="First class threading'
|
||||
self._test(url, title, doc_html_str=True)
|
||||
self._test(url, description, doc_html_str=True)
|
||||
|
@ -202,21 +202,21 @@ class DocPageTest(ZulipTestCase):
|
|||
|
||||
def test_integration_pages_open_graph_metadata(self) -> None:
|
||||
url = "/integrations/doc/github"
|
||||
title = '<meta property="og:title" content="Connect GitHub to Zulip">'
|
||||
title = '<meta property="og:title" content="Connect GitHub to Zulip" />'
|
||||
description = '<meta property="og:description" content="Zulip comes with over'
|
||||
self._test(url, title, doc_html_str=True)
|
||||
self._test(url, description, doc_html_str=True)
|
||||
|
||||
# Test category pages
|
||||
url = "/integrations/communication"
|
||||
title = '<meta property="og:title" content="Connect your Communication tools to Zulip">'
|
||||
title = '<meta property="og:title" content="Connect your Communication tools to Zulip" />'
|
||||
description = '<meta property="og:description" content="Zulip comes with over'
|
||||
self._test(url, title, doc_html_str=True)
|
||||
self._test(url, description, doc_html_str=True)
|
||||
|
||||
# Test integrations page
|
||||
url = "/integrations/"
|
||||
title = '<meta property="og:title" content="Connect the tools you use to Zulip">'
|
||||
title = '<meta property="og:title" content="Connect the tools you use to Zulip" />'
|
||||
description = '<meta property="og:description" content="Zulip comes with over'
|
||||
self._test(url, title, doc_html_str=True)
|
||||
self._test(url, description, doc_html_str=True)
|
||||
|
|
Loading…
Reference in New Issue