diff --git a/frontend_tests/node_tests/dispatch.js b/frontend_tests/node_tests/dispatch.js
index 40d1c00ef3..82b7e0c0a3 100644
--- a/frontend_tests/node_tests/dispatch.js
+++ b/frontend_tests/node_tests/dispatch.js
@@ -484,11 +484,11 @@ run_test("realm_emoji", (override) => {
}
});
-run_test("realm_filters", (override) => {
+run_test("linkifier", (override) => {
const event = event_fixtures.realm_filters;
page_params.realm_filters = [];
- override(settings_linkifiers, "populate_filters", noop);
- override(markdown, "update_realm_filter_rules", noop);
+ override(settings_linkifiers, "populate_linkifiers", noop);
+ override(markdown, "update_linkifier_rules", noop);
dispatch(event);
assert_same(page_params.realm_filters, event.realm_filters);
});
diff --git a/frontend_tests/node_tests/markdown.js b/frontend_tests/node_tests/markdown.js
index f1024be395..a91279d045 100644
--- a/frontend_tests/node_tests/markdown.js
+++ b/frontend_tests/node_tests/markdown.js
@@ -390,23 +390,23 @@ run_test("marked", () => {
expected:
'
\nMention in quote: Cordelia Lear
\n \nMention outside quote: @Cordelia Lear
',
},
- // Test only those realm filters which don't return True for
+ // Test only those linkifiers which don't return True for
// `contains_backend_only_syntax()`. Those which return True
// are tested separately.
{
- input: "This is a realm filter #1234 with text after it",
+ input: "This is a linkifier #1234 with text after it",
expected:
- 'This is a realm filter #1234 with text after it
',
+ 'This is a linkifier #1234 with text after it
',
},
- {input: "#1234is not a realm filter.", expected: "#1234is not a realm filter.
"},
+ {input: "#1234is not a linkifier.", expected: "#1234is not a linkifier.
"},
{
- input: "A pattern written as #1234is not a realm filter.",
- expected: "A pattern written as #1234is not a realm filter.
",
+ input: "A pattern written as #1234is not a linkifier.",
+ expected: "A pattern written as #1234is not a linkifier.
",
},
{
- input: "This is a realm filter with ZGROUP_123:45 groups",
+ input: "This is a linkifier with ZGROUP_123:45 groups",
expected:
- 'This is a realm filter with ZGROUP_123:45 groups
',
+ 'This is a linkifier with ZGROUP_123:45 groups
',
},
{input: "Test *italic*", expected: "Test italic
"},
{
@@ -453,8 +453,8 @@ run_test("marked", () => {
},
{input: "@*notagroup*", expected: "@*notagroup*
"},
{
- input: "This is a realm filter `hello` with text after it",
- expected: "This is a realm filter hello
with text after it
",
+ input: "This is a linkifier `hello` with text after it",
+ expected: "This is a linkifier hello
with text after it
",
},
// Test the emoticon conversion
{input: ":)", expected: ":)
"},
@@ -650,39 +650,39 @@ run_test("message_flags", () => {
assert.equal(message.mentioned, false);
});
-run_test("backend_only_realm_filters", () => {
- markdown.update_realm_filter_rules(page_params.realm_filters);
+run_test("backend_only_linkifiers", () => {
+ markdown.update_linkifier_rules(page_params.realm_filters);
- const backend_only_realm_filters = [
+ const backend_only_linkifiers = [
"Here is the PR-#123.",
"Function abc() was introduced in (PR)#123.",
];
- for (const content of backend_only_realm_filters) {
+ for (const content of backend_only_linkifiers) {
assert.equal(markdown.contains_backend_only_syntax(content), true);
}
});
-run_test("python_to_js_filter", () => {
- // The only way to reach python_to_js_filter is indirectly, hence the call
- // to update_realm_filter_rules.
- markdown.update_realm_filter_rules([["/a(?im)a/g"], ["/a(?L)a/g"]]);
- let actual_value = marked.InlineLexer.rules.zulip.realm_filters;
+run_test("python_to_js_linkifier", () => {
+ // The only way to reach python_to_js_linkifier is indirectly, hence the call
+ // to update_linkifier_rules.
+ markdown.update_linkifier_rules([["/a(?im)a/g"], ["/a(?L)a/g"]]);
+ let actual_value = marked.InlineLexer.rules.zulip.linkifiers;
let expected_value = [/\/aa\/g(?!\w)/gim, /\/aa\/g(?!\w)/g];
assert.deepEqual(actual_value, expected_value);
// Test case with multiple replacements.
- markdown.update_realm_filter_rules([
+ markdown.update_linkifier_rules([
["#cf(?P\\d+)(?P[A-Z][\\dA-Z]*)", "http://google.com"],
]);
- actual_value = marked.InlineLexer.rules.zulip.realm_filters;
+ actual_value = marked.InlineLexer.rules.zulip.linkifiers;
expected_value = [/#cf(\d+)([A-Z][\dA-Z]*)(?!\w)/g];
assert.deepEqual(actual_value, expected_value);
// Test incorrect syntax.
blueslip.expect(
"error",
- "python_to_js_filter: Invalid regular expression: /!@#@(!#&((!&(@#((?!\\w)/: Unterminated group",
+ "python_to_js_linkifier: Invalid regular expression: /!@#@(!#&((!&(@#((?!\\w)/: Unterminated group",
);
- markdown.update_realm_filter_rules([["!@#@(!#&((!&(@#(", "http://google.com"]]);
- actual_value = marked.InlineLexer.rules.zulip.realm_filters;
+ markdown.update_linkifier_rules([["!@#@(!#&((!&(@#(", "http://google.com"]]);
+ actual_value = marked.InlineLexer.rules.zulip.linkifiers;
expected_value = [];
assert.deepEqual(actual_value, expected_value);
});
diff --git a/frontend_tests/puppeteer_tests/15-realm-linkifier.ts b/frontend_tests/puppeteer_tests/15-realm-linkifier.ts
index de2f4a4730..be115d3d98 100644
--- a/frontend_tests/puppeteer_tests/15-realm-linkifier.ts
+++ b/frontend_tests/puppeteer_tests/15-realm-linkifier.ts
@@ -5,56 +5,59 @@ import type {Page} from "puppeteer";
import common from "../puppeteer_lib/common";
async function test_add_linkifier(page: Page): Promise {
- await page.waitForSelector(".admin-filter-form", {visible: true});
- await common.fill_form(page, "form.admin-filter-form", {
+ await page.waitForSelector(".admin-linkifier-form", {visible: true});
+ await common.fill_form(page, "form.admin-linkifier-form", {
pattern: "#(?P[0-9]+)",
url_format_string: "https://trac.example.com/ticket/%(id)s",
});
- await page.click("form.admin-filter-form button.button");
+ await page.click("form.admin-linkifier-form button.button");
- const admin_filter_status_selector = "div#admin-filter-status";
- await page.waitForSelector(admin_filter_status_selector, {visible: true});
- const admin_filter_status = await common.get_text_from_selector(
+ const admin_linkifier_status_selector = "div#admin-linkifier-status";
+ await page.waitForSelector(admin_linkifier_status_selector, {visible: true});
+ const admin_linkifier_status = await common.get_text_from_selector(
page,
- admin_filter_status_selector,
+ admin_linkifier_status_selector,
);
- assert.strictEqual(admin_filter_status, "Custom filter added!");
+ assert.strictEqual(admin_linkifier_status, "Custom linkifier added!");
- await page.waitForSelector(".filter_row", {visible: true});
+ await page.waitForSelector(".linkifier_row", {visible: true});
assert.strictEqual(
- await common.get_text_from_selector(page, ".filter_row span.filter_pattern"),
+ await common.get_text_from_selector(page, ".linkifier_row span.linkifier_pattern"),
"#(?P[0-9]+)",
);
assert.strictEqual(
- await common.get_text_from_selector(page, ".filter_row span.filter_url_format_string"),
+ await common.get_text_from_selector(
+ page,
+ ".linkifier_row span.linkifier_url_format_string",
+ ),
"https://trac.example.com/ticket/%(id)s",
);
}
async function test_delete_linkifier(page: Page): Promise {
- await page.click(".filter_row button");
- await page.waitForSelector(".filter_row", {hidden: true});
+ await page.click(".linkifier_row button");
+ await page.waitForSelector(".linkifier_row", {hidden: true});
}
async function test_invalid_linkifier_pattern(page: Page): Promise {
- await page.waitForSelector(".admin-filter-form", {visible: true});
- await common.fill_form(page, "form.admin-filter-form", {
+ await page.waitForSelector(".admin-linkifier-form", {visible: true});
+ await common.fill_form(page, "form.admin-linkifier-form", {
pattern: "a$",
url_format_string: "https://trac.example.com/ticket/%(id)s",
});
- await page.click("form.admin-filter-form button.button");
+ await page.click("form.admin-linkifier-form button.button");
- await page.waitForSelector("div#admin-filter-pattern-status", {visible: true});
+ await page.waitForSelector("div#admin-linkifier-pattern-status", {visible: true});
assert.strictEqual(
- await common.get_text_from_selector(page, "div#admin-filter-pattern-status"),
+ await common.get_text_from_selector(page, "div#admin-linkifier-pattern-status"),
"Failed: Invalid filter pattern. Valid characters are [ a-zA-Z_#=/:+!-].",
);
}
-async function realm_linkifier_test(page: Page): Promise {
+async function linkifier_test(page: Page): Promise {
await common.log_in(page);
await common.manage_organization(page);
- await page.click("li[data-section='filter-settings']");
+ await page.click("li[data-section='linkifier-settings']");
await test_add_linkifier(page);
await test_delete_linkifier(page);
@@ -63,4 +66,4 @@ async function realm_linkifier_test(page: Page): Promise {
await common.log_out(page);
}
-common.run_test(realm_linkifier_test);
+common.run_test(linkifier_test);
diff --git a/static/js/markdown.js b/static/js/markdown.js
index 7f697e924d..3e4ffff275 100644
--- a/static/js/markdown.js
+++ b/static/js/markdown.js
@@ -22,8 +22,8 @@ import * as message_store from "./message_store";
// for example usage.
let helpers;
-const realm_filter_map = new Map();
-let realm_filter_list = [];
+const linkifier_map = new Map();
+let linkifier_list = [];
// Regexes that match some of our common backend-only Markdown syntax
const backend_only_markdown_re = [
@@ -84,15 +84,15 @@ export function contains_backend_only_syntax(content) {
// If it doesn't, we can immediately render it client-side for local echo.
const markedup = backend_only_markdown_re.find((re) => re.test(content));
- // If a realm filter doesn't start with some specified characters
+ // If a linkifier doesn't start with some specified characters
// then don't render it locally. It is workaround for the fact that
// javascript regex doesn't support lookbehind.
- const false_filter_match = realm_filter_list.find((re) => {
+ const false_linkifier_match = linkifier_list.find((re) => {
const pattern = /[^\s"'(,:<]/.source + re[0].source + /(?!\w)/.source;
const regex = new RegExp(pattern);
return regex.test(content);
});
- return markedup !== undefined || false_filter_match !== undefined;
+ return markedup !== undefined || false_linkifier_match !== undefined;
}
export function apply_markdown(message) {
@@ -212,9 +212,9 @@ export function add_topic_links(message) {
const topic = message.topic;
let links = [];
- for (const realm_filter of realm_filter_list) {
- const pattern = realm_filter[0];
- const url = realm_filter[1];
+ for (const linkifier of linkifier_list) {
+ const pattern = linkifier[0];
+ const url = linkifier[1];
let match;
while ((match = pattern.exec(topic)) !== null) {
let link_url = url;
@@ -340,8 +340,8 @@ function handleStreamTopic(stream_name, topic) {
)}" href="/${_.escape(href)}">${_.escape(text)}`;
}
-function handleRealmFilter(pattern, matches) {
- let url = realm_filter_map.get(pattern);
+function handleLinkifier(pattern, matches) {
+ let url = linkifier_map.get(pattern);
let current_group = 1;
@@ -367,7 +367,7 @@ function handleTex(tex, fullmatch) {
}
}
-function python_to_js_filter(pattern, url) {
+function python_to_js_linkifier(pattern, url) {
// Converts a python named-group regex to a javascript-compatible numbered
// group regex... with a regex!
const named_group_re = /\(?P<([^>]+?)>/g;
@@ -404,7 +404,7 @@ function python_to_js_filter(pattern, url) {
pattern = pattern.replace(inline_flag_re, "");
}
- // Ideally we should have been checking that realm filters
+ // Ideally we should have been checking that linkifiers
// begin with certain characters but since there is no
// support for negative lookbehind in javascript, we check
// for this condition in `contains_backend_only_syntax()`
@@ -418,36 +418,36 @@ function python_to_js_filter(pattern, url) {
final_regex = new RegExp(pattern, js_flags);
} catch (error) {
// We have an error computing the generated regex syntax.
- // We'll ignore this realm filter for now, but log this
+ // We'll ignore this linkifier for now, but log this
// failure for debugging later.
- blueslip.error("python_to_js_filter: " + error.message);
+ blueslip.error("python_to_js_linkifier: " + error.message);
}
return [final_regex, url];
}
-export function update_realm_filter_rules(realm_filters) {
- // Update the marked parser with our particular set of realm filters
- realm_filter_map.clear();
- realm_filter_list = [];
+export function update_linkifier_rules(linkifiers) {
+ // Update the marked parser with our particular set of linkifiers
+ linkifier_map.clear();
+ linkifier_list = [];
const marked_rules = [];
- for (const [pattern, url] of realm_filters) {
- const [regex, final_url] = python_to_js_filter(pattern, url);
+ for (const [pattern, url] of linkifiers) {
+ const [regex, final_url] = python_to_js_linkifier(pattern, url);
if (!regex) {
- // Skip any realm filters that could not be converted
+ // Skip any linkifiers that could not be converted
continue;
}
- realm_filter_map.set(regex, final_url);
- realm_filter_list.push([regex, final_url]);
+ linkifier_map.set(regex, final_url);
+ linkifier_list.push([regex, final_url]);
marked_rules.push(regex);
}
- marked.InlineLexer.rules.zulip.realm_filters = marked_rules;
+ marked.InlineLexer.rules.zulip.linkifiers = marked_rules;
}
-export function initialize(realm_filters, helper_config) {
+export function initialize(linkifiers, helper_config) {
helpers = helper_config;
function disable_markdown_regex(rules, name) {
@@ -506,7 +506,7 @@ export function initialize(realm_filters, helper_config) {
// Disable autolink as (a) it is not used in our backend and (b) it interferes with @mentions
disable_markdown_regex(marked.InlineLexer.rules.zulip, "autolink");
- update_realm_filter_rules(realm_filters);
+ update_linkifier_rules(linkifiers);
// Tell our fenced code preprocessor how to insert arbitrary
// HTML into the output. This generated HTML is safe to not escape
@@ -525,7 +525,7 @@ export function initialize(realm_filters, helper_config) {
unicodeEmojiHandler: handleUnicodeEmoji,
streamHandler: handleStream,
streamTopicHandler: handleStreamTopic,
- realmFilterHandler: handleRealmFilter,
+ linkifierHandler: handleLinkifier,
texHandler: handleTex,
timestampHandler: handleTimestamp,
renderer: r,
diff --git a/static/js/server_events_dispatch.js b/static/js/server_events_dispatch.js
index 77982f4dbc..40775a9e87 100644
--- a/static/js/server_events_dispatch.js
+++ b/static/js/server_events_dispatch.js
@@ -286,8 +286,8 @@ export function dispatch_normal_event(event) {
case "realm_filters":
page_params.realm_filters = event.realm_filters;
- markdown.update_realm_filter_rules(page_params.realm_filters);
- settings_linkifiers.populate_filters(page_params.realm_filters);
+ markdown.update_linkifier_rules(page_params.realm_filters);
+ settings_linkifiers.populate_linkifiers(page_params.realm_filters);
break;
case "realm_domains": {
diff --git a/static/js/settings_linkifiers.js b/static/js/settings_linkifiers.js
index 4c7596d2e4..46fec41d5f 100644
--- a/static/js/settings_linkifiers.js
+++ b/static/js/settings_linkifiers.js
@@ -1,6 +1,6 @@
import $ from "jquery";
-import render_admin_filter_list from "../templates/admin_filter_list.hbs";
+import render_admin_linkifier_list from "../templates/admin_linkifier_list.hbs";
import * as channel from "./channel";
import * as ListWidget from "./list_widget";
@@ -39,42 +39,42 @@ function sort_url(a, b) {
return compare_by_index(a, b, 1);
}
-export function populate_filters(filters_data) {
+export function populate_linkifiers(linkifiers_data) {
if (!meta.loaded) {
return;
}
- const filters_table = $("#admin_filters_table").expectOne();
- ListWidget.create(filters_table, filters_data, {
+ const linkifiers_table = $("#admin_linkifiers_table").expectOne();
+ ListWidget.create(linkifiers_table, linkifiers_data, {
name: "linkifiers_list",
- modifier(filter) {
- return render_admin_filter_list({
- filter: {
- pattern: filter[0],
- url_format_string: filter[1],
- id: filter[2],
+ modifier(linkifier) {
+ return render_admin_linkifier_list({
+ linkifier: {
+ pattern: linkifier[0],
+ url_format_string: linkifier[1],
+ id: linkifier[2],
},
can_modify: page_params.is_admin,
});
},
filter: {
- element: filters_table.closest(".settings-section").find(".search"),
+ element: linkifiers_table.closest(".settings-section").find(".search"),
predicate(item, value) {
return (
item[0].toLowerCase().includes(value) || item[1].toLowerCase().includes(value)
);
},
onupdate() {
- ui.reset_scrollbar(filters_table);
+ ui.reset_scrollbar(linkifiers_table);
},
},
- parent_container: $("#filter-settings").expectOne(),
+ parent_container: $("#linkifier-settings").expectOne(),
init_sort: [sort_pattern],
sort_fields: {
pattern: sort_pattern,
url: sort_url,
},
- simplebar_container: $("#filter-settings .progressive-table-wrapper"),
+ simplebar_container: $("#linkifier-settings .progressive-table-wrapper"),
});
loading.destroy_indicator($("#admin_page_filters_loading_indicator"));
@@ -91,16 +91,16 @@ export function build_page() {
// create loading indicators
loading.make_indicator($("#admin_page_filters_loading_indicator"));
- // Populate filters table
- populate_filters(page_params.realm_filters);
+ // Populate linkifiers table
+ populate_linkifiers(page_params.realm_filters);
- $(".admin_filters_table").on("click", ".delete", function (e) {
+ $(".admin_linkifiers_table").on("click", ".delete", function (e) {
e.preventDefault();
e.stopPropagation();
const btn = $(this);
channel.del({
- url: "/json/realm/filters/" + encodeURIComponent(btn.attr("data-filter-id")),
+ url: "/json/realm/filters/" + encodeURIComponent(btn.attr("data-linkifier-id")),
error(xhr) {
ui_report.generic_row_button_error(xhr, btn);
},
@@ -111,38 +111,38 @@ export function build_page() {
});
});
- $(".organization form.admin-filter-form")
+ $(".organization form.admin-linkifier-form")
.off("submit")
.on("submit", function (e) {
e.preventDefault();
e.stopPropagation();
- const filter_status = $("#admin-filter-status");
- const pattern_status = $("#admin-filter-pattern-status");
- const format_status = $("#admin-filter-format-status");
- const add_filter_button = $(".new-filter-form button");
- add_filter_button.prop("disabled", true);
- filter_status.hide();
+ const linkifier_status = $("#admin-linkifier-status");
+ const pattern_status = $("#admin-linkifier-pattern-status");
+ const format_status = $("#admin-linkifier-format-status");
+ const add_linkifier_button = $(".new-linkifier-form button");
+ add_linkifier_button.prop("disabled", true);
+ linkifier_status.hide();
pattern_status.hide();
format_status.hide();
- const filter = {};
+ const linkifier = {};
for (const obj of $(this).serializeArray()) {
- filter[obj.name] = obj.value;
+ linkifier[obj.name] = obj.value;
}
channel.post({
url: "/json/realm/filters",
data: $(this).serialize(),
success(data) {
- $("#filter_pattern").val("");
- $("#filter_format_string").val("");
- add_filter_button.prop("disabled", false);
- filter.id = data.id;
- ui_report.success(i18n.t("Custom filter added!"), filter_status);
+ $("#linkifier_pattern").val("");
+ $("#linkifier_format_string").val("");
+ add_linkifier_button.prop("disabled", false);
+ linkifier.id = data.id;
+ ui_report.success(i18n.t("Custom linkifier added!"), linkifier_status);
},
error(xhr) {
const errors = JSON.parse(xhr.responseText).errors;
- add_filter_button.prop("disabled", false);
+ add_linkifier_button.prop("disabled", false);
if (errors.pattern !== undefined) {
xhr.responseText = JSON.stringify({msg: errors.pattern});
ui_report.error(i18n.t("Failed"), xhr, pattern_status);
@@ -153,7 +153,7 @@ export function build_page() {
}
if (errors.__all__ !== undefined) {
xhr.responseText = JSON.stringify({msg: errors.__all__});
- ui_report.error(i18n.t("Failed"), xhr, filter_status);
+ ui_report.error(i18n.t("Failed"), xhr, linkifier_status);
}
},
});
diff --git a/static/js/settings_sections.js b/static/js/settings_sections.js
index 8a418ee89b..d79fda294e 100644
--- a/static/js/settings_sections.js
+++ b/static/js/settings_sections.js
@@ -56,7 +56,7 @@ export function initialize() {
load_func_dict.set("org_users", settings_users.set_up_humans);
load_func_dict.set("emoji-settings", settings_emoji.set_up);
load_func_dict.set("default-streams-list", settings_streams.set_up);
- load_func_dict.set("filter-settings", settings_linkifiers.set_up);
+ load_func_dict.set("linkifier-settings", settings_linkifiers.set_up);
load_func_dict.set("invites-list-admin", settings_invites.set_up);
load_func_dict.set("user-groups-admin", settings_user_groups.set_up);
load_func_dict.set("profile-field-settings", settings_profile_fields.set_up);
diff --git a/static/styles/settings.css b/static/styles/settings.css
index 32a28646f4..7c30224423 100644
--- a/static/styles/settings.css
+++ b/static/styles/settings.css
@@ -185,9 +185,9 @@ h3 .fa-question-circle-o {
word-break: break-all;
}
-#filter-settings {
- #filter_pattern,
- #filter_format_string {
+#linkifier-settings {
+ #linkifier_pattern,
+ #linkifier_format_string {
width: calc(100% - 10em - 6em);
}
}
@@ -657,7 +657,7 @@ input[type="checkbox"] {
}
.add-new-profile-field-box,
-.add-new-filter-box {
+.add-new-linkifier-box {
button {
margin-left: calc(10em + 20px) !important;
}
@@ -682,8 +682,8 @@ input[type="checkbox"] {
}
}
-#admin-filter-pattern-status,
-#admin-filter-format-status {
+#admin-linkifier-pattern-status,
+#admin-linkifier-format-status {
margin: 20px 0 0 0;
}
@@ -870,7 +870,7 @@ input[type="checkbox"] {
#create_bot_form,
#create_alert_word_form,
.admin-emoji-form,
-.admin-filter-form,
+.admin-linkifier-form,
.admin-profile-field-form,
.edit_bot_form {
.control-label {
@@ -1825,12 +1825,12 @@ body:not(.night-mode) #settings_page .custom_user_field .datepicker {
margin: auto;
}
- #filter-settings .new-filter-form,
+ #linkifier-settings .new-linkifier-form,
#profile-field-settings .new-profile-field-form {
width: 100%;
}
- #filter-settings .new-filter-form .control-label,
+ #linkifier-settings .new-linkifier-form .control-label,
#profile-field-settings .new-profile-field-form .control-label {
display: block;
width: 120px;
@@ -1841,7 +1841,7 @@ body:not(.night-mode) #settings_page .custom_user_field .datepicker {
float: none;
}
- #filter-settings .new-filter-form .controls,
+ #linkifier-settings .new-linkifier-form .controls,
#profile-field-settings .new-profile-field-form .controls {
margin: auto;
text-align: center;
diff --git a/static/templates/admin_filter_list.hbs b/static/templates/admin_filter_list.hbs
deleted file mode 100644
index 40c5737cb2..0000000000
--- a/static/templates/admin_filter_list.hbs
+++ /dev/null
@@ -1,17 +0,0 @@
-{{#with filter}}
-
-
- {{pattern}}
-
-
- {{url_format_string}}
-
- {{#if ../can_modify}}
-
-
-
-
-
- {{/if}}
-
-{{/with}}
diff --git a/static/templates/admin_linkifier_list.hbs b/static/templates/admin_linkifier_list.hbs
new file mode 100644
index 0000000000..4f20d7bd3a
--- /dev/null
+++ b/static/templates/admin_linkifier_list.hbs
@@ -0,0 +1,17 @@
+{{#with linkifier}}
+
+
+ {{pattern}}
+
+
+ {{url_format_string}}
+
+ {{#if ../can_modify}}
+
+
+
+
+
+ {{/if}}
+
+{{/with}}
diff --git a/static/templates/settings/linkifier_settings_admin.hbs b/static/templates/settings/linkifier_settings_admin.hbs
index dfeba46b97..448ca3a023 100644
--- a/static/templates/settings/linkifier_settings_admin.hbs
+++ b/static/templates/settings/linkifier_settings_admin.hbs
@@ -1,4 +1,4 @@
-